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+
332338inline 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