diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -138,8 +138,6 @@ #undef PIPE_OPERATOR } // namespace llvm -namespace { - /// Get pointer operand of memory accessing instruction. If \p I is /// not a memory accessing instruction, return nullptr. If \p AllowVolatile, /// is set to false and the instruction is volatile, return nullptr. @@ -242,9 +240,10 @@ /// once. Note that the value used for the callback may still be the value /// associated with \p IRP (due to PHIs). To limit how much effort is invested, /// we will never visit more values than specified by \p MaxValues. -template +template static bool genericValueTraversal( - Attributor &A, IRPosition IRP, const AAType &QueryingAA, StateTy &State, + Attributor &A, IRPosition IRP, const AbstractAttribute &QueryingAA, + StateTy &State, function_ref VisitValueCB, const Instruction *CtxI, bool UseValueSimplify = true, int MaxValues = 16, @@ -350,6 +349,30 @@ return true; } +static bool getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, + SmallVectorImpl &Objects, + const AbstractAttribute &QueryingAA, + const Instruction *CtxI) { + auto StripCB = [&](Value *V) { + if (auto *UO = getUnderlyingObject(V)) + return UO; + return V; + }; + SmallPtrSet SeenObjects; + auto VisitValueCB = [&SeenObjects](Value &Val, const Instruction *, + SmallVectorImpl &Objects, + bool) -> bool { + if (SeenObjects.insert(&Val).second) + Objects.push_back(&Val); + return true; + }; + if (!genericValueTraversal>( + A, IRPosition::value(Ptr), QueryingAA, Objects, VisitValueCB, CtxI, + true, 32, StripCB)) + return false; + return true; +} + const Value *stripAndAccumulateMinimalOffsets( Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val, const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, @@ -1069,9 +1092,9 @@ auto VisitReturnedValue = [&](Value &RV, RVState &RVS, const Instruction *CtxI) { IRPosition RetValPos = IRPosition::value(RV, getCallBaseContext()); - return genericValueTraversal( - A, RetValPos, *this, RVS, VisitValueCB, CtxI, - /* UseValueSimplify */ false); + return genericValueTraversal(A, RetValPos, *this, RVS, + VisitValueCB, CtxI, + /* UseValueSimplify */ false); }; // Callback for all "return intructions" live in the associated function. @@ -1746,8 +1769,8 @@ }; StateType T; - if (!genericValueTraversal( - A, getIRPosition(), *this, T, VisitValueCB, getCtxI())) + if (!genericValueTraversal(A, getIRPosition(), *this, T, + VisitValueCB, getCtxI())) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -3630,8 +3653,8 @@ }; DerefState T; - if (!genericValueTraversal( - A, getIRPosition(), *this, T, VisitValueCB, getCtxI())) + if (!genericValueTraversal(A, getIRPosition(), *this, T, + VisitValueCB, getCtxI())) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -3896,8 +3919,8 @@ }; StateType T; - if (!genericValueTraversal(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + if (!genericValueTraversal(A, getIRPosition(), *this, T, + VisitValueCB, getCtxI())) return indicatePessimisticFixpoint(); // TODO: If we know we visited all incoming values, thus no are assumed @@ -4899,9 +4922,9 @@ }; bool Dummy = false; - if (!genericValueTraversal( - A, getIRPosition(), *this, Dummy, VisitValueCB, getCtxI(), - /* UseValueSimplify */ false)) + if (!genericValueTraversal(A, getIRPosition(), *this, Dummy, + VisitValueCB, getCtxI(), + /* UseValueSimplify */ false)) if (!askSimplifiedValueForOtherAAs(A)) return indicatePessimisticFixpoint(); @@ -6396,8 +6419,6 @@ removeAssumedBits(NO_WRITES); } -} // namespace - /// -------------------- Memory Locations Attributes --------------------------- /// Includes read-none, argmemonly, inaccessiblememonly, /// inaccessiblememorargmemonly @@ -6674,47 +6695,45 @@ << Ptr << " [" << getMemoryLocationsAsStr(State.getAssumed()) << "]\n"); - auto StripGEPCB = [](Value *V) -> Value * { - auto *GEP = dyn_cast(V); - while (GEP) { - V = GEP->getPointerOperand(); - GEP = dyn_cast(V); - } - return V; - }; + SmallVector Objects; + if (!getAssumedUnderlyingObjects(A, Ptr, Objects, *this, &I)) { + LLVM_DEBUG( + dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"); + updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed, + getAccessKindFromInst(&I)); + return; + } - auto VisitValueCB = [&](Value &V, const Instruction *, - AAMemoryLocation::StateType &T, - bool Stripped) -> bool { + for (Value *Obj : Objects) { // TODO: recognize the TBAA used for constant accesses. MemoryLocationsKind MLK = NO_LOCATIONS; - assert(!isa(V) && "GEPs should have been stripped."); - if (isa(V)) - return true; - if (auto *Arg = dyn_cast(&V)) { + assert(!isa(Obj) && "GEPs should have been stripped."); + if (isa(Obj)) + continue; + if (auto *Arg = dyn_cast(Obj)) { if (Arg->hasByValAttr()) MLK = NO_LOCAL_MEM; else MLK = NO_ARGUMENT_MEM; - } else if (auto *GV = dyn_cast(&V)) { + } else if (auto *GV = dyn_cast(Obj)) { // Reading constant memory is not treated as a read "effect" by the // function attr pass so we won't neither. Constants defined by TBAA are // similar. (We know we do not write it because it is constant.) if (auto *GVar = dyn_cast(GV)) if (GVar->isConstant()) - return true; + continue; if (GV->hasLocalLinkage()) MLK = NO_GLOBAL_INTERNAL_MEM; else MLK = NO_GLOBAL_EXTERNAL_MEM; - } else if (isa(V) && + } else if (isa(Obj) && !NullPointerIsDefined(getAssociatedFunction(), - V.getType()->getPointerAddressSpace())) { - return true; - } else if (isa(V)) { + Ptr.getType()->getPointerAddressSpace())) { + continue; + } else if (isa(Obj)) { MLK = NO_LOCAL_MEM; - } else if (const auto *CB = dyn_cast(&V)) { + } else if (const auto *CB = dyn_cast(Obj)) { const auto &NoAliasAA = A.getAAFor( *this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL); if (NoAliasAA.isAssumedNoAlias()) @@ -6726,28 +6745,16 @@ } assert(MLK != NO_LOCATIONS && "No location specified!"); - updateStateAndAccessesMap(T, MLK, &I, &V, Changed, - getAccessKindFromInst(&I)); - LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value cannot be categorized: " - << V << " -> " << getMemoryLocationsAsStr(T.getAssumed()) + LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: " + << *Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n"); - return true; - }; - - if (!genericValueTraversal( - A, IRPosition::value(Ptr), *this, State, VisitValueCB, getCtxI(), - /* UseValueSimplify */ true, - /* MaxValues */ 32, StripGEPCB)) { - LLVM_DEBUG( - dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"); - updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed, + updateStateAndAccessesMap(getState(), MLK, &I, Obj, Changed, getAccessKindFromInst(&I)); - } else { - LLVM_DEBUG( - dbgs() - << "[AAMemoryLocation] Accessed locations with pointer locations: " - << getMemoryLocationsAsStr(State.getAssumed()) << "\n"); } + + LLVM_DEBUG( + dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: " + << getMemoryLocationsAsStr(State.getAssumed()) << "\n"); } void AAMemoryLocationImpl::categorizeArgumentPointerLocations( @@ -7394,9 +7401,9 @@ IntegerRangeState T(getBitWidth()); - if (!genericValueTraversal( - A, getIRPosition(), *this, T, VisitValueCB, getCtxI(), - /* UseValueSimplify */ false)) + if (!genericValueTraversal(A, getIRPosition(), *this, T, + VisitValueCB, getCtxI(), + /* UseValueSimplify */ false)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -8060,8 +8067,8 @@ }; StateType T; - if (!genericValueTraversal( - A, getIRPosition(), *this, T, VisitValueCB, getCtxI())) + if (!genericValueTraversal(A, getIRPosition(), *this, T, + VisitValueCB, getCtxI())) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -54,7 +54,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@c3 ; IS__CGSCC____-SAME: (i32* nofree writeonly [[Q:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) #[[ATTR17:[0-9]+]] +; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) #[[ATTR19:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @c2(i32* %q) @@ -221,14 +221,14 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@c7 ; IS__TUNIT____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] { -; IS__TUNIT____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR15:[0-9]+]] +; IS__TUNIT____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR17:[0-9]+]] ; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 ; IS__TUNIT____-NEXT: ret i1 [[VAL]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@c7 ; IS__CGSCC____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] { -; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR18:[0-9]+]] +; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR20:[0-9]+]] ; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 ; IS__CGSCC____-NEXT: ret i1 [[VAL]] ; @@ -336,7 +336,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc2 ; IS__CGSCC____-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) #[[ATTR5]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 noundef false) #[[ATTR14:[0-9]+]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 noundef false) #[[ATTR16:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; [#uses=0] @@ -361,13 +361,13 @@ ; IS__TUNIT____: Function Attrs: argmemonly nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@nc4 ; IS__TUNIT____-SAME: (i8* [[P:%.*]]) #[[ATTR6:[0-9]+]] { -; IS__TUNIT____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR16:[0-9]+]] +; IS__TUNIT____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR18:[0-9]+]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc4 ; IS__CGSCC____-SAME: (i8* [[P:%.*]]) #[[ATTR6:[0-9]+]] { -; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR19:[0-9]+]] +; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR21:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @external(i8* %p) @@ -611,19 +611,19 @@ } define void @nocaptureLaunder(i8* %p) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureLaunder -; IS__TUNIT____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR5]] { +; IS__TUNIT____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR17:[0-9]+]] +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR19:[0-9]+]] ; IS__TUNIT____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn +; IS__CGSCC____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureLaunder ; IS__CGSCC____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR20:[0-9]+]] +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR22:[0-9]+]] ; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -638,14 +638,14 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@captureLaunder ; IS__TUNIT____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR5]] { -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR17]] +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR19]] ; IS__TUNIT____-NEXT: store i8* [[B]], i8** @g2, align 8 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureLaunder -; IS__CGSCC____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR10]] { -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR20]] +; IS__CGSCC____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR11:[0-9]+]] { +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR22]] ; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g2, align 8 ; IS__CGSCC____-NEXT: ret void ; @@ -655,19 +655,19 @@ } define void @nocaptureStrip(i8* %p) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureStrip -; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR11:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18:[0-9]+]] +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20:[0-9]+]] ; IS__TUNIT____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureStrip -; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR11:[0-9]+]] { +; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR12:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18]] +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20]] ; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -682,14 +682,14 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@captureStrip ; IS__TUNIT____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR1]] { -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18]] +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20]] ; IS__TUNIT____-NEXT: store i8* [[B]], i8** @g3, align 8 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureStrip -; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR11]] { -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18]] +; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR13:[0-9]+]] { +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20]] ; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g3, align 8 ; IS__CGSCC____-NEXT: ret void ; @@ -789,14 +789,14 @@ define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) null_pointer_is_valid { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp -; IS__TUNIT____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR10:[0-9]+]] { +; IS__TUNIT____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR12:[0-9]+]] { ; IS__TUNIT____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null ; IS__TUNIT____-NEXT: ret i1 [[TMP2]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp -; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR12:[0-9]+]] { +; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR14:[0-9]+]] { ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null ; IS__CGSCC____-NEXT: ret i1 [[TMP2]] @@ -854,13 +854,13 @@ define void @ptr_uses(i8* %ptr, i8* %wptr) { ; IS__TUNIT____: Function Attrs: nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_uses -; IS__TUNIT____-SAME: (i8* [[PTR:%.*]], i8* nocapture noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR12:[0-9]+]] { +; IS__TUNIT____-SAME: (i8* [[PTR:%.*]], i8* nocapture noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR14:[0-9]+]] { ; IS__TUNIT____-NEXT: store i8 0, i8* [[WPTR]], align 1 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_uses -; IS__CGSCC____-SAME: (i8* [[PTR:%.*]], i8* nocapture noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR14]] { +; IS__CGSCC____-SAME: (i8* [[PTR:%.*]], i8* nocapture noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR16]] { ; IS__CGSCC____-NEXT: store i8 0, i8* [[WPTR]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -884,15 +884,17 @@ ; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind writeonly } ; IS__TUNIT____: attributes #[[ATTR8]] = { nofree noreturn nosync nounwind readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR9]] = { argmemonly nofree nounwind willreturn } -; IS__TUNIT____: attributes #[[ATTR10]] = { nofree nosync nounwind null_pointer_is_valid readnone willreturn } -; IS__TUNIT____: attributes #[[ATTR11:[0-9]+]] = { nounwind readonly willreturn } -; IS__TUNIT____: attributes #[[ATTR12]] = { nounwind willreturn } -; IS__TUNIT____: attributes #[[ATTR13:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } -; IS__TUNIT____: attributes #[[ATTR14:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } -; IS__TUNIT____: attributes #[[ATTR15]] = { nofree nounwind readnone willreturn } -; IS__TUNIT____: attributes #[[ATTR16]] = { nounwind } -; IS__TUNIT____: attributes #[[ATTR17]] = { willreturn } -; IS__TUNIT____: attributes #[[ATTR18]] = { readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR11]] = { argmemonly nofree nosync nounwind willreturn writeonly } +; IS__TUNIT____: attributes #[[ATTR12]] = { nofree nosync nounwind null_pointer_is_valid readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR13:[0-9]+]] = { nounwind readonly willreturn } +; IS__TUNIT____: attributes #[[ATTR14]] = { nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR15:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } +; IS__TUNIT____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } +; IS__TUNIT____: attributes #[[ATTR17]] = { nofree nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR18]] = { nounwind } +; IS__TUNIT____: attributes #[[ATTR19]] = { willreturn } +; IS__TUNIT____: attributes #[[ATTR20]] = { readnone willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind willreturn writeonly } @@ -904,15 +906,17 @@ ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind writeonly } ; IS__CGSCC____: attributes #[[ATTR8]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR9]] = { argmemonly nofree norecurse nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR10]] = { nofree nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR12]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR13:[0-9]+]] = { nounwind readonly willreturn } -; IS__CGSCC____: attributes #[[ATTR14]] = { nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR15:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } -; IS__CGSCC____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } -; IS__CGSCC____: attributes #[[ATTR17]] = { nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR18]] = { readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR19]] = { nounwind } -; IS__CGSCC____: attributes #[[ATTR20]] = { willreturn } +; IS__CGSCC____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR12]] = { argmemonly nofree nosync nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR14]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR15:[0-9]+]] = { nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR16]] = { nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR17:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } +; IS__CGSCC____: attributes #[[ATTR18:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } +; IS__CGSCC____: attributes #[[ATTR19]] = { nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR20]] = { readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR21]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR22]] = { willreturn } ;.