Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Attributor]: AApointerInfo - store the full chain of instructions that make up the access #96526

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 199 additions & 7 deletions llvm/include/llvm/Transforms/IPO/Attributor.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/CFG.h"
Expand Down Expand Up @@ -320,6 +322,10 @@ inline bool operator==(const RangeTy &A, const RangeTy &B) {
return A.Offset == B.Offset && A.Size == B.Size;
}

inline bool operator<(const RangeTy &A, const RangeTy &B) {
return A.Offset < B.Offset;
}

inline bool operator!=(const RangeTy &A, const RangeTy &B) { return !(A == B); }

/// Return the initial value of \p Obj with type \p Ty if that is a constant.
Expand Down Expand Up @@ -5785,6 +5791,139 @@ struct AAPointerInfo : public AbstractAttribute {
AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W,
};

/// A helper containing a list of offsets computed for a Use. Ideally this
/// list should be strictly ascending, but we ensure that only when we
/// actually translate the list of offsets to a RangeList.
struct OffsetInfo {
using VecTy = SmallVector<AA::RangeTy>;
// A map to store depth 1 predecessors per offset.
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
using const_iterator = VecTy::const_iterator;
OriginsTy Origins;
VecTy Ranges;

const_iterator begin() const { return Ranges.begin(); }
const_iterator end() const { return Ranges.end(); }

bool operator==(const OffsetInfo &RHS) const {
return Ranges == RHS.Ranges && Origins == RHS.Origins;
}

bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }

// Insert a new Range and Origin
void insert(AA::RangeTy Range, Value &V) {
auto *It = std::find(Ranges.begin(), Ranges.end(), Range);
// Offset exists in Offsets map
if (It != Ranges.end()) {
size_t Index = It - Ranges.begin();
if (Index < Origins.size())
Origins[Index].insert(&V);
} else {
Ranges.push_back(Range);
Origins.emplace_back();
Origins.back().insert(&V);
}
}

// Set the size of the offset for all ranges.
void setSizeAll(uint64_t Size) {
for (auto &Range : Ranges)
Range.Size = Size;
}

// Helper function to get just the offsets from Ranges.
void getOnlyOffsets(SmallVector<int64_t> &Offsets) {
vidsinghal marked this conversation as resolved.
Show resolved Hide resolved
for (auto &Range : Ranges)
Offsets.push_back(Range.Offset);
// ensure unique
sort(Offsets.begin(), Offsets.end());
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
}

bool isUnassigned() const { return Ranges.empty(); }

bool isUnknown() const {
if (isUnassigned())
return false;
if (Ranges.size() == 1)
return Ranges.front().Offset == AA::RangeTy::Unknown;
return false;
}

void setUnknown(Value &V) {
Ranges.clear();
Origins.clear();
insert(AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
}

// Increment all ranges by Inc.
// Add an origin V to all offsets.
void addToAll(int64_t Inc, Value &V) {
for (auto &Range : Ranges)
Range.Offset += Inc;

if (!Origins.empty()) {
for (auto &Origin : Origins)
Origin.insert(&V);
} else {
for (size_t Index = 0; Index < Ranges.size(); Index++) {
Origins.emplace_back();
Origins[Index].insert(&V);
}
}
}

// Increment all ranges by Inc.
void addToAll(int64_t Inc) {
for (auto &Range : Ranges)
Range.Offset += Inc;
}

/// Copy offsets from \p R into the current list.
///
/// Ideally all lists should be strictly ascending, but we defer that to the
/// actual use of the list. So we just blindly append here.
void merge(const OffsetInfo &R) {
Ranges.append(R.Ranges);
// ensure elements are unique.
sort(Ranges.begin(), Ranges.end());
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());

OriginsTy ToBeMergeOrigins = R.Origins;
for (auto &Origin : ToBeMergeOrigins)
Origins.emplace_back(Origin);
}

// Merge two OffsetInfo structs.
// takes an additional origin argument
// and adds it to the corresponding offset in the
// origins map.
void mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
Ranges.append(R.Ranges);
// ensure elements are unique.
sort(Ranges.begin(), Ranges.end());
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
auto &ROffsets = R.Ranges;
for (auto Offset : ROffsets) {
auto *It = std::find(Ranges.begin(), Ranges.end(), Offset);
if (It == Ranges.end())
continue;
size_t Index = It - Ranges.begin();
if (Index >= Origins.size()) {
Origins.emplace_back();
Origins.back().insert(&CurPtr);
} else {
Origins[Index].insert(&CurPtr);
}
}
}
};

using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
using AccessPathTy = SmallVector<Value *, 4>;
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;

/// A container for a list of ranges.
struct RangeList {
// The set of ranges rarely contains more than one element, and is unlikely
Expand Down Expand Up @@ -5939,15 +6078,17 @@ struct AAPointerInfo : public AbstractAttribute {
/// An access description.
struct Access {
Access(Instruction *I, int64_t Offset, int64_t Size,
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
AccessPathSetTy *AccessPaths)
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
Kind(Kind), Ty(Ty) {
Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
verify();
}
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
std::optional<Value *> Content, AccessKind K, Type *Ty)
std::optional<Value *> Content, AccessKind K, Type *Ty,
AccessPathSetTy *AccessPaths)
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
Kind(K), Ty(Ty) {
Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
if (Ranges.size() > 1) {
Kind = AccessKind(Kind | AK_MAY);
Kind = AccessKind(Kind & ~AK_MUST);
Expand All @@ -5956,17 +6097,18 @@ struct AAPointerInfo : public AbstractAttribute {
}
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
Type *Ty)
Type *Ty, AccessPathSetTy *AccessPaths)
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
Ranges(Offset, Size), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
verify();
}
Access(const Access &Other) = default;

Access &operator=(const Access &Other) = default;
bool operator==(const Access &R) const {
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
Content == R.Content && Kind == R.Kind;
Content == R.Content && Kind == R.Kind &&
checkAccessPathsAreSame(R.AccessPaths);
}
bool operator!=(const Access &R) const { return !(*this == R); }

Expand Down Expand Up @@ -6078,11 +6220,57 @@ struct AAPointerInfo : public AbstractAttribute {
}
}

// Merge two access paths into one.
void mergeAccessPaths(Attributor &A,
const AccessPathSetTy *AccessPathsNew) const {
for (auto *Path : *AccessPathsNew)
if (!existsChain(Path)) {
AccessPathTy *CopiedPath =
new (A.Allocator) AccessPathTy(Path->begin(), Path->end());
AccessPaths->insert(CopiedPath);
}
}

// Check if the given access paths are same.
bool checkAccessPathsAreSame(const AccessPathSetTy *AccessPathsR) const {
bool IsSame = true;
if (AccessPaths->size() != AccessPathsR->size())
return false;

for (auto *Path : *AccessPathsR) {
if (!existsChain(Path))
IsSame = false;
}
return IsSame;
}

// Check if the chain exists in the AccessPathsSet.
bool existsChain(const AccessPathTy *NewPath) const {
for (auto *OldPath : *AccessPaths)
if (*OldPath == *NewPath)
return true;

return false;
}

void dumpAccessPaths(raw_ostream &O) const {
O << "Print all access paths found:"
<< "\n";
for (auto *It : *AccessPaths) {
O << "Backtrack a unique access path:\n";
for (Value *Ins : *It) {
O << *Ins << "\n";
}
}
}

const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
const RangeList &getRanges() const { return Ranges; }

using const_iterator = RangeList::const_iterator;
const_iterator begin() const { return Ranges.begin(); }
const_iterator end() const { return Ranges.end(); }
size_t size() const { return Ranges.size(); }

private:
/// The instruction responsible for the access with respect to the local
Expand All @@ -6105,6 +6293,10 @@ struct AAPointerInfo : public AbstractAttribute {
/// The type of the content, thus the type read/written, can be null if not
/// available.
Type *Ty;

/// The full chain of instructions that participate in the Access.
/// There may be more than one access chain.
AccessPathSetTy *AccessPaths;
};

/// Create an abstract attribute view for the position \p IRP.
Expand Down
Loading
Loading