[llvm] [Analysis] use forward DFS in `isEphemeralValueOf` (PR #196232)

Iris Shi via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 07:59:37 PDT 2026


https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/196232

>From b45116b2ae67217c85993abef0d295f2fa10dafb Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 7 May 2026 14:03:26 +0800
Subject: [PATCH 1/2] pre-commit test

---
 llvm/test/Transforms/InstSimplify/ctpop-pow2.ll | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
index 92e43654806a4..a136be19f5c19 100644
--- a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
+++ b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
@@ -119,6 +119,20 @@ define i64 @ctpop_x_and_negx_nz(i64 %x) {
   ret i64 %cnt
 }
 
+; issue #128152
+define i1 @ctpop_assume_eq_1_extra_use(i32 %x) {
+; CHECK-LABEL: @ctpop_assume_eq_1_extra_use(
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %ctpop = call i32 @llvm.ctpop.i32(i32 %x)
+  %cond = icmp eq i32 %ctpop, 1
+  %ext = zext i1 %cond to i8
+  call void @llvm.assume(i1 %cond)
+  %res = icmp eq i32 %x, 0
+  ret i1 %res
+}
+
 define <2 x i32> @ctpop_shl1_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @ctpop_shl1_vec(
 ; CHECK-NEXT:    ret <2 x i32> splat (i32 1)

>From 8ed8c3e6206090eaf433d3eed948201d76bdf7e0 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 7 May 2026 14:05:09 +0800
Subject: [PATCH 2/2] [Analysis] use forward DFS in `isEphemeralValueOf`

---
 llvm/lib/Analysis/ValueTracking.cpp           | 45 +++++++++----------
 .../Transforms/InstSimplify/ctpop-pow2.ll     |  5 ++-
 2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8f10bbae3d462..71c639643f9a0 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -608,40 +608,39 @@ void llvm::computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
 }
 
 static bool isEphemeralValueOf(const Instruction *I, const Value *E) {
-  SmallVector<const Instruction *, 16> WorkSet(1, I);
-  SmallPtrSet<const Instruction *, 32> Visited;
-  SmallPtrSet<const Instruction *, 16> EphValues;
-
   // The instruction defining an assumption's condition itself is always
   // considered ephemeral to that assumption (even if it has other
   // non-ephemeral users). See r246696's test case for an example.
   if (is_contained(I->operands(), E))
     return true;
 
-  while (!WorkSet.empty()) {
-    const Instruction *V = WorkSet.pop_back_val();
-    if (!Visited.insert(V).second)
-      continue;
-
-    // If all uses of this value are ephemeral, then so is this value.
-    if (all_of(V->users(), [&](const User *U) {
-          return EphValues.count(cast<Instruction>(U));
-        })) {
-      if (V == E)
-        return true;
+  const auto *EI = dyn_cast<Instruction>(E);
+  if (!EI)
+    return false;
 
-      if (V == I || (!V->mayHaveSideEffects() && !V->isTerminator())) {
-        EphValues.insert(V);
+  if (EI == I)
+    return true;
 
-        for (const Use &U : V->operands()) {
-          if (const auto *I = dyn_cast<Instruction>(U.get()))
-            WorkSet.push_back(I);
-        }
+  SmallPtrSet<const Instruction *, 16> Visited;
+  SmallVector<const Instruction *, 16> WorkList;
+  Visited.insert(EI);
+  WorkList.push_back(EI);
+  bool ReachesI = false;
+  while (!WorkList.empty()) {
+    const Instruction *V = WorkList.pop_back_val();
+    for (const User *U : V->users()) {
+      const auto *UI = cast<Instruction>(U);
+      if (UI == I) {
+        ReachesI = true;
+        continue;
       }
+      if (UI->mayHaveSideEffects() || UI->isTerminator())
+        return false;
+      if (Visited.insert(UI).second)
+        WorkList.push_back(UI);
     }
   }
-
-  return false;
+  return ReachesI;
 }
 
 // Is this an intrinsic that cannot be speculated but also cannot trap?
diff --git a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
index a136be19f5c19..fce04ec862321 100644
--- a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
+++ b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll
@@ -122,7 +122,10 @@ define i64 @ctpop_x_and_negx_nz(i64 %x) {
 ; issue #128152
 define i1 @ctpop_assume_eq_1_extra_use(i32 %x) {
 ; CHECK-LABEL: @ctpop_assume_eq_1_extra_use(
-; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[CTPOP:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[CTPOP]], 1
+; CHECK-NEXT:    call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[X]], 0
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %ctpop = call i32 @llvm.ctpop.i32(i32 %x)



More information about the llvm-commits mailing list