[llvm] 4b5b36e - [GVN] Avoid creating lifetime of non-alloca

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 4 03:06:51 PDT 2025


Author: Nikita Popov
Date: 2025-08-04T12:06:40+02:00
New Revision: 4b5b36e5c4b887a86fc7164d6899caaa2e2f5aed

URL: https://github.com/llvm/llvm-project/commit/4b5b36e5c4b887a86fc7164d6899caaa2e2f5aed
DIFF: https://github.com/llvm/llvm-project/commit/4b5b36e5c4b887a86fc7164d6899caaa2e2f5aed.diff

LOG: [GVN] Avoid creating lifetime of non-alloca

There is a larger problem here in that we should not be performing
arbitrary pointer replacements for assumes. This is handled for
branches, but assume goes through a different code path.

Fixes https://github.com/llvm/llvm-project/issues/151785.

Added: 
    

Modified: 
    llvm/lib/Analysis/Loads.cpp
    llvm/lib/Transforms/Scalar/GVN.cpp
    llvm/test/Transforms/GVN/lifetime-simple.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 6fc81d787c220..da76f5b3d498a 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -833,6 +833,10 @@ bool llvm::canReplacePointersInUseIfEqual(const Use &U, const Value *To,
   if (!To->getType()->isPointerTy())
     return true;
 
+  // Do not perform replacements in lifetime intrinsic arguments.
+  if (isa<LifetimeIntrinsic>(U.getUser()))
+    return false;
+
   if (isPointerAlwaysReplaceable(&*U, To, DL))
     return true;
   return isPointerUseReplacable(U);

diff  --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index f6bf09d09433d..fa6ee95d33d10 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -2502,6 +2502,10 @@ bool GVNPass::replaceOperandsForInBlockEquality(Instruction *Instr) const {
     Value *Operand = Instr->getOperand(OpNum);
     auto It = ReplaceOperandsWithMap.find(Operand);
     if (It != ReplaceOperandsWithMap.end()) {
+      // Do not replace lifetime alloca argument with something else.
+      if (Instr->isLifetimeStartOrEnd())
+        continue;
+
       LLVM_DEBUG(dbgs() << "GVN replacing: " << *Operand << " with "
                         << *It->second << " in instruction " << *Instr << '\n');
       Instr->setOperand(OpNum, It->second);

diff  --git a/llvm/test/Transforms/GVN/lifetime-simple.ll b/llvm/test/Transforms/GVN/lifetime-simple.ll
index 177f43f39d973..30883bd9dc6d3 100644
--- a/llvm/test/Transforms/GVN/lifetime-simple.ll
+++ b/llvm/test/Transforms/GVN/lifetime-simple.ll
@@ -22,5 +22,71 @@ entry:
   ret i8 %1
 }
 
+define void @assume_eq_arg(ptr %arg) {
+; CHECK-LABEL: define void @assume_eq_arg(
+; CHECK-SAME: ptr [[ARG:%.*]]) {
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ALLOCA]], [[ARG]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[ALLOCA]])
+; CHECK-NEXT:    store volatile i32 0, ptr [[ARG]], align 4
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
+; CHECK-NEXT:    ret void
+;
+  %alloca = alloca i32
+  %cmp = icmp eq ptr %alloca, %arg
+  call void @llvm.assume(i1 %cmp)
+  call void @llvm.lifetime.start.p0(i64 4, ptr %alloca)
+  store volatile i32 0, ptr %alloca
+  call void @llvm.lifetime.end.p0(i64 4, ptr %alloca)
+  ret void
+}
+
+define void @assume_eq_null() {
+; CHECK-LABEL: define void @assume_eq_null() {
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i32, align 4, addrspace(1)
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr addrspace(1) [[ALLOCA]], null
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
+; CHECK-NEXT:    store volatile i32 0, ptr addrspace(1) null, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
+; CHECK-NEXT:    ret void
+;
+  %alloca = alloca i32, addrspace(1)
+  %cmp = icmp eq ptr addrspace(1) %alloca, null
+  call void @llvm.assume(i1 %cmp)
+  call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) %alloca)
+  store volatile i32 0, ptr addrspace(1) %alloca
+  call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) %alloca)
+  ret void
+}
+
+define void @dom_eq_null() {
+; CHECK-LABEL: define void @dom_eq_null() {
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i32, align 4, addrspace(1)
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr addrspace(1) [[ALLOCA]], null
+; CHECK-NEXT:    br i1 [[CMP]], label %[[IF:.*]], label %[[ELSE:.*]]
+; CHECK:       [[IF]]:
+; CHECK-NEXT:    call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
+; CHECK-NEXT:    store volatile i32 0, ptr addrspace(1) null, align 4
+; CHECK-NEXT:    call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
+; CHECK-NEXT:    ret void
+; CHECK:       [[ELSE]]:
+; CHECK-NEXT:    ret void
+;
+  %alloca = alloca i32, addrspace(1)
+  %cmp = icmp eq ptr addrspace(1) %alloca, null
+  br i1 %cmp, label %if, label %else
+
+if:
+  call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) %alloca)
+  store volatile i32 0, ptr addrspace(1) %alloca
+  call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) %alloca)
+  ret void
+
+else:
+  ret void
+}
+
 declare void @llvm.lifetime.start.p0(i64 %S, ptr nocapture %P) readonly
 declare void @llvm.lifetime.end.p0(i64 %S, ptr nocapture %P)


        


More information about the llvm-commits mailing list