[llvm] [SCEV] Remove expensive inverted reasoning from isImpliedCond. (PR #227302)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 06:04:06 PDT 2026


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/227302

>From db2cf0e8fee33372a9ff6572bcc78d9815631726 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 25 Sep 2026 20:21:54 +0100
Subject: [PATCH 1/2] [SCEV] Remove expensive inverted reasoning from
 isImpliedCond.

The constructing the inverted expressions and the additional reasoning
is quite expensive (0.35% for CTMark O3), for marginal gain
(3 small regressions on https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1494)

I think that should allow us to spend compile-time on SCEV on areas with
higher impact.

2 of those could be recovered by constant-based reasoning about the
inverted condition.

Compile-time improvements:
stage1-O3: -0.35%
stage1-ReleaseThinLTO: -0.32%
stage1-ReleaseLTO-g: -0.28%
stage1-aarch64-O3: -0.31%
stage2-O3: -0.32%
stage2-clang: -0.06%

https://llvm-compile-time-tracker.com/compare.php?from=197c16add5b16f4bd68c4f4bae115723e74330e2&to=30dc497653f0daafd602d29a1ead334599055619&stat=instructions:u
---
 llvm/lib/Analysis/ScalarEvolution.cpp | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index cbadeaf7b347d..c03e2b5b206f7 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12256,31 +12256,14 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
     // using one of the following ways:
     // 1.  LHS Pred      RHS  <-   FoundRHS Pred      FoundLHS
     // 2.  RHS SwapPred  LHS  <-   FoundLHS SwapPred  FoundRHS
-    // 3.  LHS Pred      RHS  <-  ~FoundLHS Pred     ~FoundRHS
-    // 4. ~LHS SwapPred ~RHS  <-   FoundLHS SwapPred  FoundRHS
-    // Forms 1. and 2. require swapping the operands of one condition. Don't
-    // do this if it would break canonical constant/addrec ordering.
+    // Both require swapping the operands of one condition. Don't do this if it
+    // would break canonical constant/addrec ordering.
     if (!isa<SCEVConstant>(RHS) && !isa<SCEVAddRecExpr>(LHS))
       return isImpliedCondOperands(ICmpInst::getSwappedCmpPredicate(*P), RHS,
                                    LHS, FoundLHS, FoundRHS, CtxI);
     if (!isa<SCEVConstant>(FoundRHS) && !isa<SCEVAddRecExpr>(FoundLHS))
       return isImpliedCondOperands(*P, LHS, RHS, FoundRHS, FoundLHS, CtxI);
 
-    // There's no clear preference between forms 3. and 4., try both.  Avoid
-    // forming getNotSCEV of pointer values as the resulting subtract is
-    // not legal.
-    if (!LHS->getType()->isPointerTy() && !RHS->getType()->isPointerTy() &&
-        isImpliedCondOperands(ICmpInst::getSwappedCmpPredicate(*P),
-                              getNotSCEV(LHS), getNotSCEV(RHS), FoundLHS,
-                              FoundRHS, CtxI))
-      return true;
-
-    if (!FoundLHS->getType()->isPointerTy() &&
-        !FoundRHS->getType()->isPointerTy() &&
-        isImpliedCondOperands(*P, LHS, RHS, getNotSCEV(FoundLHS),
-                              getNotSCEV(FoundRHS), CtxI))
-      return true;
-
     return false;
   }
 

>From 79291799b3cecc25c06b374e4405660393f74d30 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 29 Sep 2026 15:25:19 +0100
Subject: [PATCH 2/2] !fixup remove unit test

---
 .../Analysis/ScalarEvolutionTest.cpp          | 39 -------------------
 1 file changed, 39 deletions(-)

diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 1fd2eaa5eb72f..f35ecb5ea5110 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1558,45 +1558,6 @@ TEST_F(ScalarEvolutionsTest, ProveImplicationViaNarrowing) {
   });
 }
 
-TEST_F(ScalarEvolutionsTest, ImpliedCond) {
-  LLVMContext C;
-  SMDiagnostic Err;
-  std::unique_ptr<Module> M = parseAssemblyString(
-      "define void @foo(i32 %len) { "
-      "entry: "
-      "  br label %loop "
-      "loop: "
-      "  %iv = phi i32 [ 0, %entry], [%iv.next, %loop] "
-      "  %iv.next = add nsw i32 %iv, 1 "
-      "  %cmp = icmp slt i32 %iv, %len "
-      "  br i1 %cmp, label %loop, label %exit "
-      "exit:"
-      "  ret void "
-      "}",
-      Err, C);
-
-  ASSERT_TRUE(M && "Could not parse module?");
-  ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
-
-  runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    Instruction *IV = getInstructionByName(F, "iv");
-    Type *Ty = IV->getType();
-    const SCEV *Zero = SE.getZero(Ty);
-    const SCEV *MinusOne = SE.getMinusOne(Ty);
-    // {0,+,1}<nuw><nsw>
-    const SCEV *AddRec_0_1 = SE.getSCEV(IV);
-    // {0,+,-1}<nw>
-    const SCEV *AddRec_0_N1 = SE.getNegativeSCEV(AddRec_0_1);
-
-    // {0,+,1}<nuw><nsw> > 0  ->  {0,+,-1}<nw> < 0
-    EXPECT_TRUE(isImpliedCond(SE, ICmpInst::ICMP_SLT, AddRec_0_N1, Zero,
-                                  ICmpInst::ICMP_SGT, AddRec_0_1, Zero));
-    // {0,+,-1}<nw> < -1  ->  {0,+,1}<nuw><nsw> > 0
-    EXPECT_TRUE(isImpliedCond(SE, ICmpInst::ICMP_SGT, AddRec_0_1, Zero,
-                                  ICmpInst::ICMP_SLT, AddRec_0_N1, MinusOne));
-  });
-}
-
 TEST_F(ScalarEvolutionsTest, MatchURem) {
   LLVMContext C;
   SMDiagnostic Err;



More information about the llvm-commits mailing list