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/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -602,6 +602,15 @@ return isLibFreeFunction(Callee, TLIFn) ? dyn_cast(I) : nullptr; } +/// isFreeLikeFunction - returns true if the function is a builtin free() or a +/// function marked allockind("free"). +bool llvm::isFreeLikeCall(const Value *I, const TargetLibraryInfo *TLI) { + if (checkFnAllocKind(I, AllocFnKind::Free)) { + return true; + } + return isFreeCall(I, TLI); +} + AllocFnKind llvm::getAllocKind(const CallBase *CB, const TargetLibraryInfo *TLI) { const Function *F = CB->getCalledFunction(); 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 @@ -2774,7 +2774,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/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll @@ -45,13 +45,13 @@ ; IS________OPM-NEXT: [[C2:%.*]] = bitcast i32* [[C1]] to i8* ; IS________OPM-NEXT: [[L:%.*]] = load i8, i8* [[C2]], align 16 ; IS________OPM-NEXT: call void @usei8(i8 [[L]]) -; IS________OPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef align 16 [[C2]]) #[[ATTR9:[0-9]+]] +; IS________OPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef align 16 [[C2]]) #[[ATTR10:[0-9]+]] ; IS________OPM-NEXT: br label [[J]] ; IS________OPM: dead: ; IS________OPM-NEXT: unreachable ; IS________OPM: j: ; IS________OPM-NEXT: [[PHI:%.*]] = phi i8* [ [[M_H2S]], [[F]] ], [ null, [[F2]] ] -; IS________OPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree noundef align 16 [[PHI]]) #[[ATTR9]] +; IS________OPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree noundef align 16 [[PHI]]) #[[ATTR10]] ; IS________OPM-NEXT: ret void ; ; IS________NPM-LABEL: define {{[^@]+}}@h2s_value_simplify_interaction @@ -146,16 +146,10 @@ ; TEST 3 - 1 malloc, 1 free define void @test3() { -; IS________OPM-LABEL: define {{[^@]+}}@test3() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test3() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test3() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -166,9 +160,8 @@ define void @test3a(i8* %p) { ; IS________OPM-LABEL: define {{[^@]+}}@test3a ; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) +; IS________OPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[DOTH2S]], i8* nocapture [[P]]) ; IS________OPM-NEXT: ret void ; ; IS________NPM-LABEL: define {{[^@]+}}@test3a @@ -188,9 +181,8 @@ define void @test3b(i8* %p) { ; IS________OPM-LABEL: define {{[^@]+}}@test3b ; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128) -; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) +; IS________OPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 128, align 1 +; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[DOTH2S]], i8* nocapture [[P]]) ; IS________OPM-NEXT: ret void ; ; IS________NPM-LABEL: define {{[^@]+}}@test3b @@ -207,16 +199,10 @@ ; leave alone non-constant alignments. define void @test3c(i64 %alignment) { -; IS________OPM-LABEL: define {{[^@]+}}@test3c -; IS________OPM-SAME: (i64 [[ALIGNMENT:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test3c -; IS________NPM-SAME: (i64 [[ALIGNMENT:%.*]]) { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 128, align 1 -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test3c +; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 128, align 1 +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128) tail call void @free(i8* %1) @@ -227,9 +213,8 @@ define void @test3d(i8* %p) { ; IS________OPM-LABEL: define {{[^@]+}}@test3d ; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128) -; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) +; IS________OPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 128, align 1 +; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[DOTH2S]], i8* nocapture [[P]]) ; IS________OPM-NEXT: ret void ; ; IS________NPM-LABEL: define {{[^@]+}}@test3d @@ -248,17 +233,11 @@ declare noalias i8* @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1) define void @test0() { -; IS________OPM-LABEL: define {{[^@]+}}@test0() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 2, i64 noundef 4) -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test0() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 8, align 1 -; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DOTH2S]], i8 0, i64 8, i1 false) -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test0() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 8, align 1 +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DOTH2S]], i8 0, i64 8, i1 false) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @calloc(i64 2, i64 4) tail call void @no_sync_func(i8* %1) @@ -284,17 +263,16 @@ define void @test5(i32, i8* %p) { ; IS________OPM-LABEL: define {{[^@]+}}@test5 ; IS________OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 -; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS________OPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; IS________OPM-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS________OPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] +; IS________OPM: 3: +; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]]) +; IS________OPM-NEXT: br label [[TMP5:%.*]] ; IS________OPM: 4: -; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) -; IS________OPM-NEXT: br label [[TMP6:%.*]] +; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[DOTH2S]], i8* nocapture [[P]]) +; IS________OPM-NEXT: br label [[TMP5]] ; IS________OPM: 5: -; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) -; IS________OPM-NEXT: br label [[TMP6]] -; IS________OPM: 6: ; IS________OPM-NEXT: ret void ; ; IS________NPM-LABEL: define {{[^@]+}}@test5 @@ -331,33 +309,18 @@ ; TEST 6 - all exit paths have a call to free define void @test6(i32) { -; IS________OPM-LABEL: define {{[^@]+}}@test6 -; IS________OPM-SAME: (i32 [[TMP0:%.*]]) { -; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 -; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] -; IS________OPM: 4: -; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) -; IS________OPM-NEXT: br label [[TMP6:%.*]] -; IS________OPM: 5: -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]]) -; IS________OPM-NEXT: br label [[TMP6]] -; IS________OPM: 6: -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test6 -; IS________NPM-SAME: (i32 [[TMP0:%.*]]) { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 -; IS________NPM-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] -; IS________NPM: 3: -; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]]) -; IS________NPM-NEXT: br label [[TMP5:%.*]] -; IS________NPM: 4: -; IS________NPM-NEXT: br label [[TMP5]] -; IS________NPM: 5: -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test6 +; CHECK-SAME: (i32 [[TMP0:%.*]]) { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] +; CHECK: 3: +; CHECK-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]]) +; CHECK-NEXT: br label [[TMP5:%.*]] +; CHECK: 4: +; CHECK-NEXT: br label [[TMP5]] +; CHECK: 5: +; CHECK-NEXT: ret void ; %2 = tail call noalias i8* @malloc(i64 4) %3 = icmp eq i32 %0, 0 @@ -379,15 +342,10 @@ ; TEST 7 - free is dead. define void @test7() { -; IS________OPM-LABEL: define {{[^@]+}}@test7() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]] -; IS________OPM-NEXT: unreachable -; -; IS________NPM-LABEL: define {{[^@]+}}@test7() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP1:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]] -; IS________NPM-NEXT: unreachable +; CHECK-LABEL: define {{[^@]+}}@test7() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]] +; CHECK-NEXT: unreachable ; %1 = tail call noalias i8* @malloc(i64 4) tail call i32 @no_return_call() @@ -419,23 +377,14 @@ ; TEST 9 - FIXME: malloc should be converted. define void @test9() { -; IS________OPM-LABEL: define {{[^@]+}}@test9() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) -; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________OPM-NEXT: tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR9]] -; IS________OPM-NEXT: tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test9() { -; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) -; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR10]] -; IS________NPM-NEXT: tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test9() { +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) +; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR10:[0-9]+]] +; CHECK-NEXT: tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -450,22 +399,13 @@ ; TEST 10 - 1 malloc, 1 free define i32 @test10() { -; IS________OPM-LABEL: define {{[^@]+}}@test10() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) -; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) -; IS________OPM-NEXT: ret i32 [[TMP3]] -; -; IS________NPM-LABEL: define {{[^@]+}}@test10() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) -; IS________NPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP1]], align 4 -; IS________NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP2]] +; CHECK-LABEL: define {{[^@]+}}@test10() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; CHECK-NEXT: ret i32 [[TMP2]] ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -477,24 +417,14 @@ } define i32 @test_lifetime() { -; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) -; IS________OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]]) -; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]]) -; IS________OPM-NEXT: ret i32 [[TMP3]] -; -; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) -; IS________NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTH2S]]) -; IS________NPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP1]], align 4 -; IS________NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP2]] +; CHECK-LABEL: define {{[^@]+}}@test_lifetime() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]]) +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTH2S]]) +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4 +; CHECK-NEXT: ret i32 [[TMP2]] ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -509,16 +439,10 @@ ; TEST 11 define void @test11() { -; IS________OPM-LABEL: define {{[^@]+}}@test11() { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: tail call void @free(i8* nocapture [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test11() { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @sync_will_return(i8* [[DOTH2S]]) #[[ATTR10]] -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test11() { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @sync_will_return(i8* [[DOTH2S]]) #[[ATTR10]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @sync_will_return(i8* %1) @@ -528,66 +452,35 @@ ; TEST 12 define i32 @irreducible_cfg(i32 %0) { -; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg -; IS________OPM-SAME: (i32 [[TMP0:%.*]]) { -; IS________OPM-NEXT: [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* -; IS________OPM-NEXT: store i32 10, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 -; IS________OPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] -; IS________OPM: 5: -; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 -; IS________OPM-NEXT: br label [[TMP13:%.*]] -; IS________OPM: 7: -; IS________OPM-NEXT: br label [[TMP8:%.*]] -; IS________OPM: 8: -; IS________OPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] -; IS________OPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 -; IS________OPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 -; IS________OPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 -; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] -; IS________OPM: 12: -; IS________OPM-NEXT: br label [[TMP13]] -; IS________OPM: 13: -; IS________OPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] -; IS________OPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 -; IS________OPM-NEXT: br label [[TMP8]] -; IS________OPM: 15: -; IS________OPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* -; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP16]]) -; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: ret i32 [[TMP17]] -; -; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg -; IS________NPM-SAME: (i32 [[TMP0:%.*]]) { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[DOTH2S]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 1 -; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]] -; IS________NPM: 4: -; IS________NPM-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP0]], 5 -; IS________NPM-NEXT: br label [[TMP12:%.*]] -; IS________NPM: 6: -; IS________NPM-NEXT: br label [[TMP7:%.*]] -; IS________NPM: 7: -; IS________NPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP13:%.*]], [[TMP12]] ], [ 1, [[TMP6]] ] -; IS________NPM-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP8]], -1 -; IS________NPM-NEXT: store i32 [[TMP9]], i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP10:%.*]] = icmp ne i32 [[TMP8]], 0 -; IS________NPM-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP14:%.*]] -; IS________NPM: 11: -; IS________NPM-NEXT: br label [[TMP12]] -; IS________NPM: 12: -; IS________NPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[DOT0]], [[TMP11]] ] -; IS________NPM-NEXT: [[TMP13]] = add nsw i32 [[DOT1]], 1 -; IS________NPM-NEXT: br label [[TMP7]] -; IS________NPM: 14: -; IS________NPM-NEXT: [[TMP15:%.*]] = bitcast i32* [[TMP2]] to i8* -; IS________NPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP16]] +; CHECK-LABEL: define {{[^@]+}}@irreducible_cfg +; CHECK-SAME: (i32 [[TMP0:%.*]]) { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[DOTH2S]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 1 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]] +; CHECK: 4: +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP0]], 5 +; CHECK-NEXT: br label [[TMP12:%.*]] +; CHECK: 6: +; CHECK-NEXT: br label [[TMP7:%.*]] +; CHECK: 7: +; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP13:%.*]], [[TMP12]] ], [ 1, [[TMP6]] ] +; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP8]], -1 +; CHECK-NEXT: store i32 [[TMP9]], i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ne i32 [[TMP8]], 0 +; CHECK-NEXT: br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP14:%.*]] +; CHECK: 11: +; CHECK-NEXT: br label [[TMP12]] +; CHECK: 12: +; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[DOT0]], [[TMP11]] ] +; CHECK-NEXT: [[TMP13]] = add nsw i32 [[DOT1]], 1 +; CHECK-NEXT: br label [[TMP7]] +; CHECK: 14: +; CHECK-NEXT: [[TMP15:%.*]] = bitcast i32* [[TMP2]] to i8* +; CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: ret i32 [[TMP16]] ; %2 = call noalias i8* @malloc(i64 4) %3 = bitcast i8* %2 to i32* @@ -755,20 +648,12 @@ } define void @test16a(i8 %v, i8** %P) { -; IS________OPM-LABEL: define {{[^@]+}}@test16a -; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: store i8 [[V]], i8* [[TMP1]], align 1 -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]]) -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test16a -; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: store i8 [[V]], i8* [[DOTH2S]], align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[DOTH2S]]) -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test16a +; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: store i8 [[V]], i8* [[DOTH2S]], align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[DOTH2S]]) +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) store i8 %v, i8* %1 @@ -794,20 +679,12 @@ } define void @test16c(i8 %v, i8** %P) { -; IS________OPM-LABEL: define {{[^@]+}}@test16c -; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 -; IS________OPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: tail call void @free(i8* nocapture [[TMP1]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test16c -; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { -; IS________NPM-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: store i8* [[DOTH2S]], i8** [[P]], align 8 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[DOTH2S]]) #[[ATTR10]] -; IS________NPM-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@test16c +; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) { +; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: store i8* [[DOTH2S]], i8** [[P]], align 8 +; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[DOTH2S]]) #[[ATTR10]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) store i8* %1, i8** %P @@ -828,26 +705,15 @@ ret void } ;. -; IS________OPM: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) } -; IS________OPM: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn } -; IS________OPM: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn } -; IS________OPM: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind } -; IS________OPM: attributes #[[ATTR4]] = { noreturn } -; IS________OPM: attributes #[[ATTR5:[0-9]+]] = { allockind("free") } -; IS________OPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn } -; IS________OPM: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) } -; IS________OPM: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) } -; IS________OPM: attributes #[[ATTR9]] = { nounwind } -;. -; IS________NPM: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) } -; IS________NPM: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn } -; IS________NPM: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn } -; IS________NPM: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind } -; IS________NPM: attributes #[[ATTR4]] = { noreturn } -; IS________NPM: attributes #[[ATTR5:[0-9]+]] = { allockind("free") } -; IS________NPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn } -; IS________NPM: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) } -; IS________NPM: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) } -; IS________NPM: attributes #[[ATTR9:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } -; IS________NPM: attributes #[[ATTR10]] = { nounwind } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn } +; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn } +; CHECK: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind } +; CHECK: attributes #[[ATTR4]] = { noreturn } +; CHECK: attributes #[[ATTR5:[0-9]+]] = { allockind("free") } +; CHECK: attributes #[[ATTR6:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) } +; CHECK: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) } +; CHECK: attributes #[[ATTR9:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } +; CHECK: attributes #[[ATTR10]] = { nounwind } ;. diff --git a/llvm/test/Transforms/Attributor/lowerheap.ll b/llvm/test/Transforms/Attributor/lowerheap.ll --- a/llvm/test/Transforms/Attributor/lowerheap.ll +++ b/llvm/test/Transforms/Attributor/lowerheap.ll @@ -11,20 +11,12 @@ declare void @free(i8*) allockind("free") "alloc-family"="malloc" define i64 @f(i64 %len) { -; IS________OPM-LABEL: define {{[^@]+}}@f -; IS________OPM-SAME: (i64 [[LEN:%.*]]) { -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @malloc(i64 [[LEN]]) -; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) #[[ATTR4:[0-9]+]] -; IS________OPM-NEXT: call void @free(i8* [[MEM]]) -; IS________OPM-NEXT: ret i64 [[RES]] -; -; IS________NPM-LABEL: define {{[^@]+}}@f -; IS________NPM-SAME: (i64 [[LEN:%.*]]) { -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 [[LEN]], align 1 -; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP0]]) #[[ATTR5:[0-9]+]] -; IS________NPM-NEXT: ret i64 [[RES]] +; CHECK-LABEL: define {{[^@]+}}@f +; CHECK-SAME: (i64 [[LEN:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = alloca i8, i64 [[LEN]], align 1 +; CHECK-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP0]]) #[[ATTR5:[0-9]+]] +; CHECK-NEXT: ret i64 [[RES]] ; entry: %mem = call i8* @malloc(i64 %len) @@ -35,22 +27,14 @@ define i64 @g(i64 %len) { -; IS________OPM-LABEL: define {{[^@]+}}@g -; IS________OPM-SAME: (i64 [[LEN:%.*]]) { -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @calloc(i64 [[LEN]], i64 noundef 8) -; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) #[[ATTR4]] -; IS________OPM-NEXT: call void @free(i8* [[MEM]]) -; IS________OPM-NEXT: ret i64 [[RES]] -; -; IS________NPM-LABEL: define {{[^@]+}}@g -; IS________NPM-SAME: (i64 [[LEN:%.*]]) { -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[TMP0:%.*]] = mul i64 [[LEN]], 8 -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], align 1 -; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 [[TMP0]], i1 false) -; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP1]]) #[[ATTR5]] -; IS________NPM-NEXT: ret i64 [[RES]] +; CHECK-LABEL: define {{[^@]+}}@g +; CHECK-SAME: (i64 [[LEN:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[LEN]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], align 1 +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 [[TMP0]], i1 false) +; CHECK-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP1]]) #[[ATTR5]] +; CHECK-NEXT: ret i64 [[RES]] ; entry: %mem = call i8* @calloc(i64 %len, i64 8) @@ -61,16 +45,10 @@ attributes #0 = { nounwind willreturn } ;. -; IS________OPM: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn } -; IS________OPM: attributes #[[ATTR1:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR2:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR3:[0-9]+]] = { allockind("free") "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR4]] = { nounwind } -;. -; IS________NPM: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn } -; IS________NPM: attributes #[[ATTR1:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR2:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR3:[0-9]+]] = { allockind("free") "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR4:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } -; IS________NPM: attributes #[[ATTR5]] = { nounwind } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR2:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR3:[0-9]+]] = { allockind("free") "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR4:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } +; CHECK: attributes #[[ATTR5]] = { nounwind } ;. 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 }