Skip to content

Commit 0edfd87

Browse files
committed
Store the full chain of instructions that make up the access.
1 parent c8f168c commit 0edfd87

File tree

3 files changed

+761
-80
lines changed

3 files changed

+761
-80
lines changed

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

Lines changed: 169 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@
104104
#include "llvm/ADT/STLExtras.h"
105105
#include "llvm/ADT/SetOperations.h"
106106
#include "llvm/ADT/SetVector.h"
107+
#include "llvm/ADT/SmallPtrSet.h"
107108
#include "llvm/ADT/SmallSet.h"
109+
#include "llvm/ADT/SmallVector.h"
108110
#include "llvm/ADT/iterator.h"
109111
#include "llvm/Analysis/AssumeBundleQueries.h"
110112
#include "llvm/Analysis/CFG.h"
@@ -329,6 +331,10 @@ inline bool operator==(const RangeTy &A, const RangeTy &B) {
329331
return A.Offset == B.Offset && A.Size == B.Size;
330332
}
331333

334+
inline bool operator<(const RangeTy &A, const RangeTy &B) {
335+
return A.Offset < B.Offset;
336+
}
337+
332338
inline bool operator!=(const RangeTy &A, const RangeTy &B) { return !(A == B); }
333339

334340
/// Return the initial value of \p Obj with type \p Ty if that is a constant.
@@ -5858,49 +5864,139 @@ struct AAPointerInfo : public AbstractAttribute {
58585864
/// list should be strictly ascending, but we ensure that only when we
58595865
/// actually translate the list of offsets to a RangeList.
58605866
struct OffsetInfo {
5861-
using VecTy = SmallSet<int64_t, 4>;
5867+
using VecTy = SmallVector<AA::RangeTy>;
5868+
// A map to store depth 1 predecessors per offset.
5869+
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
58625870
using const_iterator = VecTy::const_iterator;
5863-
VecTy Offsets;
5871+
OriginsTy Origins;
5872+
VecTy Ranges;
58645873

5865-
const_iterator begin() const { return Offsets.begin(); }
5866-
const_iterator end() const { return Offsets.end(); }
5874+
const_iterator begin() const { return Ranges.begin(); }
5875+
const_iterator end() const { return Ranges.end(); }
58675876

58685877
bool operator==(const OffsetInfo &RHS) const {
5869-
return Offsets == RHS.Offsets;
5878+
return Ranges == RHS.Ranges && Origins == RHS.Origins;
58705879
}
58715880

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

5874-
bool insert(int64_t Offset) { return Offsets.insert(Offset).second; }
5875-
bool isUnassigned() const { return Offsets.size() == 0; }
5883+
// Insert a new Range and Origin
5884+
void insert(AA::RangeTy Range, Value &V) {
5885+
auto *It = std::find(Ranges.begin(), Ranges.end(), Range);
5886+
// Offset exists in Offsets map
5887+
if (It != Ranges.end()) {
5888+
size_t Index = It - Ranges.begin();
5889+
if (Index < Origins.size())
5890+
Origins[Index].insert(&V);
5891+
} else {
5892+
Ranges.push_back(Range);
5893+
Origins.emplace_back();
5894+
Origins.back().insert(&V);
5895+
}
5896+
}
5897+
5898+
// Set the size of the offset for all ranges.
5899+
void setSizeAll(uint64_t Size) {
5900+
for (auto &Range : Ranges)
5901+
Range.Size = Size;
5902+
}
5903+
5904+
// Helper function to get just the offsets from Ranges.
5905+
void getOnlyOffsets(SmallVector<int64_t> &Offsets) {
5906+
for (auto &Range : Ranges)
5907+
Offsets.push_back(Range.Offset);
5908+
// ensure unique
5909+
sort(Offsets.begin(), Offsets.end());
5910+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5911+
}
5912+
5913+
bool isUnassigned() const { return Ranges.empty(); }
58765914

58775915
bool isUnknown() const {
58785916
if (isUnassigned())
58795917
return false;
5880-
if (Offsets.size() == 1)
5881-
return *Offsets.begin() == AA::RangeTy::Unknown;
5918+
if (Ranges.size() == 1)
5919+
return Ranges.front().Offset == AA::RangeTy::Unknown;
58825920
return false;
58835921
}
58845922

5885-
void setUnknown() {
5886-
Offsets.clear();
5887-
Offsets.insert(AA::RangeTy::Unknown);
5923+
void setUnknown(Value &V) {
5924+
Ranges.clear();
5925+
Origins.clear();
5926+
insert(AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
5927+
}
5928+
5929+
// Increment all ranges by Inc.
5930+
// Add an origin V to all offsets.
5931+
void addToAll(int64_t Inc, Value &V) {
5932+
for (auto &Range : Ranges)
5933+
Range.Offset += Inc;
5934+
5935+
if (!Origins.empty()) {
5936+
for (auto &Origin : Origins)
5937+
Origin.insert(&V);
5938+
} else {
5939+
for (size_t Index = 0; Index < Ranges.size(); Index++) {
5940+
Origins.emplace_back();
5941+
Origins[Index].insert(&V);
5942+
}
5943+
}
58885944
}
58895945

5946+
// Increment all ranges by Inc.
58905947
void addToAll(int64_t Inc) {
5891-
VecTy NewOffsets;
5892-
for (auto &Offset : Offsets)
5893-
NewOffsets.insert(Offset + Inc);
5894-
Offsets = std::move(NewOffsets);
5948+
for (auto &Range : Ranges)
5949+
Range.Offset += Inc;
58955950
}
58965951

58975952
/// Copy offsets from \p R into the current list.
58985953
///
58995954
/// Ideally all lists should be strictly ascending, but we defer that to the
59005955
/// actual use of the list. So we just blindly append here.
5901-
bool merge(const OffsetInfo &R) { return set_union(Offsets, R.Offsets); }
5956+
5957+
bool merge(const OffsetInfo &R) {
5958+
bool Changed = set_union(Ranges, R.Ranges);
5959+
// ensure elements are unique.
5960+
sort(Ranges.begin(), Ranges.end());
5961+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5962+
5963+
OriginsTy ToBeMergeOrigins = R.Origins;
5964+
for (auto &Origin : ToBeMergeOrigins)
5965+
Origins.emplace_back(Origin);
5966+
5967+
return Changed;
5968+
}
5969+
5970+
// Merge two OffsetInfo structs.
5971+
// takes an additional origin argument
5972+
// and adds it to the corresponding offset in the
5973+
// origins map.
5974+
bool mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
5975+
bool Changed = set_union(Ranges, R.Ranges);
5976+
// ensure elements are unique.
5977+
sort(Ranges.begin(), Ranges.end());
5978+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5979+
auto &ROffsets = R.Ranges;
5980+
for (auto Offset : ROffsets) {
5981+
auto *It = std::find(Ranges.begin(), Ranges.end(), Offset);
5982+
if (It == Ranges.end())
5983+
continue;
5984+
size_t Index = It - Ranges.begin();
5985+
if (Index >= Origins.size()) {
5986+
Origins.emplace_back();
5987+
Origins.back().insert(&CurPtr);
5988+
} else {
5989+
Origins[Index].insert(&CurPtr);
5990+
}
5991+
}
5992+
return Changed;
5993+
}
59025994
};
59035995

5996+
using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5997+
using AccessPathTy = SmallVector<Value *, 4>;
5998+
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;
5999+
59046000
/// A container for a list of ranges.
59056001
struct RangeList {
59066002
// The set of ranges rarely contains more than one element, and is unlikely
@@ -6055,15 +6151,17 @@ struct AAPointerInfo : public AbstractAttribute {
60556151
/// An access description.
60566152
struct Access {
60576153
Access(Instruction *I, int64_t Offset, int64_t Size,
6058-
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6154+
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6155+
AccessPathSetTy *AccessPaths)
60596156
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
6060-
Kind(Kind), Ty(Ty) {
6157+
Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
60616158
verify();
60626159
}
60636160
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
6064-
std::optional<Value *> Content, AccessKind K, Type *Ty)
6161+
std::optional<Value *> Content, AccessKind K, Type *Ty,
6162+
AccessPathSetTy *AccessPaths)
60656163
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
6066-
Kind(K), Ty(Ty) {
6164+
Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
60676165
if (Ranges.size() > 1) {
60686166
Kind = AccessKind(Kind | AK_MAY);
60696167
Kind = AccessKind(Kind & ~AK_MUST);
@@ -6072,17 +6170,18 @@ struct AAPointerInfo : public AbstractAttribute {
60726170
}
60736171
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
60746172
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
6075-
Type *Ty)
6173+
Type *Ty, AccessPathSetTy *AccessPaths)
60766174
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
6077-
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
6175+
Ranges(Offset, Size), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
60786176
verify();
60796177
}
60806178
Access(const Access &Other) = default;
60816179

60826180
Access &operator=(const Access &Other) = default;
60836181
bool operator==(const Access &R) const {
60846182
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
6085-
Content == R.Content && Kind == R.Kind;
6183+
Content == R.Content && Kind == R.Kind &&
6184+
checkAccessPathsAreSame(R.AccessPaths);
60866185
}
60876186
bool operator!=(const Access &R) const { return !(*this == R); }
60886187

@@ -6194,11 +6293,53 @@ struct AAPointerInfo : public AbstractAttribute {
61946293
}
61956294
}
61966295

6296+
// Merge two access paths into one.
6297+
void mergeAccessPaths(const AccessPathSetTy *AccessPathsNew) const {
6298+
for (auto *Path : *AccessPathsNew)
6299+
if (!existsChain(Path))
6300+
AccessPaths->insert(Path);
6301+
}
6302+
6303+
// Check if the given access paths are same.
6304+
bool checkAccessPathsAreSame(const AccessPathSetTy *AccessPathsR) const {
6305+
bool IsSame = true;
6306+
if (AccessPaths->size() != AccessPathsR->size())
6307+
return false;
6308+
6309+
for (auto *Path : *AccessPathsR) {
6310+
if (!existsChain(Path))
6311+
IsSame = false;
6312+
}
6313+
return IsSame;
6314+
}
6315+
6316+
// Check if the chain exists in the AccessPathsSet.
6317+
bool existsChain(const AccessPathTy *NewPath) const {
6318+
for (auto *OldPath : *AccessPaths)
6319+
if (*OldPath == *NewPath)
6320+
return true;
6321+
6322+
return false;
6323+
}
6324+
6325+
void dumpAccessPaths(raw_ostream &O) const {
6326+
O << "Print all access paths found:"
6327+
<< "\n";
6328+
for (auto *It : *AccessPaths) {
6329+
O << "Backtrack a unique access path:\n";
6330+
for (Value *Ins : *It) {
6331+
O << *Ins << "\n";
6332+
}
6333+
}
6334+
}
6335+
6336+
const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
61976337
const RangeList &getRanges() const { return Ranges; }
61986338

61996339
using const_iterator = RangeList::const_iterator;
62006340
const_iterator begin() const { return Ranges.begin(); }
62016341
const_iterator end() const { return Ranges.end(); }
6342+
size_t size() const { return Ranges.size(); }
62026343

62036344
private:
62046345
/// The instruction responsible for the access with respect to the local
@@ -6221,6 +6362,10 @@ struct AAPointerInfo : public AbstractAttribute {
62216362
/// The type of the content, thus the type read/written, can be null if not
62226363
/// available.
62236364
Type *Ty;
6365+
6366+
/// The full chain of instructions that participate in the Access.
6367+
/// There may be more than one access chain.
6368+
AccessPathSetTy *AccessPaths;
62246369
};
62256370

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

0 commit comments

Comments
 (0)