[IR] Only allow lifetime.start/end on allocas (#149310)

lifetime.start and lifetime.end are primarily intended for use on
allocas, to enable stack coloring and other liveness optimizations. This
is necessary because all (static) allocas are hoisted into the entry
block, so lifetime markers are the only way to convey the actual
lifetimes.

However, lifetime.start and lifetime.end are currently *allowed* to be
used on non-alloca pointers. We don't actually do this in practice, but
just the mere fact that this is possible breaks the core purpose of the
lifetime markers, which is stack coloring of allocas. Stack coloring can
only work correctly if all lifetime markers for an alloca are
analyzable.

* If a lifetime marker may operate on multiple allocas via a select/phi,
we don't know which lifetime actually starts/ends and handle it
incorrectly (https://github.com/llvm/llvm-project/issues/104776).
* Stack coloring operates on the assumption that all lifetime markers
are visible, and not, for example, hidden behind a function call or
escaped pointer. It's not possible to change this, as part of the
purpose of lifetime markers is that they work even in the presence of
escaped pointers, where simple use analysis is insufficient.

I don't think there is any way to have coherent semantics for lifetime
markers on allocas, while also permitting them on arbitrary pointer
values.

This PR restricts lifetimes to operate on allocas only. As a followup, I
will also drop the size argument, which is superfluous if we always
operate on an alloca. (This change also renders various code handling
lifetime markers on non-alloca dead. I plan to clean up that kind of
code after dropping the size argument as well.)

In practice, I've only found a few places that currently produce
lifetimes on non-allocas:

* CoroEarly replaces the promise alloca with the result of an intrinsic,
which will later be replaced back with an alloca. I think this is the
only place where there is some legitimate loss of functionality, but I
don't think this is particularly important (I don't think we'd expect
the promise in a coroutine to admit useful lifetime optimization.)
* SafeStack moves unsafe allocas onto a separate frame. We can safely
drop lifetimes here, as SafeStack performs its own stack coloring.
* Similar for AddressSanitizer, it also moves allocas into separate
memory.
* LSR sometimes replaces the lifetime argument with a GEP chain of the
alloca (where the offsets ultimately cancel out). This is just
unnecessary. (Fixed separately in
https://github.com/llvm/llvm-project/pull/149492.)
* InferAddrSpaces sometimes makes lifetimes operate on an addrspacecast
of an alloca. I don't think this is necessary.
This commit is contained in:
Nikita Popov 2025-07-21 15:04:50 +02:00 committed by GitHub
parent b78b16b213
commit 92c55a315e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
63 changed files with 376 additions and 1085 deletions

View File

@ -26639,19 +26639,14 @@ Arguments:
The first argument is a constant integer representing the size of the 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 object, or -1 if it is variable sized. The second argument is a pointer
to the object. to an ``alloca`` instruction.
Semantics: Semantics:
"""""""""" """"""""""
If ``ptr`` is a stack-allocated object and it points to the first byte of The stack-allocated object that ``ptr`` points to is initially marked as dead.
the object, the object is initially marked as dead. After '``llvm.lifetime.start``', the stack object is marked as alive and has an
``ptr`` is conservatively considered as a non-stack-allocated object if uninitialized value.
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 object is marked as dead when either The stack object is marked as dead when either
:ref:`llvm.lifetime.end <int_lifeend>` to the alloca is executed or the :ref:`llvm.lifetime.end <int_lifeend>` to the alloca is executed or the
function returns. function returns.
@ -26661,11 +26656,6 @@ After :ref:`llvm.lifetime.end <int_lifeend>` is called,
The second '``llvm.lifetime.start``' call marks the object as alive, but it The second '``llvm.lifetime.start``' call marks the object as alive, but it
does not change the address of the object. 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: .. _int_lifeend:
'``llvm.lifetime.end``' Intrinsic '``llvm.lifetime.end``' Intrinsic
@ -26689,24 +26679,16 @@ Arguments:
The first argument is a constant integer representing the size of the 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 object, or -1 if it is variable sized. The second argument is a pointer
to the object. to an ``alloca`` instruction.
Semantics: Semantics:
"""""""""" """"""""""
If ``ptr`` is a stack-allocated object and it points to the first byte of the The stack-allocated object that ``ptr`` points to becomes dead after the call
object, the object is dead. to this intrinsic.
``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.
Calling ``llvm.lifetime.end`` on an already dead alloca is no-op. 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 '``llvm.invariant.start``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -7124,9 +7124,11 @@ Error BitcodeReader::materializeModule() {
if (CallInst *CI = dyn_cast<CallInst>(U)) if (CallInst *CI = dyn_cast<CallInst>(U))
UpgradeIntrinsicCall(CI, I.second); UpgradeIntrinsicCall(CI, I.second);
} }
if (!I.first->use_empty()) if (I.first != I.second) {
I.first->replaceAllUsesWith(I.second); if (!I.first->use_empty())
I.first->eraseFromParent(); I.first->replaceAllUsesWith(I.second);
I.first->eraseFromParent();
}
} }
UpgradedIntrinsics.clear(); UpgradedIntrinsics.clear();

View File

@ -614,6 +614,13 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack(
Use &U = *AI->use_begin(); Use &U = *AI->use_begin();
Instruction *User = cast<Instruction>(U.getUser()); Instruction *User = cast<Instruction>(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; Instruction *InsertBefore;
if (auto *PHI = dyn_cast<PHINode>(User)) if (auto *PHI = dyn_cast<PHINode>(User))
InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); InsertBefore = PHI->getIncomingBlock(U)->getTerminator();

View File

@ -1310,6 +1310,18 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
return true; return true;
} }
break; 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': { case 'm': {
// Updating the memory intrinsics (memcpy/memmove/memset) that have an // Updating the memory intrinsics (memcpy/memmove/memset) that have an
// alignment parameter to embedding the alignment as an attribute of // alignment parameter to embedding the alignment as an attribute of
@ -1629,7 +1641,6 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
NewFn = nullptr; NewFn = nullptr;
bool Upgraded = bool Upgraded =
upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords); upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords);
assert(F != NewFn && "Intrinsic function upgraded to the same function");
// Upgrade intrinsic attributes. This does not change the function. // Upgrade intrinsic attributes. This does not change the function.
if (NewFn) if (NewFn)
@ -4570,6 +4581,9 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
} }
const auto &DefaultCase = [&]() -> void { const auto &DefaultCase = [&]() -> void {
if (F == NewFn)
return;
if (CI->getFunctionType() == NewFn->getFunctionType()) { if (CI->getFunctionType() == NewFn->getFunctionType()) {
// Handle generic mangling change. // Handle generic mangling change.
assert( assert(
@ -5109,6 +5123,31 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
MTI->setSourceAlignment(Align->getMaybeAlignValue()); MTI->setSourceAlignment(Align->getMaybeAlignValue());
break; break;
} }
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end: {
Value *Size = CI->getArgOperand(0);
Value *Ptr = CI->getArgOperand(1);
if (isa<AllocaInst>(Ptr)) {
DefaultCase();
return;
}
// Try to strip pointer casts, such that the lifetime works on an alloca.
Ptr = Ptr->stripPointerCasts();
if (isa<AllocaInst>(Ptr)) {
// Don't use NewFn, as we might have looked through an addrspacecast.
if (NewFn->getIntrinsicID() == Intrinsic::lifetime_start)
NewCall = Builder.CreateLifetimeStart(Ptr, cast<ConstantInt>(Size));
else
NewCall = Builder.CreateLifetimeEnd(Ptr, cast<ConstantInt>(Size));
break;
}
// Otherwise remove the lifetime marker.
CI->eraseFromParent();
return;
}
} }
assert(NewCall && "Should have either set this variable or returned through " assert(NewCall && "Should have either set this variable or returned through "
"the default case"); "the default case");
@ -5131,7 +5170,8 @@ void llvm::UpgradeCallsToIntrinsic(Function *F) {
UpgradeIntrinsicCall(CB, NewFn); UpgradeIntrinsicCall(CB, NewFn);
// Remove old function, no longer used, from the module. // Remove old function, no longer used, from the module.
F->eraseFromParent(); if (F != NewFn)
F->eraseFromParent();
} }
} }

View File

@ -6720,6 +6720,11 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
"llvm.threadlocal.address operand isThreadLocal() must be true"); "llvm.threadlocal.address operand isThreadLocal() must be true");
break; break;
} }
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
Check(isa<AllocaInst>(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. // Verify that there aren't any unmediated control transfers between funclets.

View File

@ -380,7 +380,7 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
bool Changed = false; bool Changed = false;
const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F); const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
for (BasicBlock &BB : *F) { for (BasicBlock &BB : *F) {
for (Instruction &I : BB) { for (Instruction &I : make_early_inc_range(BB)) {
auto Call = dyn_cast<CallInst>(&I); auto Call = dyn_cast<CallInst>(&I);
if (!Call) if (!Call)
continue; continue;
@ -408,12 +408,16 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
if (!STI.isShader()) { if (!STI.isShader()) {
Changed |= toSpvOverloadedIntrinsic( Changed |= toSpvOverloadedIntrinsic(
II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1}); II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1});
} else {
II->eraseFromParent();
} }
break; break;
case Intrinsic::lifetime_end: case Intrinsic::lifetime_end:
if (!STI.isShader()) { if (!STI.isShader()) {
Changed |= toSpvOverloadedIntrinsic( Changed |= toSpvOverloadedIntrinsic(
II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1}); II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1});
} else {
II->eraseFromParent();
} }
break; break;
case Intrinsic::ptr_annotation: case Intrinsic::ptr_annotation:

View File

@ -170,6 +170,12 @@ void Lowerer::hidePromiseAlloca(CoroIdInst *CoroId, CoroBeginInst *CoroBegin) {
auto *PI = Builder.CreateIntrinsic( auto *PI = Builder.CreateIntrinsic(
Builder.getPtrTy(), Intrinsic::coro_promise, Arg, {}, "promise.addr"); Builder.getPtrTy(), Intrinsic::coro_promise, Arg, {}, "promise.addr");
PI->setCannotDuplicate(); PI->setCannotDuplicate();
// Remove lifetime markers, as these are only allowed on allocas.
for (User *U : make_early_inc_range(PA->users())) {
auto *I = cast<Instruction>(U);
if (I->isLifetimeStartOrEnd())
I->eraseFromParent();
}
PA->replaceUsesWithIf(PI, [CoroId](Use &U) { PA->replaceUsesWithIf(PI, [CoroId](Use &U) {
bool IsBitcast = U == U.getUser()->stripPointerCasts(); bool IsBitcast = U == U.getUser()->stripPointerCasts();
bool IsCoroId = U.getUser() == CoroId; bool IsCoroId = U.getUser() == CoroId;

View File

@ -3637,6 +3637,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
"Variable descriptions relative to ASan stack base will be dropped"); "Variable descriptions relative to ASan stack base will be dropped");
// Replace Alloca instructions with base+offset. // Replace Alloca instructions with base+offset.
SmallVector<Value *> NewAllocaPtrs;
for (const auto &Desc : SVD) { for (const auto &Desc : SVD) {
AllocaInst *AI = Desc.AI; AllocaInst *AI = Desc.AI;
replaceDbgDeclare(AI, LocalStackBaseAllocaPtr, DIB, DIExprFlags, replaceDbgDeclare(AI, LocalStackBaseAllocaPtr, DIB, DIExprFlags,
@ -3645,6 +3646,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)), IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)),
AI->getType()); AI->getType());
AI->replaceAllUsesWith(NewAllocaPtr); AI->replaceAllUsesWith(NewAllocaPtr);
NewAllocaPtrs.push_back(NewAllocaPtr);
} }
// The left-most redzone has enough space for at least 4 pointers. // 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<Instruction>(U);
if (I->isLifetimeStartOrEnd())
I->eraseFromParent();
}
}
SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0); SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0);
SmallVector<uint8_t, 64> ShadowAfterReturn; SmallVector<uint8_t, 64> ShadowAfterReturn;
@ -3829,6 +3840,13 @@ void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) {
Value *NewAddressPtr = IRB.CreateIntToPtr(NewAddress, AI->getType()); 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<Instruction>(U);
if (I->isLifetimeStartOrEnd())
I->eraseFromParent();
}
// Replace all uses of AddessReturnedByAlloca with NewAddressPtr. // Replace all uses of AddessReturnedByAlloca with NewAddressPtr.
AI->replaceAllUsesWith(NewAddressPtr); AI->replaceAllUsesWith(NewAddressPtr);

View File

@ -430,6 +430,8 @@ bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *II,
} }
case Intrinsic::lifetime_start: case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end: { case Intrinsic::lifetime_end: {
// Always force lifetime markers to work directly on the alloca.
NewV = NewV->stripPointerCasts();
Function *NewDecl = Intrinsic::getOrInsertDeclaration( Function *NewDecl = Intrinsic::getOrInsertDeclaration(
M, II->getIntrinsicID(), {NewV->getType()}); M, II->getIntrinsicID(), {NewV->getType()});
II->setArgOperand(1, NewV); II->setArgOperand(1, NewV);

View File

@ -67,27 +67,33 @@ define i8 @test2a(ptr %P) {
ret i8 %A ret i8 %A
} }
define void @test3(ptr %P, i8 %X) { define void @test3(i8 %X) {
; CHECK-LABEL: @test3( ; 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: call void @llvm.lifetime.end.p0(i64 1, ptr [[P]])
; CHECK-NEXT: store i8 2, ptr [[P2]], align 1 ; CHECK-NEXT: store i8 2, ptr [[P2]], align 1
; CHECK-NEXT: call void @external(ptr [[P]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%P = alloca i64
%Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead.
%P2 = getelementptr i8, ptr %P, i32 2 %P2 = getelementptr i8, ptr %P, i32 2
store i8 %Y, ptr %P2 ;; Not read by lifetime.end, should be removed. store i8 %Y, ptr %P2 ;; Not read by lifetime.end, should be removed.
call void @llvm.lifetime.end.p0(i64 1, ptr %P) call void @llvm.lifetime.end.p0(i64 1, ptr %P)
store i8 2, ptr %P2 store i8 2, ptr %P2
call void @external(ptr %P)
ret void ret void
} }
define void @test3a(ptr %P, i8 %X) { define void @test3a(i8 %X) {
; CHECK-LABEL: @test3a( ; 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 ; CHECK-NEXT: ret void
; ;
%P = alloca i64
%Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead.
%P2 = getelementptr i8, ptr %P, i32 2 %P2 = getelementptr i8, ptr %P, i32 2

View File

@ -10,7 +10,7 @@
; CHECK-EMPTY: ; CHECK-EMPTY:
; CHECK-NEXT: Call graph node for function: 'bitcast_only'<<{{.*}}>> #uses=0 ; CHECK-NEXT: Call graph node for function: 'bitcast_only'<<{{.*}}>> #uses=0
; CHECK-EMPTY: ; 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-EMPTY:
; CHECK-NEXT: Call graph node for function: 'llvm.memset.p0.i64'<<{{.*}}>> #uses=2 ; CHECK-NEXT: Call graph node for function: 'llvm.memset.p0.i64'<<{{.*}}>> #uses=2
; CHECK-EMPTY: ; CHECK-EMPTY:
@ -25,18 +25,11 @@
; CHECK-NEXT: Call graph node for function: 'used_by_lifetime'<<{{.*}}>> #uses=0 ; CHECK-NEXT: Call graph node for function: 'used_by_lifetime'<<{{.*}}>> #uses=0
; CHECK-NEXT: CS<{{.*}}> calls function 'llvm.lifetime.start.p0' ; CHECK-NEXT: CS<{{.*}}> calls function 'llvm.lifetime.start.p0'
; CHECK-EMPTY: ; 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() { define internal void @used_by_lifetime() {
entry: entry:
call void @llvm.lifetime.start.p0(i64 4, ptr @used_by_lifetime) %a = alloca i8
ret void call void @llvm.lifetime.start.p0(i64 4, ptr %a)
}
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))
ret void ret void
} }

View File

@ -4,6 +4,7 @@
define i32 @trivially_free() { define i32 @trivially_free() {
; CHECK-SIZE-LABEL: '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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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 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-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
; ;
; CHECK-THROUGHPUT-LABEL: 'trivially_free' ; 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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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: 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 ; 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) %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef) call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4) 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) %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef) call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr undef) 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) %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) %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) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)

View File

@ -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() { define i32 @trivially_free() {
; CHECK-SIZE-LABEL: '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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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) ; 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-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
; ;
; CHECK-THROUGHPUT-LABEL: 'trivially_free' ; 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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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) ; 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 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 ; 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) %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef) call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4) 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) %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef) call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr undef) 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) %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) %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) %a7 = call i1 @llvm.allow.ubsan.check(i8 123)

View File

@ -4,6 +4,7 @@
define i32 @trivially_free() { define i32 @trivially_free() {
; CHECK-SIZE-LABEL: '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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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 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-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
; ;
; CHECK-THROUGHPUT-LABEL: 'trivially_free' ; 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: %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.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) ; 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: %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: %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: %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.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 undef) ; 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: %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: %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: 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 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 ; 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) %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef) call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4) 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) %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef) %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef) %a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef) call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr undef) 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) %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) %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) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)

View File

@ -2,8 +2,12 @@
; This test checks that lifetime markers are considered clobbers of %P, ; This test checks that lifetime markers are considered clobbers of %P,
; and due to lack of noalias information, of %Q as well. ; 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: entry:
%P = alloca [32 x i8]
%Q = call ptr @obscure(ptr %P)
; CHECK: 1 = MemoryDef(liveOnEntry) ; CHECK: 1 = MemoryDef(liveOnEntry)
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %P) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %P)
call void @llvm.lifetime.start.p0(i64 32, ptr %P) call void @llvm.lifetime.start.p0(i64 32, ptr %P)

View File

@ -30,7 +30,7 @@
; CHECK-NEXT: ; [[NO6:.*]] = MemoryDef([[NO7]]) ; CHECK-NEXT: ; [[NO6:.*]] = MemoryDef([[NO7]])
; CHECK-NEXT: store i16 undef, ptr %e, align 1 ; CHECK-NEXT: store i16 undef, ptr %e, align 1
; CHECK-NEXT: 3 = MemoryDef([[NO6]]) ; 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) { define void @f(i1 %arg) {
entry: entry:
@ -57,7 +57,7 @@ cleanup: ; preds = %lbl3
br i1 %switch, label %cleanup.cont, label %lbl1 br i1 %switch, label %cleanup.cont, label %lbl1
cleanup.cont: ; preds = %cleanup cleanup.cont: ; preds = %cleanup
call void @llvm.lifetime.end.p0(i64 1, ptr null) call void @g()
ret void ret void
if.else: ; preds = %lbl1 if.else: ; preds = %lbl1
@ -65,6 +65,3 @@ if.else: ; preds = %lbl1
} }
declare void @g() declare void @g()
; Function Attrs: argmemonly nounwind willreturn
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)

View File

@ -87,7 +87,7 @@ if.else: ; preds = %lbl1
] ]
if.end12: ; preds = %cleanup.cont11s, %cleanup.cont if.end12: ; preds = %cleanup.cont11s, %cleanup.cont
call void @llvm.lifetime.end.p0(i64 1, ptr undef) call i16 @g(i16 1)
ret void ret void
unreachable: ; preds = %if.else, %for.end5 unreachable: ; preds = %if.else, %for.end5
@ -95,6 +95,3 @@ unreachable: ; preds = %if.else, %for.end5
} }
declare i16 @g(i16) declare i16 @g(i16)
; Function Attrs: argmemonly nounwind willreturn
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)

View File

@ -786,83 +786,6 @@ end:
ret void ret void
} }
define void @non_alloca(ptr %p) {
; CHECK-LABEL: define void @non_alloca
entry:
; CHECK: entry:
; MAY-NEXT: Alive: <x y>
; 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: <x y>
; 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: <x y>
; 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: <x y>
; MUST-NEXT: Alive: <>
ret void
}
define void @select_alloca(i1 %v) {
; CHECK-LABEL: define void @select_alloca
entry:
; CHECK: entry:
; MAY-NEXT: Alive: <x y>
; 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: <x y>
; 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: <x y>
; 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: <x y>
; MUST-NEXT: Alive: <>
ret void
}
define void @alloca_offset() {
; CHECK-LABEL: define void @alloca_offset
entry:
; CHECK: entry:
; MAY-NEXT: Alive: <x>
; 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: <x>
; 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: <x>
; MUST-NEXT: Alive: <>
ret void
}
define void @alloca_size() { define void @alloca_size() {
; CHECK-LABEL: define void @alloca_size ; CHECK-LABEL: define void @alloca_size
entry: entry:

View File

@ -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
}

View File

@ -9,7 +9,7 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0
declare i32 @logg(...) declare i32 @logg(...)
define i32 @scanfile(i32 %call148) { define i32 @scanfile(i32 %call148, ptr %p) {
; CHECK-LABEL: scanfile: ; CHECK-LABEL: scanfile:
; CHECK: ; %bb.0: ; %entry ; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill ; 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: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; CHECK-NEXT: LBB0_3: ; %entry ; CHECK-NEXT: LBB0_3: ; %entry
; CHECK-NEXT: b.eq LBB0_2 ; CHECK-NEXT: b.eq LBB0_10
; CHECK-NEXT: ; %bb.4: ; %entry ; CHECK-NEXT: ; %bb.4: ; %entry
; CHECK-NEXT: cmp w8, #2 ; CHECK-NEXT: cmp w8, #2
; CHECK-NEXT: b.eq LBB0_6 ; CHECK-NEXT: b.eq LBB0_6
@ -46,6 +46,10 @@ define i32 @scanfile(i32 %call148) {
; CHECK-NEXT: LBB0_9: ; %sw.bb150 ; CHECK-NEXT: LBB0_9: ; %sw.bb150
; CHECK-NEXT: bl _logg ; CHECK-NEXT: bl _logg
; CHECK-NEXT: brk #0x1 ; 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: entry:
switch i32 %call148, label %common.ret [ switch i32 %call148, label %common.ret [
i32 -1, label %sw.bb i32 -1, label %sw.bb
@ -80,7 +84,7 @@ sw.bb152: ; preds = %entry
br label %common.ret br label %common.ret
sw.bb178: ; preds = %entry sw.bb178: ; preds = %entry
call void @llvm.lifetime.start.p0(i64 0, ptr null) store i32 0, ptr %p
br label %common.ret br label %common.ret
} }

View File

@ -143,54 +143,4 @@ l:
; CHECK-NOT: @llvm.aarch64.irg.sp ; CHECK-NOT: @llvm.aarch64.irg.sp
; CHECK: ret void ; 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 = !{} !0 = !{}

View File

@ -17,6 +17,7 @@ declare void @_ZNSsC1EPKcRKSaIcE() unnamed_addr #0
; CHECK: .LBB0_2 ; CHECK: .LBB0_2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttributesEPKNS_5SUnitENS_13SUnitIteratorEPKNS_11ScheduleDAGE() #0 align 2 { define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttributesEPKNS_5SUnitENS_13SUnitIteratorEPKNS_11ScheduleDAGE() #0 align 2 {
%a = alloca i8
br i1 undef, label %1, label %2 br i1 undef, label %1, label %2
; <label>:1: ; preds = %0 ; <label>:1: ; preds = %0
@ -25,7 +26,7 @@ define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttri
br label %3 br label %3
; <label>:2: ; preds = %0 ; <label>:2: ; preds = %0
call void @llvm.lifetime.start.p0(i64 1, ptr undef) #0 call void @llvm.lifetime.start.p0(i64 1, ptr %a) #0
call void @_ZNSaIcEC2Ev() #0 call void @_ZNSaIcEC2Ev() #0
br label %3 br label %3

View File

@ -229,9 +229,10 @@ define i32 @expensive_val_operand4(ptr nocapture %a, i32 %b, i32 %y, i1 %cmp) {
} }
; Expensive cold value operand with unsafe-to-sink (due to lifetime-end marker) load (partial slice sinking). ; Expensive cold value operand with unsafe-to-sink (due to lifetime-end marker) load (partial slice sinking).
define i32 @expensive_val_operand5(ptr nocapture %a, i32 %b, i32 %y, i1 %cmp) { define i32 @expensive_val_operand5(i32 %b, i32 %y, i1 %cmp) {
; CHECK-LABEL: @expensive_val_operand5( ; CHECK-LABEL: @expensive_val_operand5(
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[A:%.*]], align 8 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[A]], align 8
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr nonnull [[A]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr nonnull [[A]])
; CHECK-NEXT: [[CMP_FROZEN:%.*]] = freeze i1 [[CMP:%.*]] ; CHECK-NEXT: [[CMP_FROZEN:%.*]] = freeze i1 [[CMP:%.*]]
; CHECK-NEXT: br i1 [[CMP_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]], !prof [[PROF18]] ; CHECK-NEXT: br i1 [[CMP_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]], !prof [[PROF18]]
@ -242,6 +243,7 @@ define i32 @expensive_val_operand5(ptr nocapture %a, i32 %b, i32 %y, i1 %cmp) {
; CHECK-NEXT: [[SEL:%.*]] = phi i32 [ [[X]], [[SELECT_TRUE_SINK]] ], [ [[Y:%.*]], [[TMP0:%.*]] ] ; CHECK-NEXT: [[SEL:%.*]] = phi i32 [ [[X]], [[SELECT_TRUE_SINK]] ], [ [[Y:%.*]], [[TMP0:%.*]] ]
; CHECK-NEXT: ret i32 [[SEL]] ; CHECK-NEXT: ret i32 [[SEL]]
; ;
%a = alloca i32
%load = load i32, ptr %a, align 8 %load = load i32, ptr %a, align 8
call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %a) call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %a)
%x = add i32 %load, %b %x = add i32 %load, %b

View File

@ -47,12 +47,10 @@ define dso_local void @onealloc_noreadback(ptr nocapture %a, ptr nocapture %b) l
entry: entry:
%alloc = alloca [16 x i8], i8 2, align 1 %alloc = alloca [16 x i8], i8 2, align 1
%part2 = getelementptr inbounds [16 x i8], ptr %alloc, i64 1, i64 0 %part2 = getelementptr inbounds [16 x i8], ptr %alloc, i64 1, i64 0
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %alloc) call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloc)
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %part2)
call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %alloc, ptr align 1 %a, i64 16, i1 false) call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %alloc, ptr align 1 %a, i64 16, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %part2, ptr align 1 %b, i64 16, i1 false) tail call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 %part2, ptr align 1 %b, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %alloc) call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloc)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %part2)
ret void ret void
} }
@ -115,8 +113,9 @@ define dso_local void @onealloc_readback_1(ptr nocapture %a, ptr nocapture %b) l
; ;
; AA-LABEL: onealloc_readback_1: ; AA-LABEL: onealloc_readback_1:
; AA: # %bb.0: # %entry ; AA: # %bb.0: # %entry
; AA-NEXT: vmovups (%rsi), %xmm0 ; AA-NEXT: vmovups (%rdi), %xmm0
; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; AA-NEXT: vmovups (%rsi), %xmm0
; AA-NEXT: vmovups %xmm0, (%rdi) ; AA-NEXT: vmovups %xmm0, (%rdi)
; AA-NEXT: retq ; AA-NEXT: retq
entry: entry:

View File

@ -23,7 +23,7 @@ declare i32 @dummyPersonality(...)
define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr @__CxxFrameHandler3 { define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr @__CxxFrameHandler3 {
; CHECK-INLINE-LABEL: define void @FuncletPersonality( ; CHECK-INLINE-LABEL: define void @FuncletPersonality(
; CHECK-INLINE-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR4:[0-9]+]] personality ptr @__CxxFrameHandler3 { ; CHECK-INLINE-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR3:[0-9]+]] personality ptr @__CxxFrameHandler3 {
; CHECK-INLINE-NEXT: entry: ; CHECK-INLINE-NEXT: entry:
; CHECK-INLINE-NEXT: [[TMP0:%.*]] = alloca i64, align 32 ; CHECK-INLINE-NEXT: [[TMP0:%.*]] = alloca i64, align 32
; CHECK-INLINE-NEXT: store i64 0, ptr [[TMP0]], align 8 ; CHECK-INLINE-NEXT: store i64 0, ptr [[TMP0]], align 8
@ -87,7 +87,6 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: call void @__asan_set_shadow_f3(i64 [[TMP38]], i64 1) ; CHECK-INLINE-NEXT: call void @__asan_set_shadow_f3(i64 [[TMP38]], i64 1)
; CHECK-INLINE-NEXT: [[TMP39:%.*]] = add i64 [[TMP29]], 1066 ; CHECK-INLINE-NEXT: [[TMP39:%.*]] = add i64 [[TMP29]], 1066
; CHECK-INLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP39]], i64 1) ; CHECK-INLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP39]], i64 1)
; CHECK-INLINE-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[TMP22]])
; CHECK-INLINE-NEXT: [[TMP40:%.*]] = lshr i64 [[TMP21]], 3 ; CHECK-INLINE-NEXT: [[TMP40:%.*]] = lshr i64 [[TMP21]], 3
; CHECK-INLINE-NEXT: [[TMP41:%.*]] = add i64 [[TMP40]], [[TMP1]] ; CHECK-INLINE-NEXT: [[TMP41:%.*]] = add i64 [[TMP40]], [[TMP1]]
; CHECK-INLINE-NEXT: [[TMP42:%.*]] = inttoptr i64 [[TMP41]] to ptr ; CHECK-INLINE-NEXT: [[TMP42:%.*]] = inttoptr i64 [[TMP41]] to ptr
@ -100,13 +99,12 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP48:%.*]] = icmp sge i8 [[TMP47]], [[TMP43]] ; CHECK-INLINE-NEXT: [[TMP48:%.*]] = icmp sge i8 [[TMP47]], [[TMP43]]
; CHECK-INLINE-NEXT: br i1 [[TMP48]], label [[TMP49:%.*]], label [[TMP50]] ; CHECK-INLINE-NEXT: br i1 [[TMP48]], label [[TMP49:%.*]], label [[TMP50]]
; CHECK-INLINE: 49: ; CHECK-INLINE: 49:
; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP21]]) #[[ATTR8:[0-9]+]] ; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP21]]) #[[ATTR7:[0-9]+]]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: 50: ; CHECK-INLINE: 50:
; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP22]], align 1 ; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP22]], align 1
; CHECK-INLINE-NEXT: [[TMP51:%.*]] = add i64 [[TMP29]], 1066 ; CHECK-INLINE-NEXT: [[TMP51:%.*]] = add i64 [[TMP29]], 1066
; CHECK-INLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP51]], i64 1) ; CHECK-INLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP51]], i64 1)
; CHECK-INLINE-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP22]])
; CHECK-INLINE-NEXT: [[TMP52:%.*]] = alloca i8, i64 96, align 32 ; CHECK-INLINE-NEXT: [[TMP52:%.*]] = alloca i8, i64 96, align 32
; CHECK-INLINE-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP52]] to i64 ; CHECK-INLINE-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP52]] to i64
; CHECK-INLINE-NEXT: [[TMP54:%.*]] = add i64 [[TMP53]], 32 ; CHECK-INLINE-NEXT: [[TMP54:%.*]] = add i64 [[TMP53]], 32
@ -128,7 +126,7 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP66:%.*]] = icmp ne i8 [[TMP65]], 0 ; CHECK-INLINE-NEXT: [[TMP66:%.*]] = icmp ne i8 [[TMP65]], 0
; CHECK-INLINE-NEXT: br i1 [[TMP66]], label [[TMP67:%.*]], label [[TMP68:%.*]] ; CHECK-INLINE-NEXT: br i1 [[TMP66]], label [[TMP67:%.*]], label [[TMP68:%.*]]
; CHECK-INLINE: 67: ; CHECK-INLINE: 67:
; CHECK-INLINE-NEXT: call void @__asan_report_store8(i64 [[TMP59]]) #[[ATTR8]] ; CHECK-INLINE-NEXT: call void @__asan_report_store8(i64 [[TMP59]]) #[[ATTR7]]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: 68: ; CHECK-INLINE: 68:
; CHECK-INLINE-NEXT: store volatile i64 0, ptr [[TMP61]], align 8 ; CHECK-INLINE-NEXT: store volatile i64 0, ptr [[TMP61]], align 8
@ -158,7 +156,7 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP88:%.*]] = icmp sge i8 [[TMP87]], [[TMP83]] ; CHECK-INLINE-NEXT: [[TMP88:%.*]] = icmp sge i8 [[TMP87]], [[TMP83]]
; CHECK-INLINE-NEXT: br i1 [[TMP88]], label [[TMP89:%.*]], label [[TMP90]] ; CHECK-INLINE-NEXT: br i1 [[TMP88]], label [[TMP89:%.*]], label [[TMP90]]
; CHECK-INLINE: 89: ; CHECK-INLINE: 89:
; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP77]]) #[[ATTR8]] ; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP77]]) #[[ATTR7]]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: 90: ; CHECK-INLINE: 90:
; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP79]], align 1 ; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP79]], align 1
@ -185,7 +183,6 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE: ehcleanup: ; CHECK-INLINE: ehcleanup:
; CHECK-INLINE-NEXT: [[TMP98:%.*]] = cleanuppad within none [] ; CHECK-INLINE-NEXT: [[TMP98:%.*]] = cleanuppad within none []
; CHECK-INLINE-NEXT: call void @__asan_unpoison_stack_memory(i64 [[TMP54]], i64 4) [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @__asan_unpoison_stack_memory(i64 [[TMP54]], i64 4) [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[TMP56]])
; CHECK-INLINE-NEXT: [[TMP99:%.*]] = lshr i64 [[TMP54]], 3 ; CHECK-INLINE-NEXT: [[TMP99:%.*]] = lshr i64 [[TMP54]], 3
; CHECK-INLINE-NEXT: [[TMP100:%.*]] = add i64 [[TMP99]], [[TMP1]] ; CHECK-INLINE-NEXT: [[TMP100:%.*]] = add i64 [[TMP99]], [[TMP1]]
; CHECK-INLINE-NEXT: [[TMP101:%.*]] = inttoptr i64 [[TMP100]] to ptr ; CHECK-INLINE-NEXT: [[TMP101:%.*]] = inttoptr i64 [[TMP100]] to ptr
@ -198,12 +195,11 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP107:%.*]] = icmp sge i8 [[TMP106]], [[TMP102]] ; CHECK-INLINE-NEXT: [[TMP107:%.*]] = icmp sge i8 [[TMP106]], [[TMP102]]
; CHECK-INLINE-NEXT: br i1 [[TMP107]], label [[TMP108:%.*]], label [[TMP109]] ; CHECK-INLINE-NEXT: br i1 [[TMP107]], label [[TMP108:%.*]], label [[TMP109]]
; CHECK-INLINE: 108: ; CHECK-INLINE: 108:
; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP54]]) #[[ATTR8]] [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @__asan_report_store1(i64 [[TMP54]]) #[[ATTR7]] [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: 109: ; CHECK-INLINE: 109:
; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP56]], align 1 ; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP56]], align 1
; CHECK-INLINE-NEXT: call void @__asan_poison_stack_memory(i64 [[TMP54]], i64 4) [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @__asan_poison_stack_memory(i64 [[TMP54]], i64 4) [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP56]])
; CHECK-INLINE-NEXT: call void @DeInit(ptr [[TMP14]]) [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @DeInit(ptr [[TMP14]]) [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: [[TMP110:%.*]] = call ptr @__asan_memset(ptr [[TMP16]], i32 0, i64 4) [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: [[TMP110:%.*]] = call ptr @__asan_memset(ptr [[TMP16]], i32 0, i64 4) [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: [[TMP111:%.*]] = call ptr @__asan_memcpy(ptr [[TMP18]], ptr [[TMP16]], i64 4) [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: [[TMP111:%.*]] = call ptr @__asan_memcpy(ptr [[TMP18]], ptr [[TMP16]], i64 4) [ "funclet"(token [[TMP98]]) ]
@ -226,7 +222,7 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP125:%.*]] = icmp sge i8 [[TMP124]], [[TMP120]] ; CHECK-INLINE-NEXT: [[TMP125:%.*]] = icmp sge i8 [[TMP124]], [[TMP120]]
; CHECK-INLINE-NEXT: br i1 [[TMP125]], label [[TMP126:%.*]], label [[TMP127]] ; CHECK-INLINE-NEXT: br i1 [[TMP125]], label [[TMP126:%.*]], label [[TMP127]]
; CHECK-INLINE: 126: ; CHECK-INLINE: 126:
; CHECK-INLINE-NEXT: call void @__asan_report_store_n(i64 [[TMP116]], i64 8) #[[ATTR8]] [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @__asan_report_store_n(i64 [[TMP116]], i64 8) #[[ATTR7]] [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: 127: ; CHECK-INLINE: 127:
; CHECK-INLINE-NEXT: [[TMP128:%.*]] = lshr i64 [[TMP114]], 3 ; CHECK-INLINE-NEXT: [[TMP128:%.*]] = lshr i64 [[TMP114]], 3
@ -241,7 +237,7 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: [[TMP136:%.*]] = icmp sge i8 [[TMP135]], [[TMP131]] ; CHECK-INLINE-NEXT: [[TMP136:%.*]] = icmp sge i8 [[TMP135]], [[TMP131]]
; CHECK-INLINE-NEXT: br i1 [[TMP136]], label [[TMP137:%.*]], label [[EHEXIT]] ; CHECK-INLINE-NEXT: br i1 [[TMP136]], label [[TMP137:%.*]], label [[EHEXIT]]
; CHECK-INLINE: 137: ; CHECK-INLINE: 137:
; CHECK-INLINE-NEXT: call void @__asan_report_store_n(i64 [[TMP114]], i64 8) #[[ATTR8]] [ "funclet"(token [[TMP98]]) ] ; CHECK-INLINE-NEXT: call void @__asan_report_store_n(i64 [[TMP114]], i64 8) #[[ATTR7]] [ "funclet"(token [[TMP98]]) ]
; CHECK-INLINE-NEXT: unreachable ; CHECK-INLINE-NEXT: unreachable
; CHECK-INLINE: ehexit: ; CHECK-INLINE: ehexit:
; CHECK-INLINE-NEXT: store i64 0, ptr [[PTRPARAM]], align 1 ; CHECK-INLINE-NEXT: store i64 0, ptr [[PTRPARAM]], align 1
@ -265,7 +261,7 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-INLINE-NEXT: cleanupret from [[TMP98]] unwind to caller ; CHECK-INLINE-NEXT: cleanupret from [[TMP98]] unwind to caller
; ;
; CHECK-OUTLINE-LABEL: define void @FuncletPersonality( ; CHECK-OUTLINE-LABEL: define void @FuncletPersonality(
; CHECK-OUTLINE-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR4:[0-9]+]] personality ptr @__CxxFrameHandler3 { ; CHECK-OUTLINE-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR3:[0-9]+]] personality ptr @__CxxFrameHandler3 {
; CHECK-OUTLINE-NEXT: entry: ; CHECK-OUTLINE-NEXT: entry:
; CHECK-OUTLINE-NEXT: [[TMP0:%.*]] = alloca i64, align 32 ; CHECK-OUTLINE-NEXT: [[TMP0:%.*]] = alloca i64, align 32
; CHECK-OUTLINE-NEXT: store i64 0, ptr [[TMP0]], align 8 ; CHECK-OUTLINE-NEXT: store i64 0, ptr [[TMP0]], align 8
@ -339,12 +335,10 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f3(i64 [[TMP45]], i64 5) ; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f3(i64 [[TMP45]], i64 5)
; CHECK-OUTLINE-NEXT: [[TMP46:%.*]] = add i64 [[TMP33]], 1066 ; CHECK-OUTLINE-NEXT: [[TMP46:%.*]] = add i64 [[TMP33]], 1066
; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP46]], i64 1) ; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP46]], i64 1)
; CHECK-OUTLINE-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[TMP22]])
; CHECK-OUTLINE-NEXT: call void @__asan_store1(i64 [[TMP21]]) ; CHECK-OUTLINE-NEXT: call void @__asan_store1(i64 [[TMP21]])
; CHECK-OUTLINE-NEXT: store volatile i8 0, ptr [[TMP22]], align 1 ; CHECK-OUTLINE-NEXT: store volatile i8 0, ptr [[TMP22]], align 1
; CHECK-OUTLINE-NEXT: [[TMP47:%.*]] = add i64 [[TMP33]], 1066 ; CHECK-OUTLINE-NEXT: [[TMP47:%.*]] = add i64 [[TMP33]], 1066
; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP47]], i64 1) ; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP47]], i64 1)
; CHECK-OUTLINE-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP22]])
; CHECK-OUTLINE-NEXT: call void @__asan_store8(i64 [[TMP25]]) ; CHECK-OUTLINE-NEXT: call void @__asan_store8(i64 [[TMP25]])
; CHECK-OUTLINE-NEXT: store volatile i64 0, ptr [[TMP26]], align 8 ; CHECK-OUTLINE-NEXT: store volatile i64 0, ptr [[TMP26]], align 8
; CHECK-OUTLINE-NEXT: [[TMPCOPYI64:%.*]] = load i64, ptr [[TMP26]], align 8 ; CHECK-OUTLINE-NEXT: [[TMPCOPYI64:%.*]] = load i64, ptr [[TMP26]], align 8
@ -389,12 +383,10 @@ define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr
; CHECK-OUTLINE-NEXT: [[TMP67:%.*]] = cleanuppad within none [] ; CHECK-OUTLINE-NEXT: [[TMP67:%.*]] = cleanuppad within none []
; CHECK-OUTLINE-NEXT: [[TMP68:%.*]] = add i64 [[TMP33]], 1068 ; CHECK-OUTLINE-NEXT: [[TMP68:%.*]] = add i64 [[TMP33]], 1068
; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP68]], i64 1) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_04(i64 [[TMP68]], i64 1) [ "funclet"(token [[TMP67]]) ]
; CHECK-OUTLINE-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[TMP24]])
; CHECK-OUTLINE-NEXT: call void @__asan_store1(i64 [[TMP23]]) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: call void @__asan_store1(i64 [[TMP23]]) [ "funclet"(token [[TMP67]]) ]
; CHECK-OUTLINE-NEXT: store volatile i8 0, ptr [[TMP24]], align 1 ; CHECK-OUTLINE-NEXT: store volatile i8 0, ptr [[TMP24]], align 1
; CHECK-OUTLINE-NEXT: [[TMP69:%.*]] = add i64 [[TMP33]], 1068 ; CHECK-OUTLINE-NEXT: [[TMP69:%.*]] = add i64 [[TMP33]], 1068
; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP69]], i64 1) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP69]], i64 1) [ "funclet"(token [[TMP67]]) ]
; CHECK-OUTLINE-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP24]])
; CHECK-OUTLINE-NEXT: call void @DeInit(ptr [[TMP14]]) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: call void @DeInit(ptr [[TMP14]]) [ "funclet"(token [[TMP67]]) ]
; CHECK-OUTLINE-NEXT: [[TMP70:%.*]] = call ptr @__asan_memset(ptr [[TMP16]], i32 0, i64 4) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: [[TMP70:%.*]] = call ptr @__asan_memset(ptr [[TMP16]], i32 0, i64 4) [ "funclet"(token [[TMP67]]) ]
; CHECK-OUTLINE-NEXT: [[TMP71:%.*]] = call ptr @__asan_memcpy(ptr [[TMP18]], ptr [[TMP16]], i64 4) [ "funclet"(token [[TMP67]]) ] ; CHECK-OUTLINE-NEXT: [[TMP71:%.*]] = call ptr @__asan_memcpy(ptr [[TMP18]], ptr [[TMP16]], i64 4) [ "funclet"(token [[TMP67]]) ]
@ -495,7 +487,7 @@ nopredecessor:
; Non-Windows personality, ensure no funclet gets attached to asan runtime call. ; Non-Windows personality, ensure no funclet gets attached to asan runtime call.
define void @OtherPersonality(ptr %ptrParam) sanitize_address personality ptr @dummyPersonality { define void @OtherPersonality(ptr %ptrParam) sanitize_address personality ptr @dummyPersonality {
; CHECK-LABEL: define void @OtherPersonality( ; CHECK-LABEL: define void @OtherPersonality(
; CHECK-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR4:[0-9]+]] personality ptr @dummyPersonality { ; CHECK-SAME: ptr [[PTRPARAM:%.*]]) #[[ATTR3:[0-9]+]] personality ptr @dummyPersonality {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__asan_shadow_memory_dynamic_address, align 8 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__asan_shadow_memory_dynamic_address, align 8
; CHECK-NEXT: [[ASAN_LOCAL_STACK_BASE:%.*]] = alloca i64, align 8 ; CHECK-NEXT: [[ASAN_LOCAL_STACK_BASE:%.*]] = alloca i64, align 8

View File

@ -24,7 +24,7 @@ entry:
call void @llvm.lifetime.start.p0(i64 4, ptr %x) call void @llvm.lifetime.start.p0(i64 4, ptr %x)
; CHECK: store i8 4, ptr %{{[0-9]+}} ; CHECK: store i8 4, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.start ; CHECK-NOT: @llvm.lifetime.start
%exception = call ptr @__cxa_allocate_exception(i64 4) %exception = call ptr @__cxa_allocate_exception(i64 4)
invoke void @__cxa_throw(ptr %exception, ptr @_ZTI3ABC, ptr @_ZN3ABCD2Ev) noreturn invoke void @__cxa_throw(ptr %exception, ptr @_ZTI3ABC, ptr @_ZN3ABCD2Ev) noreturn
@ -38,7 +38,7 @@ lpad:
call void @_ZN3ABCD2Ev(ptr nonnull %x) call void @_ZN3ABCD2Ev(ptr nonnull %x)
call void @llvm.lifetime.end.p0(i64 4, ptr %x) call void @llvm.lifetime.end.p0(i64 4, ptr %x)
; CHECK: store i8 -8, ptr %{{[0-9]+}} ; CHECK: store i8 -8, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.end ; CHECK-NOT: @llvm.lifetime.end
resume { ptr, i32 } %0 resume { ptr, i32 } %0
; CHECK: store i64 0, ptr %{{[0-9]+}} ; CHECK: store i64 0, ptr %{{[0-9]+}}
@ -77,7 +77,7 @@ entry:
call void @llvm.lifetime.start.p0(i64 4, ptr %x) call void @llvm.lifetime.start.p0(i64 4, ptr %x)
; CHECK: store i8 4, ptr %{{[0-9]+}} ; CHECK: store i8 4, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.start ; CHECK-NOT: @llvm.lifetime.start
invoke void @_CxxThrowException(ptr %tmp, ptr nonnull @"_TI1?AUABC@@") noreturn invoke void @_CxxThrowException(ptr %tmp, ptr nonnull @"_TI1?AUABC@@") noreturn
to label %unreachable unwind label %ehcleanup to label %unreachable unwind label %ehcleanup
@ -89,7 +89,7 @@ ehcleanup:
call void @"\01??1ABC@@QEAA@XZ"(ptr nonnull %x) [ "funclet"(token %0) ] call void @"\01??1ABC@@QEAA@XZ"(ptr nonnull %x) [ "funclet"(token %0) ]
call void @llvm.lifetime.end.p0(i64 4, ptr %x) call void @llvm.lifetime.end.p0(i64 4, ptr %x)
; CHECK: store i8 -8, ptr %{{[0-9]+}} ; CHECK: store i8 -8, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.end ; CHECK-NOT: @llvm.lifetime.end
cleanupret from %0 unwind to caller cleanupret from %0 unwind to caller
; CHECK: store i64 0, ptr %{{[0-9]+}} ; CHECK: store i64 0, ptr %{{[0-9]+}}

View File

@ -30,7 +30,6 @@ define void @lifetime_no_size(i64 %i) sanitize_address {
; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP9]], 0 ; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP9]], 0
; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr ; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
; CHECK-NEXT: store i64 -868083117767659023, ptr [[TMP11]], align 1 ; CHECK-NEXT: store i64 -868083117767659023, ptr [[TMP11]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TMP2]])
; CHECK-NEXT: [[AI:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP2]], i64 0, i64 [[I]] ; CHECK-NEXT: [[AI:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP2]], i64 0, i64 [[I]]
; CHECK-NEXT: [[TMP12:%.*]] = ptrtoint ptr [[AI]] to i64 ; CHECK-NEXT: [[TMP12:%.*]] = ptrtoint ptr [[AI]] to i64
; CHECK-NEXT: [[TMP13:%.*]] = lshr i64 [[TMP12]], 3 ; CHECK-NEXT: [[TMP13:%.*]] = lshr i64 [[TMP12]], 3
@ -49,7 +48,6 @@ define void @lifetime_no_size(i64 %i) sanitize_address {
; CHECK-NEXT: unreachable ; CHECK-NEXT: unreachable
; CHECK: [[BB23]]: ; CHECK: [[BB23]]:
; CHECK-NEXT: store volatile i8 0, ptr [[AI]], align 4 ; CHECK-NEXT: store volatile i8 0, ptr [[AI]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[TMP2]])
; CHECK-NEXT: store i64 1172321806, ptr [[TMP3]], align 8 ; CHECK-NEXT: store i64 1172321806, ptr [[TMP3]], align 8
; CHECK-NEXT: [[TMP24:%.*]] = add i64 [[TMP9]], 0 ; CHECK-NEXT: [[TMP24:%.*]] = add i64 [[TMP9]], 0
; CHECK-NEXT: [[TMP25:%.*]] = inttoptr i64 [[TMP24]] to ptr ; CHECK-NEXT: [[TMP25:%.*]] = inttoptr i64 [[TMP24]] to ptr
@ -100,7 +98,6 @@ define void @lifetime() sanitize_address {
; CHECK-DEFAULT-NEXT: [[TMP14:%.*]] = add i64 [[TMP11]], 4 ; CHECK-DEFAULT-NEXT: [[TMP14:%.*]] = add i64 [[TMP11]], 4
; CHECK-DEFAULT-NEXT: [[TMP15:%.*]] = inttoptr i64 [[TMP14]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP15:%.*]] = inttoptr i64 [[TMP14]] to ptr
; CHECK-DEFAULT-NEXT: store i8 4, ptr [[TMP15]], align 1 ; CHECK-DEFAULT-NEXT: store i8 4, ptr [[TMP15]], align 1
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr [[TMP4]])
; CHECK-DEFAULT-NEXT: [[TMP16:%.*]] = ptrtoint ptr [[TMP4]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP16:%.*]] = ptrtoint ptr [[TMP4]] to i64
; CHECK-DEFAULT-NEXT: [[TMP17:%.*]] = lshr i64 [[TMP16]], 3 ; CHECK-DEFAULT-NEXT: [[TMP17:%.*]] = lshr i64 [[TMP16]], 3
; CHECK-DEFAULT-NEXT: [[TMP18:%.*]] = add i64 [[TMP17]], 2147450880 ; CHECK-DEFAULT-NEXT: [[TMP18:%.*]] = add i64 [[TMP17]], 2147450880
@ -121,11 +118,9 @@ define void @lifetime() sanitize_address {
; CHECK-DEFAULT-NEXT: [[TMP28:%.*]] = add i64 [[TMP11]], 4 ; CHECK-DEFAULT-NEXT: [[TMP28:%.*]] = add i64 [[TMP11]], 4
; CHECK-DEFAULT-NEXT: [[TMP29:%.*]] = inttoptr i64 [[TMP28]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP29:%.*]] = inttoptr i64 [[TMP28]] to ptr
; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP29]], align 1 ; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP29]], align 1
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP4]])
; CHECK-DEFAULT-NEXT: [[TMP30:%.*]] = add i64 [[TMP11]], 4 ; CHECK-DEFAULT-NEXT: [[TMP30:%.*]] = add i64 [[TMP11]], 4
; CHECK-DEFAULT-NEXT: [[TMP31:%.*]] = inttoptr i64 [[TMP30]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP31:%.*]] = inttoptr i64 [[TMP30]] to ptr
; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP31]], align 1 ; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP31]], align 1
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[TMP4]])
; CHECK-DEFAULT-NEXT: [[TMP32:%.*]] = alloca i8, i64 128, align 32 ; CHECK-DEFAULT-NEXT: [[TMP32:%.*]] = alloca i8, i64 128, align 32
; CHECK-DEFAULT-NEXT: [[TMP33:%.*]] = ptrtoint ptr [[TMP32]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP33:%.*]] = ptrtoint ptr [[TMP32]] to i64
; CHECK-DEFAULT-NEXT: [[TMP34:%.*]] = add i64 [[TMP33]], 32 ; CHECK-DEFAULT-NEXT: [[TMP34:%.*]] = add i64 [[TMP33]], 32
@ -135,7 +130,6 @@ define void @lifetime() sanitize_address {
; CHECK-DEFAULT-NEXT: [[TMP36:%.*]] = inttoptr i64 [[TMP34]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP36:%.*]] = inttoptr i64 [[TMP34]] to ptr
; CHECK-DEFAULT-NEXT: [[TMP37:%.*]] = ptrtoint ptr [[TMP36]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP37:%.*]] = ptrtoint ptr [[TMP36]] to i64
; CHECK-DEFAULT-NEXT: call void @__asan_unpoison_stack_memory(i64 [[TMP37]], i64 40) ; CHECK-DEFAULT-NEXT: call void @__asan_unpoison_stack_memory(i64 [[TMP37]], i64 40)
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr [[TMP36]])
; CHECK-DEFAULT-NEXT: [[TMP38:%.*]] = ptrtoint ptr [[TMP36]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP38:%.*]] = ptrtoint ptr [[TMP36]] to i64
; CHECK-DEFAULT-NEXT: [[TMP39:%.*]] = lshr i64 [[TMP38]], 3 ; CHECK-DEFAULT-NEXT: [[TMP39:%.*]] = lshr i64 [[TMP38]], 3
; CHECK-DEFAULT-NEXT: [[TMP40:%.*]] = add i64 [[TMP39]], 2147450880 ; CHECK-DEFAULT-NEXT: [[TMP40:%.*]] = add i64 [[TMP39]], 2147450880
@ -155,11 +149,9 @@ define void @lifetime() sanitize_address {
; CHECK-DEFAULT-NEXT: store volatile i8 0, ptr [[TMP36]], align 1 ; CHECK-DEFAULT-NEXT: store volatile i8 0, ptr [[TMP36]], align 1
; CHECK-DEFAULT-NEXT: [[TMP50:%.*]] = ptrtoint ptr [[TMP36]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP50:%.*]] = ptrtoint ptr [[TMP36]] to i64
; CHECK-DEFAULT-NEXT: call void @__asan_poison_stack_memory(i64 [[TMP50]], i64 40) ; CHECK-DEFAULT-NEXT: call void @__asan_poison_stack_memory(i64 [[TMP50]], i64 40)
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr [[TMP36]])
; CHECK-DEFAULT-NEXT: [[TMP51:%.*]] = add i64 [[TMP11]], 4 ; CHECK-DEFAULT-NEXT: [[TMP51:%.*]] = add i64 [[TMP11]], 4
; CHECK-DEFAULT-NEXT: [[TMP52:%.*]] = inttoptr i64 [[TMP51]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP52:%.*]] = inttoptr i64 [[TMP51]] to ptr
; CHECK-DEFAULT-NEXT: store i8 4, ptr [[TMP52]], align 1 ; CHECK-DEFAULT-NEXT: store i8 4, ptr [[TMP52]], align 1
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[TMP4]])
; CHECK-DEFAULT-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP4]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP4]] to i64
; CHECK-DEFAULT-NEXT: [[TMP54:%.*]] = lshr i64 [[TMP53]], 3 ; CHECK-DEFAULT-NEXT: [[TMP54:%.*]] = lshr i64 [[TMP53]], 3
; CHECK-DEFAULT-NEXT: [[TMP55:%.*]] = add i64 [[TMP54]], 2147450880 ; CHECK-DEFAULT-NEXT: [[TMP55:%.*]] = add i64 [[TMP54]], 2147450880
@ -180,7 +172,6 @@ define void @lifetime() sanitize_address {
; CHECK-DEFAULT-NEXT: [[TMP65:%.*]] = add i64 [[TMP11]], 4 ; CHECK-DEFAULT-NEXT: [[TMP65:%.*]] = add i64 [[TMP11]], 4
; CHECK-DEFAULT-NEXT: [[TMP66:%.*]] = inttoptr i64 [[TMP65]] to ptr ; CHECK-DEFAULT-NEXT: [[TMP66:%.*]] = inttoptr i64 [[TMP65]] to ptr
; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP66]], align 1 ; CHECK-DEFAULT-NEXT: store i8 -8, ptr [[TMP66]], align 1
; CHECK-DEFAULT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP4]])
; CHECK-DEFAULT-NEXT: [[TMP67:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; CHECK-DEFAULT-NEXT: [[TMP67:%.*]] = ptrtoint ptr [[TMP1]] to i64
; CHECK-DEFAULT-NEXT: [[TMP68:%.*]] = load i64, ptr [[TMP1]], align 8 ; CHECK-DEFAULT-NEXT: [[TMP68:%.*]] = load i64, ptr [[TMP1]], align 8
; CHECK-DEFAULT-NEXT: call void @__asan_allocas_unpoison(i64 [[TMP68]], i64 [[TMP67]]) ; CHECK-DEFAULT-NEXT: call void @__asan_allocas_unpoison(i64 [[TMP68]], i64 [[TMP67]])
@ -212,7 +203,6 @@ define void @lifetime() sanitize_address {
; CHECK-NO-DYNAMIC-NEXT: [[TMP13:%.*]] = add i64 [[TMP10]], 4 ; CHECK-NO-DYNAMIC-NEXT: [[TMP13:%.*]] = add i64 [[TMP10]], 4
; CHECK-NO-DYNAMIC-NEXT: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
; CHECK-NO-DYNAMIC-NEXT: store i8 4, ptr [[TMP14]], align 1 ; CHECK-NO-DYNAMIC-NEXT: store i8 4, ptr [[TMP14]], align 1
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr [[TMP3]])
; CHECK-NO-DYNAMIC-NEXT: [[TMP15:%.*]] = ptrtoint ptr [[TMP3]] to i64 ; CHECK-NO-DYNAMIC-NEXT: [[TMP15:%.*]] = ptrtoint ptr [[TMP3]] to i64
; CHECK-NO-DYNAMIC-NEXT: [[TMP16:%.*]] = lshr i64 [[TMP15]], 3 ; CHECK-NO-DYNAMIC-NEXT: [[TMP16:%.*]] = lshr i64 [[TMP15]], 3
; CHECK-NO-DYNAMIC-NEXT: [[TMP17:%.*]] = add i64 [[TMP16]], 2147450880 ; CHECK-NO-DYNAMIC-NEXT: [[TMP17:%.*]] = add i64 [[TMP16]], 2147450880
@ -233,11 +223,9 @@ define void @lifetime() sanitize_address {
; CHECK-NO-DYNAMIC-NEXT: [[TMP27:%.*]] = add i64 [[TMP10]], 4 ; CHECK-NO-DYNAMIC-NEXT: [[TMP27:%.*]] = add i64 [[TMP10]], 4
; CHECK-NO-DYNAMIC-NEXT: [[TMP28:%.*]] = inttoptr i64 [[TMP27]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP28:%.*]] = inttoptr i64 [[TMP27]] to ptr
; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP28]], align 1 ; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP28]], align 1
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP3]])
; CHECK-NO-DYNAMIC-NEXT: [[TMP29:%.*]] = add i64 [[TMP10]], 4 ; CHECK-NO-DYNAMIC-NEXT: [[TMP29:%.*]] = add i64 [[TMP10]], 4
; CHECK-NO-DYNAMIC-NEXT: [[TMP30:%.*]] = inttoptr i64 [[TMP29]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP30:%.*]] = inttoptr i64 [[TMP29]] to ptr
; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP30]], align 1 ; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP30]], align 1
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[TMP3]])
; CHECK-NO-DYNAMIC-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16 ; CHECK-NO-DYNAMIC-NEXT: [[ARR:%.*]] = alloca [10 x i32], align 16
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr [[ARR]]) ; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr [[ARR]])
; CHECK-NO-DYNAMIC-NEXT: [[TMP31:%.*]] = ptrtoint ptr [[ARR]] to i64 ; CHECK-NO-DYNAMIC-NEXT: [[TMP31:%.*]] = ptrtoint ptr [[ARR]] to i64
@ -261,7 +249,6 @@ define void @lifetime() sanitize_address {
; CHECK-NO-DYNAMIC-NEXT: [[TMP43:%.*]] = add i64 [[TMP10]], 4 ; CHECK-NO-DYNAMIC-NEXT: [[TMP43:%.*]] = add i64 [[TMP10]], 4
; CHECK-NO-DYNAMIC-NEXT: [[TMP44:%.*]] = inttoptr i64 [[TMP43]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP44:%.*]] = inttoptr i64 [[TMP43]] to ptr
; CHECK-NO-DYNAMIC-NEXT: store i8 4, ptr [[TMP44]], align 1 ; CHECK-NO-DYNAMIC-NEXT: store i8 4, ptr [[TMP44]], align 1
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[TMP3]])
; CHECK-NO-DYNAMIC-NEXT: [[TMP45:%.*]] = ptrtoint ptr [[TMP3]] to i64 ; CHECK-NO-DYNAMIC-NEXT: [[TMP45:%.*]] = ptrtoint ptr [[TMP3]] to i64
; CHECK-NO-DYNAMIC-NEXT: [[TMP46:%.*]] = lshr i64 [[TMP45]], 3 ; CHECK-NO-DYNAMIC-NEXT: [[TMP46:%.*]] = lshr i64 [[TMP45]], 3
; CHECK-NO-DYNAMIC-NEXT: [[TMP47:%.*]] = add i64 [[TMP46]], 2147450880 ; CHECK-NO-DYNAMIC-NEXT: [[TMP47:%.*]] = add i64 [[TMP46]], 2147450880
@ -282,7 +269,6 @@ define void @lifetime() sanitize_address {
; CHECK-NO-DYNAMIC-NEXT: [[TMP57:%.*]] = add i64 [[TMP10]], 4 ; CHECK-NO-DYNAMIC-NEXT: [[TMP57:%.*]] = add i64 [[TMP10]], 4
; CHECK-NO-DYNAMIC-NEXT: [[TMP58:%.*]] = inttoptr i64 [[TMP57]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP58:%.*]] = inttoptr i64 [[TMP57]] to ptr
; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP58]], align 1 ; CHECK-NO-DYNAMIC-NEXT: store i8 -8, ptr [[TMP58]], align 1
; CHECK-NO-DYNAMIC-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[TMP3]])
; CHECK-NO-DYNAMIC-NEXT: store i64 1172321806, ptr [[TMP4]], align 8 ; CHECK-NO-DYNAMIC-NEXT: store i64 1172321806, ptr [[TMP4]], align 8
; CHECK-NO-DYNAMIC-NEXT: [[TMP59:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NO-DYNAMIC-NEXT: [[TMP59:%.*]] = add i64 [[TMP10]], 0
; CHECK-NO-DYNAMIC-NEXT: [[TMP60:%.*]] = inttoptr i64 [[TMP59]] to ptr ; CHECK-NO-DYNAMIC-NEXT: [[TMP60:%.*]] = inttoptr i64 [[TMP59]] to ptr
@ -325,166 +311,6 @@ define void @lifetime() sanitize_address {
ret void ret void
} }
; Check that arguments of lifetime may come from phi nodes.
define void @phi_args(i1 %x) sanitize_address {
; CHECK-LABEL: define void @phi_args(
; CHECK-SAME: i1 [[X:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[MYALLOCA:%.*]] = alloca i8, i64 64, align 32
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[MYALLOCA]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 32
; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP0]] to ptr
; CHECK-NEXT: store i64 1102416563, ptr [[TMP3]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP0]], 8
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
; CHECK-NEXT: store i64 ptrtoint (ptr @___asan_gen_stack.2 to i64), ptr [[TMP5]], align 8
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP0]], 16
; CHECK-NEXT: [[TMP7:%.*]] = inttoptr i64 [[TMP6]] to ptr
; CHECK-NEXT: store i64 ptrtoint (ptr @phi_args to i64), ptr [[TMP7]], align 8
; CHECK-NEXT: [[TMP8:%.*]] = lshr i64 [[TMP0]], 3
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[TMP8]], 2147450880
; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP9]], 0
; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
; CHECK-NEXT: store i64 -868082052615769615, ptr [[TMP11]], align 1
; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[TMP9]], 4
; CHECK-NEXT: [[TMP13:%.*]] = inttoptr i64 [[TMP12]] to ptr
; CHECK-NEXT: store i8 0, ptr [[TMP13]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[TMP2]])
; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP2]] to i64
; CHECK-NEXT: [[TMP15:%.*]] = lshr i64 [[TMP14]], 3
; CHECK-NEXT: [[TMP16:%.*]] = add i64 [[TMP15]], 2147450880
; CHECK-NEXT: [[TMP17:%.*]] = inttoptr i64 [[TMP16]] to ptr
; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP17]], align 1
; CHECK-NEXT: [[TMP19:%.*]] = icmp ne i8 [[TMP18]], 0
; CHECK-NEXT: br i1 [[TMP19]], label %[[BB20:.*]], label %[[BB25:.*]], !prof [[PROF1]]
; CHECK: [[BB20]]:
; CHECK-NEXT: [[TMP21:%.*]] = and i64 [[TMP14]], 7
; CHECK-NEXT: [[TMP22:%.*]] = trunc i64 [[TMP21]] to i8
; CHECK-NEXT: [[TMP23:%.*]] = icmp sge i8 [[TMP22]], [[TMP18]]
; CHECK-NEXT: br i1 [[TMP23]], label %[[BB24:.*]], label %[[BB25]]
; CHECK: [[BB24]]:
; CHECK-NEXT: call void @__asan_report_store1(i64 [[TMP14]]) #[[ATTR4]]
; CHECK-NEXT: unreachable
; CHECK: [[BB25]]:
; CHECK-NEXT: store volatile i8 0, ptr [[TMP2]], align 1
; CHECK-NEXT: br i1 [[X]], label %[[BB0:.*]], label %[[BB1:.*]]
; CHECK: [[BB0]]:
; CHECK-NEXT: br label %[[BB1]]
; CHECK: [[BB1]]:
; CHECK-NEXT: [[I_PHI:%.*]] = phi ptr [ [[TMP2]], %[[BB25]] ], [ [[TMP2]], %[[BB0]] ]
; CHECK-NEXT: [[TMP26:%.*]] = add i64 [[TMP9]], 4
; CHECK-NEXT: [[TMP27:%.*]] = inttoptr i64 [[TMP26]] to ptr
; CHECK-NEXT: store i8 -8, ptr [[TMP27]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[I_PHI]])
; CHECK-NEXT: store i64 1172321806, ptr [[TMP3]], align 8
; CHECK-NEXT: [[TMP28:%.*]] = add i64 [[TMP9]], 0
; CHECK-NEXT: [[TMP29:%.*]] = inttoptr i64 [[TMP28]] to ptr
; CHECK-NEXT: store i64 0, ptr [[TMP29]], align 1
; CHECK-NEXT: ret void
;
entry:
%i = alloca i64, align 4
; Poison memory in prologue: F1F1F1F1F8F3F3F3
call void @llvm.lifetime.start.p0(i64 8, ptr %i)
store volatile i8 0, ptr %i
br i1 %x, label %bb0, label %bb1
bb0:
br label %bb1
bb1:
%i.phi = phi ptr [ %i, %entry ], [ %i, %bb0 ]
call void @llvm.lifetime.end.p0(i64 8, ptr %i.phi)
ret void
}
; Check that arguments of lifetime may come from getelementptr nodes.
define void @getelementptr_args(i64 %i) sanitize_address{
; CHECK-LABEL: define void @getelementptr_args(
; CHECK-SAME: i64 [[I:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[MYALLOCA:%.*]] = alloca i8, i64 1216, align 32
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[MYALLOCA]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 32
; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP0]], 1184
; CHECK-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP0]] to ptr
; CHECK-NEXT: store i64 1102416563, ptr [[TMP5]], align 8
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP0]], 8
; CHECK-NEXT: [[TMP7:%.*]] = inttoptr i64 [[TMP6]] to ptr
; CHECK-NEXT: store i64 ptrtoint (ptr @___asan_gen_stack.3 to i64), ptr [[TMP7]], align 8
; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[TMP0]], 16
; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
; CHECK-NEXT: store i64 ptrtoint (ptr @getelementptr_args to i64), ptr [[TMP9]], align 8
; CHECK-NEXT: [[TMP10:%.*]] = lshr i64 [[TMP0]], 3
; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 2147450880
; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[TMP11]], 0
; CHECK-NEXT: [[TMP13:%.*]] = inttoptr i64 [[TMP12]] to ptr
; CHECK-NEXT: store i32 -235802127, ptr [[TMP13]], align 1
; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[TMP11]], 4
; CHECK-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP14]], i64 128)
; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[TMP11]], 132
; CHECK-NEXT: [[TMP16:%.*]] = inttoptr i64 [[TMP15]] to ptr
; CHECK-NEXT: store i64 -940422246894996750, ptr [[TMP16]], align 1
; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[TMP11]], 140
; CHECK-NEXT: [[TMP18:%.*]] = inttoptr i64 [[TMP17]] to ptr
; CHECK-NEXT: store i64 -940422246894996750, ptr [[TMP18]], align 1
; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[TMP11]], 150
; CHECK-NEXT: [[TMP20:%.*]] = inttoptr i64 [[TMP19]] to ptr
; CHECK-NEXT: store i16 -3085, ptr [[TMP20]], align 1
; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[TMP11]], 4
; CHECK-NEXT: call void @__asan_set_shadow_00(i64 [[TMP21]], i64 128)
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1024, ptr [[TMP2]])
; CHECK-NEXT: [[AI:%.*]] = getelementptr inbounds [2 x ptr], ptr [[TMP4]], i64 0, i64 [[I]]
; CHECK-NEXT: [[TMP22:%.*]] = ptrtoint ptr [[AI]] to i64
; CHECK-NEXT: [[TMP23:%.*]] = lshr i64 [[TMP22]], 3
; CHECK-NEXT: [[TMP24:%.*]] = add i64 [[TMP23]], 2147450880
; CHECK-NEXT: [[TMP25:%.*]] = inttoptr i64 [[TMP24]] to ptr
; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP25]], align 1
; CHECK-NEXT: [[TMP27:%.*]] = icmp ne i8 [[TMP26]], 0
; CHECK-NEXT: br i1 [[TMP27]], label %[[BB28:.*]], label %[[BB29:.*]]
; CHECK: [[BB28]]:
; CHECK-NEXT: call void @__asan_report_store8(i64 [[TMP22]]) #[[ATTR4]]
; CHECK-NEXT: unreachable
; CHECK: [[BB29]]:
; CHECK-NEXT: store ptr [[TMP2]], ptr [[AI]], align 8
; CHECK-NEXT: [[TMP30:%.*]] = add i64 [[TMP11]], 4
; CHECK-NEXT: call void @__asan_set_shadow_f8(i64 [[TMP30]], i64 128)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1024, ptr [[TMP2]])
; CHECK-NEXT: store i64 1172321806, ptr [[TMP5]], align 8
; CHECK-NEXT: [[TMP31:%.*]] = add i64 [[TMP11]], 0
; CHECK-NEXT: call void @__asan_set_shadow_00(i64 [[TMP31]], i64 148)
; CHECK-NEXT: [[TMP32:%.*]] = add i64 [[TMP11]], 150
; CHECK-NEXT: [[TMP33:%.*]] = inttoptr i64 [[TMP32]] to ptr
; CHECK-NEXT: store i16 0, ptr [[TMP33]], align 1
; CHECK-NEXT: ret void
;
entry:
%x = alloca [1024 x i8], align 16
%a = alloca [2 x ptr], align 8
; F1F1F1F1
; 0xf2f2f2f2f2f2f2f2
; 0xf2f2f2f2f2f2f2f2
call void @llvm.lifetime.start.p0(i64 1024, ptr %x)
%ai = getelementptr inbounds [2 x ptr], ptr %a, i64 0, i64 %i
store ptr %x, ptr %ai, align 8
call void @llvm.lifetime.end.p0(i64 1024, ptr %x)
ret void
}
define void @zero_sized(i64 %a) #0 { define void @zero_sized(i64 %a) #0 {
; CHECK-LABEL: define void @zero_sized( ; CHECK-LABEL: define void @zero_sized(
; CHECK-SAME: i64 [[A:%.*]]) { ; CHECK-SAME: i64 [[A:%.*]]) {

View File

@ -100,8 +100,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 2, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 2, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 650, ptr %xx)
call void @Foo(ptr %xx) call void @Foo(ptr %xx)
; CHECK-NEXT: call void @Foo(ptr %xx) ; CHECK-NEXT: call void @Foo(ptr %xx)
@ -109,8 +107,6 @@ entry:
; ENTRY-UAS-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4 ; ENTRY-UAS-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82) ; ENTRY-UAS-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 650, ptr %xx)
call void @llvm.lifetime.start.p0(i64 13, ptr %yy) call void @llvm.lifetime.start.p0(i64 13, ptr %yy)
; 0005 ; 0005
@ -118,8 +114,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i16 5, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i16 5, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 13, ptr %yy)
call void @Foo(ptr %yy) call void @Foo(ptr %yy)
; CHECK-NEXT: call void @Foo(ptr %yy) ; CHECK-NEXT: call void @Foo(ptr %yy)
@ -129,8 +123,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i16 -1800, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i16 -1800, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 13, ptr %yy)
call void @llvm.lifetime.start.p0(i64 40, ptr %zz) call void @llvm.lifetime.start.p0(i64 40, ptr %zz)
; 00000000 ; 00000000
@ -142,8 +134,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 0, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 0, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr %zz)
call void @Foo(ptr %zz) call void @Foo(ptr %zz)
; CHECK-NEXT: call void @Foo(ptr %zz) ; CHECK-NEXT: call void @Foo(ptr %zz)
@ -157,8 +147,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 -8, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 -8, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr %zz)
; CHECK: {{^[0-9]+}}: ; CHECK: {{^[0-9]+}}:
; CHECK-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0 ; CHECK-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0

View File

@ -100,8 +100,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 2, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 2, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 650, ptr %xx)
call void @Foo(ptr %xx) call void @Foo(ptr %xx)
; CHECK-NEXT: call void @Foo(ptr %xx) ; CHECK-NEXT: call void @Foo(ptr %xx)
@ -109,8 +107,6 @@ entry:
; ENTRY-UAS-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4 ; ENTRY-UAS-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82) ; ENTRY-UAS-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 650, ptr %xx)
call void @llvm.lifetime.start.p0(i64 13, ptr %yy) call void @llvm.lifetime.start.p0(i64 13, ptr %yy)
; 0005 ; 0005
@ -118,8 +114,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i16 1280, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i16 1280, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 13, ptr %yy)
call void @Foo(ptr %yy) call void @Foo(ptr %yy)
; CHECK-NEXT: call void @Foo(ptr %yy) ; CHECK-NEXT: call void @Foo(ptr %yy)
@ -129,8 +123,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i16 -1800, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i16 -1800, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 13, ptr %yy)
call void @llvm.lifetime.start.p0(i64 40, ptr %zz) call void @llvm.lifetime.start.p0(i64 40, ptr %zz)
; 00000000 ; 00000000
@ -142,8 +134,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 0, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 0, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr %zz)
call void @Foo(ptr %zz) call void @Foo(ptr %zz)
; CHECK-NEXT: call void @Foo(ptr %zz) ; CHECK-NEXT: call void @Foo(ptr %zz)
@ -157,8 +147,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr ; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; ENTRY-UAS-NEXT: store i8 -8, ptr [[PTR]], align 1 ; ENTRY-UAS-NEXT: store i8 -8, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr %zz)
; CHECK: {{^[0-9]+}}: ; CHECK: {{^[0-9]+}}:
; CHECK-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0 ; CHECK-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
@ -209,40 +197,6 @@ entry:
; CHECK: ret void ; CHECK: ret void
} }
declare void @foo(ptr)
define void @PR41481(i1 %b) sanitize_address {
; CHECK-LABEL: @PR41481
entry:
%p1 = alloca i32
%p2 = alloca i32
br label %bb1
; Since we cannot account for all lifetime intrinsics in this function, we
; might have missed a lifetime.start one and therefore shouldn't poison the
; allocas at function entry.
; ENTRY: store i64 -935356719533264399
; ENTRY-UAS: store i64 -935356719533264399
bb1:
%p = select i1 %b, ptr %p1, ptr %p2
%q = select i1 %b, ptr %p1, ptr %p2
call void @llvm.lifetime.start.p0(i64 4, ptr %q)
call void @foo(ptr %p)
br i1 %b, label %bb2, label %bb3
bb2:
call void @llvm.lifetime.end.p0(i64 4, ptr %p1)
br label %end
bb3:
call void @llvm.lifetime.end.p0(i64 4, ptr %p2)
br label %end
end:
ret void
}
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) declare void @llvm.lifetime.end.p0(i64, ptr nocapture)

View File

@ -176,78 +176,5 @@ entry:
; CHECK: call void @llvm.lifetime.end ; CHECK: call void @llvm.lifetime.end
; CHECK: ret void ; CHECK: ret void
; If we can't trace one of the lifetime markers to a single alloca, fall back
; to poisoning allocas at the beginning of the function.
; Each alloca must be poisoned only once.
define void @lifetime_no_alloca(i8 %v) sanitize_memory {
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 @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 @llvm.lifetime.end.p0(i64 4, ptr nonnull %cxcy)
ret void
}
; CHECK-LABEL: define void @lifetime_no_alloca(
; CHECK-LABEL: entry:
; CHECK: %x = alloca i32
; INLINE: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; CHECK: %y = alloca i32
; INLINE: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; CHECK: %z = alloca i32
; INLINE: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; There're two lifetime intrinsics for %z, but we must instrument it only once.
; INLINE-NOT: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL-NOT: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN-NOT: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; CHECK-LABEL: another_bb:
; CHECK: call void @llvm.lifetime.start
; INLINE-NOT: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL-NOT: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN-NOT: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; CHECK: call void @llvm.lifetime.end
; CHECK: call void @llvm.lifetime.start
; INLINE-NOT: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 -1, i64 4, i1 false)
; CALL-NOT: call void @__msan_poison_stack(ptr {{.*}}, i64 4)
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(ptr {{.*}}, i64 4,
; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(ptr {{.*}}, i64 4,
; KMSAN-NOT: call void @__msan_poison_alloca(ptr {{.*}}, i64 4,
; CHECK: call void @llvm.lifetime.end
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)

View File

@ -393,26 +393,6 @@ bb:
ret i32 %i2 ret i32 %i2
} }
define i32 @test_lifetime() {
; CHECK-LABEL: define {{[^@]+}}@test_lifetime() {
; CHECK-NEXT: bb:
; CHECK-NEXT: [[I_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nofree nonnull align 4 captures(none) dereferenceable(4) [[I_H2S]])
; CHECK-NEXT: store i32 10, ptr [[I_H2S]], align 4
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I_H2S]], align 4
; CHECK-NEXT: ret i32 [[I2]]
;
bb:
%i = tail call noalias ptr @malloc(i64 4)
tail call void @no_sync_func(ptr %i)
call void @llvm.lifetime.start.p0(i64 4, ptr %i)
store i32 10, ptr %i, align 4
%i2 = load i32, ptr %i, align 4
tail call void @free(ptr %i)
ret i32 %i2
}
; TEST 11 ; TEST 11
define void @test11() { define void @test11() {

View File

@ -340,27 +340,6 @@ bb:
ret i32 %i2 ret i32 %i2
} }
define i32 @test_lifetime() {
; CHECK-LABEL: define {{[^@]+}}@test_lifetime() {
; CHECK-NEXT: bb:
; CHECK-NEXT: [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
; CHECK-NEXT: tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nofree nonnull align 4 captures(none) dereferenceable(4) [[I]])
; CHECK-NEXT: store i32 10, ptr [[I]], align 4
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[I]], align 4
; CHECK-NEXT: tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])
; CHECK-NEXT: ret i32 [[I2]]
;
bb:
%i = tail call noalias ptr @malloc(i64 4)
tail call void @no_sync_func(ptr %i)
call void @llvm.lifetime.start.p0(i64 4, ptr %i)
store i32 10, ptr %i, align 4
%i2 = load i32, ptr %i, align 4
tail call void @free(ptr %i)
ret i32 %i2
}
; TEST 11 ; TEST 11
define void @test11() { define void @test11() {

View File

@ -18,11 +18,11 @@ bb:
br i1 %tmp4, label %bb6, label %bb5 br i1 %tmp4, label %bb6, label %bb5
bb5: ; preds = %bb bb5: ; preds = %bb
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %tmp1) #2 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %tmp) #2
store i32 %tmp3, ptr %tmp, align 4, !tbaa !2 store i32 %tmp3, ptr %tmp, align 4, !tbaa !2
store i32 %tmp3, ptr @g, align 4, !tbaa !2 store i32 %tmp3, ptr @g, align 4, !tbaa !2
call void @bar(ptr nonnull %tmp) #2 call void @bar(ptr nonnull %tmp) #2
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %tmp1) #2 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %tmp) #2
br label %bb6 br label %bb6
bb6: ; preds = %bb5, %bb bb6: ; preds = %bb5, %bb

View File

@ -9,8 +9,7 @@
define void @_Z3foov() local_unnamed_addr { define void @_Z3foov() local_unnamed_addr {
bb: bb:
%tmp = alloca %class.A, align 1 %tmp = alloca %class.A, align 1
%tmp1 = getelementptr inbounds %class.A, ptr %tmp, i64 0, i32 0 call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %tmp)
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %tmp1)
%tmp2 = load i32, ptr @cond, align 4, !tbaa !2 %tmp2 = load i32, ptr @cond, align 4, !tbaa !2
%tmp3 = icmp eq i32 %tmp2, 0 %tmp3 = icmp eq i32 %tmp2, 0
br i1 %tmp3, label %bb4, label %bb5 br i1 %tmp3, label %bb4, label %bb5
@ -20,7 +19,7 @@ bb4: ; preds = %bb
br label %bb5 br label %bb5
bb5: ; preds = %bb4, %bb bb5: ; preds = %bb4, %bb
call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %tmp1) call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %tmp)
ret void ret void
} }
@ -38,7 +37,6 @@ define void @_Z3goov() local_unnamed_addr {
bb: bb:
; CHECK: bb: ; CHECK: bb:
; CHECK-NOT: alloca ; CHECK-NOT: alloca
; CHECK-NOT: getelementptr
; CHECK-NOT: llvm.lifetime ; CHECK-NOT: llvm.lifetime
; CHECK: br i1 ; CHECK: br i1
; CHECK: codeRepl.i: ; CHECK: codeRepl.i:
@ -50,7 +48,6 @@ bb:
; CHECK-LABEL: define internal void @_Z3foov.1. ; CHECK-LABEL: define internal void @_Z3foov.1.
; CHECK: newFuncRoot: ; CHECK: newFuncRoot:
; CHECK-NEXT: %tmp = alloca %class.A ; CHECK-NEXT: %tmp = alloca %class.A
; CHECK-NEXT: %tmp1 = getelementptr
; CHECK-NEXT: call void @llvm.lifetime.start.p0 ; CHECK-NEXT: call void @llvm.lifetime.start.p0
; CHECK: call void @llvm.lifetime.end.p0 ; CHECK: call void @llvm.lifetime.end.p0
; CHECK-NEXT: br label %bb5.exitStub ; CHECK-NEXT: br label %bb5.exitStub

View File

@ -61,10 +61,11 @@ entry:
declare i64 @llvm.aarch64.udiv.i64.i64(i64, i64) declare i64 @llvm.aarch64.udiv.i64.i64(i64, i64)
define void @test_free_intrinsics(i64 %x, ptr %ptr) { define void @test_free_intrinsics(i64 %x) {
; CHECK-LABEL: @test_free_intrinsics( ; CHECK-LABEL: @test_free_intrinsics(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100000000032, ptr [[PTR:%.*]]) ; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100000000032, ptr [[PTR]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100000000064, ptr [[PTR]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100000000064, ptr [[PTR]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 100000000128, ptr [[PTR]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 100000000128, ptr [[PTR]])
; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 100000000256, ptr [[PTR]]) ; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 100000000256, ptr [[PTR]])
@ -72,6 +73,7 @@ define void @test_free_intrinsics(i64 %x, ptr %ptr) {
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
entry: entry:
%ptr = alloca i8
call void @llvm.lifetime.start.p0(i64 100000000032, ptr %ptr) call void @llvm.lifetime.start.p0(i64 100000000032, ptr %ptr)
call void @llvm.lifetime.start.p0(i64 100000000064, ptr %ptr) call void @llvm.lifetime.start.p0(i64 100000000064, ptr %ptr)
call void @llvm.lifetime.end.p0(i64 100000000128, ptr %ptr) call void @llvm.lifetime.end.p0(i64 100000000128, ptr %ptr)

View File

@ -26,47 +26,5 @@ define i32 @test_lifetime_alloca() {
ret i32 0 ret i32 0
} }
; CHECK-LABEL: @test_lifetime_arg
define i32 @test_lifetime_arg(ptr) {
; Check that lifetime intrinsics are removed along with the pointer.
; CHECK-NEXT: #dbg_value
; CHECK-NEXT: ret i32 0
; CHECK-NOT: llvm.lifetime.start
; CHECK-NOT: llvm.lifetime.end
call void @llvm.lifetime.start.p0(i64 -1, ptr %0)
call void @llvm.lifetime.end.p0(i64 -1, ptr %0)
ret i32 0
}
@glob = global i8 1
; CHECK-LABEL: @test_lifetime_global
define i32 @test_lifetime_global() {
; Check that lifetime intrinsics are removed along with the pointer.
; CHECK-NEXT: #dbg_value
; CHECK-NEXT: ret i32 0
; CHECK-NOT: llvm.lifetime.start
; CHECK-NOT: llvm.lifetime.end
call void @llvm.lifetime.start.p0(i64 -1, ptr @glob)
call void @llvm.lifetime.end.p0(i64 -1, ptr @glob)
ret i32 0
}
; CHECK-LABEL: @test_lifetime_bitcast
define i32 @test_lifetime_bitcast(ptr %arg) {
; Check that lifetime intrinsics are NOT removed when the pointer is a bitcast.
; It's not uncommon for two bitcasts to be made: one for lifetime, one for use.
; TODO: Support the above case.
; CHECK-NEXT: bitcast
; CHECK-NEXT: #dbg_value
; CHECK-NEXT: llvm.lifetime.start.p0(i64 -1, ptr %cast)
; CHECK-NEXT: llvm.lifetime.end.p0(i64 -1, ptr %cast)
; CHECK-NEXT: ret i32 0
%cast = bitcast ptr %arg to ptr
call void @llvm.lifetime.start.p0(i64 -1, ptr %cast)
call void @llvm.lifetime.end.p0(i64 -1, ptr %cast)
ret i32 0
}
; CHECK: [[add]] = !DILocalVariable ; CHECK: [[add]] = !DILocalVariable
; CHECK: [[sub]] = !DILocalVariable ; CHECK: [[sub]] = !DILocalVariable

View File

@ -67,19 +67,6 @@ define void @test_strcat_with_lifetime(ptr %src) {
ret void ret void
} }
define void @test_strcat_with_lifetime_nonlocal(ptr %dest, ptr %src) {
; CHECK-LABEL: @test_strcat_with_lifetime_nonlocal(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr nonnull [[DEST:%.*]])
; CHECK-NEXT: [[CALL:%.*]] = call ptr @strcat(ptr [[DEST]], ptr [[SRC:%.*]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 16, ptr nonnull [[DEST]])
; CHECK-NEXT: ret void
;
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %dest)
%call = call ptr @strcat(ptr %dest, ptr %src)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %dest)
ret void
}
declare ptr @strncat(ptr %dest, ptr %src, i64 %n) nounwind declare ptr @strncat(ptr %dest, ptr %src, i64 %n) nounwind
define void @test4(ptr %src) { define void @test4(ptr %src) {
; CHECK-LABEL: @test4( ; CHECK-LABEL: @test4(

View File

@ -25,12 +25,12 @@ define void @test1() {
define void @test2(ptr %P) { define void @test2(ptr %P) {
; CHECK-LABEL: @test2( ; CHECK-LABEL: @test2(
; CHECK-NEXT: [[Q:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1 ; CHECK-NEXT: [[Q:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[Q]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[Q]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[Q]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[Q]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%Q = getelementptr i32, ptr %P, i32 1 %Q = alloca i32
call void @llvm.lifetime.start.p0(i64 4, ptr %Q) call void @llvm.lifetime.start.p0(i64 4, ptr %Q)
store i32 0, ptr %Q ;; This store is dead. store i32 0, ptr %Q ;; This store is dead.
call void @llvm.lifetime.end.p0(i64 4, ptr %Q) call void @llvm.lifetime.end.p0(i64 4, ptr %Q)
@ -114,19 +114,19 @@ exit:
; lifetime.end only marks the first two bytes of %A as dead. Make sure ; lifetime.end only marks the first two bytes of %A as dead. Make sure
; `store i8 20, ptr %A.2 is not removed. ; `store i8 20, ptr %A.2 is not removed.
define void @test5_lifetime_end_partial(ptr %A) { define void @test5_lifetime_end_partial() {
; CHECK-LABEL: @test5_lifetime_end_partial( ; CHECK-LABEL: @test5_lifetime_end_partial(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[A:%.*]]) ; CHECK-NEXT: [[A:%.*]] = alloca [4 x i8], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[A]])
; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1 ; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, ptr [[A]], i64 2 ; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, ptr [[A]], i64 2
; CHECK-NEXT: store i8 20, ptr [[A_2]], align 1 ; CHECK-NEXT: store i8 20, ptr [[A_2]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[A]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
; CHECK-NEXT: call void @use(ptr [[A_1]]) ; CHECK-NEXT: call void @use(ptr [[A_1]])
; CHECK-NEXT: store i8 30, ptr [[A_1]], align 1
; CHECK-NEXT: store i8 40, ptr [[A_2]], align 1
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%A = alloca [4 x i8]
call void @llvm.lifetime.start.p0(i64 2, ptr %A) call void @llvm.lifetime.start.p0(i64 2, ptr %A)
%A.1 = getelementptr i8, ptr %A, i64 1 %A.1 = getelementptr i8, ptr %A, i64 1
%A.2 = getelementptr i8, ptr %A, i64 2 %A.2 = getelementptr i8, ptr %A, i64 2

View File

@ -398,7 +398,7 @@ bb5:
@linenum = external local_unnamed_addr global i32, align 4 @linenum = external local_unnamed_addr global i32, align 4
define void @accessible_after_return11_loop() { define void @accessible_after_return11_loop(ptr noalias %p) {
; CHECK-LABEL: @accessible_after_return11_loop( ; CHECK-LABEL: @accessible_after_return11_loop(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY_I:%.*]] ; CHECK-NEXT: br label [[FOR_BODY_I:%.*]]
@ -406,7 +406,7 @@ define void @accessible_after_return11_loop() {
; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_1]], label [[FOR_BODY_I]], label [[INIT_PARSE_EXIT:%.*]] ; CHECK-NEXT: br i1 [[C_1]], label [[FOR_BODY_I]], label [[INIT_PARSE_EXIT:%.*]]
; CHECK: init_parse.exit: ; CHECK: init_parse.exit:
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 16, ptr nonnull undef) ; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4
; CHECK-NEXT: store i32 0, ptr @linenum, align 4 ; CHECK-NEXT: store i32 0, ptr @linenum, align 4
; CHECK-NEXT: br label [[FOR_BODY_I20:%.*]] ; CHECK-NEXT: br label [[FOR_BODY_I20:%.*]]
; CHECK: for.body.i20: ; CHECK: for.body.i20:
@ -424,7 +424,7 @@ for.body.i: ; preds = %for.body.i, %entry
init_parse.exit: ; preds = %for.body.i init_parse.exit: ; preds = %for.body.i
store i32 0, ptr @linenum, align 4 store i32 0, ptr @linenum, align 4
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull undef) #2 store i32 1, ptr %p
store i32 0, ptr @linenum, align 4 store i32 0, ptr @linenum, align 4
br label %for.body.i20 br label %for.body.i20
@ -435,7 +435,6 @@ for.body.i20: ; preds = %for.body.i20, %init
exit: exit:
ret void ret void
} }
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
declare i1 @cond() readnone nounwind declare i1 @cond() readnone nounwind
; Tests where the pointer/object is *NOT* accessible after the function returns. ; Tests where the pointer/object is *NOT* accessible after the function returns.

View File

@ -142,10 +142,12 @@ end:
;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting ;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
;; stores that, without the lifetime calls, would be writebacks. ;; stores that, without the lifetime calls, would be writebacks.
define void @test_writeback_lifetimes(ptr %p) { define void @test_writeback_lifetimes() {
; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes( ; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes(
; CHECK-NOMEMSSA-NEXT: entry: ; CHECK-NOMEMSSA-NEXT: entry:
; CHECK-NOMEMSSA-NEXT: [[Q:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1 ; CHECK-NOMEMSSA-NEXT: [[P:%.*]] = alloca i64, align 8
; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
; CHECK-NOMEMSSA-NEXT: [[Q:%.*]] = getelementptr i32, ptr [[P]], i64 1
; CHECK-NOMEMSSA-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NOMEMSSA-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NOMEMSSA-NEXT: [[QV:%.*]] = load i32, ptr [[Q]], align 4 ; CHECK-NOMEMSSA-NEXT: [[QV:%.*]] = load i32, ptr [[Q]], align 4
; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]]) ; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
@ -156,7 +158,9 @@ define void @test_writeback_lifetimes(ptr %p) {
; ;
; CHECK-LABEL: @test_writeback_lifetimes( ; CHECK-LABEL: @test_writeback_lifetimes(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[Q:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1 ; CHECK-NEXT: [[P:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
; CHECK-NEXT: [[Q:%.*]] = getelementptr i32, ptr [[P]], i64 1
; CHECK-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: [[QV:%.*]] = load i32, ptr [[Q]], align 4 ; CHECK-NEXT: [[QV:%.*]] = load i32, ptr [[Q]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
@ -166,6 +170,8 @@ define void @test_writeback_lifetimes(ptr %p) {
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
entry: entry:
%p = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %p)
%q = getelementptr i32, ptr %p, i64 1 %q = getelementptr i32, ptr %p, i64 1
%pv = load i32, ptr %p %pv = load i32, ptr %p
%qv = load i32, ptr %q %qv = load i32, ptr %q
@ -178,10 +184,12 @@ entry:
;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting ;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
;; stores that, without the lifetime calls, would be writebacks. ;; stores that, without the lifetime calls, would be writebacks.
define void @test_writeback_lifetimes_multi_arg(ptr %p, ptr %q) { define void @test_writeback_lifetimes_multi_arg(ptr %q) {
; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes_multi_arg( ; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes_multi_arg(
; CHECK-NOMEMSSA-NEXT: entry: ; CHECK-NOMEMSSA-NEXT: entry:
; CHECK-NOMEMSSA-NEXT: [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4 ; CHECK-NOMEMSSA-NEXT: [[P:%.*]] = alloca i64, align 8
; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
; CHECK-NOMEMSSA-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NOMEMSSA-NEXT: [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4 ; CHECK-NOMEMSSA-NEXT: [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4
; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]]) ; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]]) ; CHECK-NOMEMSSA-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
@ -191,15 +199,18 @@ define void @test_writeback_lifetimes_multi_arg(ptr %p, ptr %q) {
; ;
; CHECK-LABEL: @test_writeback_lifetimes_multi_arg( ; CHECK-LABEL: @test_writeback_lifetimes_multi_arg(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: [[P:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
; CHECK-NEXT: [[PV:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4 ; CHECK-NEXT: [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
; CHECK-NEXT: store i32 [[PV]], ptr [[P]], align 4 ; CHECK-NEXT: store i32 [[PV]], ptr [[P]], align 4
; CHECK-NEXT: store i32 [[QV]], ptr [[Q]], align 4
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
entry: entry:
%p = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %p)
%pv = load i32, ptr %p %pv = load i32, ptr %p
%qv = load i32, ptr %q %qv = load i32, ptr %q
call void @llvm.lifetime.end.p0(i64 8, ptr %p) call void @llvm.lifetime.end.p0(i64 8, ptr %p)

View File

@ -107,7 +107,8 @@ entry:
ret i32 %add ret i32 %add
} }
define i8 @lifetime_end(ptr %p, i8 %val) { define i8 @lifetime_end(i8 %val) {
%p = alloca [32 x i8]
call void @llvm.lifetime.start.p0(i64 32, ptr %p) call void @llvm.lifetime.start.p0(i64 32, ptr %p)
store i8 %val, ptr %p store i8 %val, ptr %p
call void @llvm.lifetime.end.p0(i64 32, ptr %p) call void @llvm.lifetime.end.p0(i64 32, ptr %p)

View File

@ -36,11 +36,10 @@ outlinedPath:
; These two uses of stack slots are overlapping. This should prevent ; These two uses of stack slots are overlapping. This should prevent
; merging of stack slots. CodeExtractor must replicate the effects of ; merging of stack slots. CodeExtractor must replicate the effects of
; these markers in the caller to inhibit stack coloring. ; these markers in the caller to inhibit stack coloring.
%gep1 = getelementptr inbounds i8, ptr %local1, i64 1 call void @llvm.lifetime.start.p0(i64 1, ptr %local1)
call void @llvm.lifetime.start.p0(i64 1, ptr %gep1)
call void @llvm.lifetime.start.p0(i64 1, ptr %local2) call void @llvm.lifetime.start.p0(i64 1, ptr %local2)
call void @cold_use2(ptr %local1, ptr %local2) call void @cold_use2(ptr %local1, ptr %local2)
call void @llvm.lifetime.end.p0(i64 1, ptr %gep1) call void @llvm.lifetime.end.p0(i64 1, ptr %local1)
call void @llvm.lifetime.end.p0(i64 1, ptr %local2) call void @llvm.lifetime.end.p0(i64 1, ptr %local2)
br i1 undef, label %outlinedPath2, label %outlinedPathExit br i1 undef, label %outlinedPath2, label %outlinedPathExit

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=infer-address-spaces %s | FileCheck %s ; RUN: opt -S -passes=infer-address-spaces %s | FileCheck %s
target triple = "nvptx64-nvidia-cuda" target triple = "nvptx64-nvidia-cuda"
@ -6,11 +7,13 @@ define i32 @lifetime_flat_pointer() {
; CHECK-LABEL: define i32 @lifetime_flat_pointer() { ; CHECK-LABEL: define i32 @lifetime_flat_pointer() {
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[ALLOCA]] to ptr addrspace(5) ; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[ALLOCA]] to ptr addrspace(5)
; CHECK-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[TMP1]]) ; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[TMP1]] to ptr
; CHECK-NEXT: [[TMP3:%.*]] = addrspacecast ptr addrspace(5) [[TMP1]] to ptr
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[ALLOCA]])
; CHECK-NEXT: store i32 1, ptr addrspace(5) [[TMP1]], align 4 ; CHECK-NEXT: store i32 1, ptr addrspace(5) [[TMP1]], align 4
; CHECK-NEXT: %ret = load i32, ptr addrspace(5) [[TMP1]], align 4 ; CHECK-NEXT: [[RET:%.*]] = load i32, ptr addrspace(5) [[TMP1]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[TMP1]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
; CHECK-NEXT: ret i32 %ret ; CHECK-NEXT: ret i32 [[RET]]
; ;
%alloca = alloca i32, align 4 %alloca = alloca i32, align 4
%1 = addrspacecast ptr %alloca to ptr addrspace(5) %1 = addrspacecast ptr %alloca to ptr addrspace(5)

View File

@ -3,8 +3,6 @@
target datalayout = "p:32:32" target datalayout = "p:32:32"
declare void @llvm.lifetime.start.p0(i64 %size, ptr nocapture %ptr)
@glbl = external global i32 @glbl = external global i32
define void @outer1() { define void @outer1() {
@ -20,7 +18,6 @@ define void @inner1(ptr %ptr) {
store i32 0, ptr %ptr store i32 0, ptr %ptr
%D = getelementptr inbounds i32, ptr %ptr, i32 1 %D = getelementptr inbounds i32, ptr %ptr, i32 1
%F = select i1 false, ptr %ptr, ptr @glbl %F = select i1 false, ptr %ptr, ptr @glbl
call void @llvm.lifetime.start.p0(i64 0, ptr %ptr)
call void @extern() call void @extern()
ret void ret void
} }
@ -39,7 +36,6 @@ define void @inner2(ptr %ptr) {
store i32 0, ptr %ptr store i32 0, ptr %ptr
%D = getelementptr inbounds i32, ptr %ptr, i32 %A %D = getelementptr inbounds i32, ptr %ptr, i32 %A
%F = select i1 false, ptr %ptr, ptr @glbl %F = select i1 false, ptr %ptr, ptr @glbl
call void @llvm.lifetime.start.p0(i64 0, ptr %ptr)
call void @extern() call void @extern()
ret void ret void
} }
@ -146,7 +142,6 @@ define void @inner5(i1 %flag, ptr %ptr) {
if.then: if.then:
%D = getelementptr inbounds i32, ptr %ptr, i32 %A %D = getelementptr inbounds i32, ptr %ptr, i32 %A
%F = select i1 false, ptr %ptr, ptr @glbl %F = select i1 false, ptr %ptr, ptr @glbl
call void @llvm.lifetime.start.p0(i64 0, ptr %ptr)
ret void ret void
exit: exit:

View File

@ -104,11 +104,8 @@ define void @outer6(ptr %a, ptr %ptr) {
ret void ret void
} }
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) argmemonly nounwind
define void @inner6(ptr %a, ptr %ptr) { define void @inner6(ptr %a, ptr %ptr) {
%1 = load i32, ptr %a %1 = load i32, ptr %a
call void @llvm.lifetime.start.p0(i64 32, ptr %ptr) ; This intrinsic does not clobber the first load.
%2 = load i32, ptr %a %2 = load i32, ptr %a
call void @pad() call void @pad()
%3 = load i32, ptr %a %3 = load i32, ptr %a

View File

@ -26,8 +26,9 @@ declare void @llvm.lifetime.start.p0(i64, ptr)
declare void @llvm.lifetime.end.p0(i64, ptr) declare void @llvm.lifetime.end.p0(i64, ptr)
define void @test3() { define void @test3() {
call void @llvm.lifetime.start.p0(i64 -1, ptr undef) %a = alloca i32
call void @llvm.lifetime.end.p0(i64 -1, ptr undef) call void @llvm.lifetime.start.p0(i64 -1, ptr %a)
call void @llvm.lifetime.end.p0(i64 -1, ptr %a)
ret void ret void
} }

View File

@ -109,8 +109,6 @@ define void @test3(ptr %src) {
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%a = call noalias ptr @malloc(i32 10) %a = call noalias ptr @malloc(i32 10)
call void @llvm.lifetime.start.p0(i64 10, ptr %a)
call void @llvm.lifetime.end.p0(i64 10, ptr %a)
%size = call i64 @llvm.objectsize.i64(ptr %a, i1 true) %size = call i64 @llvm.objectsize.i64(ptr %a, i1 true)
store i8 42, ptr %a store i8 42, ptr %a
call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %src, i32 32, i1 false) call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %src, i32 32, i1 false)

View File

@ -174,16 +174,12 @@ define { <16 x i8>, <32 x i8> } @differenttypes({ <4 x i32>, <8 x i32> } %a, ptr
; CHECK-LABEL: define { <16 x i8>, <32 x i8> } @differenttypes ; CHECK-LABEL: define { <16 x i8>, <32 x i8> } @differenttypes
; CHECK-SAME: ({ <4 x i32>, <8 x i32> } [[A:%.*]], ptr [[P:%.*]]) { ; CHECK-SAME: ({ <4 x i32>, <8 x i32> } [[A:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr nonnull [[P]])
; CHECK-NEXT: store { <4 x i32>, <8 x i32> } [[A]], ptr [[P]], align 16 ; CHECK-NEXT: store { <4 x i32>, <8 x i32> } [[A]], ptr [[P]], align 16
; CHECK-NEXT: [[TMP0:%.*]] = load { <16 x i8>, <32 x i8> }, ptr [[P]], align 16 ; CHECK-NEXT: [[TMP0:%.*]] = load { <16 x i8>, <32 x i8> }, ptr [[P]], align 16
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr nonnull [[P]])
; CHECK-NEXT: ret { <16 x i8>, <32 x i8> } [[TMP0]] ; CHECK-NEXT: ret { <16 x i8>, <32 x i8> } [[TMP0]]
; ;
entry: entry:
call void @llvm.lifetime.start.p0(i64 -1, ptr nonnull %p) #5
store { <4 x i32>, <8 x i32> } %a, ptr %p, align 16 store { <4 x i32>, <8 x i32> } %a, ptr %p, align 16
%2 = load { <16 x i8>, <32 x i8> }, ptr %p, align 16 %2 = load { <16 x i8>, <32 x i8> }, ptr %p, align 16
call void @llvm.lifetime.end.p0(i64 -1, ptr nonnull %p) #5
ret { <16 x i8>, <32 x i8> } %2 ret { <16 x i8>, <32 x i8> } %2
} }

View File

@ -431,195 +431,26 @@ exit:
ret void ret void
} }
define void @lifetime_for_ptr_first_arg_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) { define void @multiple_unrelated_lifetimes(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetime_for_ptr_first_arg_before_multiply(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]]
; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]])
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]]
; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]])
; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]]
; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]])
; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]]
; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]])
; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0
; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8
; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2
; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8
; CHECK-NEXT: ret void
;
entry:
%a = load <4 x double>, ptr %A, align 8
%b = load <4 x double>, ptr %B, align 8
br i1 %c.0, label %then, label %exit
then:
call void @llvm.lifetime.end(i64 -1, ptr %A)
br label %exit
exit:
%m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2)
store <4 x double> %m, ptr %C, align 8
ret void
}
define void @lifetime_for_both_ptr_args_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetime_for_both_ptr_args_before_multiply(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]]
; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]])
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]]
; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]])
; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]]
; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]])
; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]]
; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]])
; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0
; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8
; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2
; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8
; CHECK-NEXT: ret void
;
entry:
%a = load <4 x double>, ptr %A, align 8
%b = load <4 x double>, ptr %B, align 8
br i1 %c.0, label %then, label %exit
then:
call void @llvm.lifetime.end(i64 -1, ptr %B)
call void @llvm.lifetime.end(i64 -1, ptr %A)
br label %exit
exit:
%m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2)
store <4 x double> %m, ptr %C, align 8
ret void
}
define void @multiple_unrelated_lifetimes(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @multiple_unrelated_lifetimes( ; CHECK-LABEL: @multiple_unrelated_lifetimes(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[ALLOC_1:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[ALLOC_1:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[ALLOC_2:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[ALLOC_2:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: call void @init(ptr [[A]])
; CHECK-NEXT: call void @init(ptr [[B]])
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then: ; CHECK: then:
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_1]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_1]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_2]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_2]])
; CHECK-NEXT: br label [[EXIT]] ; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit: ; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 ; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 ; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 ; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
@ -682,6 +513,10 @@ define void @multiple_unrelated_lifetimes(ptr noalias %A, ptr noalias %B, ptr no
entry: entry:
%alloc.1 = alloca i32 %alloc.1 = alloca i32
%alloc.2 = alloca i32 %alloc.2 = alloca i32
%A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A)
call void @init(ptr %B)
%a = load <4 x double>, ptr %A, align 8 %a = load <4 x double>, ptr %A, align 8
%b = load <4 x double>, ptr %B, align 8 %b = load <4 x double>, ptr %B, align 8
br i1 %c.0, label %then, label %exit br i1 %c.0, label %then, label %exit
@ -699,106 +534,20 @@ exit:
ret void ret void
} }
define void @lifetime_for_ptr_select_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0, i1 %c.1) { define void @lifetimes_for_args_in_different_blocks(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetime_for_ptr_select_before_multiply(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[P:%.*]] = select i1 [[C_0:%.*]], ptr [[A:%.*]], ptr [[B:%.*]]
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[P]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]]
; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]])
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]]
; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]])
; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]]
; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]])
; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1>
; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0
; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]]
; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1
; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0
; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]])
; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison>
; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C:%.*]], i64 0
; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8
; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2
; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8
; CHECK-NEXT: ret void
;
entry:
%P = select i1 %c.0, ptr %A, ptr %B
%a = load <4 x double>, ptr %P, align 8
%b = load <4 x double>, ptr %B, align 8
br i1 %c.1, label %then, label %exit
then:
call void @llvm.lifetime.end(i64 -1, ptr %P)
br label %exit
exit:
%m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2)
store <4 x double> %m, ptr %C, align 8
ret void
}
define void @lifetimes_for_args_in_different_blocks(ptr noalias %B, ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetimes_for_args_in_different_blocks( ; CHECK-LABEL: @lifetimes_for_args_in_different_blocks(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: call void @init(ptr [[A]])
; CHECK-NEXT: call void @init(ptr [[B]])
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then: ; CHECK: then:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 ; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 ; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 ; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
@ -864,7 +613,9 @@ define void @lifetimes_for_args_in_different_blocks(ptr noalias %B, ptr noalias
; ;
entry: entry:
%A = alloca <4 x double> %A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A) call void @init(ptr %A)
call void @init(ptr %B)
br i1 %c.0, label %then, label %exit br i1 %c.0, label %then, label %exit
then: then:
@ -880,15 +631,17 @@ exit:
ret void ret void
} }
define void @lifetimes_for_args_in_different_blocks2(ptr noalias %B, ptr noalias %C, i1 %c.0) { define void @lifetimes_for_args_in_different_blocks2(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetimes_for_args_in_different_blocks2( ; CHECK-LABEL: @lifetimes_for_args_in_different_blocks2(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: call void @init(ptr [[A]])
; CHECK-NEXT: call void @init(ptr [[B]])
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then: ; CHECK: then:
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B:%.*]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]])
; CHECK-NEXT: br label [[EXIT]] ; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit: ; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0
@ -957,7 +710,9 @@ define void @lifetimes_for_args_in_different_blocks2(ptr noalias %B, ptr noalias
; ;
entry: entry:
%A = alloca <4 x double> %A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A) call void @init(ptr %A)
call void @init(ptr %B)
br i1 %c.0, label %then, label %exit br i1 %c.0, label %then, label %exit
then: then:
@ -973,18 +728,20 @@ exit:
ret void ret void
} }
define void @lifetimes_for_args_load0_in_different_block(ptr noalias %B, ptr noalias %C, i1 %c.0) { define void @lifetimes_for_args_load0_in_different_block(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetimes_for_args_load0_in_different_block( ; CHECK-LABEL: @lifetimes_for_args_load0_in_different_block(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: call void @init(ptr [[A]])
; CHECK-NEXT: call void @init(ptr [[B]])
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then: ; CHECK: then:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 ; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 ; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 ; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
@ -1048,7 +805,9 @@ define void @lifetimes_for_args_load0_in_different_block(ptr noalias %B, ptr noa
; ;
entry: entry:
%A = alloca <4 x double> %A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A) call void @init(ptr %A)
call void @init(ptr %B)
%a = load <4 x double>, ptr %A, align 8 %a = load <4 x double>, ptr %A, align 8
call void @llvm.lifetime.end(i64 -1, ptr %A) call void @llvm.lifetime.end(i64 -1, ptr %A)
br i1 %c.0, label %then, label %exit br i1 %c.0, label %then, label %exit
@ -1064,18 +823,20 @@ exit:
ret void ret void
} }
define void @lifetimes_for_args_load1_in_different_block(ptr noalias %B, ptr noalias %C, i1 %c.0) { define void @lifetimes_for_args_load1_in_different_block(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetimes_for_args_load1_in_different_block( ; CHECK-LABEL: @lifetimes_for_args_load1_in_different_block(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32
; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: call void @init(ptr [[A]])
; CHECK-NEXT: call void @init(ptr [[B]])
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
; CHECK: then: ; CHECK: then:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0
; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8
; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0
; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 ; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8
; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 ; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2
; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 ; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8
@ -1139,7 +900,9 @@ define void @lifetimes_for_args_load1_in_different_block(ptr noalias %B, ptr noa
; ;
entry: entry:
%A = alloca <4 x double> %A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A) call void @init(ptr %A)
call void @init(ptr %B)
%b = load <4 x double>, ptr %B, align 8 %b = load <4 x double>, ptr %B, align 8
call void @llvm.lifetime.end(i64 -1, ptr %B) call void @llvm.lifetime.end(i64 -1, ptr %B)
br i1 %c.0, label %then, label %exit br i1 %c.0, label %then, label %exit

View File

@ -116,22 +116,3 @@ define i32 @call_slot_clobber_before_lifetime_start() {
%v = load i32, ptr %dst %v = load i32, ptr %dst
ret i32 %v ret i32 %v
} }
define void @call_slot_lifetime_bitcast(ptr %ptr) {
; CHECK-LABEL: @call_slot_lifetime_bitcast(
; CHECK-NEXT: [[TMP1:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[TMP2:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP2]], ptr align 4 [[PTR:%.*]], i64 4, i1 false)
; CHECK-NEXT: [[TMP1_CAST:%.*]] = bitcast ptr [[TMP1]] to ptr
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[TMP1_CAST]])
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP1]], ptr align 4 [[PTR]], i64 4, i1 false)
; CHECK-NEXT: ret void
;
%tmp1 = alloca i32
%tmp2 = alloca i32
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp2, ptr align 4 %ptr, i64 4, i1 false)
%tmp1.cast = bitcast ptr %tmp1 to ptr
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %tmp1.cast)
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp1.cast, ptr align 4 %tmp2, i64 4, i1 false)
ret void
}

View File

@ -26,35 +26,41 @@ define i32 @test1(ptr nocapture %foobie) nounwind noinline ssp uwtable {
} }
; Check that the memcpy is removed. ; Check that the memcpy is removed.
define void @test2(ptr sret(i8) noalias nocapture %out, ptr %in) nounwind noinline ssp uwtable { define void @test2(ptr sret(i8) noalias nocapture %out) nounwind noinline ssp uwtable {
; CHECK-LABEL: @test2( ; CHECK-LABEL: @test2(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[IN:%.*]]) ; CHECK-NEXT: [[IN:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[IN]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%in = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %in) call void @llvm.lifetime.start.p0(i64 8, ptr %in)
call void @llvm.memcpy.p0.p0.i64(ptr %out, ptr %in, i64 8, i1 false) call void @llvm.memcpy.p0.p0.i64(ptr %out, ptr %in, i64 8, i1 false)
ret void ret void
} }
; Check that the memcpy is not removed. ; Check that the memcpy is not removed.
define void @test3(ptr sret(i8) noalias nocapture %out, ptr %in) nounwind noinline ssp uwtable { define void @test3(ptr sret(i8) noalias nocapture %out) nounwind noinline ssp uwtable {
; CHECK-LABEL: @test3( ; CHECK-LABEL: @test3(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[IN:%.*]]) ; CHECK-NEXT: [[IN:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[IN]])
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[OUT:%.*]], ptr [[IN]], i64 8, i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[OUT:%.*]], ptr [[IN]], i64 8, i1 false)
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%in = alloca i64
call void @llvm.lifetime.start.p0(i64 4, ptr %in) call void @llvm.lifetime.start.p0(i64 4, ptr %in)
call void @llvm.memcpy.p0.p0.i64(ptr %out, ptr %in, i64 8, i1 false) call void @llvm.memcpy.p0.p0.i64(ptr %out, ptr %in, i64 8, i1 false)
ret void ret void
} }
; Check that the memcpy is not removed. ; Check that the memcpy is not removed.
define void @test_lifetime_may_alias(ptr %lifetime, ptr %src, ptr %dst) { define void @test_lifetime_may_alias(ptr %src, ptr %dst) {
; CHECK-LABEL: @test_lifetime_may_alias( ; CHECK-LABEL: @test_lifetime_may_alias(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[LIFETIME:%.*]]) ; CHECK-NEXT: [[LIFETIME:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[LIFETIME]])
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 8, i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 8, i1 false)
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%lifetime = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %lifetime) call void @llvm.lifetime.start.p0(i64 8, ptr %lifetime)
call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 8, i1 false) call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 8, i1 false)
ret void ret void

View File

@ -37,29 +37,10 @@ define void @test_alloca_with_lifetimes(ptr %result) {
ret void ret void
} }
define void @test_malloc_with_lifetimes(ptr %result) {
; CHECK-LABEL: @test_malloc_with_lifetimes(
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr [[A]])
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[RESULT:%.*]], i8 0, i64 12, i1 false)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 16, ptr [[A]])
; CHECK-NEXT: call void @free(ptr [[A]])
; CHECK-NEXT: ret void
;
%a = call ptr @malloc(i64 16)
call void @llvm.lifetime.start.p0(i64 16, ptr %a)
call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)
call void @llvm.lifetime.end.p0(i64 16, ptr %a)
call void @free(ptr %a)
ret void
}
; memcpy size is larger than lifetime, don't optimize. ; memcpy size is larger than lifetime, don't optimize.
define void @test_copy_larger_than_lifetime_size(ptr %result) { define void @test_copy_larger_than_lifetime_size(ptr %result) {
; CHECK-LABEL: @test_copy_larger_than_lifetime_size( ; CHECK-LABEL: @test_copy_larger_than_lifetime_size(
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 16) ; CHECK-NEXT: [[A:%.*]] = alloca [[T:%.*]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr [[A]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr [[A]])
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false) ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false) ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)
@ -67,7 +48,7 @@ define void @test_copy_larger_than_lifetime_size(ptr %result) {
; CHECK-NEXT: call void @free(ptr [[A]]) ; CHECK-NEXT: call void @free(ptr [[A]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%a = call ptr @malloc(i64 16) %a = alloca %T, align 8
call void @llvm.lifetime.start.p0(i64 12, ptr %a) call void @llvm.lifetime.start.p0(i64 12, ptr %a)
call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false) call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false) call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)

View File

@ -94,21 +94,6 @@ entry:
ret void ret void
} }
define i8 @test6(ptr %ptr, ptr noalias %ptr.1) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr [[PTR:%.*]])
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[PTR]], align 8
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[PTR]], ptr [[PTR_1:%.*]], i64 24, i1 false)
; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
call void @llvm.lifetime.start.p0(i64 24, ptr %ptr)
%0 = load i8, ptr %ptr, align 8
call void @llvm.memmove.p0.p0.i64(ptr %ptr, ptr %ptr.1, i64 24, i1 false)
ret i8 %0
}
define void @test7(ptr %ptr) { define void @test7(ptr %ptr) {
; CHECK-LABEL: @test7( ; CHECK-LABEL: @test7(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:

View File

@ -10,14 +10,14 @@ define i32 @foo(i32 noundef %0, i32 noundef %1, i32 noundef %2) #0 {
; CHECK-NEXT: [[TMP4:%.*]] = alloca [100 x i8], align 16 ; CHECK-NEXT: [[TMP4:%.*]] = alloca [100 x i8], align 16
; CHECK-NEXT: [[TMP5:%.*]] = alloca [2 x i8], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = alloca [2 x i8], align 1
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [100 x i8], ptr [[TMP4]], i64 0, i64 0 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [100 x i8], ptr [[TMP4]], i64 0, i64 0
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100, ptr nonnull [[TMP6]]) #[[ATTR3:[0-9]+]] ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 100, ptr nonnull [[TMP4]]) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 0 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 0
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr nonnull [[TMP7]]) #[[ATTR3]] ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr nonnull [[TMP5]]) #[[ATTR3]]
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 1 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 1
; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP1:%.*]], 0 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP1:%.*]], 0
; CHECK-NEXT: br i1 [[TMP9]], label [[TMP15:%.*]], label [[TMP10:%.*]] ; CHECK-NEXT: br i1 [[TMP9]], label [[TMP15:%.*]], label [[TMP10:%.*]]
; CHECK: 10: ; CHECK: 10:
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(100) [[TMP6]], i8 -86, i64 100, i1 false), !annotation !0 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(100) [[TMP6]], i8 -86, i64 100, i1 false), !annotation [[META0:![0-9]+]]
; CHECK-NEXT: [[TMP11:%.*]] = sext i32 [[TMP0:%.*]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = sext i32 [[TMP0:%.*]] to i64
; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [100 x i8], ptr [[TMP4]], i64 0, i64 [[TMP11]] ; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [100 x i8], ptr [[TMP4]], i64 0, i64 [[TMP11]]
; CHECK-NEXT: store i8 12, ptr [[TMP12]], align 1 ; CHECK-NEXT: store i8 12, ptr [[TMP12]], align 1
@ -28,8 +28,8 @@ define i32 @foo(i32 noundef %0, i32 noundef %1, i32 noundef %2) #0 {
; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP2:%.*]], 0 ; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP2:%.*]], 0
; CHECK-NEXT: br i1 [[TMP16]], label [[TMP22]], label [[TMP17:%.*]] ; CHECK-NEXT: br i1 [[TMP16]], label [[TMP22]], label [[TMP17:%.*]]
; CHECK: 17: ; CHECK: 17:
; CHECK-NEXT: store i8 -86, ptr [[TMP7]], align 1, !annotation !0 ; CHECK-NEXT: store i8 -86, ptr [[TMP7]], align 1, !annotation [[META0]]
; CHECK-NEXT: store i8 -86, ptr [[TMP8]], align 1, !annotation !0 ; CHECK-NEXT: store i8 -86, ptr [[TMP8]], align 1, !annotation [[META0]]
; CHECK-NEXT: [[TMP18:%.*]] = sext i32 [[TMP0]] to i64 ; CHECK-NEXT: [[TMP18:%.*]] = sext i32 [[TMP0]] to i64
; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 [[TMP18]] ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 [[TMP18]]
; CHECK-NEXT: store i8 12, ptr [[TMP19]], align 1 ; CHECK-NEXT: store i8 12, ptr [[TMP19]], align 1
@ -38,19 +38,19 @@ define i32 @foo(i32 noundef %0, i32 noundef %1, i32 noundef %2) #0 {
; CHECK-NEXT: br label [[TMP22]] ; CHECK-NEXT: br label [[TMP22]]
; CHECK: 22: ; CHECK: 22:
; CHECK-NEXT: [[TMP23:%.*]] = phi i32 [ [[TMP14]], [[TMP10]] ], [ [[TMP21]], [[TMP17]] ], [ 0, [[TMP15]] ] ; CHECK-NEXT: [[TMP23:%.*]] = phi i32 [ [[TMP14]], [[TMP10]] ], [ [[TMP21]], [[TMP17]] ], [ 0, [[TMP15]] ]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr nonnull [[TMP7]]) #[[ATTR3]] ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr nonnull [[TMP5]]) #[[ATTR3]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 100, ptr nonnull [[TMP6]]) #[[ATTR3]] ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 100, ptr nonnull [[TMP4]]) #[[ATTR3]]
; CHECK-NEXT: ret i32 [[TMP23]] ; CHECK-NEXT: ret i32 [[TMP23]]
; ;
%4 = alloca [100 x i8], align 16 %4 = alloca [100 x i8], align 16
%5 = alloca [2 x i8], align 1 %5 = alloca [2 x i8], align 1
%6 = getelementptr inbounds [100 x i8], ptr %4, i64 0, i64 0 %6 = getelementptr inbounds [100 x i8], ptr %4, i64 0, i64 0
call void @llvm.lifetime.start.p0(i64 100, ptr nonnull %6) #3 call void @llvm.lifetime.start.p0(i64 100, ptr nonnull %4) #3
; This memset must move. ; This memset must move.
call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(100) %6, i8 -86, i64 100, i1 false), !annotation !0 call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(100) %6, i8 -86, i64 100, i1 false), !annotation !0
%7 = getelementptr inbounds [2 x i8], ptr %5, i64 0, i64 0 %7 = getelementptr inbounds [2 x i8], ptr %5, i64 0, i64 0
call void @llvm.lifetime.start.p0(i64 2, ptr nonnull %7) #3 call void @llvm.lifetime.start.p0(i64 2, ptr nonnull %5) #3
; This store must move. ; This store must move.
store i8 -86, ptr %7, align 1, !annotation !0 store i8 -86, ptr %7, align 1, !annotation !0
%8 = getelementptr inbounds [2 x i8], ptr %5, i64 0, i64 1 %8 = getelementptr inbounds [2 x i8], ptr %5, i64 0, i64 1
@ -81,8 +81,8 @@ define i32 @foo(i32 noundef %0, i32 noundef %1, i32 noundef %2) #0 {
22: 22:
%23 = phi i32 [ %14, %10 ], [ %21, %17 ], [ 0, %15 ] %23 = phi i32 [ %14, %10 ], [ %21, %17 ], [ 0, %15 ]
call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %7) #3 call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %5) #3
call void @llvm.lifetime.end.p0(i64 100, ptr nonnull %6) #3 call void @llvm.lifetime.end.p0(i64 100, ptr nonnull %4) #3
ret i32 %23 ret i32 %23
} }

View File

@ -4,10 +4,11 @@
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin7" target triple = "i386-apple-darwin7"
define i8 @test(ptr %P) nounwind { define i8 @test() nounwind {
; CHECK-LABEL: define i8 @test( ; CHECK-LABEL: define i8 @test(
; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: [[P:%.*]] = alloca [32 x i8], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr [[P]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr [[P]])
; CHECK-NEXT: store i8 1, ptr [[P]], align 1 ; CHECK-NEXT: store i8 1, ptr [[P]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[P]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[P]])
@ -15,6 +16,7 @@ define i8 @test(ptr %P) nounwind {
; CHECK-NEXT: ret i8 [[TMP0]] ; CHECK-NEXT: ret i8 [[TMP0]]
; ;
entry: entry:
%P = alloca [32 x i8]
call void @llvm.lifetime.start.p0(i64 32, ptr %P) call void @llvm.lifetime.start.p0(i64 32, ptr %P)
%0 = load i8, ptr %P %0 = load i8, ptr %P
store i8 1, ptr %P store i8 1, ptr %P

View File

@ -80,12 +80,14 @@ entry:
; CHECK-LABEL: define ptr @elide_with_retainRV_splitByLifetime( ; CHECK-LABEL: define ptr @elide_with_retainRV_splitByLifetime(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %x = alloca ptr
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %x) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %x)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr %x) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr %x)
; CHECK-NEXT: ret ptr %x ; CHECK-NEXT: ret ptr %x
define ptr @elide_with_retainRV_splitByLifetime(ptr %x) nounwind { define ptr @elide_with_retainRV_splitByLifetime() nounwind {
entry: entry:
; Cleanup should skip over lifetime intrinsics. ; Cleanup should skip over lifetime intrinsics.
%x = alloca ptr
call void @llvm.lifetime.start(i64 8, ptr %x) call void @llvm.lifetime.start(i64 8, ptr %x)
%b = call ptr @llvm.objc.autoreleaseReturnValue(ptr %x) nounwind %b = call ptr @llvm.objc.autoreleaseReturnValue(ptr %x) nounwind
call void @llvm.lifetime.end(i64 8, ptr %x) call void @llvm.lifetime.end(i64 8, ptr %x)
@ -218,13 +220,15 @@ entry:
; CHECK-LABEL: define ptr @elide_with_claimRV_splitByLifetime( ; CHECK-LABEL: define ptr @elide_with_claimRV_splitByLifetime(
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %x = alloca ptr
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %x) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %x)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr %x) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr %x)
; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x) ; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x)
; CHECK-NEXT: ret ptr %x ; CHECK-NEXT: ret ptr %x
define ptr @elide_with_claimRV_splitByLifetime(ptr %x) nounwind { define ptr @elide_with_claimRV_splitByLifetime() nounwind {
entry: entry:
; Cleanup should skip over lifetime intrinsics. ; Cleanup should skip over lifetime intrinsics.
%x = alloca ptr
call void @llvm.lifetime.start(i64 8, ptr %x) call void @llvm.lifetime.start(i64 8, ptr %x)
%b = call ptr @llvm.objc.autoreleaseReturnValue(ptr %x) nounwind %b = call ptr @llvm.objc.autoreleaseReturnValue(ptr %x) nounwind
call void @llvm.lifetime.end(i64 8, ptr %x) call void @llvm.lifetime.end(i64 8, ptr %x)

View File

@ -478,43 +478,6 @@ l2:
br label %l2 br label %l2
} }
; This test checks for a bug where the stack coloring algorithm was not tracking
; the live range of allocas through phi instructions, so it did not consider
; alloca and alloca2 to be live at the same time. As a result it was using
; the same stack slot for both allocas. To ensure this bug isn't present, we
; check that there are 64 bytes allocated for the unsafe stack which is enough
; space for both allocas.
; CHECK-LABEL: @stack_coloring_liveness_bug
define void @stack_coloring_liveness_bug(i32 %arg0) #0 {
entry:
; CHECK: %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
; CHECK-NEXT: getelementptr i8, ptr %[[USP]], i32 -64
%alloca = alloca [32 x i8], align 16
%alloca2 = alloca [32 x i8], align 16
%cond = icmp eq i32 %arg0, 0
br i1 %cond, label %if, label %else
if:
br label %end
else:
; CHECK: getelementptr i8, ptr %[[USP]], i32 -32
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca)
call void @capture8(ptr %alloca)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca)
br label %end
end:
; CHECK: getelementptr i8, ptr %[[USP]], i32 -64
%alloca.end = phi ptr [ %alloca, %if], [%alloca, %else]
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca2)
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca.end)
call void @capture2_8(ptr %alloca2, ptr %alloca.end)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca2)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca.end)
ret void
}
attributes #0 = { safestack } attributes #0 = { safestack }
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.start.p0(i64, ptr nocapture)

View File

@ -164,19 +164,21 @@ define void @test_scatter_8i32(<8 x i32> %a1, <8 x ptr> %ptr, <8 x i1> %mask, i3
} }
declare void @llvm.lifetime.start.p0(i64, ptr) declare void @llvm.lifetime.start.p0(i64, ptr)
define void @test_lifetime_start(i64 %arg0, ptr %ptr) { define void @test_lifetime_start(i64 %arg0) {
; CHECK: immarg operand has non-immediate parameter ; CHECK: immarg operand has non-immediate parameter
; CHECK-NEXT: i64 %arg0 ; CHECK-NEXT: i64 %arg0
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 %arg0, ptr %ptr) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 %arg0, ptr %ptr)
%ptr = alloca i64
call void @llvm.lifetime.start.p0(i64 %arg0, ptr %ptr) call void @llvm.lifetime.start.p0(i64 %arg0, ptr %ptr)
ret void ret void
} }
declare void @llvm.lifetime.end.p0(i64, ptr) declare void @llvm.lifetime.end.p0(i64, ptr)
define void @test_lifetime_end(i64 %arg0, ptr %ptr) { define void @test_lifetime_end(i64 %arg0) {
; CHECK: immarg operand has non-immediate parameter ; CHECK: immarg operand has non-immediate parameter
; CHECK-NEXT: i64 %arg0 ; CHECK-NEXT: i64 %arg0
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 %arg0, ptr %ptr) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 %arg0, ptr %ptr)
%ptr = alloca i64
call void @llvm.lifetime.end.p0(i64 %arg0, ptr %ptr) call void @llvm.lifetime.end.p0(i64 %arg0, ptr %ptr)
ret void ret void
} }

View File

@ -37,12 +37,14 @@ define void @atomicrmw(ptr %a, i32 %i) {
ret void ret void
} }
define void @opaque_mangle(ptr %a) { define void @opaque_mangle() {
; CHECK-LABEL: @opaque_mangle( ; CHECK-LABEL: @opaque_mangle(
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[A:%.*]]) ; CHECK-NEXT: [[A:%.*]] = alloca i64, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[A]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[A]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%a = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %a) call void @llvm.lifetime.start.p0(i64 8, ptr %a)
call void @llvm.lifetime.end.p0(i64 8, ptr %a) call void @llvm.lifetime.end.p0(i64 8, ptr %a)
ret void ret void

View File

@ -1,10 +1,11 @@
; RUN: mlir-translate -import-llvm -prefer-unregistered-intrinsics %s | FileCheck %s ; RUN: mlir-translate -import-llvm -prefer-unregistered-intrinsics %s | FileCheck %s
; CHECK-LABEL: llvm.func @lifetime ; CHECK-LABEL: llvm.func @lifetime
define void @lifetime(ptr %0) { define void @lifetime() {
; CHECK: llvm.call_intrinsic "llvm.lifetime.start.p0"({{.*}}, %arg0) : (i64, !llvm.ptr {llvm.nonnull}) -> () %a = alloca [16 x i8]
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %0) ; CHECK: llvm.call_intrinsic "llvm.lifetime.start.p0"({{.*}}, %[[ptr:.*]]) : (i64, !llvm.ptr {llvm.nonnull}) -> ()
; CHECK: llvm.call_intrinsic "llvm.lifetime.end.p0"({{.*}}, %arg0) : (i64, !llvm.ptr {llvm.nonnull}) -> () call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %a)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %0) ; CHECK: llvm.call_intrinsic "llvm.lifetime.end.p0"({{.*}}, %[[ptr]]) : (i64, !llvm.ptr {llvm.nonnull}) -> ()
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %a)
ret void ret void
} }

View File

@ -874,11 +874,12 @@ define void @stack_restore(ptr %0, ptr addrspace(1) %1) {
} }
; CHECK-LABEL: llvm.func @lifetime ; CHECK-LABEL: llvm.func @lifetime
define void @lifetime(ptr %0) { define void @lifetime() {
%a = alloca [16 x i8]
; CHECK: llvm.intr.lifetime.start 16, %{{.*}} : !llvm.ptr ; CHECK: llvm.intr.lifetime.start 16, %{{.*}} : !llvm.ptr
call void @llvm.lifetime.start.p0(i64 16, ptr %0) call void @llvm.lifetime.start.p0(i64 16, ptr %a)
; CHECK: llvm.intr.lifetime.end 32, %{{.*}} : !llvm.ptr ; CHECK: llvm.intr.lifetime.end 32, %{{.*}} : !llvm.ptr
call void @llvm.lifetime.end.p0(i64 32, ptr %0) call void @llvm.lifetime.end.p0(i64 32, ptr %a)
ret void ret void
} }

View File

@ -1096,11 +1096,13 @@ llvm.func @vector_deinterleave2(%vec1: vector<4xf64>, %vec2: vector<[8]xi32>) {
} }
// CHECK-LABEL: @lifetime // CHECK-LABEL: @lifetime
llvm.func @lifetime(%p: !llvm.ptr) { llvm.func @lifetime() {
%c = llvm.mlir.constant(16 : i64) : i64
%a = llvm.alloca %c x i8 : (i64) -> !llvm.ptr
// CHECK: call void @llvm.lifetime.start // CHECK: call void @llvm.lifetime.start
llvm.intr.lifetime.start 16, %p : !llvm.ptr llvm.intr.lifetime.start 16, %a : !llvm.ptr
// CHECK: call void @llvm.lifetime.end // CHECK: call void @llvm.lifetime.end
llvm.intr.lifetime.end 16, %p : !llvm.ptr llvm.intr.lifetime.end 16, %a : !llvm.ptr
llvm.return llvm.return
} }

View File

@ -66,8 +66,8 @@ if.then52: ; preds = %land.lhs.true49
br label %cleanup br label %cleanup
cleanup: ; preds = %if.then52, %land.lhs.true49, %entry.split cleanup: ; preds = %if.then52, %land.lhs.true49, %entry.split
call void @llvm.lifetime.end(i64 24, i8* %0) call void @dummy(ptr %0)
ret void ret void
} }
declare void @llvm.lifetime.end(i64, i8* nocapture) declare void @dummy(ptr)