Index: llvm/include/llvm/Analysis/ValueTracking.h =================================================================== --- llvm/include/llvm/Analysis/ValueTracking.h +++ llvm/include/llvm/Analysis/ValueTracking.h @@ -365,12 +365,16 @@ /// 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. + /// be stripped off. If a NoAlias vector is provided, it is filled with any + /// llvm.noalias intrinsics looked through to find the underlying object. Value *GetUnderlyingObject(Value *V, const DataLayout &DL, - unsigned MaxLookup = 6); - inline const Value *GetUnderlyingObject(const Value *V, const DataLayout &DL, - unsigned MaxLookup = 6) { - return GetUnderlyingObject(const_cast(V), DL, MaxLookup); + unsigned MaxLookup = 6, + SmallVectorImpl *NoAlias = nullptr); + inline const Value * + GetUnderlyingObject(const Value *V, const DataLayout &DL, + unsigned MaxLookup = 6, + SmallVectorImpl *NoAlias = nullptr) { + return GetUnderlyingObject(const_cast(V), DL, MaxLookup, NoAlias); } /// This method is similar to GetUnderlyingObject except that it can @@ -400,11 +404,14 @@ /// /// 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. + /// it shouldn't look through the phi above. If a NoAlias vector is provided, + /// it is filled with any llvm.noalias intrinsics looked through to find the + /// underlying objects. void GetUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, const DataLayout &DL, LoopInfo *LI = nullptr, - unsigned MaxLookup = 6); + unsigned MaxLookup = 6, + SmallVectorImpl *NoAlias = nullptr); /// 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 @@ -608,7 +608,11 @@ case Intrinsic::invariant_end: case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: + case Intrinsic::noalias_decl: case Intrinsic::noalias: + case Intrinsic::provenance_noalias: + case Intrinsic::noalias_arg_guard: + case Intrinsic::noalias_copy_guard: case Intrinsic::objectsize: case Intrinsic::ptr_annotation: case Intrinsic::var_annotation: @@ -4097,6 +4101,8 @@ const CallBase *Call, bool MustPreserveNullness) { switch (Call->getIntrinsicID()) { case Intrinsic::launder_invariant_group: + case Intrinsic::noalias_arg_guard: + case Intrinsic::noalias_copy_guard: case Intrinsic::strip_invariant_group: case Intrinsic::aarch64_irg: case Intrinsic::aarch64_tagp: @@ -4136,7 +4142,8 @@ } Value *llvm::GetUnderlyingObject(Value *V, const DataLayout &DL, - unsigned MaxLookup) { + unsigned MaxLookup, + SmallVectorImpl *NoAlias) { if (!V->getType()->isPointerTy()) return V; for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { @@ -4159,6 +4166,29 @@ continue; } } else if (auto *Call = dyn_cast(V)) { + if (NoAlias) { + // We are gathering information for ScopedAANoAlias - + // Look through noalias and provenance.noalias intrinsic + if (Call->getIntrinsicID() == Intrinsic::provenance_noalias || + Call->getIntrinsicID() == Intrinsic::noalias) { + NoAlias->push_back(Call); + V = Call->getArgOperand(0); + continue; + } + // Look trough noalias.arg.guard, and follow the ptr_provenance + if (Call->getIntrinsicID() == Intrinsic::noalias_arg_guard) { + V = Call->getArgOperand(1); + continue; + } + } else { + // We are not gathering information for SCopedAANoAlias - + // Look through noalias.arg.guard and follow the pointer path + if (Call->getIntrinsicID() == Intrinsic::noalias_arg_guard) { + V = Call->getArgOperand(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. @@ -4184,13 +4214,14 @@ void llvm::GetUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, const DataLayout &DL, LoopInfo *LI, - unsigned MaxLookup) { + unsigned MaxLookup, + SmallVectorImpl *NoAlias) { SmallPtrSet Visited; SmallVector Worklist; Worklist.push_back(V); do { const Value *P = Worklist.pop_back_val(); - P = GetUnderlyingObject(P, DL, MaxLookup); + P = GetUnderlyingObject(P, DL, MaxLookup, NoAlias); if (!Visited.insert(P).second) continue;