103
103
#include " llvm/ADT/STLExtras.h"
104
104
#include " llvm/ADT/SetOperations.h"
105
105
#include " llvm/ADT/SetVector.h"
106
+ #include " llvm/ADT/SmallPtrSet.h"
106
107
#include " llvm/ADT/SmallSet.h"
108
+ #include " llvm/ADT/SmallVector.h"
107
109
#include " llvm/ADT/iterator.h"
108
110
#include " llvm/Analysis/AssumeBundleQueries.h"
109
111
#include " llvm/Analysis/CFG.h"
137
139
#include " llvm/TargetParser/Triple.h"
138
140
#include " llvm/Transforms/Utils/CallGraphUpdater.h"
139
141
142
+ #include < cstddef>
143
+ #include < cstdint>
140
144
#include < limits>
141
145
#include < map>
142
146
#include < optional>
@@ -5784,6 +5788,120 @@ struct AAPointerInfo : public AbstractAttribute {
5784
5788
AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W,
5785
5789
};
5786
5790
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
+
5787
5905
// / A container for a list of ranges.
5788
5906
struct RangeList {
5789
5907
// The set of ranges rarely contains more than one element, and is unlikely
@@ -5938,15 +6056,17 @@ struct AAPointerInfo : public AbstractAttribute {
5938
6056
// / An access description.
5939
6057
struct Access {
5940
6058
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)
5942
6061
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size ),
5943
- Kind (Kind), Ty(Ty) {
6062
+ Kind (Kind), Ty(Ty), AccessPaths(findAllAccessPaths(OffsetInfoMap)) {
5944
6063
verify ();
5945
6064
}
5946
6065
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)
5948
6068
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
5949
- Kind(K), Ty(Ty) {
6069
+ Kind(K), Ty(Ty), AccessPaths(findAllAccessPaths(OffsetInfoMap)) {
5950
6070
if (Ranges.size () > 1 ) {
5951
6071
Kind = AccessKind (Kind | AK_MAY);
5952
6072
Kind = AccessKind (Kind & ~AK_MUST);
@@ -5955,9 +6075,10 @@ struct AAPointerInfo : public AbstractAttribute {
5955
6075
}
5956
6076
Access (Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
5957
6077
int64_t Size , std::optional<Value *> Content, AccessKind Kind,
5958
- Type *Ty)
6078
+ Type *Ty, OffsetInfoMapTy &OffsetInfoMap )
5959
6079
: 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)) {
5961
6082
verify ();
5962
6083
}
5963
6084
Access (const Access &Other) = default;
@@ -6077,11 +6198,110 @@ struct AAPointerInfo : public AbstractAttribute {
6077
6198
}
6078
6199
}
6079
6200
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
+
6080
6299
const RangeList &getRanges () const { return Ranges; }
6081
6300
6082
6301
using const_iterator = RangeList::const_iterator;
6083
6302
const_iterator begin () const { return Ranges.begin (); }
6084
6303
const_iterator end () const { return Ranges.end (); }
6304
+ size_t size () const { return Ranges.size (); }
6085
6305
6086
6306
private:
6087
6307
// / The instruction responsible for the access with respect to the local
@@ -6104,6 +6324,10 @@ struct AAPointerInfo : public AbstractAttribute {
6104
6324
// / The type of the content, thus the type read/written, can be null if not
6105
6325
// / available.
6106
6326
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;
6107
6331
};
6108
6332
6109
6333
// / Create an abstract attribute view for the position \p IRP.
0 commit comments