[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