[llvm] InstCombine: Fold samesign ult to slt with added constant when the range is known (PR #134556)

Rajagopalan Gangadharan via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 6 11:57:22 PDT 2025


https://github.com/RAJAGOPALAN-GANGADHARAN created https://github.com/llvm/llvm-project/pull/134556

### Notes
Optimizer at O2 and above can deduct that addition is `nsw` when the range is known and is partially negative. When this is followed by a icmp samesign ult, it can be folded/reduced into an icmp slt with constant resolved/added during compile time. This optimizes the compare instruction a bit.

### Testing
Tested manually in alive2
Wrote unit tests to validate functionality
Test 1 checks when the folding is performed from samesign ult to slt on a partially negative range
Test 2 makes sure existing functionality is not broken by validating a completely positive range.

### Issue:

This PR fixes issue: #134208 


>From d27f5e2195bf220a03d1d619cc8470e001c02b8d Mon Sep 17 00:00:00 2001
From: Rajagopalan Gangadharan <g.raju2000 at gmail.com>
Date: Mon, 7 Apr 2025 00:11:01 +0530
Subject: [PATCH 1/2] Precommit baseline tests

---
 llvm/test/Transforms/InstCombine/icmp-add.ll | 25 ++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index a8cdf80948a84..29c93668e1e52 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3302,3 +3302,28 @@ entry:
   %cmp = icmp ult i32 %add, 253
   ret i1 %cmp
 }
+
+define i1 @icmp_partial_negative_samesign_ult_folded_to_slt(i8 range(i8 -1, 5) %x) {
+; CHECK-LABEL: @icmp_partial_negative_samesign_ult_folded_to_slt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[X:%.*]], -5
+; CHECK-NEXT:    [[CMP:%.*]] = icmp samesign ult i8 [[ADD]], -3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %add = add nsw i8 %x, -5
+  %cmp = icmp samesign ult i8 %add, -3
+  ret i1 %cmp
+}
+
+define i1 @icmp_positive_samesign_ult_folded_to_ult(i8 range(i8 1, 5) %x) {
+; CHECK-LABEL: @icmp_positive_samesign_ult_folded_to_ult(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp samesign ult i8 [[X:%.*]], 2
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %add = add nsw i8 %x, 1
+  %cmp = icmp samesign slt i8 %add, 3
+  ret i1 %cmp
+}

>From ffb56f6ae6151f980dd4c533f33e4e518b40f75f Mon Sep 17 00:00:00 2001
From: Rajagopalan Gangadharan <g.raju2000 at gmail.com>
Date: Mon, 7 Apr 2025 00:14:16 +0530
Subject: [PATCH 2/2] InstCombine: Fold samesign ult to slt with resolved
 constant

Signed-off-by: Rajagopalan-Gangadharan <g.raju2000 at gmail.com>
---
 .../Transforms/InstCombine/InstCombineCompares.cpp  | 13 +++++++++----
 llvm/test/Transforms/InstCombine/icmp-add.ll        |  3 +--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index e75b4026d5424..863b59454b478 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3119,7 +3119,7 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
 
   Value *Op0, *Op1;
   Instruction *Ext0, *Ext1;
-  const CmpInst::Predicate Pred = Cmp.getPredicate();
+  const CmpPredicate Pred = Cmp.getCmpPredicate();
   if (match(Add,
             m_Add(m_CombineAnd(m_Instruction(Ext0), m_ZExtOrSExt(m_Value(Op0))),
                   m_CombineAnd(m_Instruction(Ext1),
@@ -3156,7 +3156,8 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
   // the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
   // are canonicalized to SGT/SLT/UGT/ULT.
   if ((Add->hasNoSignedWrap() &&
-       (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLT)) ||
+       (Pred.getPreferredSignedPredicate() == ICmpInst::ICMP_SGT ||
+        Pred.getPreferredSignedPredicate() == ICmpInst::ICMP_SLT)) ||
       (Add->hasNoUnsignedWrap() &&
        (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT))) {
     bool Overflow;
@@ -3165,9 +3166,13 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
     // If there is overflow, the result must be true or false.
     // TODO: Can we assert there is no overflow because InstSimplify always
     // handles those cases?
-    if (!Overflow)
+    if (!Overflow) {
+      const CmpInst::Predicate EquivPredicate =
+          Add->hasNoSignedWrap() ? Pred.getPreferredSignedPredicate()
+                                 : Cmp.getPredicate();
       // icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2)
-      return new ICmpInst(Pred, X, ConstantInt::get(Ty, NewC));
+      return new ICmpInst(EquivPredicate, X, ConstantInt::get(Ty, NewC));
+    }
   }
 
   if (ICmpInst::isUnsigned(Pred) && Add->hasNoSignedWrap() &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 29c93668e1e52..eb693244f2057 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3306,8 +3306,7 @@ entry:
 define i1 @icmp_partial_negative_samesign_ult_folded_to_slt(i8 range(i8 -1, 5) %x) {
 ; CHECK-LABEL: @icmp_partial_negative_samesign_ult_folded_to_slt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[X:%.*]], -5
-; CHECK-NEXT:    [[CMP:%.*]] = icmp samesign ult i8 [[ADD]], -3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 2
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
 entry:



More information about the llvm-commits mailing list