[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:
parent
b78b16b213
commit
92c55a315e
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
57
llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll
Normal file
57
llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 = !{}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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]+}}
|
||||
|
@ -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:%.*]]) {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user