[llvm] b1b065f - [ValueTracking] Refactor `isKnownNonEqualFromContext` (#127388)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 18 07:14:10 PDT 2025


Author: Yingwei Zheng
Date: 2025-04-18T22:14:06+08:00
New Revision: b1b065f2bf5d626fee277d67b0014577f7e4e499

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

LOG: [ValueTracking] Refactor `isKnownNonEqualFromContext` (#127388)

This patch avoids adding RHS for comparisons with two variable operands
(https://github.com/llvm/llvm-project/pull/118493#discussion_r1949397482).
Instead, we iterate over related dominating conditions of both V1 and V2
in `isKnownNonEqualFromContext`, as suggested by goldsteinn
(https://github.com/llvm/llvm-project/pull/117442#discussion_r1944058002).

Compile-time improvement:
https://llvm-compile-time-tracker.com/compare.php?from=c6d95c441a29a45782ff72d6cb82839b86fd0e4a&to=88464baedd7b1731281eaa0ce4438122b4d218a7&stat=instructions:u

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstCombine/icmp-dom.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ff8f3b6ae3bc8..cdf7f052943c8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3804,6 +3804,63 @@ static bool isNonEqualPointersWithRecursiveGEP(const Value *A, const Value *B,
           (StartOffset.sle(OffsetB) && StepOffset.isNegative()));
 }
 
+static bool isKnownNonEqualFromContext(const Value *V1, const Value *V2,
+                                       unsigned Depth, const SimplifyQuery &Q) {
+  if (!Q.CxtI)
+    return false;
+
+  // Try to infer NonEqual based on information from dominating conditions.
+  if (Q.DC && Q.DT) {
+    auto IsKnownNonEqualFromDominatingCondition = [&](const Value *V) {
+      for (BranchInst *BI : Q.DC->conditionsFor(V)) {
+        Value *Cond = BI->getCondition();
+        BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
+        if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
+            isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+                               /*LHSIsTrue=*/true, Depth)
+                .value_or(false))
+          return true;
+
+        BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
+        if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
+            isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+                               /*LHSIsTrue=*/false, Depth)
+                .value_or(false))
+          return true;
+      }
+
+      return false;
+    };
+
+    if (IsKnownNonEqualFromDominatingCondition(V1) ||
+        IsKnownNonEqualFromDominatingCondition(V2))
+      return true;
+  }
+
+  if (!Q.AC)
+    return false;
+
+  // Try to infer NonEqual based on information from assumptions.
+  for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
+    if (!AssumeVH)
+      continue;
+    CallInst *I = cast<CallInst>(AssumeVH);
+
+    assert(I->getFunction() == Q.CxtI->getFunction() &&
+           "Got assumption for the wrong function!");
+    assert(I->getIntrinsicID() == Intrinsic::assume &&
+           "must be an assume intrinsic");
+
+    if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
+                           /*LHSIsTrue=*/true, Depth)
+            .value_or(false) &&
+        isValidAssumeForContext(I, Q.CxtI, Q.DT))
+      return true;
+  }
+
+  return false;
+}
+
 /// Return true if it is known that V1 != V2.
 static bool isKnownNonEqual(const Value *V1, const Value *V2,
                             const APInt &DemandedElts, unsigned Depth,
@@ -3875,49 +3932,8 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
       match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
     return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
 
-  if (!Q.CxtI)
-    return false;
-
-  // Try to infer NonEqual based on information from dominating conditions.
-  if (Q.DC && Q.DT) {
-    for (BranchInst *BI : Q.DC->conditionsFor(V1)) {
-      Value *Cond = BI->getCondition();
-      BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
-      if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
-          isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
-                             /*LHSIsTrue=*/true, Depth)
-              .value_or(false))
-        return true;
-
-      BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
-      if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
-          isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
-                             /*LHSIsTrue=*/false, Depth)
-              .value_or(false))
-        return true;
-    }
-  }
-
-  if (!Q.AC)
-    return false;
-
-  // Try to infer NonEqual based on information from assumptions.
-  for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
-    if (!AssumeVH)
-      continue;
-    CallInst *I = cast<CallInst>(AssumeVH);
-
-    assert(I->getFunction() == Q.CxtI->getFunction() &&
-           "Got assumption for the wrong function!");
-    assert(I->getIntrinsicID() == Intrinsic::assume &&
-           "must be an assume intrinsic");
-
-    if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
-                           /*LHSIsTrue=*/true, Depth)
-            .value_or(false) &&
-        isValidAssumeForContext(I, Q.CxtI, Q.DT))
-      return true;
-  }
+  if (isKnownNonEqualFromContext(V1, V2, Depth, Q))
+    return true;
 
   return false;
 }
@@ -10348,7 +10364,8 @@ void llvm::findValuesAffectedByCondition(
       bool HasRHSC = match(B, m_ConstantInt());
       if (ICmpInst::isEquality(Pred)) {
         AddAffected(A);
-        AddAffected(B);
+        if (IsAssume)
+          AddAffected(B);
         if (HasRHSC) {
           Value *Y;
           // (X & C) or (X | C).

diff  --git a/llvm/test/Transforms/InstCombine/icmp-dom.ll b/llvm/test/Transforms/InstCombine/icmp-dom.ll
index 07793e8951de5..6613bbeb8d6ae 100644
--- a/llvm/test/Transforms/InstCombine/icmp-dom.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-dom.ll
@@ -733,4 +733,82 @@ entry:
   ret i1 %cmp
 }
 
+; TODO: We can prove `%cond2` is always false
+define void @test_nonequal_domcond_loop1(i32 %x0, i1 %x1) {
+; CHECK-LABEL: @test_nonequal_domcond_loop1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X0:%.*]], [[LATCH:%.*]] ]
+; CHECK-NEXT:    br label [[LATCH]]
+; CHECK:       latch:
+; CHECK-NEXT:    br i1 [[X1:%.*]], label [[IF_THEN:%.*]], label [[LOOP_HEADER]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X0]], 1
+; CHECK-NEXT:    [[COND1:%.*]] = icmp eq i32 [[AND]], [[PHI]]
+; CHECK-NEXT:    br i1 [[COND1]], label [[IF_THEN2:%.*]], label [[LATCH]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    br label [[BB:%.*]]
+; CHECK:       indirectbb:
+; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i32 [[PHI]], 31
+; CHECK-NEXT:    br i1 [[COND2]], label [[EXIT:%.*]], label [[LATCH]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %phi = phi i32 [ 0, %entry ], [ %x0, %latch ]
+  br label %latch
+
+latch:
+  br i1 %x1, label %if.then, label %loop.header
+
+if.then:
+  %and = and i32 %x0, 1
+  %cond1 = icmp eq i32 %and, %phi
+  br i1 %cond1, label %if.then2, label %latch
+
+if.then2:
+  br label %indirectbb
+
+indirectbb:
+  %cond2 = icmp eq i32 %phi, 31
+  br i1 %cond2, label %exit, label %latch
+
+exit:
+  ret void
+}
+
+define void @test_nonequal_domcond_loop2(ptr %p) {
+; CHECK-LABEL: @test_nonequal_domcond_loop2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load volatile i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load volatile i8, ptr [[P]], align 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[LOAD2]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 [[LOAD2]], [[LOAD1]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR]], label [[WHILE_COND]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    br i1 false, label [[WHILE_COND]], label [[FOR_BODY]]
+;
+entry:
+  %load1 = load volatile i8, ptr %p, align 1
+  br label %while.cond
+
+while.cond:
+  %load2 = load volatile i8, ptr %p, align 1
+  %cmp1 = icmp eq i8 %load2, 0
+  %cmp2 = icmp uge i8 %load2, %load1
+  %or = select i1 %cmp1, i1 true, i1 %cmp2
+  br i1 %or, label %while.cond, label %for.body
+
+for.body:
+  %cond = icmp eq i8 %load1, %load2
+  br i1 %cond, label %while.cond, label %for.body
+}
+
 declare void @side_effect()


        


More information about the llvm-commits mailing list