diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -87,6 +87,10 @@ return const_cast(isFreeCall((const Value*)I, TLI)); } +/// isFreeLikeFunction - returns true if the function is a builtin free() or a +/// function marked allockind("free"). +bool isFreeLikeCall(const Value *I, const TargetLibraryInfo *TLI); + //===----------------------------------------------------------------------===// // Properties of allocation functions // diff --git a/llvm/lib/Analysis/CFLGraph.h b/llvm/lib/Analysis/CFLGraph.h --- a/llvm/lib/Analysis/CFLGraph.h +++ b/llvm/lib/Analysis/CFLGraph.h @@ -434,7 +434,7 @@ // introduce any aliases. // TODO: address other common library functions such as realloc(), // strdup(), etc. - if (isMallocOrCallocLikeFn(&Call, &TLI) || isFreeCall(&Call, &TLI)) + if (isMallocOrCallocLikeFn(&Call, &TLI) || isFreeLikeCall(&Call, &TLI)) return; // TODO: Add support for noalias args/all the other fun function diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp --- a/llvm/lib/Analysis/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/GlobalsModRef.cpp @@ -361,7 +361,7 @@ if (Call->isDataOperand(&U)) { // Detect calls to free. if (Call->isArgOperand(&U) && - isFreeCall(I, &GetTLI(*Call->getFunction()))) { + isFreeLikeCall(I, &GetTLI(*Call->getFunction()))) { if (Writers) Writers->insert(Call->getParent()->getParent()); } else { @@ -581,7 +581,12 @@ // We handle calls specially because the graph-relevant aspects are // handled above. if (auto *Call = dyn_cast(&I)) { - if (Function *Callee = Call->getCalledFunction()) { + auto &TLI = GetTLI(*Node->getFunction()); + if (isAllocationFn(Call, &TLI) || llvm::isFreeLikeCall(Call, &TLI)) { + // FIXME: It is completely unclear why this is necessary and not + // handled by the above graph code. + FI.addModRefInfo(ModRefInfo::ModRef); + } else if (Function *Callee = Call->getCalledFunction()) { // The callgraph doesn't include intrinsic calls. if (Callee->isIntrinsic()) { if (isa(Call)) 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 @@ -1529,7 +1529,7 @@ if (auto *CB = dyn_cast(Usr)) { if (CB->isLifetimeStartOrEnd()) return true; - if (TLI && isFreeCall(CB, TLI)) + if (TLI && isFreeLikeCall(CB, TLI)) return true; if (CB->isArgOperand(&U)) { unsigned ArgNo = CB->getArgOperandNo(&U); @@ -6153,7 +6153,7 @@ CallBase *CB = dyn_cast(&I); if (!CB) return true; - if (isFreeCall(CB, TLI)) { + if (llvm::isFreeLikeCall(CB, TLI)) { DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB}; return true; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1140,7 +1140,7 @@ if (Value *V = simplifyCall(&CI, SQ.getWithInstruction(&CI))) return replaceInstUsesWith(CI, V); - if (isFreeCall(&CI, &TLI)) + if (isFreeLikeCall(&CI, &TLI)) return visitFree(CI); // If the caller function (i.e. us, the function that contains this CallInst) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2801,7 +2801,7 @@ continue; } - if (isFreeCall(I, &TLI) && getAllocationFamily(I, &TLI) == Family) { + if (isFreeLikeCall(I, &TLI) && getAllocationFamily(I, &TLI) == Family) { assert(Family); Users.emplace_back(I); continue; diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1103,7 +1103,7 @@ return {std::make_pair(MemoryLocation(Ptr, Len), false)}; if (auto *CB = dyn_cast(I)) { - if (isFreeCall(I, &TLI)) + if (isFreeLikeCall(I, &TLI)) return {std::make_pair(MemoryLocation::getAfter(CB->getArgOperand(0)), true)}; } @@ -1116,7 +1116,7 @@ bool isMemTerminatorInst(Instruction *I) const { IntrinsicInst *II = dyn_cast(I); return (II && II->getIntrinsicID() == Intrinsic::lifetime_end) || - isFreeCall(I, &TLI); + isFreeLikeCall(I, &TLI); } /// Returns true if \p MaybeTerm is a memory terminator for \p Loc from diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll --- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll +++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll @@ -3407,12 +3407,11 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @malloc(i64 noundef 4) #[[ATTR23:[0-9]+]] -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* -; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR24:[0-9]+]] -; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* +; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_malloc @@ -3427,12 +3426,11 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@round_trip_malloc ; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR11:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @malloc(i64 noundef 4) #[[ATTR25:[0-9]+]] -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* -; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR26:[0-9]+]] -; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* +; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@round_trip_malloc @@ -3458,12 +3456,11 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant ; IS__TUNIT_OPM-SAME: () #[[ATTR10]] { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @malloc(i64 noundef 4) #[[ATTR23]] -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* -; IS__TUNIT_OPM-NEXT: store i32 7, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR24]] -; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* +; IS__TUNIT_OPM-NEXT: store i32 7, i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant @@ -3475,12 +3472,11 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant ; IS__CGSCC_OPM-SAME: () #[[ATTR11]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @malloc(i64 noundef 4) #[[ATTR25]] -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* -; IS__CGSCC_OPM-NEXT: store i32 7, i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR26]] -; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* +; IS__CGSCC_OPM-NEXT: store i32 7, i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant @@ -3687,18 +3683,18 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_calloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR10]] { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR23]] -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false) +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__TUNIT_OPM: if.then: -; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 +; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP1]], align 4 ; IS__TUNIT_OPM-NEXT: br label [[IF_END]] ; IS__TUNIT_OPM: if.end: -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP2]]) #[[ATTR24]] -; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@conditional_calloc @@ -3720,18 +3716,18 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@conditional_calloc ; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR11]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR25]] -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false) +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__CGSCC_OPM: if.then: -; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 +; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[TMP1]], align 4 ; IS__CGSCC_OPM-NEXT: br label [[IF_END]] ; IS__CGSCC_OPM: if.end: -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__CGSCC_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP2]]) #[[ATTR26]] -; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@conditional_calloc @@ -3771,17 +3767,17 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_calloc_zero ; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR10]] { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR23]] -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false) +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__TUNIT_OPM: if.then: -; IS__TUNIT_OPM-NEXT: store i32 0, i32* [[TMP0]], align 4 +; IS__TUNIT_OPM-NEXT: store i32 0, i32* [[TMP1]], align 4 ; IS__TUNIT_OPM-NEXT: br label [[IF_END]] ; IS__TUNIT_OPM: if.end: -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP2]]) #[[ATTR24]] -; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@conditional_calloc_zero @@ -3799,17 +3795,17 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@conditional_calloc_zero ; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR11]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR25]] -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1 +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false) +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32* ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__CGSCC_OPM: if.then: -; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[TMP0]], align 4 +; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[TMP1]], align 4 ; IS__CGSCC_OPM-NEXT: br label [[IF_END]] ; IS__CGSCC_OPM: if.end: -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__CGSCC_OPM-NEXT: call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP2]]) #[[ATTR26]] -; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP2]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@conditional_calloc_zero @@ -3845,7 +3841,7 @@ ; IS__TUNIT_OPM-SAME: (i32 [[S:%.*]]) #[[ATTR15:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64 -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias noundef i8* @malloc(i64 noundef [[CONV]]) #[[ATTR23]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias noundef i8* @malloc(i64 noundef [[CONV]]) #[[ATTR23:[0-9]+]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: ret i32* [[TMP0]] ; @@ -3863,7 +3859,7 @@ ; IS__CGSCC_OPM-SAME: (i32 [[S:%.*]]) #[[ATTR16:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64 -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias noundef i8* @malloc(i64 noundef [[CONV]]) #[[ATTR25]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias noundef i8* @malloc(i64 noundef [[CONV]]) #[[ATTR25:[0-9]+]] ; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__CGSCC_OPM-NEXT: ret i32* [[TMP0]] ; @@ -3888,11 +3884,11 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_like ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR10]] { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i32* @malloc_like(i32 noundef 4) #[[ATTR25:[0-9]+]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i32* @malloc_like(i32 noundef 4) #[[ATTR24:[0-9]+]] ; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef [[TMP1]]) #[[ATTR24]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* nocapture noundef [[TMP1]]) #[[ATTR25:[0-9]+]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP0]] ; ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn @@ -3910,7 +3906,7 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_like ; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) #[[ATTR11]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i32* @malloc_like(i32 noundef 4) #[[ATTR26]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call noalias nonnull align 4 dereferenceable(4) i32* @malloc_like(i32 noundef 4) #[[ATTR26:[0-9]+]] ; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* @@ -4624,8 +4620,8 @@ ; IS__TUNIT_OPM: attributes #[[ATTR21]] = { nofree nosync nounwind willreturn writeonly } ; IS__TUNIT_OPM: attributes #[[ATTR22]] = { nofree nosync nounwind writeonly } ; IS__TUNIT_OPM: attributes #[[ATTR23]] = { norecurse willreturn } -; IS__TUNIT_OPM: attributes #[[ATTR24]] = { norecurse nounwind willreturn } -; IS__TUNIT_OPM: attributes #[[ATTR25]] = { nofree norecurse nounwind willreturn } +; IS__TUNIT_OPM: attributes #[[ATTR24]] = { nofree norecurse nounwind willreturn } +; IS__TUNIT_OPM: attributes #[[ATTR25]] = { norecurse nounwind willreturn } ; IS__TUNIT_OPM: attributes #[[ATTR26]] = { norecurse } ; IS__TUNIT_OPM: attributes #[[ATTR27]] = { norecurse nounwind } ; IS__TUNIT_OPM: attributes #[[ATTR28]] = { nofree nosync nounwind }