Skip to content

Commit 5b11d5d

Browse files
committed
[InstCombine] Add a >= b - a<=b to scmp and ucmp folds
https://alive2.llvm.org/ce/z/QiMA_i
1 parent ee46e02 commit 5b11d5d

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
16601660
return replaceInstUsesWith(I, Constant::getNullValue(I.getType()));
16611661

16621662
// sext(A < B) + zext(A > B) => ucmp/scmp(A, B)
1663+
// sext(A <= B) + zext(A >= B) => ucmp/scmp(A, B)
16631664
CmpPredicate LTPred, GTPred;
16641665
if (match(&I,
16651666
m_c_Add(m_SExt(m_c_ICmp(LTPred, m_Value(A), m_Value(B))),
@@ -1670,13 +1671,50 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
16701671
std::swap(A, B);
16711672
}
16721673

1673-
if (ICmpInst::isLT(LTPred) && ICmpInst::isGT(GTPred) &&
1674-
ICmpInst::isSigned(LTPred) == ICmpInst::isSigned(GTPred))
1675-
return replaceInstUsesWith(
1676-
I, Builder.CreateIntrinsic(
1677-
Ty,
1678-
ICmpInst::isSigned(LTPred) ? Intrinsic::scmp : Intrinsic::ucmp,
1679-
{A, B}));
1674+
if (ICmpInst::isSigned(LTPred) == ICmpInst::isSigned(GTPred)) {
1675+
Intrinsic::ID IID =
1676+
ICmpInst::isSigned(LTPred) ? Intrinsic::scmp : Intrinsic::ucmp;
1677+
1678+
// Handle strict inequalities: sext(A < B) + zext(A > B) => scmp/ucmp(A,
1679+
// B)
1680+
if (ICmpInst::isLT(LTPred) && ICmpInst::isGT(GTPred)) {
1681+
return replaceInstUsesWith(I, Builder.CreateIntrinsic(Ty, IID, {A, B}));
1682+
}
1683+
1684+
// Handle non-strict inequalities: sext(A <= B) + zext(A >= B) =>
1685+
// scmp/ucmp(A, B)
1686+
if (ICmpInst::isLE(LTPred) && ICmpInst::isGE(GTPred)) {
1687+
return replaceInstUsesWith(I, Builder.CreateIntrinsic(Ty, IID, {A, B}));
1688+
}
1689+
}
1690+
}
1691+
1692+
// Handle constant case: sext(x > C1) + zext(x < C2) where C2 = C1 + 1
1693+
// This represents (x >= C1+1) - (x <= C1+1) => scmp/ucmp(x, C1+1)
1694+
Value *X, *Const1, *Const2;
1695+
CmpPredicate Pred1, Pred2;
1696+
if (match(&I,
1697+
m_c_Add(m_SExt(m_c_ICmp(Pred1, m_Value(X), m_Value(Const1))),
1698+
m_ZExt(m_c_ICmp(Pred2, m_Deferred(X), m_Value(Const2))))) &&
1699+
X->getType()->isIntOrIntVectorTy() && isa<ConstantInt>(Const1) &&
1700+
isa<ConstantInt>(Const2)) {
1701+
1702+
// Check if we have x > C1 and x < C2 where C2 = C1 + 2
1703+
if (ICmpInst::isGT(Pred1) && ICmpInst::isLT(Pred2)) {
1704+
ConstantInt *ConstC1 = cast<ConstantInt>(Const1);
1705+
ConstantInt *ConstC2 = cast<ConstantInt>(Const2);
1706+
1707+
// Check if C2 = C1 + 2
1708+
if (ConstC2->getValue() == ConstC1->getValue() + 2) {
1709+
// This represents (x >= C1+1) - (x <= C1+1) => scmp/ucmp(x, C1+1)
1710+
Intrinsic::ID IID =
1711+
ICmpInst::isSigned(Pred1) ? Intrinsic::scmp : Intrinsic::ucmp;
1712+
Constant *C1Plus1 =
1713+
ConstantInt::get(Const1->getType(), ConstC1->getValue() + 1);
1714+
return replaceInstUsesWith(
1715+
I, Builder.CreateIntrinsic(Ty, IID, {X, C1Plus1}));
1716+
}
1717+
}
16801718
}
16811719

16821720
// A+B --> A|B iff A and B have no bits set in common.

llvm/test/Transforms/InstCombine/sext-a-lt-b-plus-zext-a-gt-b-to-uscmp.ll

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,7 @@ define i8 @signed_add_neg5(i32 %a, i32 %b) {
187187
define i8 @signed_add_ge_le(i32 %a, i32 %b) {
188188
; CHECK-LABEL: define i8 @signed_add_ge_le(
189189
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
190-
; CHECK-NEXT: [[LE:%.*]] = icmp sle i32 [[A]], [[B]]
191-
; CHECK-NEXT: [[LE8:%.*]] = sext i1 [[LE]] to i8
192-
; CHECK-NEXT: [[GE:%.*]] = icmp sge i32 [[A]], [[B]]
193-
; CHECK-NEXT: [[GE8:%.*]] = zext i1 [[GE]] to i8
194-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LE8]], [[GE8]]
190+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])
195191
; CHECK-NEXT: ret i8 [[R]]
196192
;
197193
%le = icmp sle i32 %a, %b
@@ -206,11 +202,7 @@ define i8 @signed_add_ge_le(i32 %a, i32 %b) {
206202
define i8 @unsigned_add_ge_le(i32 %a, i32 %b) {
207203
; CHECK-LABEL: define i8 @unsigned_add_ge_le(
208204
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
209-
; CHECK-NEXT: [[LE:%.*]] = icmp ule i32 [[A]], [[B]]
210-
; CHECK-NEXT: [[LE8:%.*]] = sext i1 [[LE]] to i8
211-
; CHECK-NEXT: [[GE:%.*]] = icmp uge i32 [[A]], [[B]]
212-
; CHECK-NEXT: [[GE8:%.*]] = zext i1 [[GE]] to i8
213-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LE8]], [[GE8]]
205+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])
214206
; CHECK-NEXT: ret i8 [[R]]
215207
;
216208
%le = icmp ule i32 %a, %b
@@ -225,11 +217,7 @@ define i8 @unsigned_add_ge_le(i32 %a, i32 %b) {
225217
define i8 @signed_sub_ge_le(i32 %a, i32 %b) {
226218
; CHECK-LABEL: define i8 @signed_sub_ge_le(
227219
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
228-
; CHECK-NEXT: [[LE:%.*]] = icmp sle i32 [[A]], [[B]]
229-
; CHECK-NEXT: [[LE8_NEG:%.*]] = sext i1 [[LE]] to i8
230-
; CHECK-NEXT: [[GE:%.*]] = icmp sge i32 [[A]], [[B]]
231-
; CHECK-NEXT: [[GE8:%.*]] = zext i1 [[GE]] to i8
232-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LE8_NEG]], [[GE8]]
220+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])
233221
; CHECK-NEXT: ret i8 [[R]]
234222
;
235223
%le = icmp sle i32 %a, %b
@@ -244,11 +232,7 @@ define i8 @signed_sub_ge_le(i32 %a, i32 %b) {
244232
define i8 @unsigned_sub_ge_le(i32 %a, i32 %b) {
245233
; CHECK-LABEL: define i8 @unsigned_sub_ge_le(
246234
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
247-
; CHECK-NEXT: [[LE:%.*]] = icmp ule i32 [[A]], [[B]]
248-
; CHECK-NEXT: [[LE8_NEG:%.*]] = sext i1 [[LE]] to i8
249-
; CHECK-NEXT: [[GE:%.*]] = icmp uge i32 [[A]], [[B]]
250-
; CHECK-NEXT: [[GE8:%.*]] = zext i1 [[GE]] to i8
251-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LE8_NEG]], [[GE8]]
235+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])
252236
; CHECK-NEXT: ret i8 [[R]]
253237
;
254238
%le = icmp ule i32 %a, %b

0 commit comments

Comments
 (0)