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

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 6 11:58:12 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Rajagopalan Gangadharan (RAJAGOPALAN-GANGADHARAN)

<details>
<summary>Changes</summary>

### 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 


---
Full diff: https://github.com/llvm/llvm-project/pull/134556.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+9-4) 
- (modified) llvm/test/Transforms/InstCombine/icmp-add.ll (+24) 


``````````diff
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 a8cdf80948a84..eb693244f2057 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3302,3 +3302,27 @@ 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:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 2
+; 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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/134556


More information about the llvm-commits mailing list