[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
object, or -1 if it is variable sized. The second argument is a pointer
to the object.
to an ``alloca`` instruction.
Semantics:
""""""""""
If ``ptr`` is a stack-allocated object and it points to the first byte of
the object, the object is initially marked as dead.
``ptr`` is conservatively considered as a non-stack-allocated object if
the stack coloring algorithm that is used in the optimization pipeline cannot
conclude that ``ptr`` is a stack-allocated object.
After '``llvm.lifetime.start``', the stack object that ``ptr`` points is marked
as alive and has an uninitialized value.
The stack-allocated object that ``ptr`` points to is initially marked as dead.
After '``llvm.lifetime.start``', the stack object is marked as alive and has an
uninitialized value.
The stack object is marked as dead when either
:ref:`llvm.lifetime.end <int_lifeend>` to the alloca is executed or the
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
does not change the address of the object.
If ``ptr`` is a non-stack-allocated object, it does not point to the first
byte of the object or it is a stack object that is already alive, it simply
fills all bytes of the object with ``poison``.
.. _int_lifeend:
'``llvm.lifetime.end``' Intrinsic
@ -26689,24 +26679,16 @@ Arguments:
The first argument is a constant integer representing the size of the
object, or -1 if it is variable sized. The second argument is a pointer
to the object.
to an ``alloca`` instruction.
Semantics:
""""""""""
If ``ptr`` is a stack-allocated object and it points to the first byte of the
object, the object is dead.
``ptr`` is conservatively considered as a non-stack-allocated object if
the stack coloring algorithm that is used in the optimization pipeline cannot
conclude that ``ptr`` is a stack-allocated object.
The stack-allocated object that ``ptr`` points to becomes dead after the call
to this intrinsic.
Calling ``llvm.lifetime.end`` on an already dead alloca is no-op.
If ``ptr`` is a non-stack-allocated object or it does not point to the first
byte of the object, it is equivalent to simply filling all bytes of the object
with ``poison``.
'``llvm.invariant.start``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

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

View File

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

View File

@ -1310,6 +1310,18 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
return true;
}
break;
case 'l':
if (Name.starts_with("lifetime.start") ||
Name.starts_with("lifetime.end")) {
// Unless remangling is required, do not upgrade the function declaration,
// but do upgrade the calls.
if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F))
NewFn = *Result;
else
NewFn = F;
return true;
}
break;
case 'm': {
// Updating the memory intrinsics (memcpy/memmove/memset) that have an
// alignment parameter to embedding the alignment as an attribute of
@ -1629,7 +1641,6 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
NewFn = nullptr;
bool Upgraded =
upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords);
assert(F != NewFn && "Intrinsic function upgraded to the same function");
// Upgrade intrinsic attributes. This does not change the function.
if (NewFn)
@ -4570,6 +4581,9 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
}
const auto &DefaultCase = [&]() -> void {
if (F == NewFn)
return;
if (CI->getFunctionType() == NewFn->getFunctionType()) {
// Handle generic mangling change.
assert(
@ -5109,6 +5123,31 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
MTI->setSourceAlignment(Align->getMaybeAlignValue());
break;
}
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end: {
Value *Size = CI->getArgOperand(0);
Value *Ptr = CI->getArgOperand(1);
if (isa<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 "
"the default case");
@ -5131,7 +5170,8 @@ void llvm::UpgradeCallsToIntrinsic(Function *F) {
UpgradeIntrinsicCall(CB, NewFn);
// Remove old function, no longer used, from the module.
F->eraseFromParent();
if (F != NewFn)
F->eraseFromParent();
}
}

View File

@ -6720,6 +6720,11 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
"llvm.threadlocal.address operand isThreadLocal() must be true");
break;
}
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
Check(isa<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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,6 +4,7 @@
define i32 @trivially_free() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -13,14 +14,15 @@ define i32 @trivially_free() {
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
;
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -30,13 +32,14 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef
;
%alloca = alloca i8
%a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4)
@ -46,8 +49,8 @@ define i32 @trivially_free() {
%a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef)
call void @llvm.lifetime.end.p0(i64 1, ptr undef)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
%a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1)
%a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)

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() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 4
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -15,8 +16,8 @@ define i32 @trivially_free() {
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123)
@ -25,6 +26,7 @@ define i32 @trivially_free() {
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
;
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 4
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -34,8 +36,8 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123)
@ -43,6 +45,7 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
;
%alloca = alloca i8
%a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4)
@ -52,8 +55,8 @@ define i32 @trivially_free() {
%a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef)
call void @llvm.lifetime.end.p0(i64 1, ptr undef)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
%a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1)
%a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
%a7 = call i1 @llvm.allow.ubsan.check(i8 123)

View File

@ -4,6 +4,7 @@
define i32 @trivially_free() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -13,8 +14,8 @@ define i32 @trivially_free() {
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
@ -23,6 +24,7 @@ define i32 @trivially_free() {
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
;
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %alloca = alloca i8, align 1
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32.p0(i32 undef, ptr undef, ptr undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !3)
@ -32,8 +34,8 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a4 = call i1 @llvm.is.constant.i32(i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
@ -41,6 +43,7 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check")
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
;
%alloca = alloca i8
%a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef)
call void @llvm.assume(i1 undef)
call void @llvm.experimental.noalias.scope.decl(metadata !4)
@ -50,8 +53,8 @@ define i32 @trivially_free() {
%a2 = call ptr @llvm.launder.invariant.group.p0(ptr undef)
%a3 = call ptr @llvm.strip.invariant.group.p0(ptr undef)
%a4 = call i1 @llvm.is.constant.i32(i32 undef)
call void @llvm.lifetime.start.p0(i64 1, ptr undef)
call void @llvm.lifetime.end.p0(i64 1, ptr undef)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloca)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloca)
%a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1)
%a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)
call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef)

View File

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

View File

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

View File

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

View File

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

View File

@ -143,54 +143,4 @@ l:
; CHECK-NOT: @llvm.aarch64.irg.sp
; CHECK: ret void
; If we can't trace one of the lifetime markers to a single alloca, fall back
; to poisoning all allocas at the beginning of the function.
; Each alloca must be poisoned only once.
define void @UnrecognizedLifetime(i8 %v) sanitize_memtag {
entry:
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
%tobool = icmp eq i8 %v, 0
%xy = select i1 %tobool, ptr %x, ptr %y
%cxcy = select i1 %tobool, ptr %x, ptr %y
br label %another_bb
another_bb:
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z)
store i32 7, ptr %z
call void @noUse32(ptr %z)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z)
store i32 7, ptr %z
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cxcy)
store i32 8, ptr %xy
call void @noUse32(ptr %x)
call void @noUse32(ptr %y)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cxcy)
ret void
}
; CHECK-LABEL: define void @UnrecognizedLifetime(
; CHECK: call ptr @llvm.aarch64.irg.sp(i64 0)
; CHECK: alloca { i32, [12 x i8] }, align 16
; CHECK: call ptr @llvm.aarch64.tagp
; CHECK: call void @llvm.aarch64.settag(
; CHECK: alloca { i32, [12 x i8] }, align 16
; CHECK: call ptr @llvm.aarch64.tagp
; CHECK: call void @llvm.aarch64.settag(
; CHECK: alloca { i32, [12 x i8] }, align 16
; CHECK: call ptr @llvm.aarch64.tagp
; CHECK: call void @llvm.aarch64.settag(
; CHECK: store i32
; CHECK: call void @noUse32(ptr
; CHECK: store i32
; CHECK: store i32
; CHECK: call void @noUse32(ptr
; CHECK: call void @llvm.aarch64.settag(
; CHECK: call void @llvm.aarch64.settag(
; CHECK: call void @llvm.aarch64.settag(
; CHECK: ret void
!0 = !{}

View File

@ -17,6 +17,7 @@ declare void @_ZNSsC1EPKcRKSaIcE() unnamed_addr #0
; CHECK: .LBB0_2
; Function Attrs: nounwind
define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttributesEPKNS_5SUnitENS_13SUnitIteratorEPKNS_11ScheduleDAGE() #0 align 2 {
%a = alloca i8
br i1 undef, label %1, label %2
; <label>:1: ; preds = %0
@ -25,7 +26,7 @@ define hidden void @_ZN4llvm14DOTGraphTraitsIPNS_13ScheduleDAGMIEE17getEdgeAttri
br label %3
; <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
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).
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-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: [[CMP_FROZEN:%.*]] = freeze i1 [[CMP:%.*]]
; 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: ret i32 [[SEL]]
;
%a = alloca i32
%load = load i32, ptr %a, align 8
call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %a)
%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:
%alloc = alloca [16 x i8], i8 2, align 1
%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 16, ptr nonnull %part2)
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloc)
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)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %alloc)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %part2)
call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloc)
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: # %bb.0: # %entry
; AA-NEXT: vmovups (%rsi), %xmm0
; AA-NEXT: vmovups (%rdi), %xmm0
; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; AA-NEXT: vmovups (%rsi), %xmm0
; AA-NEXT: vmovups %xmm0, (%rdi)
; AA-NEXT: retq
entry:

View File

@ -23,7 +23,7 @@ declare i32 @dummyPersonality(...)
define void @FuncletPersonality(ptr %ptrParam) sanitize_address personality ptr @__CxxFrameHandler3 {
; 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: [[TMP0:%.*]] = alloca i64, align 32
; 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: [[TMP39:%.*]] = add i64 [[TMP29]], 1066
; 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: [[TMP41:%.*]] = add i64 [[TMP40]], [[TMP1]]
; 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: br i1 [[TMP48]], label [[TMP49:%.*]], label [[TMP50]]
; 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: 50:
; CHECK-INLINE-NEXT: store volatile i8 0, ptr [[TMP22]], align 1
; 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 @llvm.lifetime.end.p0(i64 4, ptr [[TMP22]])
; CHECK-INLINE-NEXT: [[TMP52:%.*]] = alloca i8, i64 96, align 32
; CHECK-INLINE-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP52]] to i64
; 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: br i1 [[TMP66]], label [[TMP67:%.*]], label [[TMP68:%.*]]
; 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: 68:
; 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: br i1 [[TMP88]], label [[TMP89:%.*]], label [[TMP90]]
; 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: 90:
; 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-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 @llvm.lifetime.start.p0(i64 4, ptr [[TMP56]])
; CHECK-INLINE-NEXT: [[TMP99:%.*]] = lshr i64 [[TMP54]], 3
; CHECK-INLINE-NEXT: [[TMP100:%.*]] = add i64 [[TMP99]], [[TMP1]]
; 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: br i1 [[TMP107]], label [[TMP108:%.*]], label [[TMP109]]
; 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: 109:
; 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 @llvm.lifetime.end.p0(i64 4, ptr [[TMP56]])
; 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: [[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: br i1 [[TMP125]], label [[TMP126:%.*]], label [[TMP127]]
; 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: 127:
; 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: br i1 [[TMP136]], label [[TMP137:%.*]], label [[EHEXIT]]
; 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: ehexit:
; 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-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: [[TMP0:%.*]] = alloca i64, align 32
; 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: [[TMP46:%.*]] = add i64 [[TMP33]], 1066
; 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: store volatile i8 0, ptr [[TMP22]], align 1
; 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 @llvm.lifetime.end.p0(i64 4, ptr [[TMP22]])
; CHECK-OUTLINE-NEXT: call void @__asan_store8(i64 [[TMP25]])
; CHECK-OUTLINE-NEXT: store volatile i64 0, 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: [[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 @llvm.lifetime.start.p0(i64 4, ptr [[TMP24]])
; 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: [[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 @llvm.lifetime.end.p0(i64 4, ptr [[TMP24]])
; 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: [[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.
define void @OtherPersonality(ptr %ptrParam) sanitize_address personality ptr @dummyPersonality {
; 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: [[TMP0:%.*]] = load i64, ptr @__asan_shadow_memory_dynamic_address, 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)
; 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)
invoke void @__cxa_throw(ptr %exception, ptr @_ZTI3ABC, ptr @_ZN3ABCD2Ev) noreturn
@ -38,7 +38,7 @@ lpad:
call void @_ZN3ABCD2Ev(ptr nonnull %x)
call void @llvm.lifetime.end.p0(i64 4, ptr %x)
; CHECK: store i8 -8, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.end
; CHECK-NOT: @llvm.lifetime.end
resume { ptr, i32 } %0
; CHECK: store i64 0, ptr %{{[0-9]+}}
@ -77,7 +77,7 @@ entry:
call void @llvm.lifetime.start.p0(i64 4, ptr %x)
; 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
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 @llvm.lifetime.end.p0(i64 4, ptr %x)
; CHECK: store i8 -8, ptr %{{[0-9]+}}
; CHECK-NEXT: @llvm.lifetime.end
; CHECK-NOT: @llvm.lifetime.end
cleanupret from %0 unwind to caller
; 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: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
; 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: [[TMP12:%.*]] = ptrtoint ptr [[AI]] to i64
; CHECK-NEXT: [[TMP13:%.*]] = lshr i64 [[TMP12]], 3
@ -49,7 +48,6 @@ define void @lifetime_no_size(i64 %i) sanitize_address {
; CHECK-NEXT: unreachable
; CHECK: [[BB23]]:
; 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: [[TMP24:%.*]] = add i64 [[TMP9]], 0
; 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: [[TMP15:%.*]] = inttoptr i64 [[TMP14]] to ptr
; 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: [[TMP17:%.*]] = lshr i64 [[TMP16]], 3
; 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: [[TMP29:%.*]] = inttoptr i64 [[TMP28]] to ptr
; 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: [[TMP31:%.*]] = inttoptr i64 [[TMP30]] to ptr
; 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: [[TMP33:%.*]] = ptrtoint ptr [[TMP32]] to i64
; 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: [[TMP37:%.*]] = ptrtoint ptr [[TMP36]] to i64
; 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: [[TMP39:%.*]] = lshr i64 [[TMP38]], 3
; 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: [[TMP50:%.*]] = ptrtoint ptr [[TMP36]] to i64
; 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: [[TMP52:%.*]] = inttoptr i64 [[TMP51]] to ptr
; 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: [[TMP54:%.*]] = lshr i64 [[TMP53]], 3
; 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: [[TMP66:%.*]] = inttoptr i64 [[TMP65]] to ptr
; 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: [[TMP68:%.*]] = load i64, ptr [[TMP1]], align 8
; 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: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
; 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: [[TMP16:%.*]] = lshr i64 [[TMP15]], 3
; 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: [[TMP28:%.*]] = inttoptr i64 [[TMP27]] to ptr
; 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: [[TMP30:%.*]] = inttoptr i64 [[TMP29]] to ptr
; 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: call void @llvm.lifetime.start.p0(i64 40, ptr [[ARR]])
; 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: [[TMP44:%.*]] = inttoptr i64 [[TMP43]] to ptr
; 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: [[TMP46:%.*]] = lshr i64 [[TMP45]], 3
; 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: [[TMP58:%.*]] = inttoptr i64 [[TMP57]] to ptr
; 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: [[TMP59:%.*]] = add i64 [[TMP10]], 0
; CHECK-NO-DYNAMIC-NEXT: [[TMP60:%.*]] = inttoptr i64 [[TMP59]] to ptr
@ -325,166 +311,6 @@ define void @lifetime() sanitize_address {
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 {
; CHECK-LABEL: define void @zero_sized(
; 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: store i8 2, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 650, ptr %xx)
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: 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)
; 0005
@ -118,8 +114,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; 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)
; 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: 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)
; 00000000
@ -142,8 +134,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; 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)
; 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: store i8 -8, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr %zz)
; CHECK: {{^[0-9]+}}:
; 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: store i8 2, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 650, ptr %xx)
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: 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)
; 0005
@ -118,8 +114,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; 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)
; 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: 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)
; 00000000
@ -142,8 +134,6 @@ entry:
; ENTRY-UAS-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to ptr
; 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)
; 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: store i8 -8, ptr [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr %zz)
; CHECK: {{^[0-9]+}}:
; CHECK-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
@ -209,40 +197,6 @@ entry:
; 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.end.p0(i64, ptr nocapture)

View File

@ -176,78 +176,5 @@ entry:
; CHECK: call void @llvm.lifetime.end
; 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.end.p0(i64 immarg, ptr nocapture)

View File

@ -393,26 +393,6 @@ bb:
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
define void @test11() {

View File

@ -340,27 +340,6 @@ bb:
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
define void @test11() {

View File

@ -18,11 +18,11 @@ bb:
br i1 %tmp4, label %bb6, label %bb5
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 @g, align 4, !tbaa !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
bb6: ; preds = %bb5, %bb

View File

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

View File

@ -61,10 +61,11 @@ entry:
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-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.end.p0(i64 100000000128, 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
;
entry:
%ptr = alloca i8
call void @llvm.lifetime.start.p0(i64 100000000032, ptr %ptr)
call void @llvm.lifetime.start.p0(i64 100000000064, 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
}
; 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: [[sub]] = !DILocalVariable

View File

@ -67,19 +67,6 @@ define void @test_strcat_with_lifetime(ptr %src) {
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
define void @test4(ptr %src) {
; CHECK-LABEL: @test4(

View File

@ -25,12 +25,12 @@ define void @test1() {
define void @test2(ptr %P) {
; 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.end.p0(i64 4, ptr [[Q]])
; CHECK-NEXT: ret void
;
%Q = getelementptr i32, ptr %P, i32 1
%Q = alloca i32
call void @llvm.lifetime.start.p0(i64 4, ptr %Q)
store i32 0, ptr %Q ;; This store is dead.
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
; `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-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_2:%.*]] = getelementptr i8, ptr [[A]], i64 2
; 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 @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
;
%A = alloca [4 x i8]
call void @llvm.lifetime.start.p0(i64 2, ptr %A)
%A.1 = getelementptr i8, ptr %A, i64 1
%A.2 = getelementptr i8, ptr %A, i64 2

View File

@ -398,7 +398,7 @@ bb5:
@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-NEXT: entry:
; 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: br i1 [[C_1]], label [[FOR_BODY_I]], label [[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: br label [[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
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
br label %for.body.i20
@ -435,7 +435,6 @@ for.body.i20: ; preds = %for.body.i20, %init
exit:
ret void
}
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
declare i1 @cond() readnone nounwind
; 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
;; 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-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: [[QV:%.*]] = load i32, ptr [[Q]], align 4
; 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-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: [[QV:%.*]] = load i32, ptr [[Q]], align 4
; 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
;
entry:
%p = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %p)
%q = getelementptr i32, ptr %p, i64 1
%pv = load i32, ptr %p
%qv = load i32, ptr %q
@ -178,10 +184,12 @@ entry:
;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
;; 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-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: call void @llvm.lifetime.end.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-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: call void @llvm.lifetime.end.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 [[QV]], ptr [[Q]], align 4
; CHECK-NEXT: ret void
;
entry:
%p = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %p)
%pv = load i32, ptr %p
%qv = load i32, ptr %q
call void @llvm.lifetime.end.p0(i64 8, ptr %p)

View File

@ -107,7 +107,8 @@ entry:
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)
store i8 %val, 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
; merging of stack slots. CodeExtractor must replicate the effects of
; 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 %gep1)
call void @llvm.lifetime.start.p0(i64 1, ptr %local1)
call void @llvm.lifetime.start.p0(i64 1, 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)
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
target triple = "nvptx64-nvidia-cuda"
@ -6,11 +7,13 @@ define i32 @lifetime_flat_pointer() {
; CHECK-LABEL: define i32 @lifetime_flat_pointer() {
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4
; 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: %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: ret i32 %ret
; CHECK-NEXT: [[RET:%.*]] = load i32, ptr addrspace(5) [[TMP1]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
; CHECK-NEXT: ret i32 [[RET]]
;
%alloca = alloca i32, align 4
%1 = addrspacecast ptr %alloca to ptr addrspace(5)

View File

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

View File

@ -104,11 +104,8 @@ define void @outer6(ptr %a, ptr %ptr) {
ret void
}
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) argmemonly nounwind
define void @inner6(ptr %a, ptr %ptr) {
%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
call void @pad()
%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)
define void @test3() {
call void @llvm.lifetime.start.p0(i64 -1, ptr undef)
call void @llvm.lifetime.end.p0(i64 -1, ptr undef)
%a = alloca i32
call void @llvm.lifetime.start.p0(i64 -1, ptr %a)
call void @llvm.lifetime.end.p0(i64 -1, ptr %a)
ret void
}

View File

@ -109,8 +109,6 @@ define void @test3(ptr %src) {
; CHECK-NEXT: ret void
;
%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)
store i8 42, ptr %a
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-SAME: ({ <4 x i32>, <8 x i32> } [[A:%.*]], ptr [[P:%.*]]) {
; 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: [[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]]
;
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
%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
}

View File

@ -431,195 +431,26 @@ exit:
ret void
}
define void @lifetime_for_ptr_first_arg_before_multiply(ptr noalias %A, ptr noalias %B, 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) {
define void @multiple_unrelated_lifetimes(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @multiple_unrelated_lifetimes(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ALLOC_1:%.*]] = 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: 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_2]])
; CHECK-NEXT: br label [[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: [[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: [[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
@ -682,6 +513,10 @@ define void @multiple_unrelated_lifetimes(ptr noalias %A, ptr noalias %B, ptr no
entry:
%alloc.1 = 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
%b = load <4 x double>, ptr %B, align 8
br i1 %c.0, label %then, label %exit
@ -699,106 +534,20 @@ exit:
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) {
; 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) {
define void @lifetimes_for_args_in_different_blocks(ptr noalias %C, i1 %c.0) {
; CHECK-LABEL: @lifetimes_for_args_in_different_blocks(
; CHECK-NEXT: entry:
; 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: then:
; 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: [[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
@ -864,7 +613,9 @@ define void @lifetimes_for_args_in_different_blocks(ptr noalias %B, ptr noalias
;
entry:
%A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A)
call void @init(ptr %B)
br i1 %c.0, label %then, label %exit
then:
@ -880,15 +631,17 @@ exit:
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-NEXT: entry:
; 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: then:
; 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: exit:
; 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:
%A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A)
call void @init(ptr %B)
br i1 %c.0, label %then, label %exit
then:
@ -973,18 +728,20 @@ exit:
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-NEXT: entry:
; 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: then:
; 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: [[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
@ -1048,7 +805,9 @@ define void @lifetimes_for_args_load0_in_different_block(ptr noalias %B, ptr noa
;
entry:
%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
call void @llvm.lifetime.end(i64 -1, ptr %A)
br i1 %c.0, label %then, label %exit
@ -1064,18 +823,20 @@ exit:
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-NEXT: entry:
; 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: then:
; 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: [[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
@ -1139,7 +900,9 @@ define void @lifetimes_for_args_load1_in_different_block(ptr noalias %B, ptr noa
;
entry:
%A = alloca <4 x double>
%B = alloca <4 x double>
call void @init(ptr %A)
call void @init(ptr %B)
%b = load <4 x double>, ptr %B, align 8
call void @llvm.lifetime.end(i64 -1, ptr %B)
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
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.
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-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
;
%in = alloca i64
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)
ret void
}
; 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-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: ret void
;
%in = alloca i64
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)
ret void
}
; 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-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: ret void
;
%lifetime = alloca i64
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)
ret void

View File

@ -37,29 +37,10 @@ define void @test_alloca_with_lifetimes(ptr %result) {
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.
define void @test_copy_larger_than_lifetime_size(ptr %result) {
; 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.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)
@ -67,7 +48,7 @@ define void @test_copy_larger_than_lifetime_size(ptr %result) {
; CHECK-NEXT: call void @free(ptr [[A]])
; 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.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)

View File

@ -94,21 +94,6 @@ entry:
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) {
; CHECK-LABEL: @test7(
; 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: [[TMP5:%.*]] = alloca [2 x i8], align 1
; 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: 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: [[TMP9:%.*]] = icmp eq i32 [[TMP1:%.*]], 0
; CHECK-NEXT: br i1 [[TMP9]], label [[TMP15:%.*]], label [[TMP10:%.*]]
; 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: [[TMP12:%.*]] = getelementptr inbounds [100 x i8], ptr [[TMP4]], i64 0, i64 [[TMP11]]
; 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: br i1 [[TMP16]], label [[TMP22]], label [[TMP17:%.*]]
; CHECK: 17:
; CHECK-NEXT: store i8 -86, ptr [[TMP7]], align 1, !annotation !0
; CHECK-NEXT: store i8 -86, ptr [[TMP8]], 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 [[META0]]
; CHECK-NEXT: [[TMP18:%.*]] = sext i32 [[TMP0]] to i64
; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [2 x i8], ptr [[TMP5]], i64 0, i64 [[TMP18]]
; 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: 22:
; 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 100, ptr nonnull [[TMP6]]) #[[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 [[TMP4]]) #[[ATTR3]]
; CHECK-NEXT: ret i32 [[TMP23]]
;
%4 = alloca [100 x i8], align 16
%5 = alloca [2 x i8], align 1
%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.
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
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.
store i8 -86, ptr %7, align 1, !annotation !0
%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:
%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 100, ptr nonnull %6) #3
call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %5) #3
call void @llvm.lifetime.end.p0(i64 100, ptr nonnull %4) #3
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 triple = "i386-apple-darwin7"
define i8 @test(ptr %P) nounwind {
define i8 @test() nounwind {
; CHECK-LABEL: define i8 @test(
; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
; 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: store i8 1, ptr [[P]], align 1
; 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]]
;
entry:
%P = alloca [32 x i8]
call void @llvm.lifetime.start.p0(i64 32, ptr %P)
%0 = load i8, ptr %P
store i8 1, ptr %P

View File

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

View File

@ -478,43 +478,6 @@ 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 }
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)
define void @test_lifetime_start(i64 %arg0, ptr %ptr) {
define void @test_lifetime_start(i64 %arg0) {
; CHECK: immarg operand has non-immediate parameter
; CHECK-NEXT: i64 %arg0
; 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)
ret void
}
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-NEXT: i64 %arg0
; 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)
ret void
}

View File

@ -37,12 +37,14 @@ define void @atomicrmw(ptr %a, i32 %i) {
ret void
}
define void @opaque_mangle(ptr %a) {
define void @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: ret void
;
%a = alloca i64
call void @llvm.lifetime.start.p0(i64 8, ptr %a)
call void @llvm.lifetime.end.p0(i64 8, ptr %a)
ret void

View File

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

View File

@ -874,11 +874,12 @@ define void @stack_restore(ptr %0, ptr addrspace(1) %1) {
}
; 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
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
call void @llvm.lifetime.end.p0(i64 32, ptr %0)
call void @llvm.lifetime.end.p0(i64 32, ptr %a)
ret void
}

View File

@ -1096,11 +1096,13 @@ llvm.func @vector_deinterleave2(%vec1: vector<4xf64>, %vec2: vector<[8]xi32>) {
}
// 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
llvm.intr.lifetime.start 16, %p : !llvm.ptr
llvm.intr.lifetime.start 16, %a : !llvm.ptr
// CHECK: call void @llvm.lifetime.end
llvm.intr.lifetime.end 16, %p : !llvm.ptr
llvm.intr.lifetime.end 16, %a : !llvm.ptr
llvm.return
}

View File

@ -66,8 +66,8 @@ if.then52: ; preds = %land.lhs.true49
br label %cleanup
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
}
declare void @llvm.lifetime.end(i64, i8* nocapture)
declare void @dummy(ptr)