Skip to content

Commit 86727fe

Browse files
authored
[IR] Allow poison argument to lifetime markers (#151148)
This slightly relaxes the invariant established in #149310, by also allowing the lifetime argument to be poison. This is to support the typical pattern of RAUWing with poison when removing an instruction. It's worth noting that this does not require any conservative assumptions, lifetimes with poison arguments can simply be skipped. Fixes #151119.
1 parent d95dadf commit 86727fe

File tree

14 files changed

+138
-36
lines changed

14 files changed

+138
-36
lines changed

llvm/docs/LangRef.rst

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26658,14 +26658,17 @@ Arguments:
2665826658
The first argument is a constant integer, which is ignored and will be removed
2665926659
in the future.
2666026660

26661-
The second argument is a pointer to an ``alloca`` instruction.
26661+
The second argument is either a pointer to an ``alloca`` instruction or
26662+
a ``poison`` value.
2666226663

2666326664
Semantics:
2666426665
""""""""""
2666526666

26666-
The stack-allocated object that ``ptr`` points to is initially marked as dead.
26667-
After '``llvm.lifetime.start``', the stack object is marked as alive and has an
26668-
uninitialized value.
26667+
If ``ptr`` is a ``poison`` value, the intrinsic has no effect.
26668+
26669+
Otherwise, the stack-allocated object that ``ptr`` points to is initially
26670+
marked as dead. After '``llvm.lifetime.start``', the stack object is marked as
26671+
alive and has an uninitialized value.
2666926672
The stack object is marked as dead when either
2667026673
:ref:`llvm.lifetime.end <int_lifeend>` to the alloca is executed or the
2667126674
function returns.
@@ -26699,13 +26702,16 @@ Arguments:
2669926702
The first argument is a constant integer, which is ignored and will be removed
2670026703
in the future.
2670126704

26702-
The second argument is a pointer to an ``alloca`` instruction.
26705+
The second argument is either a pointer to an ``alloca`` instruction or
26706+
a ``poison`` value.
2670326707

2670426708
Semantics:
2670526709
""""""""""
2670626710

26707-
The stack-allocated object that ``ptr`` points to becomes dead after the call
26708-
to this intrinsic.
26711+
If ``ptr`` is a ``poison`` value, the intrinsic has no effect.
26712+
26713+
Otherwise, the stack-allocated object that ``ptr`` points to becomes dead after
26714+
the call to this intrinsic.
2670926715

2671026716
Calling ``llvm.lifetime.end`` on an already dead alloca is no-op.
2671126717

llvm/lib/Analysis/StackLifetime.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ bool StackLifetime::isAliveAfter(const AllocaInst *AI,
6363
// markers has the same size and points to the alloca start.
6464
static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II,
6565
const DataLayout &DL) {
66-
const AllocaInst *AI = cast<AllocaInst>(II.getArgOperand(1));
66+
const AllocaInst *AI = dyn_cast<AllocaInst>(II.getArgOperand(1));
67+
if (!AI)
68+
return nullptr;
69+
6770
auto AllocaSize = AI->getAllocationSize(DL);
6871
if (!AllocaSize)
6972
return nullptr;

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,8 +2189,8 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
21892189
unsigned Op = ID == Intrinsic::lifetime_start ? TargetOpcode::LIFETIME_START
21902190
: TargetOpcode::LIFETIME_END;
21912191

2192-
const AllocaInst *AI = cast<AllocaInst>(CI.getArgOperand(1));
2193-
if (!AI->isStaticAlloca())
2192+
const AllocaInst *AI = dyn_cast<AllocaInst>(CI.getArgOperand(1));
2193+
if (!AI || !AI->isStaticAlloca())
21942194
return true;
21952195

21962196
MIRBuilder.buildInstr(Op).addFrameIndex(getOrCreateFrameIndex(*AI));

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7598,7 +7598,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
75987598
if (TM.getOptLevel() == CodeGenOptLevel::None)
75997599
return;
76007600

7601-
const AllocaInst *LifetimeObject = cast<AllocaInst>(I.getArgOperand(1));
7601+
const AllocaInst *LifetimeObject = dyn_cast<AllocaInst>(I.getArgOperand(1));
7602+
if (!LifetimeObject)
7603+
return;
76027604

76037605
// First check that the Alloca is static, otherwise it won't have a
76047606
// valid frame index.

llvm/lib/IR/Verifier.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6769,10 +6769,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
67696769
break;
67706770
}
67716771
case Intrinsic::lifetime_start:
6772-
case Intrinsic::lifetime_end:
6773-
Check(isa<AllocaInst>(Call.getArgOperand(1)),
6774-
"llvm.lifetime.start/end can only be used on alloca", &Call);
6772+
case Intrinsic::lifetime_end: {
6773+
Value *Ptr = Call.getArgOperand(1);
6774+
Check(isa<AllocaInst>(Ptr) || isa<PoisonValue>(Ptr),
6775+
"llvm.lifetime.start/end can only be used on alloca or poison",
6776+
&Call);
67756777
break;
6778+
}
67766779
};
67776780

67786781
// Verify that there aren't any unmediated control transfers between funclets.

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,9 +1222,9 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
12221222
!ConstantInt::isValueValidForType(IntptrTy, SizeValue))
12231223
return;
12241224
// Find alloca instruction that corresponds to llvm.lifetime argument.
1225-
AllocaInst *AI = cast<AllocaInst>(II.getArgOperand(1));
1225+
AllocaInst *AI = dyn_cast<AllocaInst>(II.getArgOperand(1));
12261226
// We're interested only in allocas we can handle.
1227-
if (!ASan.isInterestingAlloca(*AI))
1227+
if (!AI || !ASan.isInterestingAlloca(*AI))
12281228
return;
12291229
bool DoPoison = (ID == Intrinsic::lifetime_end);
12301230
AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison};

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,8 +3301,9 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
33013301
void handleLifetimeStart(IntrinsicInst &I) {
33023302
if (!PoisonStack)
33033303
return;
3304-
AllocaInst *AI = cast<AllocaInst>(I.getArgOperand(1));
3305-
LifetimeStartList.push_back(std::make_pair(&I, AI));
3304+
AllocaInst *AI = dyn_cast<AllocaInst>(I.getArgOperand(1));
3305+
if (AI)
3306+
LifetimeStartList.push_back(std::make_pair(&I, AI));
33063307
}
33073308

33083309
void handleBswap(IntrinsicInst &I) {

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ bool llvm::wouldInstructionBeTriviallyDead(const Instruction *I,
482482

483483
if (II->isLifetimeStartOrEnd()) {
484484
auto *Arg = II->getArgOperand(1);
485+
if (isa<PoisonValue>(Arg))
486+
return true;
487+
485488
// If the only uses of the alloca are lifetime intrinsics, then the
486489
// intrinsics are dead.
487490
return llvm::all_of(Arg->uses(), [](Use &Use) {

llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ void StackInfoBuilder::visit(OptimizationRemarkEmitter &ORE,
155155
return;
156156
}
157157
if (auto *II = dyn_cast<LifetimeIntrinsic>(&Inst)) {
158-
AllocaInst *AI = cast<AllocaInst>(II->getArgOperand(1));
159-
if (getAllocaInterestingness(*AI) != AllocaInterestingness::kInteresting)
158+
AllocaInst *AI = dyn_cast<AllocaInst>(II->getArgOperand(1));
159+
if (!AI ||
160+
getAllocaInterestingness(*AI) != AllocaInterestingness::kInteresting)
160161
return;
161162
if (II->getIntrinsicID() == Intrinsic::lifetime_start)
162163
Info.AllocasToInstrument[AI].LifetimeStart.push_back(II);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=aarch64 -global-isel=0 < %s | FileCheck %s
3+
; RUN: llc -mtriple=aarch64 -global-isel=1 < %s | FileCheck %s
4+
5+
; Check that lifetime.start/end with poison argument are ignored.
6+
7+
define void @test() {
8+
; CHECK-LABEL: test:
9+
; CHECK: // %bb.0:
10+
; CHECK-NEXT: ret
11+
call void @llvm.lifetime.start.p0(i64 4, ptr poison)
12+
call void @llvm.lifetime.end.p0(i64 4, ptr poison)
13+
ret void
14+
}

0 commit comments

Comments
 (0)