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"
@@ -320,6 +322,10 @@ inline bool operator==(const RangeTy &A, const RangeTy &B) {
320
322
return A.Offset == B.Offset && A.Size == B.Size ;
321
323
}
322
324
325
+ inline bool operator <(const RangeTy &A, const RangeTy &B) {
326
+ return A.Offset < B.Offset ;
327
+ }
328
+
323
329
inline bool operator !=(const RangeTy &A, const RangeTy &B) { return !(A == B); }
324
330
325
331
// / Return the initial value of \p Obj with type \p Ty if that is a constant.
@@ -5785,6 +5791,139 @@ struct AAPointerInfo : public AbstractAttribute {
5785
5791
AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W,
5786
5792
};
5787
5793
5794
+ // / A helper containing a list of offsets computed for a Use. Ideally this
5795
+ // / list should be strictly ascending, but we ensure that only when we
5796
+ // / actually translate the list of offsets to a RangeList.
5797
+ struct OffsetInfo {
5798
+ using VecTy = SmallVector<AA::RangeTy>;
5799
+ // A map to store depth 1 predecessors per offset.
5800
+ using OriginsTy = SmallVector<SmallPtrSet<Value *, 4 >>;
5801
+ using const_iterator = VecTy::const_iterator;
5802
+ OriginsTy Origins;
5803
+ VecTy Ranges;
5804
+
5805
+ const_iterator begin () const { return Ranges.begin (); }
5806
+ const_iterator end () const { return Ranges.end (); }
5807
+
5808
+ bool operator ==(const OffsetInfo &RHS) const {
5809
+ return Ranges == RHS.Ranges && Origins == RHS.Origins ;
5810
+ }
5811
+
5812
+ bool operator !=(const OffsetInfo &RHS) const { return !(*this == RHS); }
5813
+
5814
+ // Insert a new Range and Origin
5815
+ void insert (AA::RangeTy Range, Value &V) {
5816
+ auto *It = std::find (Ranges.begin (), Ranges.end (), Range);
5817
+ // Offset exists in Offsets map
5818
+ if (It != Ranges.end ()) {
5819
+ size_t Index = It - Ranges.begin ();
5820
+ if (Index < Origins.size ())
5821
+ Origins[Index].insert (&V);
5822
+ } else {
5823
+ Ranges.push_back (Range);
5824
+ Origins.emplace_back ();
5825
+ Origins.back ().insert (&V);
5826
+ }
5827
+ }
5828
+
5829
+ // Set the size of the offset for all ranges.
5830
+ void setSizeAll (uint64_t Size ) {
5831
+ for (auto &Range : Ranges)
5832
+ Range.Size = Size ;
5833
+ }
5834
+
5835
+ // Helper function to get just the offsets from Ranges.
5836
+ void getOnlyOffsets (SmallVector<int64_t > &Offsets) {
5837
+ for (auto &Range : Ranges)
5838
+ Offsets.push_back (Range.Offset );
5839
+ // ensure unique
5840
+ sort (Offsets.begin (), Offsets.end ());
5841
+ Offsets.erase (std::unique (Offsets.begin (), Offsets.end ()), Offsets.end ());
5842
+ }
5843
+
5844
+ bool isUnassigned () const { return Ranges.empty (); }
5845
+
5846
+ bool isUnknown () const {
5847
+ if (isUnassigned ())
5848
+ return false ;
5849
+ if (Ranges.size () == 1 )
5850
+ return Ranges.front ().Offset == AA::RangeTy::Unknown;
5851
+ return false ;
5852
+ }
5853
+
5854
+ void setUnknown (Value &V) {
5855
+ Ranges.clear ();
5856
+ Origins.clear ();
5857
+ insert (AA::RangeTy{AA::RangeTy::Unknown, AA::RangeTy::Unknown}, V);
5858
+ }
5859
+
5860
+ // Increment all ranges by Inc.
5861
+ // Add an origin V to all offsets.
5862
+ void addToAll (int64_t Inc, Value &V) {
5863
+ for (auto &Range : Ranges)
5864
+ Range.Offset += Inc;
5865
+
5866
+ if (!Origins.empty ()) {
5867
+ for (auto &Origin : Origins)
5868
+ Origin.insert (&V);
5869
+ } else {
5870
+ for (size_t Index = 0 ; Index < Ranges.size (); Index++) {
5871
+ Origins.emplace_back ();
5872
+ Origins[Index].insert (&V);
5873
+ }
5874
+ }
5875
+ }
5876
+
5877
+ // Increment all ranges by Inc.
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
+ // Merge two OffsetInfo structs.
5899
+ // takes an additional origin argument
5900
+ // and adds it to the corresponding offset in the
5901
+ // origins map.
5902
+ void mergeWithOffset (const OffsetInfo &R, Value &CurPtr) {
5903
+ Ranges.append (R.Ranges );
5904
+ // ensure elements are unique.
5905
+ sort (Ranges.begin (), Ranges.end ());
5906
+ Ranges.erase (std::unique (Ranges.begin (), Ranges.end ()), Ranges.end ());
5907
+ auto &ROffsets = R.Ranges ;
5908
+ for (auto Offset : ROffsets) {
5909
+ auto *It = std::find (Ranges.begin (), Ranges.end (), Offset);
5910
+ if (It == Ranges.end ())
5911
+ continue ;
5912
+ size_t Index = It - Ranges.begin ();
5913
+ if (Index >= Origins.size ()) {
5914
+ Origins.emplace_back ();
5915
+ Origins.back ().insert (&CurPtr);
5916
+ } else {
5917
+ Origins[Index].insert (&CurPtr);
5918
+ }
5919
+ }
5920
+ }
5921
+ };
5922
+
5923
+ using OffsetInfoMapTy = DenseMap<Value *, OffsetInfo>;
5924
+ using AccessPathTy = SmallVector<Value *, 4 >;
5925
+ using AccessPathSetTy = SmallPtrSet<AccessPathTy *, 4 >;
5926
+
5788
5927
// / A container for a list of ranges.
5789
5928
struct RangeList {
5790
5929
// The set of ranges rarely contains more than one element, and is unlikely
@@ -5939,15 +6078,17 @@ struct AAPointerInfo : public AbstractAttribute {
5939
6078
// / An access description.
5940
6079
struct Access {
5941
6080
Access (Instruction *I, int64_t Offset, int64_t Size ,
5942
- std::optional<Value *> Content, AccessKind Kind, Type *Ty)
6081
+ std::optional<Value *> Content, AccessKind Kind, Type *Ty,
6082
+ AccessPathSetTy *AccessPaths)
5943
6083
: LocalI(I), RemoteI(I), Content(Content), Ranges(Offset, Size ),
5944
- Kind (Kind), Ty(Ty) {
6084
+ Kind (Kind), Ty(Ty), AccessPaths(AccessPaths) {
5945
6085
verify ();
5946
6086
}
5947
6087
Access (Instruction *LocalI, Instruction *RemoteI, const RangeList &Ranges,
5948
- std::optional<Value *> Content, AccessKind K, Type *Ty)
6088
+ std::optional<Value *> Content, AccessKind K, Type *Ty,
6089
+ AccessPathSetTy *AccessPaths)
5949
6090
: LocalI(LocalI), RemoteI(RemoteI), Content(Content), Ranges(Ranges),
5950
- Kind(K), Ty(Ty) {
6091
+ Kind(K), Ty(Ty), AccessPaths(AccessPaths) {
5951
6092
if (Ranges.size () > 1 ) {
5952
6093
Kind = AccessKind (Kind | AK_MAY);
5953
6094
Kind = AccessKind (Kind & ~AK_MUST);
@@ -5956,17 +6097,18 @@ struct AAPointerInfo : public AbstractAttribute {
5956
6097
}
5957
6098
Access (Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
5958
6099
int64_t Size , std::optional<Value *> Content, AccessKind Kind,
5959
- Type *Ty)
6100
+ Type *Ty, AccessPathSetTy *AccessPaths )
5960
6101
: LocalI(LocalI), RemoteI(RemoteI), Content(Content),
5961
- Ranges(Offset, Size ), Kind(Kind), Ty(Ty) {
6102
+ Ranges(Offset, Size ), Kind(Kind), Ty(Ty), AccessPaths(AccessPaths) {
5962
6103
verify ();
5963
6104
}
5964
6105
Access (const Access &Other) = default;
5965
6106
5966
6107
Access &operator =(const Access &Other) = default ;
5967
6108
bool operator ==(const Access &R) const {
5968
6109
return LocalI == R.LocalI && RemoteI == R.RemoteI && Ranges == R.Ranges &&
5969
- Content == R.Content && Kind == R.Kind ;
6110
+ Content == R.Content && Kind == R.Kind &&
6111
+ checkAccessPathsAreSame (R.AccessPaths );
5970
6112
}
5971
6113
bool operator !=(const Access &R) const { return !(*this == R); }
5972
6114
@@ -6078,11 +6220,53 @@ struct AAPointerInfo : public AbstractAttribute {
6078
6220
}
6079
6221
}
6080
6222
6223
+ // Merge two access paths into one.
6224
+ void mergeAccessPaths (const AccessPathSetTy *AccessPathsNew) const {
6225
+ for (auto *Path : *AccessPathsNew)
6226
+ if (!existsChain (Path))
6227
+ AccessPaths->insert (Path);
6228
+ }
6229
+
6230
+ // Check if the given access paths are same.
6231
+ bool checkAccessPathsAreSame (const AccessPathSetTy *AccessPathsR) const {
6232
+ bool IsSame = true ;
6233
+ if (AccessPaths->size () != AccessPathsR->size ())
6234
+ return false ;
6235
+
6236
+ for (auto *Path : *AccessPathsR) {
6237
+ if (!existsChain (Path))
6238
+ IsSame = false ;
6239
+ }
6240
+ return IsSame;
6241
+ }
6242
+
6243
+ // Check if the chain exists in the AccessPathsSet.
6244
+ bool existsChain (const AccessPathTy *NewPath) const {
6245
+ for (auto *OldPath : *AccessPaths)
6246
+ if (*OldPath == *NewPath)
6247
+ return true ;
6248
+
6249
+ return false ;
6250
+ }
6251
+
6252
+ void dumpAccessPaths (raw_ostream &O) const {
6253
+ O << " Print all access paths found:"
6254
+ << " \n " ;
6255
+ for (auto *It : *AccessPaths) {
6256
+ O << " Backtrack a unique access path:\n " ;
6257
+ for (Value *Ins : *It) {
6258
+ O << *Ins << " \n " ;
6259
+ }
6260
+ }
6261
+ }
6262
+
6263
+ const AccessPathSetTy *getAccessChain () const { return AccessPaths; }
6081
6264
const RangeList &getRanges () const { return Ranges; }
6082
6265
6083
6266
using const_iterator = RangeList::const_iterator;
6084
6267
const_iterator begin () const { return Ranges.begin (); }
6085
6268
const_iterator end () const { return Ranges.end (); }
6269
+ size_t size () const { return Ranges.size (); }
6086
6270
6087
6271
private:
6088
6272
// / The instruction responsible for the access with respect to the local
@@ -6105,6 +6289,10 @@ struct AAPointerInfo : public AbstractAttribute {
6105
6289
// / The type of the content, thus the type read/written, can be null if not
6106
6290
// / available.
6107
6291
Type *Ty;
6292
+
6293
+ // / The full chain of instructions that participate in the Access.
6294
+ // / There may be more than one access chain.
6295
+ AccessPathSetTy *AccessPaths;
6108
6296
};
6109
6297
6110
6298
// / Create an abstract attribute view for the position \p IRP.
0 commit comments