Index: llvm/include/llvm/Analysis/ValueTracking.h =================================================================== --- llvm/include/llvm/Analysis/ValueTracking.h +++ llvm/include/llvm/Analysis/ValueTracking.h @@ -369,9 +369,14 @@ /// the specified value, returning the original object being addressed. Note /// that the returned value has pointer type if the specified value does. If /// the MaxLookup value is non-zero, it limits the number of instructions to - /// be stripped off. - const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6); - inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6) { + /// be stripped off. When FollowProvenance is set, the provenance side of + /// llvm.experimental.ptr.provenance is taken. For provenance, + /// `UnknownProvenance` indicates that any valid object can be the underlying + /// object. + const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6, + bool FollowProvenance = false); + inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6, + bool FollowProvenance = false) { // Force const to avoid infinite recursion. const Value *VConst = V; return const_cast(getUnderlyingObject(VConst, MaxLookup)); @@ -405,9 +410,12 @@ /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects /// should not assume that Curr and Prev share the same underlying object thus /// it shouldn't look through the phi above. + /// When FollowProvenance is set, the provenance side of + /// llvm.experimental.ptr.provenance is taken. void getUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, - LoopInfo *LI = nullptr, unsigned MaxLookup = 6); + LoopInfo *LI = nullptr, unsigned MaxLookup = 6, + bool FollowProvenance = false); /// This is a wrapper around getUnderlyingObjects and adds support for basic /// ptrtoint+arithmetic+inttoptr sequences. Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4374,7 +4374,8 @@ return true; } -const Value *llvm::getUnderlyingObject(const Value *V, unsigned MaxLookup) { +const Value *llvm::getUnderlyingObject(const Value *V, unsigned MaxLookup, + bool FollowProvenance) { if (!V->getType()->isPointerTy()) return V; for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { @@ -4397,6 +4398,11 @@ continue; } } else if (auto *Call = dyn_cast(V)) { + if (Call->getIntrinsicID() == Intrinsic::experimental_ptr_provenance) { + V = Call->getArgOperand(FollowProvenance ? 1 : 0); + continue; + } + // CaptureTracking can know about special capturing properties of some // intrinsics like launder.invariant.group, that can't be expressed with // the attributes, but have properties like returning aliasing pointer. @@ -4421,13 +4427,14 @@ void llvm::getUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, - LoopInfo *LI, unsigned MaxLookup) { + LoopInfo *LI, unsigned MaxLookup, + bool FollowProvenance) { SmallPtrSet Visited; SmallVector Worklist; Worklist.push_back(V); do { const Value *P = Worklist.pop_back_val(); - P = getUnderlyingObject(P, MaxLookup); + P = getUnderlyingObject(P, MaxLookup, FollowProvenance); if (!Visited.insert(P).second) continue;