Skip to content

[MemoryLocation] Compute lifetime size from alloca size #151982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 5, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Aug 4, 2025

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.

Split out from llvm#150248:

Since llvm#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.
@llvmbot llvmbot added llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Aug 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 4, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/151982.diff

3 Files Affected:

  • (modified) llvm/lib/Analysis/MemoryLocation.cpp (+15-1)
  • (modified) llvm/test/Transforms/DeadStoreElimination/lifetime.ll (-106)
  • (modified) llvm/unittests/Analysis/MemorySSATest.cpp (+15-20)
diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp
index c8daab7abde18..28a264093af23 100644
--- a/llvm/lib/Analysis/MemoryLocation.cpp
+++ b/llvm/lib/Analysis/MemoryLocation.cpp
@@ -190,7 +190,21 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
       return MemoryLocation::getAfter(Arg, AATags);
 
     case Intrinsic::lifetime_start:
-    case Intrinsic::lifetime_end:
+    case Intrinsic::lifetime_end: {
+      assert(ArgIdx == 1 && "Invalid argument index");
+      auto *AI = dyn_cast<AllocaInst>(Arg);
+      if (!AI)
+        // lifetime of poison value.
+        return MemoryLocation::getBeforeOrAfter(Arg);
+
+      std::optional<TypeSize> AllocSize =
+          AI->getAllocationSize(II->getDataLayout());
+      return MemoryLocation(Arg,
+                            AllocSize ? LocationSize::precise(*AllocSize)
+                                      : LocationSize::afterPointer(),
+                            AATags);
+    }
+
     case Intrinsic::invariant_start:
       assert(ArgIdx == 1 && "Invalid argument index");
       return MemoryLocation(
diff --git a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
index 19e7b0d1eacd9..f2a372eafb0b7 100644
--- a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
@@ -37,110 +37,4 @@ define void @test2(ptr %P) {
   ret void
 }
 
-; 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 @test3_lifetime_end_partial() {
-; CHECK-LABEL: @test3_lifetime_end_partial(
-; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
-; 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:    ret void
-;
-  %A = alloca i32
-
-  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
-
-  store i8 0, ptr %A
-  store i8 10, ptr %A.1
-  store i8 20, ptr %A.2
-
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-  call void @use(ptr %A.1)
-  ret void
-}
-
-; 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 @test4_lifetime_end_partial_loop() {
-; CHECK-LABEL: @test4_lifetime_end_partial_loop(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; 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:    call void @use(ptr [[A_1]])
-; CHECK-NEXT:    store i8 20, ptr [[A_2]], align 1
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
-; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 10
-; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i8 [[IV_NEXT]], 10
-; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %A = alloca i32
-
-  br label %loop
-
-loop:
-  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
-  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
-
-  call void @use(ptr %A.1)
-
-  store i8 20, ptr %A.2
-  store i8 10, ptr %A.1
-  store i8 0, ptr %A
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-
-  %iv.next = add i8 %iv, 10
-  %exitcond = icmp eq i8 %iv.next, 10
-  br i1 %exitcond, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-; 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() {
-; CHECK-LABEL: @test5_lifetime_end_partial(
-; 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:    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
-
-  store i8 0, ptr %A
-  store i8 10, ptr %A.1
-  store i8 20, ptr %A.2
-
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-
-  call void @use(ptr %A.1)
-  store i8 30, ptr %A.1
-  store i8 40, ptr %A.2
-  ret void
-}
-
 declare void @use(ptr) readonly
diff --git a/llvm/unittests/Analysis/MemorySSATest.cpp b/llvm/unittests/Analysis/MemorySSATest.cpp
index a6f002b63dff1..faf0519e7aff5 100644
--- a/llvm/unittests/Analysis/MemorySSATest.cpp
+++ b/llvm/unittests/Analysis/MemorySSATest.cpp
@@ -1086,16 +1086,17 @@ TEST_F(MemorySSATest, TestStoreMayAlias) {
 
 TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   // Example code:
-  // define void @a(i8* %foo) {
-  //   %bar = getelementptr i8, i8* %foo, i64 1
-  //   %baz = getelementptr i8, i8* %foo, i64 2
-  //   store i8 0, i8* %foo
-  //   store i8 0, i8* %bar
-  //   call void @llvm.lifetime.end.p0i8(i64 3, i8* %foo)
-  //   call void @llvm.lifetime.start.p0i8(i64 3, i8* %foo)
-  //   store i8 0, i8* %foo
-  //   store i8 0, i8* %bar
-  //   call void @llvm.memset.p0i8(i8* %baz, i8 0, i64 1)
+  // define void @a() {
+  //   %foo = alloca i32
+  //   %bar = getelementptr i8, ptr %foo, i64 1
+  //   %baz = getelementptr i8, ptr %foo, i64 2
+  //   store i8 0, ptr %foo
+  //   store i8 0, ptr %bar
+  //   call void @llvm.lifetime.end.p0(i64 3, ptr %foo)
+  //   call void @llvm.lifetime.start.p0(i64 3, ptr %foo)
+  //   store i8 0, ptr %foo
+  //   store i8 0, ptr %bar
+  //   call void @llvm.memset.p0i8(ptr %baz, i8 0, i64 1)
   //   ret void
   // }
   //
@@ -1104,14 +1105,14 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   // it.
 
   IRBuilder<> B(C);
-  F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getPtrTy()}, false),
+  F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
                        GlobalValue::ExternalLinkage, "F", &M);
 
   // Make blocks
   BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
 
   B.SetInsertPoint(Entry);
-  Value *Foo = &*F->arg_begin();
+  Value *Foo = B.CreateAlloca(B.getInt32Ty());
 
   Value *Bar = B.CreatePtrAdd(Foo, B.getInt64(1), "bar");
   Value *Baz = B.CreatePtrAdd(Foo, B.getInt64(2), "baz");
@@ -1119,14 +1120,8 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   B.CreateStore(B.getInt8(0), Foo);
   B.CreateStore(B.getInt8(0), Bar);
 
-  auto GetLifetimeIntrinsic = [&](Intrinsic::ID ID) {
-    return Intrinsic::getOrInsertDeclaration(&M, ID, {Foo->getType()});
-  };
-
-  B.CreateCall(GetLifetimeIntrinsic(Intrinsic::lifetime_end),
-               {B.getInt64(3), Foo});
-  Instruction *LifetimeStart = B.CreateCall(
-      GetLifetimeIntrinsic(Intrinsic::lifetime_start), {B.getInt64(3), Foo});
+  B.CreateLifetimeEnd(Foo, B.getInt64(3));
+  Instruction *LifetimeStart = B.CreateLifetimeStart(Foo, B.getInt64(3));
 
   Instruction *FooStore = B.CreateStore(B.getInt8(0), Foo);
   Instruction *BarStore = B.CreateStore(B.getInt8(0), Bar);

@llvmbot
Copy link
Member

llvmbot commented Aug 4, 2025

@llvm/pr-subscribers-llvm-analysis

Author: Nikita Popov (nikic)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/151982.diff

3 Files Affected:

  • (modified) llvm/lib/Analysis/MemoryLocation.cpp (+15-1)
  • (modified) llvm/test/Transforms/DeadStoreElimination/lifetime.ll (-106)
  • (modified) llvm/unittests/Analysis/MemorySSATest.cpp (+15-20)
diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp
index c8daab7abde18..28a264093af23 100644
--- a/llvm/lib/Analysis/MemoryLocation.cpp
+++ b/llvm/lib/Analysis/MemoryLocation.cpp
@@ -190,7 +190,21 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
       return MemoryLocation::getAfter(Arg, AATags);
 
     case Intrinsic::lifetime_start:
-    case Intrinsic::lifetime_end:
+    case Intrinsic::lifetime_end: {
+      assert(ArgIdx == 1 && "Invalid argument index");
+      auto *AI = dyn_cast<AllocaInst>(Arg);
+      if (!AI)
+        // lifetime of poison value.
+        return MemoryLocation::getBeforeOrAfter(Arg);
+
+      std::optional<TypeSize> AllocSize =
+          AI->getAllocationSize(II->getDataLayout());
+      return MemoryLocation(Arg,
+                            AllocSize ? LocationSize::precise(*AllocSize)
+                                      : LocationSize::afterPointer(),
+                            AATags);
+    }
+
     case Intrinsic::invariant_start:
       assert(ArgIdx == 1 && "Invalid argument index");
       return MemoryLocation(
diff --git a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
index 19e7b0d1eacd9..f2a372eafb0b7 100644
--- a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
@@ -37,110 +37,4 @@ define void @test2(ptr %P) {
   ret void
 }
 
-; 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 @test3_lifetime_end_partial() {
-; CHECK-LABEL: @test3_lifetime_end_partial(
-; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
-; 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:    ret void
-;
-  %A = alloca i32
-
-  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
-
-  store i8 0, ptr %A
-  store i8 10, ptr %A.1
-  store i8 20, ptr %A.2
-
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-  call void @use(ptr %A.1)
-  ret void
-}
-
-; 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 @test4_lifetime_end_partial_loop() {
-; CHECK-LABEL: @test4_lifetime_end_partial_loop(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; 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:    call void @use(ptr [[A_1]])
-; CHECK-NEXT:    store i8 20, ptr [[A_2]], align 1
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 2, ptr [[A]])
-; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 10
-; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i8 [[IV_NEXT]], 10
-; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %A = alloca i32
-
-  br label %loop
-
-loop:
-  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
-  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
-
-  call void @use(ptr %A.1)
-
-  store i8 20, ptr %A.2
-  store i8 10, ptr %A.1
-  store i8 0, ptr %A
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-
-  %iv.next = add i8 %iv, 10
-  %exitcond = icmp eq i8 %iv.next, 10
-  br i1 %exitcond, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-; 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() {
-; CHECK-LABEL: @test5_lifetime_end_partial(
-; 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:    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
-
-  store i8 0, ptr %A
-  store i8 10, ptr %A.1
-  store i8 20, ptr %A.2
-
-  call void @llvm.lifetime.end.p0(i64 2, ptr %A)
-
-  call void @use(ptr %A.1)
-  store i8 30, ptr %A.1
-  store i8 40, ptr %A.2
-  ret void
-}
-
 declare void @use(ptr) readonly
diff --git a/llvm/unittests/Analysis/MemorySSATest.cpp b/llvm/unittests/Analysis/MemorySSATest.cpp
index a6f002b63dff1..faf0519e7aff5 100644
--- a/llvm/unittests/Analysis/MemorySSATest.cpp
+++ b/llvm/unittests/Analysis/MemorySSATest.cpp
@@ -1086,16 +1086,17 @@ TEST_F(MemorySSATest, TestStoreMayAlias) {
 
 TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   // Example code:
-  // define void @a(i8* %foo) {
-  //   %bar = getelementptr i8, i8* %foo, i64 1
-  //   %baz = getelementptr i8, i8* %foo, i64 2
-  //   store i8 0, i8* %foo
-  //   store i8 0, i8* %bar
-  //   call void @llvm.lifetime.end.p0i8(i64 3, i8* %foo)
-  //   call void @llvm.lifetime.start.p0i8(i64 3, i8* %foo)
-  //   store i8 0, i8* %foo
-  //   store i8 0, i8* %bar
-  //   call void @llvm.memset.p0i8(i8* %baz, i8 0, i64 1)
+  // define void @a() {
+  //   %foo = alloca i32
+  //   %bar = getelementptr i8, ptr %foo, i64 1
+  //   %baz = getelementptr i8, ptr %foo, i64 2
+  //   store i8 0, ptr %foo
+  //   store i8 0, ptr %bar
+  //   call void @llvm.lifetime.end.p0(i64 3, ptr %foo)
+  //   call void @llvm.lifetime.start.p0(i64 3, ptr %foo)
+  //   store i8 0, ptr %foo
+  //   store i8 0, ptr %bar
+  //   call void @llvm.memset.p0i8(ptr %baz, i8 0, i64 1)
   //   ret void
   // }
   //
@@ -1104,14 +1105,14 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   // it.
 
   IRBuilder<> B(C);
-  F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getPtrTy()}, false),
+  F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
                        GlobalValue::ExternalLinkage, "F", &M);
 
   // Make blocks
   BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
 
   B.SetInsertPoint(Entry);
-  Value *Foo = &*F->arg_begin();
+  Value *Foo = B.CreateAlloca(B.getInt32Ty());
 
   Value *Bar = B.CreatePtrAdd(Foo, B.getInt64(1), "bar");
   Value *Baz = B.CreatePtrAdd(Foo, B.getInt64(2), "baz");
@@ -1119,14 +1120,8 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
   B.CreateStore(B.getInt8(0), Foo);
   B.CreateStore(B.getInt8(0), Bar);
 
-  auto GetLifetimeIntrinsic = [&](Intrinsic::ID ID) {
-    return Intrinsic::getOrInsertDeclaration(&M, ID, {Foo->getType()});
-  };
-
-  B.CreateCall(GetLifetimeIntrinsic(Intrinsic::lifetime_end),
-               {B.getInt64(3), Foo});
-  Instruction *LifetimeStart = B.CreateCall(
-      GetLifetimeIntrinsic(Intrinsic::lifetime_start), {B.getInt64(3), Foo});
+  B.CreateLifetimeEnd(Foo, B.getInt64(3));
+  Instruction *LifetimeStart = B.CreateLifetimeStart(Foo, B.getInt64(3));
 
   Instruction *FooStore = B.CreateStore(B.getInt8(0), Foo);
   Instruction *BarStore = B.CreateStore(B.getInt8(0), Bar);

auto *AI = dyn_cast<AllocaInst>(Arg);
if (!AI)
// lifetime of poison value.
return MemoryLocation::getBeforeOrAfter(Arg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be worth asserting here or does the verifier check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verifier checks it (see #151148).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

{B.getInt64(3), Foo});
Instruction *LifetimeStart = B.CreateCall(
GetLifetimeIntrinsic(Intrinsic::lifetime_start), {B.getInt64(3), Foo});
B.CreateLifetimeEnd(Foo, B.getInt64(3));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped it in this PR as well. I didn't realize the argument in the IRBuilder API was already optional.

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

auto *AI = dyn_cast<AllocaInst>(Arg);
if (!AI)
// lifetime of poison value.
return MemoryLocation::getBeforeOrAfter(Arg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

@nikic nikic merged commit c1b387e into llvm:main Aug 5, 2025
9 checks passed
@nikic nikic deleted the memloc-lifetime-size branch August 5, 2025 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants