Skip to content

Commit e87d1ad

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

File tree

3 files changed

+803
-110
lines changed

3 files changed

+803
-110
lines changed

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

+200-7
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@
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"
109+
#include "llvm/ADT/StringExtras.h"
107110
#include "llvm/ADT/iterator.h"
108111
#include "llvm/Analysis/AssumeBundleQueries.h"
109112
#include "llvm/Analysis/CFG.h"
@@ -141,6 +144,7 @@
141144
#include <limits>
142145
#include <map>
143146
#include <optional>
147+
#include <tuple>
144148

145149
namespace llvm {
146150

@@ -320,6 +324,10 @@ inline bool operator==(const RangeTy &A, const RangeTy &B) {
320324
return A.Offset == B.Offset && A.Size == B.Size;
321325
}
322326

327+
inline bool operator<(const RangeTy &A, const RangeTy &B) {
328+
return A.Offset < B.Offset;
329+
}
330+
323331
inline bool operator!=(const RangeTy &A, const RangeTy &B) { return !(A == B); }
324332

325333
/// Return the initial value of \p Obj with type \p Ty if that is a constant.
@@ -5785,6 +5793,136 @@ struct AAPointerInfo : public AbstractAttribute {
57855793
AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W,
57865794
};
57875795

5796+
/// A helper containing a list of offsets computed for a Use. Ideally this
5797+
/// list should be strictly ascending, but we ensure that only when we
5798+
/// actually translate the list of offsets to a RangeList.
5799+
struct OffsetInfo {
5800+
using VecTy = SmallVector<AA::RangeTy>;
5801+
// A map to store depth 1 predecessors per offset.
5802+
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
5803+
using const_iterator = VecTy::const_iterator;
5804+
OriginsTy Origins;
5805+
VecTy Ranges;
5806+
5807+
const_iterator begin() const { return Ranges.begin(); }
5808+
const_iterator end() const { return Ranges.end(); }
5809+
5810+
bool operator==(const OffsetInfo &RHS) const {
5811+
return Ranges == RHS.Ranges && Origins == RHS.Origins;
5812+
}
5813+
5814+
bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
5815+
5816+
void insert(AA::RangeTy Range, Value &V) {
5817+
5818+
auto *It = std::find(Ranges.begin(), Ranges.end(), Range);
5819+
5820+
// Offset exists in Offsets map
5821+
if (It != Ranges.end()) {
5822+
size_t Index = It - Ranges.begin();
5823+
if (Index < Origins.size())
5824+
Origins[Index].insert(&V);
5825+
} else {
5826+
Ranges.push_back(Range);
5827+
Origins.emplace_back();
5828+
Origins.back().insert(&V);
5829+
}
5830+
}
5831+
5832+
void setSizeAll(uint64_t Size) {
5833+
for (auto &Range : Ranges)
5834+
Range.Size = Size;
5835+
}
5836+
5837+
void getOnlyOffsets(SmallVector<int64_t> &Offsets) {
5838+
5839+
for (auto &Range : Ranges)
5840+
Offsets.push_back(Range.Offset);
5841+
5842+
// ensure unique
5843+
sort(Offsets.begin(), Offsets.end());
5844+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5845+
}
5846+
5847+
bool isUnassigned() const { return Ranges.empty(); }
5848+
5849+
bool isUnknown() const {
5850+
if (isUnassigned())
5851+
return false;
5852+
if (Ranges.size() == 1)
5853+
return Ranges.front().Offset == AA::RangeTy::Unknown;
5854+
return false;
5855+
}
5856+
5857+
void setUnknown(Value &V) {
5858+
Ranges.clear();
5859+
Origins.clear();
5860+
insert(AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
5861+
}
5862+
5863+
void addToAll(int64_t Inc, Value &V) {
5864+
for (auto &Range : Ranges)
5865+
Range.Offset += Inc;
5866+
5867+
if (!Origins.empty()) {
5868+
for (auto &Origin : Origins)
5869+
Origin.insert(&V);
5870+
} else {
5871+
for (size_t Index = 0; Index < Ranges.size(); Index++) {
5872+
Origins.emplace_back();
5873+
Origins[Index].insert(&V);
5874+
}
5875+
}
5876+
}
5877+
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+
void mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
5899+
5900+
Ranges.append(R.Ranges);
5901+
// ensure elements are unique.
5902+
sort(Ranges.begin(), Ranges.end());
5903+
Ranges.erase(std::unique(Ranges.begin(), Ranges.end()), Ranges.end());
5904+
5905+
auto &ROffsets = R.Ranges;
5906+
for (auto Offset : ROffsets) {
5907+
5908+
auto *It = std::find(Ranges.begin(), Ranges.end(), Offset);
5909+
if (It == Ranges.end())
5910+
continue;
5911+
5912+
size_t Index = It - Ranges.begin();
5913+
5914+
if (Index >= Origins.size()) {
5915+
Origins.emplace_back();
5916+
Origins.back().insert(&CurPtr);
5917+
} else {
5918+
Origins[Index].insert(&CurPtr);
5919+
}
5920+
}
5921+
}
5922+
};
5923+
5924+
using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5925+
57885926
/// A container for a list of ranges.
57895927
struct RangeList {
57905928
// The set of ranges rarely contains more than one element, and is unlikely
@@ -5938,16 +6076,21 @@ struct AAPointerInfo : public AbstractAttribute {
59386076

59396077
/// An access description.
59406078
struct Access {
6079+
using AccessPathTy = SmallVector<Value *, 4>;
6080+
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;
6081+
59416082
Access(Instruction *I, int64_t Offset, int64_t Size,
5942-
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6083+
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6084+
AccessPathSetTy *AccessPaths)
59436085
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
5944-
Kind(Kind), Ty(Ty) {
6086+
Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
59456087
verify();
59466088
}
59476089
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
5948-
std::optional<Value *> Content, AccessKind K, Type *Ty)
6090+
std::optional<Value *> Content, AccessKind K, Type *Ty,
6091+
AccessPathSetTy *AccessPaths)
59496092
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
5950-
Kind(K), Ty(Ty) {
6093+
Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
59516094
if (Ranges.size() > 1) {
59526095
Kind = AccessKind(Kind | AK_MAY);
59536096
Kind = AccessKind(Kind & ~AK_MUST);
@@ -5956,17 +6099,18 @@ struct AAPointerInfo : public AbstractAttribute {
59566099
}
59576100
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
59586101
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
5959-
Type *Ty)
6102+
Type *Ty, AccessPathSetTy *AccessPaths)
59606103
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
5961-
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
6104+
Ranges(Offset, Size), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
59626105
verify();
59636106
}
59646107
Access(const Access &Other) = default;
59656108

59666109
Access &operator=(const Access &Other) = default;
59676110
bool operator==(const Access &R) const {
59686111
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
5969-
Content == R.Content && Kind == R.Kind;
6112+
Content == R.Content && Kind == R.Kind &&
6113+
checkAccessPathsAreSame(R.AccessPaths);
59706114
}
59716115
bool operator!=(const Access &R) const { return !(*this == R); }
59726116

@@ -6078,11 +6222,56 @@ struct AAPointerInfo : public AbstractAttribute {
60786222
}
60796223
}
60806224

6225+
void mergeAccessPaths(const AccessPathSetTy *AccessPathsNew) const {
6226+
6227+
for (auto *Path : *AccessPathsNew)
6228+
if (!existsChain(Path))
6229+
AccessPaths->insert(Path);
6230+
}
6231+
6232+
bool checkAccessPathsAreSame(const AccessPathSetTy *AccessPathsR) const {
6233+
6234+
bool IsSame = true;
6235+
6236+
if (AccessPaths->size() != AccessPathsR->size())
6237+
return false;
6238+
6239+
for (auto *Path : *AccessPathsR) {
6240+
if (!existsChain(Path))
6241+
IsSame = false;
6242+
}
6243+
return IsSame;
6244+
}
6245+
6246+
bool existsChain(const AccessPathTy *NewPath) const {
6247+
6248+
for (auto *OldPath : *AccessPaths)
6249+
if (*OldPath == *NewPath)
6250+
return true;
6251+
6252+
return false;
6253+
}
6254+
6255+
void dumpAccessPaths(raw_ostream &O) {
6256+
6257+
O << "Print all access paths found:"
6258+
<< "\n";
6259+
for (auto *It : *AccessPaths) {
6260+
O << "Backtrack a unique access path:\n";
6261+
for (Value *Ins : *It) {
6262+
O << *Ins << "\n";
6263+
}
6264+
}
6265+
}
6266+
6267+
const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
6268+
60816269
const RangeList &getRanges() const { return Ranges; }
60826270

60836271
using const_iterator = RangeList::const_iterator;
60846272
const_iterator begin() const { return Ranges.begin(); }
60856273
const_iterator end() const { return Ranges.end(); }
6274+
size_t size() const { return Ranges.size(); }
60866275

60876276
private:
60886277
/// The instruction responsible for the access with respect to the local
@@ -6105,6 +6294,10 @@ struct AAPointerInfo : public AbstractAttribute {
61056294
/// The type of the content, thus the type read/written, can be null if not
61066295
/// available.
61076296
Type *Ty;
6297+
6298+
/// The full chain of instructions that participate in the Access.
6299+
/// There may be more than one access chain.
6300+
AccessPathSetTy *AccessPaths;
61086301
};
61096302

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

0 commit comments

Comments
 (0)