Skip to content

Commit 6c41e13

Browse files
committed
[Instcombine][Tests] Add test for folding select
to cmp with weak inequalities and constants on RHS. Tests has baseline CHECK lines.
1 parent 339797d commit 6c41e13

File tree

1 file changed

+295
-0
lines changed

1 file changed

+295
-0
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3+
4+
; Fold (x < y) ? -1 : zext(x != y) to scmp(x, y)
5+
define i32 @scmp_x_y_from_lt(i32 %x, i32 %y) {
6+
; CHECK-LABEL: define i32 @scmp_x_y_from_lt(
7+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
8+
; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
9+
; CHECK-NEXT: ret i32 [[SEL]]
10+
;
11+
%cmp1 = icmp ne i32 %x, %y
12+
%zext = zext i1 %cmp1 to i32
13+
%cmp2 = icmp slt i32 %x, %y
14+
%sel = select i1 %cmp2, i32 -1, i32 %zext
15+
ret i32 %sel
16+
}
17+
18+
; Fold (x < y) ? -1 : zext(x > y) to scmp(x, y)
19+
define i32 @scmp_x_y_from_lt_gt(i32 %x, i32 %y) {
20+
; CHECK-LABEL: define i32 @scmp_x_y_from_lt_gt(
21+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
22+
; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
23+
; CHECK-NEXT: ret i32 [[SEL]]
24+
;
25+
%cmp1 = icmp sgt i32 %x, %y
26+
%zext = zext i1 %cmp1 to i32
27+
%cmp2 = icmp slt i32 %x, %y
28+
%sel = select i1 %cmp2, i32 -1, i32 %zext
29+
ret i32 %sel
30+
}
31+
32+
; Fold (x > y) ? 1 : sext(x != y) to scmp(x, y)
33+
define i32 @scmp_x_y_from_gt_sext_ne(i32 %x, i32 %y) {
34+
; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sext_ne(
35+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
36+
; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
37+
; CHECK-NEXT: ret i32 [[SEL]]
38+
;
39+
%cmp1 = icmp ne i32 %x, %y
40+
%sext = sext i1 %cmp1 to i32
41+
%cmp2 = icmp sgt i32 %x, %y
42+
%sel = select i1 %cmp2, i32 1, i32 %sext
43+
ret i32 %sel
44+
}
45+
46+
; Fold (x > y) ? 1 : sext(x < y) to scmp(x, y)
47+
define i32 @scmp_x_y_from_gt_sext_lt(i32 %x, i32 %y) {
48+
; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sext_lt(
49+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
50+
; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
51+
; CHECK-NEXT: ret i32 [[SEL]]
52+
;
53+
%cmp1 = icmp slt i32 %x, %y
54+
%sext = sext i1 %cmp1 to i32
55+
%cmp2 = icmp sgt i32 %x, %y
56+
%sel = select i1 %cmp2, i32 1, i32 %sext
57+
ret i32 %sel
58+
}
59+
60+
; Fold (x <= y - 1) ? -1 : zext(x != y) to ucmp(x, y)
61+
define i32 @ucmp_x_y_from_le_sub_zext_ne(i32 %x, i32 %y) {
62+
; CHECK-LABEL: define i32 @ucmp_x_y_from_le_sub_zext_ne(
63+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
64+
; CHECK-NEXT: [[YM1:%.*]] = add i32 [[Y]], -1
65+
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp ugt i32 [[X]], [[YM1]]
66+
; CHECK-NEXT: [[NEQ:%.*]] = icmp ne i32 [[X]], [[Y]]
67+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[NEQ]] to i32
68+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1_NOT]], i32 [[ZEXT]], i32 -1
69+
; CHECK-NEXT: ret i32 [[SEL]]
70+
;
71+
%ym1 = sub i32 %y, 1
72+
%cmp1 = icmp ule i32 %x, %ym1
73+
%neq = icmp ne i32 %x, %y
74+
%zext = zext i1 %neq to i32
75+
%sel = select i1 %cmp1, i32 -1, i32 %zext
76+
ret i32 %sel
77+
}
78+
79+
; Fold (x <= y - 1) ? -1 : zext(x > y) to ucmp(x, y)
80+
define i32 @ucmp_x_y_from_le_sub_zext_gt(i32 %x, i32 %y) {
81+
; CHECK-LABEL: define i32 @ucmp_x_y_from_le_sub_zext_gt(
82+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
83+
; CHECK-NEXT: [[YM1:%.*]] = add i32 [[Y]], -1
84+
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp ugt i32 [[X]], [[YM1]]
85+
; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[X]], [[Y]]
86+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[GT]] to i32
87+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1_NOT]], i32 [[ZEXT]], i32 -1
88+
; CHECK-NEXT: ret i32 [[SEL]]
89+
;
90+
%ym1 = sub i32 %y, 1
91+
%cmp1 = icmp ule i32 %x, %ym1
92+
%gt = icmp ugt i32 %x, %y
93+
%zext = zext i1 %gt to i32
94+
%sel = select i1 %cmp1, i32 -1, i32 %zext
95+
ret i32 %sel
96+
}
97+
98+
; Fold (x >= y + 1) ? 1 : sext(x != y) to ucmp(x, y)
99+
define i32 @ucmp_x_y_from_ge_add_sext_ne(i32 %x, i32 %y) {
100+
; CHECK-LABEL: define i32 @ucmp_x_y_from_ge_add_sext_ne(
101+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
102+
; CHECK-NEXT: [[YP1:%.*]] = add i32 [[Y]], 1
103+
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp ult i32 [[X]], [[YP1]]
104+
; CHECK-NEXT: [[NEQ:%.*]] = icmp ne i32 [[X]], [[Y]]
105+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[NEQ]] to i32
106+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1_NOT]], i32 [[SEXT]], i32 1
107+
; CHECK-NEXT: ret i32 [[SEL]]
108+
;
109+
%yp1 = add i32 %y, 1
110+
%cmp1 = icmp uge i32 %x, %yp1
111+
%neq = icmp ne i32 %x, %y
112+
%sext = sext i1 %neq to i32
113+
%sel = select i1 %cmp1, i32 1, i32 %sext
114+
ret i32 %sel
115+
}
116+
117+
; Fold (x >= y + 1) ? 1 : sext(x < y) to ucmp(x, y)
118+
define i32 @ucmp_x_y_from_ge_add_sext_lt(i32 %x, i32 %y) {
119+
; CHECK-LABEL: define i32 @ucmp_x_y_from_ge_add_sext_lt(
120+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
121+
; CHECK-NEXT: [[YP1:%.*]] = add i32 [[Y]], 1
122+
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp ult i32 [[X]], [[YP1]]
123+
; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[X]], [[Y]]
124+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[LT]] to i32
125+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1_NOT]], i32 [[SEXT]], i32 1
126+
; CHECK-NEXT: ret i32 [[SEL]]
127+
;
128+
%yp1 = add i32 %y, 1
129+
%cmp1 = icmp uge i32 %x, %yp1
130+
%lt = icmp ult i32 %x, %y
131+
%sext = sext i1 %lt to i32
132+
%sel = select i1 %cmp1, i32 1, i32 %sext
133+
ret i32 %sel
134+
}
135+
136+
; Fold (x > y - 1) ? zext(x != y) : -1 to scmp(x, y)
137+
define i32 @scmp_x_y_from_gt_sub_zext_ne(i32 %x, i32 %y) {
138+
; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sub_zext_ne(
139+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
140+
; CHECK-NEXT: [[YM1:%.*]] = add i32 [[Y]], -1
141+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], [[YM1]]
142+
; CHECK-NEXT: [[NE:%.*]] = icmp ne i32 [[X]], [[Y]]
143+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[NE]] to i32
144+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[ZEXT]], i32 -1
145+
; CHECK-NEXT: ret i32 [[SEL]]
146+
;
147+
%ym1 = sub i32 %y, 1
148+
%cmp1 = icmp sgt i32 %x, %ym1
149+
%ne = icmp ne i32 %x, %y
150+
%zext = zext i1 %ne to i32
151+
%sel = select i1 %cmp1, i32 %zext, i32 -1
152+
ret i32 %sel
153+
}
154+
155+
; Fold (x > y - 1) ? zext(x > y) : -1 to ucmp(x, y)
156+
define i32 @ucmp_x_y_from_gt_sub_zext_gt(i32 %x, i32 %y) {
157+
; CHECK-LABEL: define i32 @ucmp_x_y_from_gt_sub_zext_gt(
158+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
159+
; CHECK-NEXT: [[YM1:%.*]] = add i32 [[Y]], -1
160+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[X]], [[YM1]]
161+
; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[X]], [[Y]]
162+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[GT]] to i32
163+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[ZEXT]], i32 -1
164+
; CHECK-NEXT: ret i32 [[SEL]]
165+
;
166+
%ym1 = sub i32 %y, 1
167+
%cmp1 = icmp ugt i32 %x, %ym1
168+
%gt = icmp ugt i32 %x, %y
169+
%zext = zext i1 %gt to i32
170+
%sel = select i1 %cmp1, i32 %zext, i32 -1
171+
ret i32 %sel
172+
}
173+
174+
; Fold (x < y + 1) ? sext(x != y) : 1 to scmp(x, y)
175+
define i32 @scmp_x_y_from_lt_add_sext_ne(i32 %x, i32 %y) {
176+
; CHECK-LABEL: define i32 @scmp_x_y_from_lt_add_sext_ne(
177+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
178+
; CHECK-NEXT: [[YP1:%.*]] = add i32 [[Y]], 1
179+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], [[YP1]]
180+
; CHECK-NEXT: [[NE:%.*]] = icmp ne i32 [[X]], [[Y]]
181+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[NE]] to i32
182+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[SEXT]], i32 1
183+
; CHECK-NEXT: ret i32 [[SEL]]
184+
;
185+
%yp1 = add i32 %y, 1
186+
%cmp1 = icmp slt i32 %x, %yp1
187+
%ne = icmp ne i32 %x, %y
188+
%sext = sext i1 %ne to i32
189+
%sel = select i1 %cmp1, i32 %sext, i32 1
190+
ret i32 %sel
191+
}
192+
193+
; Fold (x < y + 1) ? sext(x < y) : 1 to ucmp(x, y)
194+
define i32 @ucmp_x_y_from_lt_add_sext_lt(i32 %x, i32 %y) {
195+
; CHECK-LABEL: define i32 @ucmp_x_y_from_lt_add_sext_lt(
196+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
197+
; CHECK-NEXT: [[YP1:%.*]] = add i32 [[Y]], 1
198+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X]], [[YP1]]
199+
; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[X]], [[Y]]
200+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[LT]] to i32
201+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[SEXT]], i32 1
202+
; CHECK-NEXT: ret i32 [[SEL]]
203+
;
204+
%yp1 = add i32 %y, 1
205+
%cmp1 = icmp ult i32 %x, %yp1
206+
%lt = icmp ult i32 %x, %y
207+
%sext = sext i1 %lt to i32
208+
%sel = select i1 %cmp1, i32 %sext, i32 1
209+
ret i32 %sel
210+
}
211+
212+
; Testing with constants
213+
214+
define i32 @scmp_x_0_inverted(i32 %x) {
215+
; CHECK-LABEL: define i32 @scmp_x_0_inverted(
216+
; CHECK-SAME: i32 [[X:%.*]]) {
217+
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[X]], 0
218+
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP4]] to i32
219+
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[X]], -1
220+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 -1
221+
; CHECK-NEXT: ret i32 [[TMP1]]
222+
;
223+
%2 = icmp ne i32 %x, 0
224+
%3 = zext i1 %2 to i32
225+
%4 = icmp sgt i32 %x, -1
226+
%5 = select i1 %4, i32 %3, i32 -1
227+
ret i32 %5
228+
}
229+
230+
define i32 @scmp_x_neg_6_sgt_form(i32 %x) {
231+
; CHECK-LABEL: define i32 @scmp_x_neg_6_sgt_form(
232+
; CHECK-SAME: i32 [[X:%.*]]) {
233+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], -6
234+
; CHECK-NEXT: [[NE:%.*]] = icmp ne i32 [[X]], -5
235+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[NE]] to i32
236+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[ZEXT]], i32 -1
237+
; CHECK-NEXT: ret i32 [[SEL]]
238+
;
239+
%cmp1 = icmp sgt i32 %x, -6
240+
%ne = icmp ne i32 %x, -5
241+
%zext = zext i1 %ne to i32
242+
%sel = select i1 %cmp1, i32 %zext, i32 -1
243+
ret i32 %sel
244+
}
245+
246+
define i32 @ucmp_x_5_ult_form(i32 %x) {
247+
; CHECK-LABEL: define i32 @ucmp_x_5_ult_form(
248+
; CHECK-SAME: i32 [[X:%.*]]) {
249+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X]], 6
250+
; CHECK-NEXT: [[NE:%.*]] = icmp ne i32 [[X]], 5
251+
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[NE]] to i32
252+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32 [[SEXT]], i32 1
253+
; CHECK-NEXT: ret i32 [[SEL]]
254+
;
255+
%cmp1 = icmp ult i32 %x, 6
256+
%ne = icmp ne i32 %x, 5
257+
%sext = sext i1 %ne to i32
258+
%sel = select i1 %cmp1, i32 %sext, i32 1
259+
ret i32 %sel
260+
}
261+
262+
; Negative examples
263+
264+
; (x < y) ? -1 : zext(x == y)
265+
define i32 @scmp_negative_1(i32 %x, i32 %y) {
266+
; CHECK-LABEL: define i32 @scmp_negative_1(
267+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
268+
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
269+
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP1]] to i32
270+
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], [[Y]]
271+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i32 -1, i32 [[ZEXT]]
272+
; CHECK-NEXT: ret i32 [[SEL]]
273+
;
274+
%cmp1 = icmp eq i32 %x, %y
275+
%zext = zext i1 %cmp1 to i32
276+
%cmp2 = icmp slt i32 %x, %y
277+
%sel = select i1 %cmp2, i32 -1, i32 %zext
278+
ret i32 %sel
279+
}
280+
281+
define i32 @scmp_ne_0(i32 noundef %0) {
282+
; CHECK-LABEL: define i32 @scmp_ne_0(
283+
; CHECK-SAME: i32 noundef [[TMP0:%.*]]) {
284+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP0]], 0
285+
; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP5]] to i32
286+
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP0]], 1
287+
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1
288+
; CHECK-NEXT: ret i32 [[TMP2]]
289+
;
290+
%2 = icmp ne i32 %0, 0
291+
%3 = zext i1 %2 to i32
292+
%4 = icmp sgt i32 %0, 1
293+
%5 = select i1 %4, i32 %3, i32 -1
294+
ret i32 %5
295+
}

0 commit comments

Comments
 (0)