[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