Skip to content

Commit a8a794a

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

File tree

3 files changed

+579
-97
lines changed

3 files changed

+579
-97
lines changed

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

+230-6
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"
@@ -137,6 +139,8 @@
137139
#include "llvm/TargetParser/Triple.h"
138140
#include "llvm/Transforms/Utils/CallGraphUpdater.h"
139141

142+
#include <cstddef>
143+
#include <cstdint>
140144
#include <limits>
141145
#include <map>
142146
#include <optional>
@@ -5784,6 +5788,120 @@ struct AAPointerInfo : public AbstractAttribute {
57845788
AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W,
57855789
};
57865790

5791+
/// A helper containing a list of offsets computed for a Use. Ideally this
5792+
/// list should be strictly ascending, but we ensure that only when we
5793+
/// actually translate the list of offsets to a RangeList.
5794+
struct OffsetInfo {
5795+
using VecTy = SmallVector<int64_t>;
5796+
using OriginsTy = SmallVector<SmallPtrSet<Value *, 4>>;
5797+
using const_iterator = VecTy::const_iterator;
5798+
OriginsTy Origins;
5799+
VecTy Offsets;
5800+
5801+
const_iterator begin() const { return Offsets.begin(); }
5802+
const_iterator end() const { return Offsets.end(); }
5803+
5804+
bool operator==(const OffsetInfo &RHS) const {
5805+
return Offsets == RHS.Offsets && Origins == RHS.Origins;
5806+
}
5807+
5808+
bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }
5809+
5810+
void insert(int64_t Offset, Value &V) {
5811+
Offsets.push_back(Offset);
5812+
5813+
auto *It = std::find(Offsets.begin(), Offsets.end(), Offsets.size());
5814+
// Offset exists in Offsets map
5815+
if (It != Offsets.end()) {
5816+
size_t Index = It - Offsets.begin();
5817+
if (Index < Origins.size())
5818+
Origins[Index].insert(&V);
5819+
}
5820+
5821+
Origins.emplace_back();
5822+
Origins.back().insert(&V);
5823+
}
5824+
5825+
bool isUnassigned() const { return Offsets.empty(); }
5826+
5827+
bool isUnknown() const {
5828+
if (isUnassigned())
5829+
return false;
5830+
if (Offsets.size() == 1)
5831+
return Offsets.front() == AA::RangeTy::Unknown;
5832+
return false;
5833+
}
5834+
5835+
void setUnknown(Value &V) {
5836+
Offsets.clear();
5837+
Origins.clear();
5838+
insert(AA::RangeTy::Unknown, V);
5839+
}
5840+
5841+
void addToAll(int64_t Inc, Value &V) {
5842+
for (auto &Offset : Offsets)
5843+
Offset += Inc;
5844+
5845+
if (!Origins.empty()) {
5846+
for (auto &Origin : Origins)
5847+
Origin.insert(&V);
5848+
} else {
5849+
for (size_t Index = 0; Index < Offsets.size(); Index++) {
5850+
Origins.emplace_back();
5851+
Origins[Index].insert(&V);
5852+
}
5853+
}
5854+
}
5855+
5856+
void addToAll(int64_t Inc) {
5857+
for (auto &Offset : Offsets)
5858+
Offset += Inc;
5859+
}
5860+
5861+
/// Copy offsets from \p R into the current list.
5862+
///
5863+
/// Ideally all lists should be strictly ascending, but we defer that to the
5864+
/// actual use of the list. So we just blindly append here.
5865+
void merge(const OffsetInfo &R) {
5866+
Offsets.append(R.Offsets);
5867+
// ensure elements are unique.
5868+
sort(Offsets.begin(), Offsets.end());
5869+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5870+
5871+
OriginsTy ToBeMergeOrigins = R.Origins;
5872+
for (auto &Origin : ToBeMergeOrigins) {
5873+
Origins.emplace_back(Origin);
5874+
}
5875+
}
5876+
5877+
void mergeWithOffset(const OffsetInfo &R, Value &CurPtr) {
5878+
5879+
Offsets.append(R.Offsets);
5880+
// ensure elements are unique.
5881+
sort(Offsets.begin(), Offsets.end());
5882+
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
5883+
5884+
auto &ROffsets = R.Offsets;
5885+
for (auto Offset : ROffsets) {
5886+
5887+
auto *It = std::find(Offsets.begin(), Offsets.end(), Offset);
5888+
if (It == Offsets.end())
5889+
continue;
5890+
5891+
size_t Index = It - Offsets.begin();
5892+
5893+
if (Index >= Origins.size()) {
5894+
Origins.emplace_back();
5895+
Origins.back().insert(&CurPtr);
5896+
} else {
5897+
Origins[Index].insert(&CurPtr);
5898+
}
5899+
}
5900+
}
5901+
};
5902+
5903+
using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5904+
57875905
/// A container for a list of ranges.
57885906
struct RangeList {
57895907
// The set of ranges rarely contains more than one element, and is unlikely
@@ -5938,15 +6056,17 @@ struct AAPointerInfo : public AbstractAttribute {
59386056
/// An access description.
59396057
struct Access {
59406058
Access(Instruction *I, int64_t Offset, int64_t Size,
5941-
std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6059+
std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6060+
OffsetInfoMapTy &OffsetInfoMap)
59426061
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size),
5943-
Kind(Kind), Ty(Ty) {
6062+
Kind(Kind), Ty(Ty), AccessPaths(findAllAccessPaths(OffsetInfoMap)) {
59446063
verify();
59456064
}
59466065
Access(Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
5947-
std::optional<Value *> Content, AccessKind K, Type *Ty)
6066+
std::optional<Value *> Content, AccessKind K, Type *Ty,
6067+
OffsetInfoMapTy &OffsetInfoMap)
59486068
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
5949-
Kind(K), Ty(Ty) {
6069+
Kind(K), Ty(Ty), AccessPaths(findAllAccessPaths(OffsetInfoMap)) {
59506070
if (Ranges.size() > 1) {
59516071
Kind = AccessKind(Kind | AK_MAY);
59526072
Kind = AccessKind(Kind & ~AK_MUST);
@@ -5955,9 +6075,10 @@ struct AAPointerInfo : public AbstractAttribute {
59556075
}
59566076
Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
59576077
int64_t Size, std::optional<Value *> Content, AccessKind Kind,
5958-
Type *Ty)
6078+
Type *Ty, OffsetInfoMapTy &OffsetInfoMap)
59596079
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
5960-
Ranges(Offset, Size), Kind(Kind), Ty(Ty) {
6080+
Ranges(Offset, Size), Kind(Kind), Ty(Ty),
6081+
AccessPaths(findAllAccessPaths(OffsetInfoMap)) {
59616082
verify();
59626083
}
59636084
Access(const Access &Other) = default;
@@ -6077,11 +6198,110 @@ struct AAPointerInfo : public AbstractAttribute {
60776198
}
60786199
}
60796200

6201+
using AccessPathTy = SmallVector<Value *, 4>;
6202+
using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4>;
6203+
6204+
void mergeAccessPaths(const AccessPathSetTy *AccessPathsNew) {
6205+
6206+
for (auto *Path : *AccessPathsNew) {
6207+
if (!existsChain(Path))
6208+
AccessPaths->insert(Path);
6209+
}
6210+
}
6211+
6212+
bool existsChain(AccessPathTy *NewPath) {
6213+
6214+
for (auto *OldPath : *AccessPaths) {
6215+
if (*OldPath == *NewPath)
6216+
return true;
6217+
}
6218+
return false;
6219+
}
6220+
6221+
AccessPathSetTy *findAllAccessPaths(OffsetInfoMapTy &OffsetInfoMap) {
6222+
6223+
AccessPathSetTy *AccessPathsSet = new AccessPathSetTy();
6224+
SmallPtrSet<Value *, 16> Visited;
6225+
AccessPathTy *Start = new AccessPathTy();
6226+
AccessPathsSet->insert(Start);
6227+
Start->push_back(LocalI);
6228+
for (auto *It = LocalI->op_begin(); It != LocalI->op_end(); It++)
6229+
if (Instruction *I = dyn_cast<Instruction>(It))
6230+
findAccessPathsHelper(OffsetInfoMap, Visited, I, Start,
6231+
AccessPathsSet);
6232+
6233+
return AccessPathsSet;
6234+
}
6235+
6236+
void findAccessPathsHelper(OffsetInfoMapTy &OffsetInfoMap,
6237+
SmallPtrSet<Value *, 16> &Visited,
6238+
Value *Instruction, AccessPathTy *CurrentChain,
6239+
AccessPathSetTy *AccessPathsSet) {
6240+
// Add all the successors
6241+
if (!OffsetInfoMap.contains(Instruction))
6242+
return;
6243+
6244+
Visited.insert(Instruction);
6245+
CurrentChain->push_back(Instruction);
6246+
6247+
// Recurse on the successors of the Current Instruction.
6248+
6249+
auto OI = OffsetInfoMap.lookup(Instruction);
6250+
auto &Origins = OI.Origins;
6251+
6252+
SmallPtrSet<Value *, 16> Successors;
6253+
for (auto &Origin : Origins) {
6254+
for (auto *Ins : Origin) {
6255+
// Recurse on each instruction.
6256+
if (Ins != Instruction && !Visited.contains(Ins))
6257+
Successors.insert(Ins);
6258+
}
6259+
}
6260+
6261+
if (Successors.size() == 0) {
6262+
Visited.erase(Instruction);
6263+
return;
6264+
}
6265+
6266+
if (Successors.size() > 1) {
6267+
6268+
for (auto *Ins : Successors) {
6269+
AccessPathTy *NextChain =
6270+
new AccessPathTy(CurrentChain->begin(), CurrentChain->end());
6271+
AccessPathsSet->insert(NextChain);
6272+
findAccessPathsHelper(OffsetInfoMap, Visited, Ins, NextChain,
6273+
AccessPathsSet);
6274+
}
6275+
AccessPathsSet->erase(CurrentChain);
6276+
} else {
6277+
Value *Successor = *Successors.begin();
6278+
findAccessPathsHelper(OffsetInfoMap, Visited, Successor, CurrentChain,
6279+
AccessPathsSet);
6280+
}
6281+
6282+
Visited.erase(Instruction);
6283+
}
6284+
6285+
void dumpAccessPaths(raw_ostream &O) {
6286+
6287+
O << "Dump all access paths:"
6288+
<< "\n";
6289+
for (auto *It : *AccessPaths) {
6290+
O << "Printing a unique access path:\n";
6291+
for (Value *Ins : *It) {
6292+
O << *Ins << "\n";
6293+
}
6294+
}
6295+
}
6296+
6297+
const AccessPathSetTy *getAccessChain() const { return AccessPaths; }
6298+
60806299
const RangeList &getRanges() const { return Ranges; }
60816300

60826301
using const_iterator = RangeList::const_iterator;
60836302
const_iterator begin() const { return Ranges.begin(); }
60846303
const_iterator end() const { return Ranges.end(); }
6304+
size_t size() const { return Ranges.size(); }
60856305

60866306
private:
60876307
/// The instruction responsible for the access with respect to the local
@@ -6104,6 +6324,10 @@ struct AAPointerInfo : public AbstractAttribute {
61046324
/// The type of the content, thus the type read/written, can be null if not
61056325
/// available.
61066326
Type *Ty;
6327+
6328+
/// The full chain of instructions that participate in the Access.
6329+
/// There may be more than one access chain.
6330+
AccessPathSetTy *AccessPaths;
61076331
};
61086332

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

0 commit comments

Comments
 (0)