From 955b13373b13e12458cd89bd2cd1475a454f7ae0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 16 Jul 2025 18:14:09 +0200 Subject: [PATCH 1/2] only allow lifetime markers on allocas --- llvm/docs/LangRef.rst | 32 +- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 8 +- llvm/lib/CodeGen/SafeStack.cpp | 7 + llvm/lib/IR/AutoUpgrade.cpp | 44 ++- llvm/lib/IR/Verifier.cpp | 5 + .../Target/SPIRV/SPIRVPrepareFunctions.cpp | 6 +- llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 6 + .../Instrumentation/AddressSanitizer.cpp | 18 + .../Transforms/Scalar/InferAddressSpaces.cpp | 2 + llvm/test/Analysis/BasicAA/modref.ll | 14 +- .../CallGraph/ignore-assumelike-calls.ll | 13 +- .../Analysis/CostModel/X86/free-intrinsics.ll | 15 +- .../CostModel/free-intrinsics-datalayout.ll | 15 +- .../CostModel/free-intrinsics-no_info.ll | 15 +- .../Analysis/MemorySSA/lifetime-simple.ll | 6 +- llvm/test/Analysis/MemorySSA/pr43427.ll | 7 +- llvm/test/Analysis/MemorySSA/pr43438.ll | 5 +- .../Analysis/StackSafetyAnalysis/lifetime.ll | 77 ----- .../autoupgrade-lifetime-intrinsics.ll | 57 ++++ .../GlobalISel/irtranslator-switch-split.ll | 10 +- llvm/test/CodeGen/AArch64/stack-tagging.ll | 50 --- .../Thumb2/ifcvt-rescan-bug-2016-08-22.ll | 3 +- llvm/test/CodeGen/X86/select-optimize.ll | 6 +- llvm/test/CodeGen/X86/swap.ll | 9 +- .../AddressSanitizer/asan-funclet.ll | 26 +- .../AddressSanitizer/lifetime-throw.ll | 8 +- .../AddressSanitizer/lifetime.ll | 174 ---------- .../stack-poisoning-and-lifetime-be.ll | 12 - .../stack-poisoning-and-lifetime.ll | 46 --- .../Instrumentation/MemorySanitizer/alloca.ll | 73 ----- .../Transforms/Attributor/heap_to_stack.ll | 20 -- .../Attributor/heap_to_stack_gpu.ll | 21 -- .../CodeExtractor/PartialInlineAlloca5.ll | 4 +- .../CodeExtractor/live_shrink_gep.ll | 7 +- .../AArch64/const-hoist-intrinsics.ll | 6 +- llvm/test/Transforms/DCE/basic.ll | 42 --- .../DeadStoreElimination/libcalls.ll | 13 - .../DeadStoreElimination/lifetime.ll | 12 +- .../multiblock-multipath.ll | 7 +- llvm/test/Transforms/EarlyCSE/memoryssa.ll | 25 +- llvm/test/Transforms/GVN/opt-remarks.ll | 3 +- .../lifetime-markers-on-inputs-1.ll | 5 +- .../InferAddressSpaces/NVPTX/lifetime.ll | 11 +- llvm/test/Transforms/Inline/alloca-bonus.ll | 5 - .../test/Transforms/Inline/redundant-loads.ll | 3 - llvm/test/Transforms/InstCombine/deadcode.ll | 5 +- .../Transforms/InstCombine/malloc-free.ll | 2 - .../InstCombine/scalable-vector-struct.ll | 4 - .../multiply-fused-lifetime-ends.ll | 307 ++---------------- llvm/test/Transforms/MemCpyOpt/lifetime.ll | 19 -- .../test/Transforms/MemCpyOpt/memcpy-undef.ll | 18 +- .../MemCpyOpt/memset-memcpy-oversized.ll | 23 +- .../Transforms/MemCpyOpt/preserve-memssa.ll | 15 - llvm/test/Transforms/MoveAutoInit/clobber.ll | 22 +- .../test/Transforms/NewGVN/lifetime-simple.ll | 6 +- .../inlined-autorelease-return-value.ll | 8 +- .../Transforms/SafeStack/X86/coloring2.ll | 37 --- llvm/test/Verifier/intrinsic-immarg.ll | 6 +- llvm/test/Verifier/opaque-ptr.ll | 6 +- .../Import/intrinsic-prefer-unregistered.ll | 11 +- mlir/test/Target/LLVMIR/Import/intrinsic.ll | 7 +- .../test/Target/LLVMIR/llvmir-intrinsics.mlir | 8 +- .../invariant_load_in_non_affine_subregion.ll | 4 +- 63 files changed, 376 insertions(+), 1085 deletions(-) create mode 100644 llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 371f356c80b0a..db05f6eb90c8e 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -26634,19 +26634,14 @@ Arguments: The first argument is a constant integer representing the size of the object, or -1 if it is variable sized. The second argument is a pointer -to the object. +to to an ``alloca`` instruction. Semantics: """""""""" -If ``ptr`` is a stack-allocated object and it points to the first byte of -the object, the object is initially marked as dead. -``ptr`` is conservatively considered as a non-stack-allocated object if -the stack coloring algorithm that is used in the optimization pipeline cannot -conclude that ``ptr`` is a stack-allocated object. - -After '``llvm.lifetime.start``', the stack object that ``ptr`` points is marked -as alive and has an uninitialized value. +The stack-allocated object that ``ptr`` points to is initially marked as dead. +After '``llvm.lifetime.start``', the stack object is marked as alive and has an +uninitialized value. The stack object is marked as dead when either :ref:`llvm.lifetime.end ` to the alloca is executed or the function returns. @@ -26656,11 +26651,6 @@ After :ref:`llvm.lifetime.end ` is called, The second '``llvm.lifetime.start``' call marks the object as alive, but it does not change the address of the object. -If ``ptr`` is a non-stack-allocated object, it does not point to the first -byte of the object or it is a stack object that is already alive, it simply -fills all bytes of the object with ``poison``. - - .. _int_lifeend: '``llvm.lifetime.end``' Intrinsic @@ -26684,24 +26674,16 @@ Arguments: The first argument is a constant integer representing the size of the object, or -1 if it is variable sized. The second argument is a pointer -to the object. +to an ``alloca`` instruction. Semantics: """""""""" -If ``ptr`` is a stack-allocated object and it points to the first byte of the -object, the object is dead. -``ptr`` is conservatively considered as a non-stack-allocated object if -the stack coloring algorithm that is used in the optimization pipeline cannot -conclude that ``ptr`` is a stack-allocated object. +The stack-allocated object that ``ptr`` points becomes dead after the call to +this intrinsic. Calling ``llvm.lifetime.end`` on an already dead alloca is no-op. -If ``ptr`` is a non-stack-allocated object or it does not point to the first -byte of the object, it is equivalent to simply filling all bytes of the object -with ``poison``. - - '``llvm.invariant.start``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 66ecc69c9874d..82c94b689aca6 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -7116,9 +7116,11 @@ Error BitcodeReader::materializeModule() { if (CallInst *CI = dyn_cast(U)) UpgradeIntrinsicCall(CI, I.second); } - if (!I.first->use_empty()) - I.first->replaceAllUsesWith(I.second); - I.first->eraseFromParent(); + if (I.first != I.second) { + if (!I.first->use_empty()) + I.first->replaceAllUsesWith(I.second); + I.first->eraseFromParent(); + } } UpgradedIntrinsics.clear(); diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index 996207034d076..908ed96172615 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -614,6 +614,13 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( Use &U = *AI->use_begin(); Instruction *User = cast(U.getUser()); + // Drop lifetime markers now that this is no longer an alloca. + // SafeStack has already performed its own stack coloring. + if (User->isLifetimeStartOrEnd()) { + User->eraseFromParent(); + continue; + } + Instruction *InsertBefore; if (auto *PHI = dyn_cast(User)) InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 86285a03c66bb..28ed1e520ce52 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -1310,6 +1310,18 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn, return true; } break; + case 'l': + if (Name.starts_with("lifetime.start") || + Name.starts_with("lifetime.end")) { + // Unless remangling is required, do not upgrade the function declaration, + // but do upgrade the calls. + if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F)) + NewFn = *Result; + else + NewFn = F; + return true; + } + break; case 'm': { // Updating the memory intrinsics (memcpy/memmove/memset) that have an // alignment parameter to embedding the alignment as an attribute of @@ -1629,7 +1641,6 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn, NewFn = nullptr; bool Upgraded = upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords); - assert(F != NewFn && "Intrinsic function upgraded to the same function"); // Upgrade intrinsic attributes. This does not change the function. if (NewFn) @@ -4570,6 +4581,9 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { } const auto &DefaultCase = [&]() -> void { + if (F == NewFn) + return; + if (CI->getFunctionType() == NewFn->getFunctionType()) { // Handle generic mangling change. assert( @@ -5109,6 +5123,31 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { MTI->setSourceAlignment(Align->getMaybeAlignValue()); break; } + + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: { + Value *Size = CI->getArgOperand(0); + Value *Ptr = CI->getArgOperand(1); + if (isa(Ptr)) { + DefaultCase(); + return; + } + + // Try to strip pointer casts, such that the lifetime works on an alloca. + Ptr = Ptr->stripPointerCasts(); + if (isa(Ptr)) { + // Don't use NewFn, as we might have looked through an addrspacecast. + if (NewFn->getIntrinsicID() == Intrinsic::lifetime_start) + NewCall = Builder.CreateLifetimeStart(Ptr, cast(Size)); + else + NewCall = Builder.CreateLifetimeEnd(Ptr, cast(Size)); + break; + } + + // Otherwise remove the lifetime marker. + CI->eraseFromParent(); + return; + } } assert(NewCall && "Should have either set this variable or returned through " "the default case"); @@ -5131,7 +5170,8 @@ void llvm::UpgradeCallsToIntrinsic(Function *F) { UpgradeIntrinsicCall(CB, NewFn); // Remove old function, no longer used, from the module. - F->eraseFromParent(); + if (F != NewFn) + F->eraseFromParent(); } } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 8c8ed3c5e47ba..196a52cc07120 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6679,6 +6679,11 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "llvm.threadlocal.address operand isThreadLocal() must be true"); break; } + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + Check(isa(Call.getArgOperand(1)), + "llvm.lifetime.start/end can only be used on alloca", &Call); + break; }; // Verify that there aren't any unmediated control transfers between funclets. diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp index 2bffbf73b574a..6766bd866cd2e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp @@ -380,7 +380,7 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) { bool Changed = false; const SPIRVSubtarget &STI = TM.getSubtarget(*F); for (BasicBlock &BB : *F) { - for (Instruction &I : BB) { + for (Instruction &I : make_early_inc_range(BB)) { auto Call = dyn_cast(&I); if (!Call) continue; @@ -408,12 +408,16 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) { if (!STI.isShader()) { Changed |= toSpvOverloadedIntrinsic( II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1}); + } else { + II->eraseFromParent(); } break; case Intrinsic::lifetime_end: if (!STI.isShader()) { Changed |= toSpvOverloadedIntrinsic( II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1}); + } else { + II->eraseFromParent(); } break; case Intrinsic::ptr_annotation: diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp index e279fec18bdbc..6561b1cd4ade1 100644 --- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -170,6 +170,12 @@ void Lowerer::hidePromiseAlloca(CoroIdInst *CoroId, CoroBeginInst *CoroBegin) { auto *PI = Builder.CreateIntrinsic( Builder.getPtrTy(), Intrinsic::coro_promise, Arg, {}, "promise.addr"); PI->setCannotDuplicate(); + // Remove lifetime markers, as these are only allowed on allocas. + for (User *U : make_early_inc_range(PA->users())) { + auto *I = cast(U); + if (I->isLifetimeStartOrEnd()) + I->eraseFromParent(); + } PA->replaceUsesWithIf(PI, [CoroId](Use &U) { bool IsBitcast = U == U.getUser()->stripPointerCasts(); bool IsCoroId = U.getUser() == CoroId; diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 5957940add577..fbaa651641566 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -3637,6 +3637,7 @@ void FunctionStackPoisoner::processStaticAllocas() { "Variable descriptions relative to ASan stack base will be dropped"); // Replace Alloca instructions with base+offset. + SmallVector NewAllocaPtrs; for (const auto &Desc : SVD) { AllocaInst *AI = Desc.AI; replaceDbgDeclare(AI, LocalStackBaseAllocaPtr, DIB, DIExprFlags, @@ -3645,6 +3646,7 @@ void FunctionStackPoisoner::processStaticAllocas() { IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)), AI->getType()); AI->replaceAllUsesWith(NewAllocaPtr); + NewAllocaPtrs.push_back(NewAllocaPtr); } // The left-most redzone has enough space for at least 4 pointers. @@ -3694,6 +3696,15 @@ void FunctionStackPoisoner::processStaticAllocas() { } } + // Remove lifetime markers now that these are no longer allocas. + for (Value *NewAllocaPtr : NewAllocaPtrs) { + for (User *U : make_early_inc_range(NewAllocaPtr->users())) { + auto *I = cast(U); + if (I->isLifetimeStartOrEnd()) + I->eraseFromParent(); + } + } + SmallVector ShadowClean(ShadowAfterScope.size(), 0); SmallVector ShadowAfterReturn; @@ -3829,6 +3840,13 @@ void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) { Value *NewAddressPtr = IRB.CreateIntToPtr(NewAddress, AI->getType()); + // Remove lifetime markers now that this is no longer an alloca. + for (User *U : make_early_inc_range(AI->users())) { + auto *I = cast(U); + if (I->isLifetimeStartOrEnd()) + I->eraseFromParent(); + } + // Replace all uses of AddessReturnedByAlloca with NewAddressPtr. AI->replaceAllUsesWith(NewAddressPtr); diff --git a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp index 66836ef05d5db..85ee824b67121 100644 --- a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp +++ b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp @@ -430,6 +430,8 @@ bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *II, } case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: { + // Always force lifetime markers to work directly on the alloca. + NewV = NewV->stripPointerCasts(); Function *NewDecl = Intrinsic::getOrInsertDeclaration( M, II->getIntrinsicID(), {NewV->getType()}); II->setArgOperand(1, NewV); diff --git a/llvm/test/Analysis/BasicAA/modref.ll b/llvm/test/Analysis/BasicAA/modref.ll index 0619f8e615b80..1aab28f3f1871 100644 --- a/llvm/test/Analysis/BasicAA/modref.ll +++ b/llvm/test/Analysis/BasicAA/modref.ll @@ -67,27 +67,33 @@ define i8 @test2a(ptr %P) { ret i8 %A } -define void @test3(ptr %P, i8 %X) { +define void @test3(i8 %X) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 2 +; CHECK-NEXT: [[P:%.*]] = alloca i64, align 8 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2 ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr [[P]]) ; CHECK-NEXT: store i8 2, ptr [[P2]], align 1 +; CHECK-NEXT: call void @external(ptr [[P]]) ; CHECK-NEXT: ret void ; + %P = alloca i64 %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. %P2 = getelementptr i8, ptr %P, i32 2 store i8 %Y, ptr %P2 ;; Not read by lifetime.end, should be removed. call void @llvm.lifetime.end.p0(i64 1, ptr %P) store i8 2, ptr %P2 + call void @external(ptr %P) ret void } -define void @test3a(ptr %P, i8 %X) { +define void @test3a(i8 %X) { ; CHECK-LABEL: @test3a( -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 10, ptr [[P:%.*]]) +; CHECK-NEXT: [[P:%.*]] = alloca i64, align 8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 10, ptr [[P]]) ; CHECK-NEXT: ret void ; + %P = alloca i64 %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. %P2 = getelementptr i8, ptr %P, i32 2 diff --git a/llvm/test/Analysis/CallGraph/ignore-assumelike-calls.ll b/llvm/test/Analysis/CallGraph/ignore-assumelike-calls.ll index 658d73804c174..1c9d20193869e 100644 --- a/llvm/test/Analysis/CallGraph/ignore-assumelike-calls.ll +++ b/llvm/test/Analysis/CallGraph/ignore-assumelike-calls.ll @@ -10,7 +10,7 @@ ; CHECK-EMPTY: ; CHECK-NEXT: Call graph node for function: 'bitcast_only'<<{{.*}}>> #uses=0 ; CHECK-EMPTY: -; CHECK-NEXT: Call graph node for function: 'llvm.lifetime.start.p0'<<{{.*}}>> #uses=3 +; CHECK-NEXT: Call graph node for function: 'llvm.lifetime.start.p0'<<{{.*}}>> #uses=2 ; CHECK-EMPTY: ; CHECK-NEXT: Call graph node for function: 'llvm.memset.p0.i64'<<{{.*}}>> #uses=2 ; CHECK-EMPTY: @@ -25,18 +25,11 @@ ; CHECK-NEXT: Call graph node for function: 'used_by_lifetime'<<{{.*}}>> #uses=0 ; CHECK-NEXT: CS<{{.*}}> calls function 'llvm.lifetime.start.p0' ; CHECK-EMPTY: -; CHECK-NEXT: Call graph node for function: 'used_by_lifetime_cast'<<{{.*}}>> #uses=0 -; CHECK-NEXT: CS<{{.*}}> calls function 'llvm.lifetime.start.p0' -; CHECK-EMPTY: define internal void @used_by_lifetime() { entry: - call void @llvm.lifetime.start.p0(i64 4, ptr @used_by_lifetime) - ret void -} - -define internal void @used_by_lifetime_cast() addrspace(1) { - call void @llvm.lifetime.start.p0(i64 4, ptr addrspacecast (ptr addrspace(1) @used_by_lifetime_cast to ptr)) + %a = alloca i8 + call void @llvm.lifetime.start.p0(i64 4, ptr %a) ret void } diff --git a/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll b/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll index a8c5c43c3a9f8..3a54428bd8291 100644 --- a/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll +++ b/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll @@ -4,6 +4,7 @@ define i32 @trivially_free() { ; CHECK-SIZE-LABEL: 'trivially_free' +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1 ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -13,14 +14,15 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; ; CHECK-THROUGHPUT-LABEL: 'trivially_free' +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1 ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -30,13 +32,14 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; + %alloca = alloca i8 %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef) call void @llvm.assume(i1 undef) call void @llvm.experimental.noalias.scope.decl(metadata !4) @@ -46,8 +49,8 @@ define i32 @trivially_free() { %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef) - call void @llvm.lifetime.start.p0(i64 1, ptr undef) - call void @llvm.lifetime.end.p0(i64 1, ptr undef) + call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) + call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll index 560af3d2b48fc..96064dc3af60b 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll @@ -6,6 +6,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define i32 @trivially_free() { ; CHECK-SIZE-LABEL: 'trivially_free' +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 4 ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -15,8 +16,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) @@ -25,6 +26,7 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; ; CHECK-THROUGHPUT-LABEL: 'trivially_free' +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 4 ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -34,8 +36,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) @@ -43,6 +45,7 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; + %alloca = alloca i8 %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef) call void @llvm.assume(i1 undef) call void @llvm.experimental.noalias.scope.decl(metadata !4) @@ -52,8 +55,8 @@ define i32 @trivially_free() { %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef) - call void @llvm.lifetime.start.p0(i64 1, ptr undef) - call void @llvm.lifetime.end.p0(i64 1, ptr undef) + call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) + call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) %a7 = call i1 @llvm.allow.ubsan.check(i8 123) diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll index 53828f2f07277..f989ebe592a11 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll @@ -4,6 +4,7 @@ define i32 @trivially_free() { ; CHECK-SIZE-LABEL: 'trivially_free' +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1 ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -13,8 +14,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) @@ -23,6 +24,7 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; ; CHECK-THROUGHPUT-LABEL: 'trivially_free' +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1 ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3) @@ -32,8 +34,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef) -; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) @@ -41,6 +43,7 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; + %alloca = alloca i8 %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef) call void @llvm.assume(i1 undef) call void @llvm.experimental.noalias.scope.decl(metadata !4) @@ -50,8 +53,8 @@ define i32 @trivially_free() { %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef) - call void @llvm.lifetime.start.p0(i64 1, ptr undef) - call void @llvm.lifetime.end.p0(i64 1, ptr undef) + call void @llvm.lifetime.start.p0(i64 1, ptr %alloca) + call void @llvm.lifetime.end.p0(i64 1, ptr %alloca) %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) diff --git a/llvm/test/Analysis/MemorySSA/lifetime-simple.ll b/llvm/test/Analysis/MemorySSA/lifetime-simple.ll index d409c140dc7b2..18d2459b42c40 100644 --- a/llvm/test/Analysis/MemorySSA/lifetime-simple.ll +++ b/llvm/test/Analysis/MemorySSA/lifetime-simple.ll @@ -2,8 +2,12 @@ ; This test checks that lifetime markers are considered clobbers of %P, ; and due to lack of noalias information, of %Q as well. -define i8 @test(ptr %P, ptr %Q) { +declare ptr @obscure(ptr) memory(none) + +define i8 @test() { entry: + %P = alloca [32 x i8] + %Q = call ptr @obscure(ptr %P) ; CHECK: 1 = MemoryDef(liveOnEntry) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %P) call void @llvm.lifetime.start.p0(i64 32, ptr %P) diff --git a/llvm/test/Analysis/MemorySSA/pr43427.ll b/llvm/test/Analysis/MemorySSA/pr43427.ll index a9b442c735b60..254fb1104c590 100644 --- a/llvm/test/Analysis/MemorySSA/pr43427.ll +++ b/llvm/test/Analysis/MemorySSA/pr43427.ll @@ -30,7 +30,7 @@ ; CHECK-NEXT: ; [[NO6:.*]] = MemoryDef([[NO7]]) ; CHECK-NEXT: store i16 undef, ptr %e, align 1 ; CHECK-NEXT: 3 = MemoryDef([[NO6]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr null) +; CHECK-NEXT: call void @g() define void @f(i1 %arg) { entry: @@ -57,7 +57,7 @@ cleanup: ; preds = %lbl3 br i1 %switch, label %cleanup.cont, label %lbl1 cleanup.cont: ; preds = %cleanup - call void @llvm.lifetime.end.p0(i64 1, ptr null) + call void @g() ret void if.else: ; preds = %lbl1 @@ -65,6 +65,3 @@ if.else: ; preds = %lbl1 } declare void @g() - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) diff --git a/llvm/test/Analysis/MemorySSA/pr43438.ll b/llvm/test/Analysis/MemorySSA/pr43438.ll index d137c52e3e0ff..0e09137c1cf9a 100644 --- a/llvm/test/Analysis/MemorySSA/pr43438.ll +++ b/llvm/test/Analysis/MemorySSA/pr43438.ll @@ -87,7 +87,7 @@ if.else: ; preds = %lbl1 ] if.end12: ; preds = %cleanup.cont11s, %cleanup.cont - call void @llvm.lifetime.end.p0(i64 1, ptr undef) + call i16 @g(i16 1) ret void unreachable: ; preds = %if.else, %for.end5 @@ -95,6 +95,3 @@ unreachable: ; preds = %if.else, %for.end5 } declare i16 @g(i16) - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) diff --git a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll index 37fa7d3e84eae..7fa1cf47f06be 100644 --- a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll +++ b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll @@ -786,83 +786,6 @@ end: ret void } -define void @non_alloca(ptr %p) { -; CHECK-LABEL: define void @non_alloca -entry: -; CHECK: entry: -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - %x = alloca i8, align 4 - %y = alloca i8, align 4 - - call void @llvm.lifetime.start.p0(i64 4, ptr %p) -; CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %p) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - call void @llvm.lifetime.start.p0(i64 4, ptr %x) -; CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %x) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - call void @llvm.lifetime.end.p0(i64 4, ptr %p) -; CHECK: call void @llvm.lifetime.end.p0(i64 4, ptr %p) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - ret void -} - -define void @select_alloca(i1 %v) { -; CHECK-LABEL: define void @select_alloca -entry: -; CHECK: entry: -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - %x = alloca i8, align 4 - %y = alloca i8, align 4 - %cxcy = select i1 %v, ptr %x, ptr %y - - call void @llvm.lifetime.start.p0(i64 1, ptr %cxcy) -; CHECK: call void @llvm.lifetime.start.p0(i64 1, ptr %cxcy) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - call void @llvm.lifetime.start.p0(i64 1, ptr %x) -; CHECK: call void @llvm.lifetime.start.p0(i64 1, ptr %x) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - call void @llvm.lifetime.end.p0(i64 1, ptr %x) -; CHECK: call void @llvm.lifetime.end.p0(i64 1, ptr %x) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - ret void -} - -define void @alloca_offset() { -; CHECK-LABEL: define void @alloca_offset -entry: -; CHECK: entry: -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - %x = alloca [5 x i32], align 4 - %x2 = getelementptr [5 x i32], ptr %x, i64 0, i64 1 - - call void @llvm.lifetime.start.p0(i64 20, ptr %x2) -; CHECK: call void @llvm.lifetime.start.p0(i64 20, ptr %x2) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - call void @llvm.lifetime.end.p0(i64 20, ptr %x2) -; CHECK: call void @llvm.lifetime.end.p0(i64 20, ptr %x2) -; MAY-NEXT: Alive: -; MUST-NEXT: Alive: <> - - ret void -} - define void @alloca_size() { ; CHECK-LABEL: define void @alloca_size entry: diff --git a/llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll b/llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll new file mode 100644 index 0000000000000..00ab93470c193 --- /dev/null +++ b/llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S < %s | FileCheck %s + +define void @strip_bitcast() { +; CHECK-LABEL: define void @strip_bitcast() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: [[B:%.*]] = bitcast ptr [[A]] to ptr +; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: ret void +; + %a = alloca i8 + %b = bitcast ptr %a to ptr + call void @llvm.lifetime.start.p0(i64 1, ptr %b) + call void @llvm.lifetime.end.p0(i64 1, ptr %b) + ret void +} + +define void @strip_addrspacecast() { +; CHECK-LABEL: define void @strip_addrspacecast() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: [[B:%.*]] = addrspacecast ptr [[A]] to ptr addrspace(1) +; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: ret void +; + %a = alloca i8 + %b = addrspacecast ptr %a to ptr addrspace(1) + call void @llvm.lifetime.start.p1(i64 1, ptr addrspace(1) %b) + call void @llvm.lifetime.end.p1(i64 1, ptr addrspace(1) %b) + ret void +} + +define void @strip_gep() { +; CHECK-LABEL: define void @strip_gep() { +; CHECK-NEXT: [[A:%.*]] = alloca [2 x i8], align 1 +; CHECK-NEXT: [[B:%.*]] = getelementptr [2 x i8], ptr [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: ret void +; + %a = alloca [2 x i8] + %b = getelementptr [2 x i8], ptr %a, i64 0, i64 0 + call void @llvm.lifetime.start.p0(i64 1, ptr %b) + call void @llvm.lifetime.end.p0(i64 1, ptr %b) + ret void +} + +define void @remove_unanalyzable(ptr %p) { +; CHECK-LABEL: define void @remove_unanalyzable( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: ret void +; + call void @llvm.lifetime.start.p0(i64 1, ptr %p) + call void @llvm.lifetime.end.p0(i64 1, ptr %p) + ret void +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-switch-split.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-switch-split.ll index 55cf48ed2245f..d1a6584a331c1 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-switch-split.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-switch-split.ll @@ -9,7 +9,7 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0 declare i32 @logg(...) -define i32 @scanfile(i32 %call148) { +define i32 @scanfile(i32 %call148, ptr %p) { ; CHECK-LABEL: scanfile: ; CHECK: ; %bb.0: ; %entry ; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill @@ -26,7 +26,7 @@ define i32 @scanfile(i32 %call148) { ; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload ; CHECK-NEXT: ret ; CHECK-NEXT: LBB0_3: ; %entry -; CHECK-NEXT: b.eq LBB0_2 +; CHECK-NEXT: b.eq LBB0_10 ; CHECK-NEXT: ; %bb.4: ; %entry ; CHECK-NEXT: cmp w8, #2 ; CHECK-NEXT: b.eq LBB0_6 @@ -46,6 +46,10 @@ define i32 @scanfile(i32 %call148) { ; CHECK-NEXT: LBB0_9: ; %sw.bb150 ; CHECK-NEXT: bl _logg ; CHECK-NEXT: brk #0x1 +; CHECK-NEXT: LBB0_10: ; %sw.bb178 +; CHECK-NEXT: str wzr, [x1] +; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; CHECK-NEXT: ret entry: switch i32 %call148, label %common.ret [ i32 -1, label %sw.bb @@ -80,7 +84,7 @@ sw.bb152: ; preds = %entry br label %common.ret sw.bb178: ; preds = %entry - call void @llvm.lifetime.start.p0(i64 0, ptr null) + store i32 0, ptr %p br label %common.ret } diff --git a/llvm/test/CodeGen/AArch64/stack-tagging.ll b/llvm/test/CodeGen/AArch64/stack-tagging.ll index 8759fb12bea77..5d73c7ba968aa 100644 --- a/llvm/test/CodeGen/AArch64/stack-tagging.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging.ll @@ -143,54 +143,4 @@ l: ; CHECK-NOT: @llvm.aarch64.irg.sp ; CHECK: ret void -; If we can't trace one of the lifetime markers to a single alloca, fall back -; to poisoning all allocas at the beginning of the function. -; Each alloca must be poisoned only once. -define void @UnrecognizedLifetime(i8 %v) sanitize_memtag { -entry: - %x = alloca i32, align 4 - %y = alloca i32, align 4 - %z = alloca i32, align 4 - %tobool = icmp eq i8 %v, 0 - %xy = select i1 %tobool, ptr %x, ptr %y - %cxcy = select i1 %tobool, ptr %x, ptr %y - br label %another_bb - -another_bb: - call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z) - store i32 7, ptr %z - call void @noUse32(ptr %z) - call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z) - call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z) - store i32 7, ptr %z - call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z) - call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cxcy) - store i32 8, ptr %xy - call void @noUse32(ptr %x) - call void @noUse32(ptr %y) - call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cxcy) - ret void -} - -; CHECK-LABEL: define void @UnrecognizedLifetime( -; CHECK: call ptr @llvm.aarch64.irg.sp(i64 0) -; CHECK: alloca { i32, [12 x i8] }, align 16 -; CHECK: call ptr @llvm.aarch64.tagp -; CHECK: call void @llvm.aarch64.settag( -; CHECK: alloca { i32, [12 x i8] }, align 16 -; CHECK: call ptr @llvm.aarch64.tagp -; CHECK: call void @llvm.aarch64.settag( -; CHECK: alloca { i32, [12 x i8] }, align 16 -; CHECK: call ptr @llvm.aarch64.tagp -; CHECK: call void @llvm.aarch64.settag( -; CHECK: store i32 -; CHECK: call void @noUse32(ptr -; CHECK: store i32 -; CHECK: store i32 -; CHECK: call void @noUse32(ptr -; CHECK: call void @llvm.aarch64.settag( -; CHECK: call void @llvm.aarch64.settag( -; CHECK: call void @llvm.aarch64.settag( -; CHECK: ret void - !0 = !{} diff --git a/llvm/test/CodeGen/Thumb2/ifcvt-rescan-bug-2016-08-22.ll b/llvm/test/CodeGen/Thumb2/ifcvt-rescan-bug-2016-08-22.ll index 9acdd7e4a8adb..b70505cad4711 100644 --- a/llvm/test/CodeGen/Thumb2/ifcvt-rescan-bug-2016-08-22.ll +++ b/llvm/test/CodeGen/Thumb2/ifcvt-rescan-bug-2016-08-22.ll @@ -17,6 +17,7 @@ declare void @_ZNSsC1EPKcRKSaIcE() unnamed_addr #0 ; CHECK: .LBB0_2 ; Function Attrs: nounwind define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttributesEPKNS_5SUnitENS_13SUnitIteratorEPKNS_11ScheduleDAGE() #0 align 2 { + %a = alloca i8 br i1 undef, label %1, label %2 ;