Skip to content

Commit 357c6b8

Browse files
committed
Implement the fold and update tests
1 parent 992a02d commit 357c6b8

File tree

3 files changed

+27
-32
lines changed

3 files changed

+27
-32
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,25 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
16221622
A->getType()->isIntOrIntVectorTy(1))
16231623
return replaceInstUsesWith(I, Constant::getNullValue(I.getType()));
16241624

1625+
// sext(A < B) + zext(A > B) => ucmp/scmp(A, B)
1626+
ICmpInst::Predicate LTPred, GTPred;
1627+
if (match(&I,
1628+
m_c_Add(m_SExt(m_c_ICmp(LTPred, m_Value(A), m_Value(B))),
1629+
m_ZExt(m_c_ICmp(GTPred, m_Deferred(A), m_Deferred(B)))))) {
1630+
if (ICmpInst::isGT(LTPred)) {
1631+
std::swap(LTPred, GTPred);
1632+
std::swap(A, B);
1633+
}
1634+
1635+
if (ICmpInst::isLT(LTPred) && ICmpInst::isGT(GTPred) &&
1636+
ICmpInst::isSigned(LTPred) == ICmpInst::isSigned(GTPred))
1637+
return replaceInstUsesWith(
1638+
I, Builder.CreateIntrinsic(
1639+
Ty,
1640+
ICmpInst::isSigned(LTPred) ? Intrinsic::scmp : Intrinsic::ucmp,
1641+
{A, B}));
1642+
}
1643+
16251644
// A+B --> A|B iff A and B have no bits set in common.
16261645
WithCache<const Value *> LHSCache(LHS), RHSCache(RHS);
16271646
if (haveNoCommonBitsSet(LHSCache, RHSCache, SQ.getWithInstruction(&I)))

llvm/test/Transforms/InstCombine/add.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,8 +1277,8 @@ define <2 x i8> @ashr_add_commute(<2 x i1> %x, <2 x i1> %y) {
12771277

12781278
define i32 @cmp_math(i32 %x, i32 %y) {
12791279
; CHECK-LABEL: @cmp_math(
1280-
; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
1281-
; CHECK-NEXT: [[R:%.*]] = zext i1 [[LT]] to i32
1280+
; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
1281+
; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31
12821282
; CHECK-NEXT: ret i32 [[R]]
12831283
;
12841284
%gt = icmp ugt i32 %x, %y

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

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55
define i8 @signed_add(i32 %a, i32 %b) {
66
; CHECK-LABEL: define i8 @signed_add(
77
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
8-
; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]
9-
; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8
10-
; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]
11-
; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8
12-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]
8+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])
139
; CHECK-NEXT: ret i8 [[R]]
1410
;
1511
%lt = icmp slt i32 %a, %b
@@ -24,11 +20,7 @@ define i8 @signed_add(i32 %a, i32 %b) {
2420
define i8 @unsigned_add(i32 %a, i32 %b) {
2521
; CHECK-LABEL: define i8 @unsigned_add(
2622
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
27-
; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A]], [[B]]
28-
; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8
29-
; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], [[B]]
30-
; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8
31-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]
23+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])
3224
; CHECK-NEXT: ret i8 [[R]]
3325
;
3426
%lt = icmp ult i32 %a, %b
@@ -43,11 +35,7 @@ define i8 @unsigned_add(i32 %a, i32 %b) {
4335
define i8 @signed_add_commuted1(i32 %a, i32 %b) {
4436
; CHECK-LABEL: define i8 @signed_add_commuted1(
4537
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
46-
; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]
47-
; CHECK-NEXT: [[LT8:%.*]] = zext i1 [[LT]] to i8
48-
; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]
49-
; CHECK-NEXT: [[GT8:%.*]] = sext i1 [[GT]] to i8
50-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]
38+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[B]], i32 [[A]])
5139
; CHECK-NEXT: ret i8 [[R]]
5240
;
5341
%lt = icmp slt i32 %a, %b
@@ -61,11 +49,7 @@ define i8 @signed_add_commuted1(i32 %a, i32 %b) {
6149
define i8 @signed_add_commuted2(i32 %a, i32 %b) {
6250
; CHECK-LABEL: define i8 @signed_add_commuted2(
6351
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
64-
; CHECK-NEXT: [[LT:%.*]] = icmp sgt i32 [[B]], [[A]]
65-
; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8
66-
; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]
67-
; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8
68-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]
52+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])
6953
; CHECK-NEXT: ret i8 [[R]]
7054
;
7155
%lt = icmp sgt i32 %b, %a
@@ -80,11 +64,7 @@ define i8 @signed_add_commuted2(i32 %a, i32 %b) {
8064
define i8 @signed_sub(i32 %a, i32 %b) {
8165
; CHECK-LABEL: define i8 @signed_sub(
8266
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
83-
; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]
84-
; CHECK-NEXT: [[LT8_NEG:%.*]] = sext i1 [[LT]] to i8
85-
; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]
86-
; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8
87-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8_NEG]], [[GT8]]
67+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])
8868
; CHECK-NEXT: ret i8 [[R]]
8969
;
9070
%lt = icmp slt i32 %a, %b
@@ -99,11 +79,7 @@ define i8 @signed_sub(i32 %a, i32 %b) {
9979
define i8 @unsigned_sub(i32 %a, i32 %b) {
10080
; CHECK-LABEL: define i8 @unsigned_sub(
10181
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
102-
; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A]], [[B]]
103-
; CHECK-NEXT: [[LT8_NEG:%.*]] = sext i1 [[LT]] to i8
104-
; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], [[B]]
105-
; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8
106-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8_NEG]], [[GT8]]
82+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])
10783
; CHECK-NEXT: ret i8 [[R]]
10884
;
10985
%lt = icmp ult i32 %a, %b

0 commit comments

Comments
 (0)