[llvm] [NewGVN] Fix lifetime coercion (PR #141477)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 26 08:19:16 PDT 2025


https://github.com/ManuelJBrito updated https://github.com/llvm/llvm-project/pull/141477

>From acd36fff83a9be9bd06978573b89bc1caffa1f92 Mon Sep 17 00:00:00 2001
From: ManuelJBrito <manuel.brito at tecnico.ulisboa.pt>
Date: Mon, 26 May 2025 16:18:18 +0100
Subject: [PATCH] [NewGVN] Fix lifetime load coercion

---
 llvm/lib/Transforms/Scalar/NewGVN.cpp         | 19 +++++++++++--------
 .../NewGVN/coercion-different-ptr.ll          |  5 +++--
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 3eb118908959f..0a0ea65a1f036 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -1529,10 +1529,19 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
     }
   }
 
+  if (auto *II = dyn_cast<IntrinsicInst>(DepInst)) {
+    auto *LifetimePtr = II->getOperand(1);
+    if (II->getIntrinsicID() == Intrinsic::lifetime_start &&
+        (LoadPtr == lookupOperandLeader(LifetimePtr) ||
+         AA->isMustAlias(LoadPtr, LifetimePtr)))
+      return createConstantExpression(UndefValue::get(LoadType));
+  }
+
   // All of the below are only true if the loaded pointer is produced
   // by the dependent instruction.
-  if (LoadPtr != lookupOperandLeader(DepInst) &&
-      DepInst->getType()->isPointerTy() && !AA->isMustAlias(LoadPtr, DepInst))
+  if (!DepInst->getType()->isPointerTy() ||
+      (LoadPtr != lookupOperandLeader(DepInst) &&
+       !AA->isMustAlias(LoadPtr, DepInst)))
     return nullptr;
   // If this load really doesn't depend on anything, then we must be loading an
   // undef value.  This can happen when loading for a fresh allocation with no
@@ -1540,12 +1549,6 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
   // that the result of the allocation is pointer equal to the load ptr.
   if (isa<AllocaInst>(DepInst)) {
     return createConstantExpression(UndefValue::get(LoadType));
-  }
-  // If this load occurs either right after a lifetime begin,
-  // then the loaded value is undefined.
-  else if (auto *II = dyn_cast<IntrinsicInst>(DepInst)) {
-    if (II->getIntrinsicID() == Intrinsic::lifetime_start)
-      return createConstantExpression(UndefValue::get(LoadType));
   } else if (auto *InitVal =
                  getInitialValueOfAllocation(DepInst, TLI, LoadType))
       return createConstantExpression(InitVal);
diff --git a/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll b/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll
index 61a6a633788e1..dfd6d7d9f53a5 100644
--- a/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll
+++ b/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll
@@ -2,7 +2,7 @@
 ; RUN: opt -S -passes=newgvn < %s | FileCheck %s
 
 
-; FIXME: MemorySSA says that load1 depends on the lifetime start.
+; MemorySSA says that load1 depends on the lifetime start.
 ; That's OK since MemorySSA is may-alias; however, NewGVN should
 ; check whether the lifetime start *actually* defines the loaded pointer
 ; before simplifying to uninitialized memory.
@@ -13,7 +13,8 @@ define void @foo(ptr %arg) {
 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i8, align 16
 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 1, ptr [[ALLOCA]])
 ; CHECK-NEXT:    [[LOAD:%.*]] = load ptr, ptr [[ARG]], align 8
-; CHECK-NEXT:    [[CALL:%.*]] = call ptr undef(ptr [[ALLOCA]])
+; CHECK-NEXT:    [[LOAD1:%.*]] = load ptr, ptr [[LOAD]], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[LOAD1]](ptr [[ALLOCA]])
 ; CHECK-NEXT:    ret void
 ;
 bb:



More information about the llvm-commits mailing list