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 @@ -377,7 +377,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 { @@ -598,7 +598,7 @@ // handled above. if (auto *Call = dyn_cast(&I)) { auto &TLI = GetTLI(*Node->getFunction()); - if (isAllocationFn(Call, &TLI) || isFreeCall(Call, &TLI)) { + 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); 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 @@ -575,6 +575,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 @@ -1488,7 +1488,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); @@ -6095,7 +6095,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 @@ -1081,7 +1081,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 @@ -2804,7 +2804,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 @@ -1102,7 +1102,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)}; } @@ -1115,7 +1115,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 @@ -147,20 +147,12 @@ ; TEST 3 - 1 malloc, 1 free define void @test3() { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test3 -; IS________OPM-SAME: () #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test3 -; IS________NPM-SAME: () #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test3 +; CHECK-SAME: () #[[ATTR7]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -172,9 +164,8 @@ ; IS__TUNIT_OPM: Function Attrs: willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3a ; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) #[[ATTR7]] { -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 ; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP1]], i8* nocapture [[P]]) #[[ATTR7]] -; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] ; IS__TUNIT_OPM-NEXT: ret void ; ; IS__TUNIT_NPM: Function Attrs: willreturn @@ -187,9 +178,8 @@ ; IS__CGSCC_OPM: Function Attrs: willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3a ; IS__CGSCC_OPM-SAME: (i8* nocapture noundef [[P:%.*]]) #[[ATTR7]] { -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 ; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP1]], i8* nocapture noundef [[P]]) #[[ATTR7]] -; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] ; IS__CGSCC_OPM-NEXT: ret void ; ; IS__CGSCC_NPM: Function Attrs: willreturn @@ -211,9 +201,8 @@ ; IS__TUNIT_OPM: Function Attrs: willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3b ; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) #[[ATTR7]] { -; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128) #[[ATTR7]] +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 128, align 32 ; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP1]], i8* nocapture [[P]]) #[[ATTR7]] -; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] ; IS__TUNIT_OPM-NEXT: ret void ; ; IS__TUNIT_NPM: Function Attrs: willreturn @@ -226,9 +215,8 @@ ; IS__CGSCC_OPM: Function Attrs: willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3b ; IS__CGSCC_OPM-SAME: (i8* nocapture noundef [[P:%.*]]) #[[ATTR7]] { -; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128) #[[ATTR7]] +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 128, align 32 ; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP1]], i8* nocapture noundef [[P]]) #[[ATTR7]] -; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] ; IS__CGSCC_OPM-NEXT: ret void ; ; IS__CGSCC_NPM: Function Attrs: willreturn @@ -302,21 +290,13 @@ declare noalias i8* @calloc(i64, i64) define void @test0() { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test0 -; IS________OPM-SAME: () #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 2, i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test0 -; IS________NPM-SAME: () #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 8, align 1 -; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 8, i1 false) -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test0 +; CHECK-SAME: () #[[ATTR7]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 8, align 1 +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 8, i1 false) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @calloc(i64 2, i64 4) tail call void @no_sync_func(i8* %1) @@ -345,7 +325,7 @@ ; IS__TUNIT_OPM: Function Attrs: willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test5 ; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) #[[ATTR7]] { -; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 ; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] ; IS__TUNIT_OPM: 4: @@ -353,7 +333,6 @@ ; IS__TUNIT_OPM-NEXT: br label [[TMP6:%.*]] ; IS__TUNIT_OPM: 5: ; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP2]], i8* nocapture [[P]]) #[[ATTR7]] -; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP2]]) #[[ATTR9]] ; IS__TUNIT_OPM-NEXT: br label [[TMP6]] ; IS__TUNIT_OPM: 6: ; IS__TUNIT_OPM-NEXT: ret void @@ -376,7 +355,7 @@ ; IS__CGSCC_OPM: Function Attrs: willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test5 ; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) #[[ATTR7]] { -; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 ; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 ; IS__CGSCC_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] ; IS__CGSCC_OPM: 4: @@ -384,7 +363,6 @@ ; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]] ; IS__CGSCC_OPM: 5: ; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree noundef [[TMP2]], i8* nocapture noundef [[P]]) #[[ATTR7]] -; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP2]]) #[[ATTR9]] ; IS__CGSCC_OPM-NEXT: br label [[TMP6]] ; IS__CGSCC_OPM: 6: ; IS__CGSCC_OPM-NEXT: ret void @@ -424,35 +402,19 @@ ; TEST 6 - all exit paths have a call to free define void @test6(i32) { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test6 -; IS________OPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; 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 noundef [[TMP2]]) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP2]]) #[[ATTR9]] -; IS________OPM-NEXT: br label [[TMP6:%.*]] -; IS________OPM: 5: -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef [[TMP2]]) #[[ATTR9]] -; IS________OPM-NEXT: br label [[TMP6]] -; IS________OPM: 6: -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test6 -; IS________NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 -; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] -; IS________NPM: 4: -; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree noundef [[TMP2]]) #[[ATTR7]] -; IS________NPM-NEXT: br label [[TMP6:%.*]] -; IS________NPM: 5: -; IS________NPM-NEXT: br label [[TMP6]] -; IS________NPM: 6: -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test6 +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR7]] { +; CHECK-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; CHECK: 4: +; CHECK-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree noundef [[TMP2]]) #[[ATTR7]] +; CHECK-NEXT: br label [[TMP6:%.*]] +; CHECK: 5: +; CHECK-NEXT: br label [[TMP6]] +; CHECK: 6: +; CHECK-NEXT: ret void ; %2 = tail call noalias i8* @malloc(i64 4) %3 = icmp eq i32 %0, 0 @@ -474,15 +436,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) #[[ATTR7]] -; 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: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]] -; IS________NPM-NEXT: unreachable +; CHECK-LABEL: define {{[^@]+}}@test7() { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP2:%.*]] = 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() @@ -536,26 +493,15 @@ ; TEST 10 - 1 malloc, 1 free define i32 @test10() { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test10 -; IS________OPM-SAME: () #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; 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]]) #[[ATTR9]] -; IS________OPM-NEXT: ret i32 [[TMP3]] -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test10 -; IS________NPM-SAME: () #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP3]] +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test10 +; CHECK-SAME: () #[[ATTR7]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: ret i32 [[TMP3]] ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -567,28 +513,16 @@ } define i32 @test_lifetime() { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime -; IS________OPM-SAME: () #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]]) #[[ATTR7]] -; 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]]) #[[ATTR9]] -; IS________OPM-NEXT: ret i32 [[TMP3]] -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime -; IS________NPM-SAME: () #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP3]] +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test_lifetime +; CHECK-SAME: () #[[ATTR7]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: ret i32 [[TMP3]] ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @no_sync_func(i8* %1) @@ -603,20 +537,12 @@ ; TEST 11 define void @test11() { -; IS________OPM: Function Attrs: nounwind willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test11 -; IS________OPM-SAME: () #[[ATTR9]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @sync_will_return(i8* noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: tail call void @free(i8* nocapture noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: nounwind willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test11 -; IS________NPM-SAME: () #[[ATTR9]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: tail call void @sync_will_return(i8* noundef [[TMP1]]) #[[ATTR9]] -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@test11 +; CHECK-SAME: () #[[ATTR9]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: tail call void @sync_will_return(i8* noundef [[TMP1]]) #[[ATTR9]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) tail call void @sync_will_return(i8* %1) @@ -626,68 +552,36 @@ ; TEST 12 define i32 @irreducible_cfg(i32 %0) { -; IS________OPM: Function Attrs: nounwind -; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg -; IS________OPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR12]] { -; IS________OPM-NEXT: [[TMP2:%.*]] = call noalias nonnull align 4 dereferenceable(4) 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 nonnull align 4 dereferenceable(4) [[TMP16]]) #[[ATTR12]] -; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: ret i32 [[TMP17]] -; -; IS________NPM: Function Attrs: nounwind -; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg -; IS________NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR12]] { -; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* -; IS________NPM-NEXT: store i32 10, i32* [[TMP3]], align 4 -; IS________NPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 -; IS________NPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] -; IS________NPM: 5: -; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 -; IS________NPM-NEXT: br label [[TMP13:%.*]] -; IS________NPM: 7: -; IS________NPM-NEXT: br label [[TMP8:%.*]] -; IS________NPM: 8: -; IS________NPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] -; IS________NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________NPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 -; IS________NPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 -; IS________NPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 -; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] -; IS________NPM: 12: -; IS________NPM-NEXT: br label [[TMP13]] -; IS________NPM: 13: -; IS________NPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] -; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 -; IS________NPM-NEXT: br label [[TMP8]] -; IS________NPM: 15: -; IS________NPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* -; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP17]] +; CHECK: Function Attrs: nounwind +; CHECK-LABEL: define {{[^@]+}}@irreducible_cfg +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR12]] { +; CHECK-NEXT: [[TMP2:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 +; CHECK-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] +; CHECK: 5: +; CHECK-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 +; CHECK-NEXT: br label [[TMP13:%.*]] +; CHECK: 7: +; CHECK-NEXT: br label [[TMP8:%.*]] +; CHECK: 8: +; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] +; CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 +; CHECK-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 +; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] +; CHECK: 12: +; CHECK-NEXT: br label [[TMP13]] +; CHECK: 13: +; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] +; CHECK-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 +; CHECK-NEXT: br label [[TMP8]] +; CHECK: 15: +; CHECK-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* +; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 +; CHECK-NEXT: ret i32 [[TMP17]] ; %2 = call noalias i8* @malloc(i64 4) %3 = bitcast i8* %2 to i32* @@ -865,22 +759,13 @@ } define void @test16a(i8 %v, i8** %P) { -; IS________OPM: Function Attrs: willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test16a -; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) #[[ATTR7]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias nonnull dereferenceable(1) i8* @malloc(i64 noundef 4) #[[ATTR7]] -; 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]]) #[[ATTR7]] -; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test16a -; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) #[[ATTR7]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: store i8 [[V]], i8* [[TMP1]], align 1 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]]) #[[ATTR7]] -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: willreturn +; CHECK-LABEL: define {{[^@]+}}@test16a +; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) #[[ATTR7]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: store i8 [[V]], i8* [[TMP1]], align 1 +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]]) #[[ATTR7]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) store i8 %v, i8* %1 @@ -907,22 +792,13 @@ } define void @test16c(i8 %v, i8** %P) { -; IS________OPM: Function Attrs: nounwind willreturn -; IS________OPM-LABEL: define {{[^@]+}}@test16c -; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR9]] { -; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) #[[ATTR7]] -; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 -; IS________OPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: tail call void @free(i8* nocapture noundef [[TMP1]]) #[[ATTR9]] -; IS________OPM-NEXT: ret void -; -; IS________NPM: Function Attrs: nounwind willreturn -; IS________NPM-LABEL: define {{[^@]+}}@test16c -; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR9]] { -; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 -; IS________NPM-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 -; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree noundef [[TMP1]]) #[[ATTR9]] -; IS________NPM-NEXT: ret void +; CHECK: Function Attrs: nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@test16c +; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR9]] { +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 +; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8 +; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree noundef [[TMP1]]) #[[ATTR9]] +; CHECK-NEXT: ret void ; %1 = tail call noalias i8* @malloc(i64 4) store i8* %1, i8** %P @@ -944,34 +820,19 @@ ret void } ;. -; IS________OPM: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(0) "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR1:[0-9]+]] = { mustprogress nounwind willreturn } -; IS________OPM: attributes #[[ATTR2:[0-9]+]] = { mustprogress nofree nosync willreturn } -; IS________OPM: attributes #[[ATTR3]] = { nofree nounwind } -; IS________OPM: attributes #[[ATTR4]] = { noreturn } -; IS________OPM: attributes #[[ATTR5:[0-9]+]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("free") "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } -; IS________OPM: attributes #[[ATTR7]] = { willreturn } -; IS________OPM: attributes #[[ATTR8:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(1) "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR9]] = { nounwind willreturn } -; IS________OPM: attributes #[[ATTR10:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,zeroed") allocsize(0,1) "alloc-family"="malloc" } -; IS________OPM: attributes #[[ATTR11]] = { nofree willreturn } -; IS________OPM: attributes #[[ATTR12]] = { nounwind } -; IS________OPM: attributes #[[ATTR13]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn } -;. -; IS________NPM: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(0) "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR1:[0-9]+]] = { mustprogress nounwind willreturn } -; IS________NPM: attributes #[[ATTR2:[0-9]+]] = { mustprogress nofree nosync willreturn } -; IS________NPM: attributes #[[ATTR3]] = { nofree nounwind } -; IS________NPM: attributes #[[ATTR4]] = { noreturn } -; IS________NPM: attributes #[[ATTR5:[0-9]+]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("free") "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } -; IS________NPM: attributes #[[ATTR7]] = { willreturn } -; IS________NPM: attributes #[[ATTR8:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(1) "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR9]] = { nounwind willreturn } -; IS________NPM: attributes #[[ATTR10:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,zeroed") allocsize(0,1) "alloc-family"="malloc" } -; IS________NPM: attributes #[[ATTR11]] = { nofree willreturn } -; IS________NPM: attributes #[[ATTR12]] = { nounwind } -; IS________NPM: attributes #[[ATTR13]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn } -; IS________NPM: attributes #[[ATTR14:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(0) "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress nounwind willreturn } +; CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress nofree nosync willreturn } +; CHECK: attributes #[[ATTR3]] = { nofree nounwind } +; CHECK: attributes #[[ATTR4]] = { noreturn } +; CHECK: attributes #[[ATTR5:[0-9]+]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("free") "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR6:[0-9]+]] = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #[[ATTR7]] = { willreturn } +; CHECK: attributes #[[ATTR8:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,uninitialized") allocsize(1) "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR9]] = { nounwind willreturn } +; CHECK: attributes #[[ATTR10:[0-9]+]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("new,zeroed") allocsize(0,1) "alloc-family"="malloc" } +; CHECK: attributes #[[ATTR11]] = { nofree willreturn } +; CHECK: attributes #[[ATTR12]] = { nounwind } +; CHECK: attributes #[[ATTR13]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn } +; CHECK: attributes #[[ATTR14:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } ;. 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 @@ -3424,12 +3424,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 @@ -3444,12 +3443,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 @@ -3475,12 +3473,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 @@ -3492,12 +3489,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 @@ -3704,18 +3700,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 @@ -3737,18 +3733,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 @@ -3788,17 +3784,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 @@ -3816,17 +3812,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 @@ -3862,7 +3858,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]] ; @@ -3880,7 +3876,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]] ; @@ -3905,11 +3901,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 @@ -3927,7 +3923,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* @@ -4641,8 +4637,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 }