Skip to content

Commit c73157e

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

File tree

2 files changed

+21
-27
lines changed

2 files changed

+21
-27
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 17 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,22 @@ 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+
}
16801690
}
16811691

16821692
// 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)