Skip to content

Commit 5a52f5b

Browse files
vidsinghalVidush Singhal
authored and
Vidush Singhal
committed
Store the full chain of instructions that make up the access.
1 parent e8e05c3 commit 5a52f5b

File tree

3 files changed

+784
-111
lines changed

3 files changed

+784
-111
lines changed

llvm/include/llvm/Transforms/IPO/Attributor.h

+195-7
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@
103103
#include "llvm/ADT/STLExtras.h"
104104
#include "llvm/ADT/SetOperations.h"
105105
#include "llvm/ADT/SetVector.h"
106+
#include "llvm/ADT/SmallPtrSet.h"
106107
#include "llvm/ADT/SmallSet.h"
108+
#include "llvm/ADT/SmallVector.h"
107109
#include "llvm/ADT/iterator.h"
108110
#include "llvm/Analysis/AssumeBundleQueries.h"
109111
#include "llvm/Analysis/CFG.h"
@@ -320,6 +322,10 @@ inline bool operator==(const RangeTy &A, const RangeTy &B) {
320322
return A.Offset == B.Offset && A.Size == B.Size;
321323
}
322324

325+
inline bool operator<(const RangeTy &A, const RangeTy &B) {
326+
return A.Offset < B.Offset;
327+
}
328+
323329
inline bool operator!=(const RangeTy &A, const RangeTy &B) { return !(A == B); }
324330

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

5794+
/// A helper containing a list of offsets computed for a Use. Ideally this
5795+
/// list should be strictly ascending, but we ensure that only when we
5796+
/// actually translate the list of offsets to a RangeList.
5797+
struct OffsetInfo {
5798+
using VecTy = SmallVector<AA::RangeTy>;
5799+
// A map to store depth 1 predecessors per offset.
5800+
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
5801+
using const_iterator = VecTy::const_iterator;
5802+
OriginsTy Origins;
5803+
VecTy Ranges;
5804+
5805+
const_iterator begin() const { return Ranges.begin(); }
5806+
const_iterator end() const { return Ranges.end(); }
5807+
5808+
bool operator==(const OffsetInfo &RHS) const {
5809+
return Ranges == RHS.Ranges && Origins == RHS.Origins;
5810+
}
5811+
5812+
bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
5813+
5814+
// Insert a new Range and Origin
5815+
void insert(AA::RangeTy Range, Value &V) {
5816+
auto *It = std::find(Ranges.begin(), Ranges.end(), Range);
5817+
// Offset exists in Offsets map
5818+
if (It != Ranges.end()) {
5819+
size_t Index = It - Ranges.begin();
5820+
if (Index < Origins.size())
5821+
Origins[Index].insert(&V);
5822+
} else {
5823+
Ranges.push_back(Range);
5824+
Origins.emplace_back();
5825+
Origins.back().insert(&V);
5826+
}
5827+
}
5828+
5829+
// Set the size of the offset for all ranges.
5830+
void setSizeAll(uint64_t Size) {
5831+
for (auto &Range : Ranges)
5832+
Range.Size = Size;
5833+
}
5834+
5835+
// Helper function to get just the offsets from Ranges.
5836+
void getOnlyOffsets(SmallVector<int64_t> &Offsets) {
5837+
for (auto &Range : Ranges)
5838+
Offsets.push_back(Range.Offset);
5839+
// ensure unique
5840+
sort(Offsets.begin(), Offsets.end());
5841+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5842+
}
5843+
5844+
bool isUnassigned() const { return Ranges.empty(); }
5845+
5846+
bool isUnknown() const {
5847+
if (isUnassigned())
5848+
return false;
5849+
if (Ranges.size() == 1)
5850+
return Ranges.front().Offset == AA::RangeTy::Unknown;
5851+
return false;
5852+
}
5853+
5854+
void setUnknown(Value &V) {
5855+
Ranges.clear();
5856+
Origins.clear();
5857+
insert(AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
5858+
}
5859+
5860+
// Increment all ranges by Inc.
5861+
// Add an origin V to all offsets.
5862+
void addToAll(int64_t Inc, Value &V) {
5863+
for (auto &Range : Ranges)
5864+
Range.Offset += Inc;
5865+
5866+
if (!Origins.empty()) {
5867+
for (auto &Origin : Origins)
5868+
Origin.insert(&V);
5869+
} else {
5870+
for (size_t Index = 0; Index < Ranges.size(); Index++) {
5871+
Origins.emplace_back();
5872+
Origins[Index].insert(&V);
5873+
}
5874+
}
5875+
}
5876+
5877+
// Increment all ranges by Inc.
5878+
void addToAll(int64_t Inc) {
5879+
for (auto &Range : Ranges)
5880+
Range.Offset += Inc;
5881+
}
5882+
5883+
/// Copy offsets from \p R into the current list.
5884+
///
5885+
/// Ideally all lists should be strictly ascending, but we defer that to the
5886+
/// actual use of the list. So we just blindly append here.
5887+
void merge(const OffsetInfo &R) {
5888+
Ranges.append(R.Ranges);
5889+
// ensure elements are unique.
5890+
sort(Ranges.begin(), Ranges.end());
5891+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5892+
5893+
OriginsTy ToBeMergeOrigins = R.Origins;
5894+
for (auto &Origin : ToBeMergeOrigins)
5895+
Origins.emplace_back(Origin);
5896+
}
5897+
5898+
// Merge two OffsetInfo structs.
5899+
// takes an additional origin argument
5900+
// and adds it to the corresponding offset in the
5901+
// origins map.
5902+
void mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
5903+
Ranges.append(R.Ranges);
5904+
// ensure elements are unique.
5905+
sort(Ranges.begin(), Ranges.end());
5906+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5907+
auto &ROffsets = R.Ranges;
5908+
for (auto Offset : ROffsets) {
5909+
auto *It = std::find(Ranges.begin(), Ranges.end(), Offset);
5910+
if (It == Ranges.end())
5911+
continue;
5912+
size_t Index = It - Ranges.begin();
5913+
if (Index >= Origins.size()) {
5914+
Origins.emplace_back();
5915+
Origins.back().insert(&CurPtr);
5916+
} else {
5917+
Origins[Index].insert(&CurPtr);
5918+
}
5919+
}
5920+
}
5921+
};
5922+
5923+
using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5924+
using AccessPathTy = SmallVector<Value *, 4>;
5925+
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;
5926+
57885927
/// A container for a list of ranges.
57895928
struct RangeList {
57905929
// The set of ranges rarely contains more than one element, and is unlikely
@@ -5939,15 +6078,17 @@ struct AAPointerInfo : public AbstractAttribute {
59396078
/// An access description.
59406079
struct Access {
59416080
Access(Instruction *I, int64_t Offset, int64_t Size,
5942-
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6081+
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6082+
AccessPathSetTy *AccessPaths)
59436083
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
5944-
Kind(Kind), Ty(Ty) {
6084+
Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
59456085
verify();
59466086
}
59476087
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
5948-
std::optional<Value *> Content, AccessKind K, Type *Ty)
6088+
std::optional<Value *> Content, AccessKind K, Type *Ty,
6089+
AccessPathSetTy *AccessPaths)
59496090
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
5950-
Kind(K), Ty(Ty) {
6091+
Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
59516092
if (Ranges.size() > 1) {
59526093
Kind = AccessKind(Kind | AK_MAY);
59536094
Kind = AccessKind(Kind & ~AK_MUST);
@@ -5956,17 +6097,18 @@ struct AAPointerInfo : public AbstractAttribute {
59566097
}
59576098
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
59586099
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
5959-
Type *Ty)
6100+
Type *Ty, AccessPathSetTy *AccessPaths)
59606101
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
5961-
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
6102+
Ranges(Offset, Size), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
59626103
verify();
59636104
}
59646105
Access(const Access &Other) = default;
59656106

59666107
Access &operator=(const Access &Other) = default;
59676108
bool operator==(const Access &R) const {
59686109
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
5969-
Content == R.Content && Kind == R.Kind;
6110+
Content == R.Content && Kind == R.Kind &&
6111+
checkAccessPathsAreSame(R.AccessPaths);
59706112
}
59716113
bool operator!=(const Access &R) const { return !(*this == R); }
59726114

@@ -6078,11 +6220,53 @@ struct AAPointerInfo : public AbstractAttribute {
60786220
}
60796221
}
60806222

6223+
// Merge two access paths into one.
6224+
void mergeAccessPaths(const AccessPathSetTy *AccessPathsNew) const {
6225+
for (auto *Path : *AccessPathsNew)
6226+
if (!existsChain(Path))
6227+
AccessPaths->insert(Path);
6228+
}
6229+
6230+
// Check if the given access paths are same.
6231+
bool checkAccessPathsAreSame(const AccessPathSetTy *AccessPathsR) const {
6232+
bool IsSame = true;
6233+
if (AccessPaths->size() != AccessPathsR->size())
6234+
return false;
6235+
6236+
for (auto *Path : *AccessPathsR) {
6237+
if (!existsChain(Path))
6238+
IsSame = false;
6239+
}
6240+
return IsSame;
6241+
}
6242+
6243+
// Check if the chain exists in the AccessPathsSet.
6244+
bool existsChain(const AccessPathTy *NewPath) const {
6245+
for (auto *OldPath : *AccessPaths)
6246+
if (*OldPath == *NewPath)
6247+
return true;
6248+
6249+
return false;
6250+
}
6251+
6252+
void dumpAccessPaths(raw_ostream &O) const {
6253+
O << "Print all access paths found:"
6254+
<< "\n";
6255+
for (auto *It : *AccessPaths) {
6256+
O << "Backtrack a unique access path:\n";
6257+
for (Value *Ins : *It) {
6258+
O << *Ins << "\n";
6259+
}
6260+
}
6261+
}
6262+
6263+
const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
60816264
const RangeList &getRanges() const { return Ranges; }
60826265

60836266
using const_iterator = RangeList::const_iterator;
60846267
const_iterator begin() const { return Ranges.begin(); }
60856268
const_iterator end() const { return Ranges.end(); }
6269+
size_t size() const { return Ranges.size(); }
60866270

60876271
private:
60886272
/// The instruction responsible for the access with respect to the local
@@ -6105,6 +6289,10 @@ struct AAPointerInfo : public AbstractAttribute {
61056289
/// The type of the content, thus the type read/written, can be null if not
61066290
/// available.
61076291
Type *Ty;
6292+
6293+
/// The full chain of instructions that participate in the Access.
6294+
/// There may be more than one access chain.
6295+
AccessPathSetTy *AccessPaths;
61086296
};
61096297

61106298
/// Create an abstract attribute view for the position \p IRP.

0 commit comments

Comments
 (0)