[llvm] ValueTracking: generalize isNonEqualPHIs (PR #108820)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 16 06:21:16 PDT 2024


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/108820

>From e1309e4b7568bd7c50b0e56223f1ca1506d25241 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 16 Sep 2024 13:20:19 +0100
Subject: [PATCH 1/2] ValueTracking: generalize isNonEqualPHIs

isNonEqualPHIs was originally added in 3fd64cc ([ValueTracking] Handle
two PHIs in isKnownNonEqual()), but as the new test case shows, it is
not powerful enough. Generalize it, removing the APInt-specific
comparison, and extend isKnownNonEqual to handle the case when one of
the operands is a constant.
---
 llvm/lib/Analysis/ValueTracking.cpp           | 21 +++++----------
 .../Analysis/ValueTracking/known-non-equal.ll | 26 +++++++++++++++++++
 2 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ba3ba7cc98136d..c46152f60aab32 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2696,11 +2696,6 @@ static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
   if (matchOpWithOpEqZero(X, Y))
     return true;
 
-  // TODO: Move this case into isKnownNonEqual().
-  if (auto *C = dyn_cast<Constant>(X))
-    if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Q, Depth))
-      return true;
-
   return ::isKnownNonEqual(X, Y, DemandedElts, Depth, Q);
 }
 
@@ -3536,25 +3531,15 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
     return false;
 
   SmallPtrSet<const BasicBlock *, 8> VisitedBBs;
-  bool UsedFullRecursion = false;
   for (const BasicBlock *IncomBB : PN1->blocks()) {
     if (!VisitedBBs.insert(IncomBB).second)
       continue; // Don't reprocess blocks that we have dealt with already.
     const Value *IV1 = PN1->getIncomingValueForBlock(IncomBB);
     const Value *IV2 = PN2->getIncomingValueForBlock(IncomBB);
-    const APInt *C1, *C2;
-    if (match(IV1, m_APInt(C1)) && match(IV2, m_APInt(C2)) && *C1 != *C2)
-      continue;
-
-    // Only one pair of phi operands is allowed for full recursion.
-    if (UsedFullRecursion)
-      return false;
-
     SimplifyQuery RecQ = Q.getWithoutCondContext();
     RecQ.CxtI = IncomBB->getTerminator();
     if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
       return false;
-    UsedFullRecursion = true;
   }
   return true;
 }
@@ -3641,6 +3626,12 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
     // We can't look through casts yet.
     return false;
 
+  if (isa<Constant>(V2))
+    std::swap(V1, V2);
+  if (auto *C = dyn_cast<Constant>(V1))
+    if (C->isNullValue() && isKnownNonZero(V2, DemandedElts, Q, Depth))
+      return true;
+
   if (Depth >= MaxAnalysisRecursionDepth)
     return false;
 
diff --git a/llvm/test/Analysis/ValueTracking/known-non-equal.ll b/llvm/test/Analysis/ValueTracking/known-non-equal.ll
index d67f1b56621476..824a62b618d983 100644
--- a/llvm/test/Analysis/ValueTracking/known-non-equal.ll
+++ b/llvm/test/Analysis/ValueTracking/known-non-equal.ll
@@ -316,6 +316,32 @@ exit:
   ret i1 %cmp
 }
 
+define i1 @known_non_equal_phis2(i8 %p, i8 %n) {
+; CHECK-LABEL: @known_non_equal_phis2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[A:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[NEXT]] = add nsw i8 [[A]], 2
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %known.nonzero = add nuw i8 %p, 1
+  br label %loop
+loop:
+  %A = phi i8 [ 0, %entry ], [ %next, %loop ]
+  %B = phi i8 [ %known.nonzero, %entry ], [ %A, %loop ]
+  %next = add nsw i8 %A, 2
+  %cmp1 = icmp eq i8 %A, %n
+  br i1 %cmp1, label %exit, label %loop
+exit:
+  %cmp = icmp ne i8 %A, %B
+  ret i1 %cmp
+}
+
 define i1 @known_non_equal_phis_fail(i8 %p, ptr %pq, i8 %n, i8 %r) {
 ; CHECK-LABEL: @known_non_equal_phis_fail(
 ; CHECK-NEXT:  entry:

>From 045d3b0cc0febf65d530b4786d307580cfdf4a51 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 16 Sep 2024 14:05:34 +0100
Subject: [PATCH 2/2] ValueTracking: avoid compile-time blowup

---
 llvm/lib/Analysis/ValueTracking.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c46152f60aab32..4377dd789f3b34 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3536,9 +3536,11 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
       continue; // Don't reprocess blocks that we have dealt with already.
     const Value *IV1 = PN1->getIncomingValueForBlock(IncomBB);
     const Value *IV2 = PN2->getIncomingValueForBlock(IncomBB);
+    const unsigned PhiRecursionLimit =
+        std::max(Depth, MaxAnalysisRecursionDepth - 2);
     SimplifyQuery RecQ = Q.getWithoutCondContext();
     RecQ.CxtI = IncomBB->getTerminator();
-    if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
+    if (!isKnownNonEqual(IV1, IV2, DemandedElts, PhiRecursionLimit, RecQ))
       return false;
   }
   return true;



More information about the llvm-commits mailing list