Skip to content

Commit e862077

Browse files
committed
Store the full chain of instructions that make up the access.
1 parent d748a12 commit e862077

File tree

3 files changed

+755
-79
lines changed

3 files changed

+755
-79
lines changed

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

Lines changed: 165 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.
@@ -5845,49 +5851,135 @@ struct AAPointerInfo : public AbstractAttribute {
58455851
/// list should be strictly ascending, but we ensure that only when we
58465852
/// actually translate the list of offsets to a RangeList.
58475853
struct OffsetInfo {
5848-
using VecTy = SmallSet<int64_t, 4>;
5854+
using VecTy = SmallVector<AA::RangeTy>;
5855+
// A map to store depth 1 predecessors per offset.
5856+
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
58495857
using const_iterator = VecTy::const_iterator;
5850-
VecTy Offsets;
5858+
OriginsTy Origins;
5859+
VecTy Ranges;
58515860

5852-
const_iterator begin() const { return Offsets.begin(); }
5853-
const_iterator end() const { return Offsets.end(); }
5861+
const_iterator begin() const { return Ranges.begin(); }
5862+
const_iterator end() const { return Ranges.end(); }
58545863

58555864
bool operator==(const OffsetInfo &RHS) const {
5856-
return Offsets == RHS.Offsets;
5865+
return Ranges == RHS.Ranges && Origins == RHS.Origins;
58575866
}
58585867

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

5861-
bool insert(int64_t Offset) { return Offsets.insert(Offset).second; }
5862-
bool isUnassigned() const { return Offsets.size() == 0; }
5870+
// Insert a new Range and Origin
5871+
void insert(AA::RangeTy Range, Value &V) {
5872+
auto *It = std::find(Ranges.begin(), Ranges.end(), Range);
5873+
// Offset exists in Offsets map
5874+
if (It != Ranges.end()) {
5875+
size_t Index = It - Ranges.begin();
5876+
if (Index < Origins.size())
5877+
Origins[Index].insert(&V);
5878+
} else {
5879+
Ranges.push_back(Range);
5880+
Origins.emplace_back();
5881+
Origins.back().insert(&V);
5882+
}
5883+
}
5884+
5885+
// Set the size of the offset for all ranges.
5886+
void setSizeAll(uint64_t Size) {
5887+
for (auto &Range : Ranges)
5888+
Range.Size = Size;
5889+
}
5890+
5891+
// Helper function to get just the offsets from Ranges.
5892+
void getOnlyOffsets(SmallVector<int64_t> &Offsets) {
5893+
for (auto &Range : Ranges)
5894+
Offsets.push_back(Range.Offset);
5895+
// ensure unique
5896+
sort(Offsets.begin(), Offsets.end());
5897+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5898+
}
5899+
5900+
bool isUnassigned() const { return Ranges.empty(); }
58635901

58645902
bool isUnknown() const {
58655903
if (isUnassigned())
58665904
return false;
5867-
if (Offsets.size() == 1)
5868-
return *Offsets.begin() == AA::RangeTy::Unknown;
5905+
if (Ranges.size() == 1)
5906+
return Ranges.front().Offset == AA::RangeTy::Unknown;
58695907
return false;
58705908
}
58715909

5872-
void setUnknown() {
5873-
Offsets.clear();
5874-
Offsets.insert(AA::RangeTy::Unknown);
5910+
void setUnknown(Value &V) {
5911+
Ranges.clear();
5912+
Origins.clear();
5913+
insert(AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
58755914
}
58765915

5916+
// Increment all ranges by Inc.
5917+
// Add an origin V to all offsets.
5918+
void addToAll(int64_t Inc, Value &V) {
5919+
for (auto &Range : Ranges)
5920+
Range.Offset += Inc;
5921+
5922+
if (!Origins.empty()) {
5923+
for (auto &Origin : Origins)
5924+
Origin.insert(&V);
5925+
} else {
5926+
for (size_t Index = 0; Index < Ranges.size(); Index++) {
5927+
Origins.emplace_back();
5928+
Origins[Index].insert(&V);
5929+
}
5930+
}
5931+
}
5932+
5933+
// Increment all ranges by Inc.
58775934
void addToAll(int64_t Inc) {
5878-
VecTy NewOffsets;
5879-
for (auto &Offset : Offsets)
5880-
NewOffsets.insert(Offset + Inc);
5881-
Offsets = std::move(NewOffsets);
5935+
for (auto &Range : Ranges)
5936+
Range.Offset += Inc;
58825937
}
58835938

58845939
/// Copy offsets from \p R into the current list.
58855940
///
58865941
/// Ideally all lists should be strictly ascending, but we defer that to the
58875942
/// actual use of the list. So we just blindly append here.
5888-
bool merge(const OffsetInfo &R) { return set_union(Offsets, R.Offsets); }
5943+
void merge(const OffsetInfo &R) {
5944+
Ranges.append(R.Ranges);
5945+
// ensure elements are unique.
5946+
sort(Ranges.begin(), Ranges.end());
5947+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5948+
5949+
OriginsTy ToBeMergeOrigins = R.Origins;
5950+
for (auto &Origin : ToBeMergeOrigins)
5951+
Origins.emplace_back(Origin);
5952+
}
5953+
5954+
// Merge two OffsetInfo structs.
5955+
// takes an additional origin argument
5956+
// and adds it to the corresponding offset in the
5957+
// origins map.
5958+
void mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
5959+
Ranges.append(R.Ranges);
5960+
// ensure elements are unique.
5961+
sort(Ranges.begin(), Ranges.end());
5962+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5963+
auto &ROffsets = R.Ranges;
5964+
for (auto Offset : ROffsets) {
5965+
auto *It = std::find(Ranges.begin(), Ranges.end(), Offset);
5966+
if (It == Ranges.end())
5967+
continue;
5968+
size_t Index = It - Ranges.begin();
5969+
if (Index >= Origins.size()) {
5970+
Origins.emplace_back();
5971+
Origins.back().insert(&CurPtr);
5972+
} else {
5973+
Origins[Index].insert(&CurPtr);
5974+
}
5975+
}
5976+
}
58895977
};
58905978

5979+
using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5980+
using AccessPathTy = SmallVector<Value *, 4>;
5981+
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;
5982+
58915983
/// A container for a list of ranges.
58925984
struct RangeList {
58935985
// The set of ranges rarely contains more than one element, and is unlikely
@@ -6042,15 +6134,17 @@ struct AAPointerInfo : public AbstractAttribute {
60426134
/// An access description.
60436135
struct Access {
60446136
Access(Instruction *I, int64_t Offset, int64_t Size,
6045-
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6137+
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6138+
AccessPathSetTy *AccessPaths)
60466139
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
6047-
Kind(Kind), Ty(Ty) {
6140+
Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
60486141
verify();
60496142
}
60506143
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
6051-
std::optional<Value *> Content, AccessKind K, Type *Ty)
6144+
std::optional<Value *> Content, AccessKind K, Type *Ty,
6145+
AccessPathSetTy *AccessPaths)
60526146
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
6053-
Kind(K), Ty(Ty) {
6147+
Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
60546148
if (Ranges.size() > 1) {
60556149
Kind = AccessKind(Kind | AK_MAY);
60566150
Kind = AccessKind(Kind & ~AK_MUST);
@@ -6059,17 +6153,18 @@ struct AAPointerInfo : public AbstractAttribute {
60596153
}
60606154
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
60616155
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
6062-
Type *Ty)
6156+
Type *Ty, AccessPathSetTy *AccessPaths)
60636157
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
6064-
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
6158+
Ranges(Offset, Size), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
60656159
verify();
60666160
}
60676161
Access(const Access &Other) = default;
60686162

60696163
Access &operator=(const Access &Other) = default;
60706164
bool operator==(const Access &R) const {
60716165
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
6072-
Content == R.Content && Kind == R.Kind;
6166+
Content == R.Content && Kind == R.Kind &&
6167+
checkAccessPathsAreSame(R.AccessPaths);
60736168
}
60746169
bool operator!=(const Access &R) const { return !(*this == R); }
60756170

@@ -6181,11 +6276,53 @@ struct AAPointerInfo : public AbstractAttribute {
61816276
}
61826277
}
61836278

6279+
// Merge two access paths into one.
6280+
void mergeAccessPaths(const AccessPathSetTy *AccessPathsNew) const {
6281+
for (auto *Path : *AccessPathsNew)
6282+
if (!existsChain(Path))
6283+
AccessPaths->insert(Path);
6284+
}
6285+
6286+
// Check if the given access paths are same.
6287+
bool checkAccessPathsAreSame(const AccessPathSetTy *AccessPathsR) const {
6288+
bool IsSame = true;
6289+
if (AccessPaths->size() != AccessPathsR->size())
6290+
return false;
6291+
6292+
for (auto *Path : *AccessPathsR) {
6293+
if (!existsChain(Path))
6294+
IsSame = false;
6295+
}
6296+
return IsSame;
6297+
}
6298+
6299+
// Check if the chain exists in the AccessPathsSet.
6300+
bool existsChain(const AccessPathTy *NewPath) const {
6301+
for (auto *OldPath : *AccessPaths)
6302+
if (*OldPath == *NewPath)
6303+
return true;
6304+
6305+
return false;
6306+
}
6307+
6308+
void dumpAccessPaths(raw_ostream &O) const {
6309+
O << "Print all access paths found:"
6310+
<< "\n";
6311+
for (auto *It : *AccessPaths) {
6312+
O << "Backtrack a unique access path:\n";
6313+
for (Value *Ins : *It) {
6314+
O << *Ins << "\n";
6315+
}
6316+
}
6317+
}
6318+
6319+
const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
61846320
const RangeList &getRanges() const { return Ranges; }
61856321

61866322
using const_iterator = RangeList::const_iterator;
61876323
const_iterator begin() const { return Ranges.begin(); }
61886324
const_iterator end() const { return Ranges.end(); }
6325+
size_t size() const { return Ranges.size(); }
61896326

61906327
private:
61916328
/// The instruction responsible for the access with respect to the local
@@ -6208,6 +6345,10 @@ struct AAPointerInfo : public AbstractAttribute {
62086345
/// The type of the content, thus the type read/written, can be null if not
62096346
/// available.
62106347
Type *Ty;
6348+
6349+
/// The full chain of instructions that participate in the Access.
6350+
/// There may be more than one access chain.
6351+
AccessPathSetTy *AccessPaths;
62116352
};
62126353

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

0 commit comments

Comments
 (0)