Skip to content

Commit f4dd537

Browse files
committed
[InstCombine] Fold select to cmp with constants in non-canonical inequalities
For constant y, inequalities aren't always canonical so we need to check the conditions such as - (x > y - 1) ? zext(x != y) : -1 - (x > y - 1) ? zext(x > y) : -1 - (x < y + 1) ? sext(x != y) : 1 - (x < y + 1) ? sext(x < y) : 1 and similary non-strict equalities. Fold select into scmp/ucmp based on signedness of the comparison predicate. Resolves #143259
1 parent 90a256e commit f4dd537

File tree

2 files changed

+37
-48
lines changed

2 files changed

+37
-48
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3572,6 +3572,28 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) {
35723572
if (!LHS->getType()->isIntOrIntVectorTy())
35733573
return nullptr;
35743574

3575+
// If there is no -1, 0 or 1 at TV, then invert the select statement and try
3576+
// to canonicalize to one of the forms above
3577+
if (!isa<Constant>(TV)) {
3578+
if (!isa<Constant>(FV))
3579+
return nullptr;
3580+
Pred = ICmpInst::getInverseCmpPredicate(Pred);
3581+
std::swap(TV, FV);
3582+
}
3583+
3584+
if (ICmpInst::isNonStrictPredicate(Pred)) {
3585+
if (Constant *C = dyn_cast<Constant>(RHS)) {
3586+
auto FlippedPredAndConst =
3587+
getFlippedStrictnessPredicateAndConstant(Pred, C);
3588+
if (!FlippedPredAndConst)
3589+
return nullptr;
3590+
Pred = FlippedPredAndConst->first;
3591+
RHS = FlippedPredAndConst->second;
3592+
} else {
3593+
return nullptr;
3594+
}
3595+
}
3596+
35753597
// Try to swap operands and the predicate. We need to be careful when doing
35763598
// so because two of the patterns have opposite predicates, so use the
35773599
// constant inside select to determine if swapping operands would be

llvm/test/Transforms/InstCombine/select-to-cmp.ll

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
define i32 @scmp_x_0_inverted(i32 %x) {
77
; CHECK-LABEL: define i32 @scmp_x_0_inverted(
88
; CHECK-SAME: i32 [[X:%.*]]) {
9-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[X]], 0
10-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
11-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[X]], -1
12-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
9+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 0)
1310
; CHECK-NEXT: ret i32 [[TMP1]]
1411
;
1512
%2 = icmp ne i32 %x, 0
@@ -23,10 +20,7 @@ define i32 @scmp_x_0_inverted(i32 %x) {
2320
define i32 @scmp_x_0_inverted_const_neg10(i32 %x) {
2421
; CHECK-LABEL: define i32 @scmp_x_0_inverted_const_neg10(
2522
; CHECK-SAME: i32 [[X:%.*]]) {
26-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[X]], -10
27-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
28-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[X]], -11
29-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
23+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 -10)
3024
; CHECK-NEXT: ret i32 [[TMP1]]
3125
;
3226
%1 = icmp ne i32 %x, -10
@@ -40,10 +34,7 @@ define i32 @scmp_x_0_inverted_const_neg10(i32 %x) {
4034
define i8 @scmp_x_0_inverted_i8(i8 %x) {
4135
; CHECK-LABEL: define i8 @scmp_x_0_inverted_i8(
4236
; CHECK-SAME: i8 [[X:%.*]]) {
43-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i8 [[X]], 7
44-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i8
45-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i8 [[X]], 6
46-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 -1
37+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i8(i8 [[X]], i8 7)
4738
; CHECK-NEXT: ret i8 [[TMP1]]
4839
;
4940
%1 = icmp ne i8 %x, 7
@@ -57,10 +48,8 @@ define i8 @scmp_x_0_inverted_i8(i8 %x) {
5748
define i32 @scmp_x_0_inverted_i64_neq(i32 %x) {
5849
; CHECK-LABEL: define i32 @scmp_x_0_inverted_i64_neq(
5950
; CHECK-SAME: i32 [[X:%.*]]) {
60-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X]], 0
61-
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], -1
62-
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP1]] to i32
63-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP2]], i32 [[TMP1]], i32 -1
51+
; CHECK-NEXT: [[SEL:%.*]] = call i64 @llvm.scmp.i64.i32(i32 [[X]], i32 0)
52+
; CHECK-NEXT: [[RET:%.*]] = trunc i64 [[SEL]] to i32
6453
; CHECK-NEXT: ret i32 [[RET]]
6554
;
6655
%x64 = sext i32 %x to i64
@@ -76,10 +65,8 @@ define i32 @scmp_x_0_inverted_i64_neq(i32 %x) {
7665
define i32 @scmp_x_0_inverted_i64_sgt(i32 %x) {
7766
; CHECK-LABEL: define i32 @scmp_x_0_inverted_i64_sgt(
7867
; CHECK-SAME: i32 [[X:%.*]]) {
79-
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], 0
80-
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], -1
81-
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP1]] to i32
82-
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP2]], i32 [[TMP1]], i32 -1
68+
; CHECK-NEXT: [[SEL:%.*]] = call i64 @llvm.scmp.i64.i32(i32 [[X]], i32 0)
69+
; CHECK-NEXT: [[RET:%.*]] = trunc i64 [[SEL]] to i32
8370
; CHECK-NEXT: ret i32 [[RET]]
8471
;
8572
%x64 = sext i32 %x to i64
@@ -95,10 +82,7 @@ define i32 @scmp_x_0_inverted_i64_sgt(i32 %x) {
9582
define i32 @scmp_x_0_inverted_const_neg1000(i32 %x) {
9683
; CHECK-LABEL: define i32 @scmp_x_0_inverted_const_neg1000(
9784
; CHECK-SAME: i32 [[X:%.*]]) {
98-
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[X]], -1000
99-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
100-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[X]], -1001
101-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
85+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 -1000)
10286
; CHECK-NEXT: ret i32 [[TMP1]]
10387
;
10488
%1 = icmp sgt i32 %x, -1000
@@ -112,10 +96,7 @@ define i32 @scmp_x_0_inverted_const_neg1000(i32 %x) {
11296
define i32 @scmp_x_0_inverted_const_1729_sgt(i32 %x) {
11397
; CHECK-LABEL: define i32 @scmp_x_0_inverted_const_1729_sgt(
11498
; CHECK-SAME: i32 [[X:%.*]]) {
115-
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[X]], 1729
116-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
117-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[X]], 1728
118-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
99+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 1729)
119100
; CHECK-NEXT: ret i32 [[TMP1]]
120101
;
121102
%1 = icmp sgt i32 %x, 1729
@@ -129,10 +110,7 @@ define i32 @scmp_x_0_inverted_const_1729_sgt(i32 %x) {
129110
define i32 @ucmp_x_10_inverted(i32 %x) {
130111
; CHECK-LABEL: define i32 @ucmp_x_10_inverted(
131112
; CHECK-SAME: i32 [[X:%.*]]) {
132-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[X]], 10
133-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
134-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[X]], 9
135-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
113+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 10)
136114
; CHECK-NEXT: ret i32 [[TMP1]]
137115
;
138116
%1 = icmp ne i32 %x, 10
@@ -146,10 +124,7 @@ define i32 @ucmp_x_10_inverted(i32 %x) {
146124
define i32 @ucmp_x_neg1_inverted(i32 %x) {
147125
; CHECK-LABEL: define i32 @ucmp_x_neg1_inverted(
148126
; CHECK-SAME: i32 [[X:%.*]]) {
149-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[X]], -3
150-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
151-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[X]], -4
152-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
127+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 -3)
153128
; CHECK-NEXT: ret i32 [[TMP1]]
154129
;
155130
%1 = icmp ne i32 %x, -3
@@ -163,10 +138,7 @@ define i32 @ucmp_x_neg1_inverted(i32 %x) {
163138
define i8 @ucmp_x_neg4_i8_ugt(i8 %x) {
164139
; CHECK-LABEL: define i8 @ucmp_x_neg4_i8_ugt(
165140
; CHECK-SAME: i8 [[X:%.*]]) {
166-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], -4
167-
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i8
168-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i8 [[X]], -5
169-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 -1
141+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i8(i8 [[X]], i8 -4)
170142
; CHECK-NEXT: ret i8 [[TMP1]]
171143
;
172144
%1 = icmp ugt i8 %x, -4
@@ -182,10 +154,7 @@ define i8 @ucmp_x_neg4_i8_ugt(i8 %x) {
182154
define <4 x i32> @scmp_x_0_inverted_splat_vec(<4 x i32> %x) {
183155
; CHECK-LABEL: define <4 x i32> @scmp_x_0_inverted_splat_vec(
184156
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
185-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i32> [[X]], zeroinitializer
186-
; CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i32>
187-
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt <4 x i32> [[X]], splat (i32 -1)
188-
; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[TMP3]], <4 x i32> [[TMP2]], <4 x i32> splat (i32 -1)
157+
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32> [[X]], <4 x i32> zeroinitializer)
189158
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
190159
;
191160
%2 = icmp ne <4 x i32> %x, zeroinitializer
@@ -199,10 +168,8 @@ define <4 x i32> @scmp_x_0_inverted_splat_vec(<4 x i32> %x) {
199168
define <4 x i32> @non_splat_vec_scmp_diff_bitwidth(<4 x i32> %x) {
200169
; CHECK-LABEL: define <4 x i32> @non_splat_vec_scmp_diff_bitwidth(
201170
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
202-
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <4 x i32> [[X]], <i32 0, i32 1, i32 -1, i32 5>
203-
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <4 x i32> [[X]], <i32 1, i32 2, i32 0, i32 6>
204-
; CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i1> [[CMP1]] to <4 x i32>
205-
; CHECK-NEXT: [[RET:%.*]] = select <4 x i1> [[CMP2]], <4 x i32> [[TMP1]], <4 x i32> splat (i32 1)
171+
; CHECK-NEXT: [[SEL:%.*]] = call <4 x i64> @llvm.scmp.v4i64.v4i32(<4 x i32> [[X]], <4 x i32> <i32 0, i32 1, i32 -1, i32 5>)
172+
; CHECK-NEXT: [[RET:%.*]] = trunc <4 x i64> [[SEL]] to <4 x i32>
206173
; CHECK-NEXT: ret <4 x i32> [[RET]]
207174
;
208175
%x64 = sext <4 x i32> %x to <4 x i64>

0 commit comments

Comments
 (0)