Skip to content

Commit c1b387e

Browse files
authored
[MemoryLocation] Compute lifetime size from alloca size (#151982)
Split out from #150248: Since #150944 the size passed to lifetime.start/end is considered meaningless. The lifetime always applies to the whole alloca. This adjusts MemoryLocation to determine the MemoryLocation size from the alloca size, instead of using the argument.
1 parent c9dd14d commit c1b387e

File tree

3 files changed

+30
-127
lines changed

3 files changed

+30
-127
lines changed

llvm/lib/Analysis/MemoryLocation.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,21 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
190190
return MemoryLocation::getAfter(Arg, AATags);
191191

192192
case Intrinsic::lifetime_start:
193-
case Intrinsic::lifetime_end:
193+
case Intrinsic::lifetime_end: {
194+
assert(ArgIdx == 1 && "Invalid argument index");
195+
auto *AI = dyn_cast<AllocaInst>(Arg);
196+
if (!AI)
197+
// lifetime of poison value.
198+
return MemoryLocation::getBeforeOrAfter(Arg);
199+
200+
std::optional<TypeSize> AllocSize =
201+
AI->getAllocationSize(II->getDataLayout());
202+
return MemoryLocation(Arg,
203+
AllocSize ? LocationSize::precise(*AllocSize)
204+
: LocationSize::afterPointer(),
205+
AATags);
206+
}
207+
194208
case Intrinsic::invariant_start:
195209
assert(ArgIdx == 1 && "Invalid argument index");
196210
return MemoryLocation(

llvm/test/Transforms/DeadStoreElimination/lifetime.ll

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -37,110 +37,4 @@ define void @test2(ptr %P) {
3737
ret void
3838
}
3939

40-
; lifetime.end only marks the first two bytes of %A as dead. Make sure
41-
; `store i8 20, ptr %A.2 is not removed.
42-
define void @test3_lifetime_end_partial() {
43-
; CHECK-LABEL: @test3_lifetime_end_partial(
44-
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
45-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[A]])
46-
; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1
47-
; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, ptr [[A]], i64 2
48-
; CHECK-NEXT: store i8 20, ptr [[A_2]], align 1
49-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
50-
; CHECK-NEXT: call void @use(ptr [[A_1]])
51-
; CHECK-NEXT: ret void
52-
;
53-
%A = alloca i32
54-
55-
call void @llvm.lifetime.start.p0(i64 2, ptr %A)
56-
%A.1 = getelementptr i8, ptr %A, i64 1
57-
%A.2 = getelementptr i8, ptr %A, i64 2
58-
59-
store i8 0, ptr %A
60-
store i8 10, ptr %A.1
61-
store i8 20, ptr %A.2
62-
63-
call void @llvm.lifetime.end.p0(i64 2, ptr %A)
64-
call void @use(ptr %A.1)
65-
ret void
66-
}
67-
68-
; lifetime.end only marks the first two bytes of %A as dead. Make sure
69-
; `store i8 20, ptr %A.2 is not removed.
70-
define void @test4_lifetime_end_partial_loop() {
71-
; CHECK-LABEL: @test4_lifetime_end_partial_loop(
72-
; CHECK-NEXT: entry:
73-
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
74-
; CHECK-NEXT: br label [[LOOP:%.*]]
75-
; CHECK: loop:
76-
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
77-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[A]])
78-
; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1
79-
; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, ptr [[A]], i64 2
80-
; CHECK-NEXT: call void @use(ptr [[A_1]])
81-
; CHECK-NEXT: store i8 20, ptr [[A_2]], align 1
82-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
83-
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 10
84-
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i8 [[IV_NEXT]], 10
85-
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]]
86-
; CHECK: exit:
87-
; CHECK-NEXT: ret void
88-
;
89-
entry:
90-
%A = alloca i32
91-
92-
br label %loop
93-
94-
loop:
95-
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
96-
call void @llvm.lifetime.start.p0(i64 2, ptr %A)
97-
%A.1 = getelementptr i8, ptr %A, i64 1
98-
%A.2 = getelementptr i8, ptr %A, i64 2
99-
100-
call void @use(ptr %A.1)
101-
102-
store i8 20, ptr %A.2
103-
store i8 10, ptr %A.1
104-
store i8 0, ptr %A
105-
call void @llvm.lifetime.end.p0(i64 2, ptr %A)
106-
107-
%iv.next = add i8 %iv, 10
108-
%exitcond = icmp eq i8 %iv.next, 10
109-
br i1 %exitcond, label %exit, label %loop
110-
111-
exit:
112-
ret void
113-
}
114-
115-
; lifetime.end only marks the first two bytes of %A as dead. Make sure
116-
; `store i8 20, ptr %A.2 is not removed.
117-
define void @test5_lifetime_end_partial() {
118-
; CHECK-LABEL: @test5_lifetime_end_partial(
119-
; CHECK-NEXT: [[A:%.*]] = alloca [4 x i8], align 1
120-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 2, ptr [[A]])
121-
; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1
122-
; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, ptr [[A]], i64 2
123-
; CHECK-NEXT: store i8 20, ptr [[A_2]], align 1
124-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
125-
; CHECK-NEXT: call void @use(ptr [[A_1]])
126-
; CHECK-NEXT: ret void
127-
;
128-
129-
%A = alloca [4 x i8]
130-
call void @llvm.lifetime.start.p0(i64 2, ptr %A)
131-
%A.1 = getelementptr i8, ptr %A, i64 1
132-
%A.2 = getelementptr i8, ptr %A, i64 2
133-
134-
store i8 0, ptr %A
135-
store i8 10, ptr %A.1
136-
store i8 20, ptr %A.2
137-
138-
call void @llvm.lifetime.end.p0(i64 2, ptr %A)
139-
140-
call void @use(ptr %A.1)
141-
store i8 30, ptr %A.1
142-
store i8 40, ptr %A.2
143-
ret void
144-
}
145-
14640
declare void @use(ptr) readonly

llvm/unittests/Analysis/MemorySSATest.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,16 +1086,17 @@ TEST_F(MemorySSATest, TestStoreMayAlias) {
10861086

10871087
TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
10881088
// Example code:
1089-
// define void @a(i8* %foo) {
1090-
// %bar = getelementptr i8, i8* %foo, i64 1
1091-
// %baz = getelementptr i8, i8* %foo, i64 2
1092-
// store i8 0, i8* %foo
1093-
// store i8 0, i8* %bar
1094-
// call void @llvm.lifetime.end.p0i8(i64 3, i8* %foo)
1095-
// call void @llvm.lifetime.start.p0i8(i64 3, i8* %foo)
1096-
// store i8 0, i8* %foo
1097-
// store i8 0, i8* %bar
1098-
// call void @llvm.memset.p0i8(i8* %baz, i8 0, i64 1)
1089+
// define void @a() {
1090+
// %foo = alloca i32
1091+
// %bar = getelementptr i8, ptr %foo, i64 1
1092+
// %baz = getelementptr i8, ptr %foo, i64 2
1093+
// store i8 0, ptr %foo
1094+
// store i8 0, ptr %bar
1095+
// call void @llvm.lifetime.end.p0(i64 3, ptr %foo)
1096+
// call void @llvm.lifetime.start.p0(i64 3, ptr %foo)
1097+
// store i8 0, ptr %foo
1098+
// store i8 0, ptr %bar
1099+
// call void @llvm.memset.p0i8(ptr %baz, i8 0, i64 1)
10991100
// ret void
11001101
// }
11011102
//
@@ -1104,29 +1105,23 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
11041105
// it.
11051106

11061107
IRBuilder<> B(C);
1107-
F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getPtrTy()}, false),
1108+
F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
11081109
GlobalValue::ExternalLinkage, "F", &M);
11091110

11101111
// Make blocks
11111112
BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
11121113

11131114
B.SetInsertPoint(Entry);
1114-
Value *Foo = &*F->arg_begin();
1115+
Value *Foo = B.CreateAlloca(B.getInt32Ty());
11151116

11161117
Value *Bar = B.CreatePtrAdd(Foo, B.getInt64(1), "bar");
11171118
Value *Baz = B.CreatePtrAdd(Foo, B.getInt64(2), "baz");
11181119

11191120
B.CreateStore(B.getInt8(0), Foo);
11201121
B.CreateStore(B.getInt8(0), Bar);
11211122

1122-
auto GetLifetimeIntrinsic = [&](Intrinsic::ID ID) {
1123-
return Intrinsic::getOrInsertDeclaration(&M, ID, {Foo->getType()});
1124-
};
1125-
1126-
B.CreateCall(GetLifetimeIntrinsic(Intrinsic::lifetime_end),
1127-
{B.getInt64(3), Foo});
1128-
Instruction *LifetimeStart = B.CreateCall(
1129-
GetLifetimeIntrinsic(Intrinsic::lifetime_start), {B.getInt64(3), Foo});
1123+
B.CreateLifetimeEnd(Foo);
1124+
Instruction *LifetimeStart = B.CreateLifetimeStart(Foo);
11301125

11311126
Instruction *FooStore = B.CreateStore(B.getInt8(0), Foo);
11321127
Instruction *BarStore = B.CreateStore(B.getInt8(0), Bar);

0 commit comments

Comments
 (0)