• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; If we have a relational comparison with a constant, and said comparison is
5; used in a select, and there is a constant in select, see if we can make
6; those constants match.
7
8; We can't ever get non-canonical scalar predicates.
9
10; Likewise, while we can get non-canonical vector predicates, there must be an
11; extra use on that `icmp`, which precludes the fold from happening.
12
13;------------------------------------------------------------------------------;
14; Canonical scalar predicates
15;------------------------------------------------------------------------------;
16
17!0 = !{!"branch_weights", i32 2000, i32 1}
18
19define i32 @p0_ult_65536(i32 %x, i32 %y) {
20; CHECK-LABEL: @p0_ult_65536(
21; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
22; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof !0
23; CHECK-NEXT:    ret i32 [[R]]
24;
25  %t = icmp ult i32 %x, 65536
26  %r = select i1 %t, i32 %y, i32 65535, !prof !0
27  ret i32 %r
28}
29define i32 @p1_ugt(i32 %x, i32 %y) {
30; CHECK-LABEL: @p1_ugt(
31; CHECK-NEXT:    [[T_INV:%.*]] = icmp ult i32 [[X:%.*]], 65535
32; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
33; CHECK-NEXT:    ret i32 [[R]]
34;
35  %t = icmp ugt i32 %x, 65534
36  %r = select i1 %t, i32 %y, i32 65535
37  ret i32 %r
38}
39define i32 @p2_slt_65536(i32 %x, i32 %y) {
40; CHECK-LABEL: @p2_slt_65536(
41; CHECK-NEXT:    [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], 65535
42; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
43; CHECK-NEXT:    ret i32 [[R]]
44;
45  %t = icmp slt i32 %x, 65536
46  %r = select i1 %t, i32 %y, i32 65535
47  ret i32 %r
48}
49define i32 @p3_sgt(i32 %x, i32 %y) {
50; CHECK-LABEL: @p3_sgt(
51; CHECK-NEXT:    [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 65535
52; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
53; CHECK-NEXT:    ret i32 [[R]]
54;
55  %t = icmp sgt i32 %x, 65534
56  %r = select i1 %t, i32 %y, i32 65535
57  ret i32 %r
58}
59
60;------------------------------------------------------------------------------;
61; Vectors
62;------------------------------------------------------------------------------;
63
64define <2 x i32> @p4_vec_splat_ult_65536(<2 x i32> %x, <2 x i32> %y) {
65; CHECK-LABEL: @p4_vec_splat_ult_65536(
66; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
67; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
68; CHECK-NEXT:    ret <2 x i32> [[R]]
69;
70  %t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>
71  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
72  ret <2 x i32> %r
73}
74define <2 x i32> @p5_vec_splat_ugt(<2 x i32> %x, <2 x i32> %y) {
75; CHECK-LABEL: @p5_vec_splat_ugt(
76; CHECK-NEXT:    [[T_INV:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
77; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
78; CHECK-NEXT:    ret <2 x i32> [[R]]
79;
80  %t = icmp ugt <2 x i32> %x, <i32 65534, i32 65534>
81  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
82  ret <2 x i32> %r
83}
84define <2 x i32> @p6_vec_splat_slt_65536(<2 x i32> %x, <2 x i32> %y) {
85; CHECK-LABEL: @p6_vec_splat_slt_65536(
86; CHECK-NEXT:    [[T_INV:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
87; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
88; CHECK-NEXT:    ret <2 x i32> [[R]]
89;
90  %t = icmp slt <2 x i32> %x, <i32 65536, i32 65536>
91  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
92  ret <2 x i32> %r
93}
94define <2 x i32> @p7_vec_splat_sgt(<2 x i32> %x, <2 x i32> %y) {
95; CHECK-LABEL: @p7_vec_splat_sgt(
96; CHECK-NEXT:    [[T_INV:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
97; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
98; CHECK-NEXT:    ret <2 x i32> [[R]]
99;
100  %t = icmp sgt <2 x i32> %x, <i32 65534, i32 65534>
101  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
102  ret <2 x i32> %r
103}
104
105; Vectors with undef
106
107define <2 x i32> @p8_vec_nonsplat_undef0(<2 x i32> %x, <2 x i32> %y) {
108; CHECK-LABEL: @p8_vec_nonsplat_undef0(
109; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
110; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
111; CHECK-NEXT:    ret <2 x i32> [[R]]
112;
113  %t = icmp ult <2 x i32> %x, <i32 65536, i32 undef>
114  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
115  ret <2 x i32> %r
116}
117define <2 x i32> @p9_vec_nonsplat_undef1(<2 x i32> %x, <2 x i32> %y) {
118; CHECK-LABEL: @p9_vec_nonsplat_undef1(
119; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
120; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 undef>, <2 x i32> [[Y:%.*]]
121; CHECK-NEXT:    ret <2 x i32> [[R]]
122;
123  %t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>
124  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 undef>
125  ret <2 x i32> %r
126}
127define <2 x i32> @p10_vec_nonsplat_undef2(<2 x i32> %x, <2 x i32> %y) {
128; CHECK-LABEL: @p10_vec_nonsplat_undef2(
129; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
130; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 undef>, <2 x i32> [[Y:%.*]]
131; CHECK-NEXT:    ret <2 x i32> [[R]]
132;
133  %t = icmp ult <2 x i32> %x, <i32 65536, i32 undef>
134  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 undef>
135  ret <2 x i32> %r
136}
137
138; Non-splat vectors
139
140define <2 x i32> @p11_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
141; CHECK-LABEL: @p11_vec_nonsplat(
142; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 32767>
143; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 32767>, <2 x i32> [[Y:%.*]]
144; CHECK-NEXT:    ret <2 x i32> [[R]]
145;
146  %t = icmp ult <2 x i32> %x, <i32 65536, i32 32768>
147  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 32767>
148  ret <2 x i32> %r
149}
150
151;------------------------------------------------------------------------------;
152; Extra uses prevent the fold.
153;------------------------------------------------------------------------------;
154
155declare void @use1(i1)
156
157define i32 @n12_extrause(i32 %x, i32 %y) {
158; CHECK-LABEL: @n12_extrause(
159; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
160; CHECK-NEXT:    call void @use1(i1 [[T]])
161; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
162; CHECK-NEXT:    ret i32 [[R]]
163;
164  %t = icmp ult i32 %x, 65536
165  call void @use1(i1 %t)
166  %r = select i1 %t, i32 %y, i32 65535
167  ret i32 %r
168}
169
170;------------------------------------------------------------------------------;
171; Commutativity
172;------------------------------------------------------------------------------;
173
174; We don't care if the constant in select is true value or false value
175define i32 @p13_commutativity0(i32 %x, i32 %y) {
176; CHECK-LABEL: @p13_commutativity0(
177; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
178; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 65535
179; CHECK-NEXT:    ret i32 [[R]]
180;
181  %t = icmp ult i32 %x, 65536
182  %r = select i1 %t, i32 65535, i32 %y
183  ret i32 %r
184}
185
186; Which means, if both possibilities are constants, we must check both of them.
187define i32 @p14_commutativity1(i32 %x, i32 %y) {
188; CHECK-LABEL: @p14_commutativity1(
189; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
190; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 42, i32 65535
191; CHECK-NEXT:    ret i32 [[R]]
192;
193  %t = icmp ult i32 %x, 65536
194  %r = select i1 %t, i32 65535, i32 42
195  ret i32 %r
196}
197define i32 @p15_commutativity2(i32 %x, i32 %y) {
198; CHECK-LABEL: @p15_commutativity2(
199; CHECK-NEXT:    [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
200; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 42
201; CHECK-NEXT:    ret i32 [[R]]
202;
203  %t = icmp ult i32 %x, 65536
204  %r = select i1 %t, i32 42, i32 65535
205  ret i32 %r
206}
207
208;------------------------------------------------------------------------------;
209; Negative tests
210;------------------------------------------------------------------------------;
211
212; For vectors, make sure we handle edge cases correctly
213define <2 x i32> @n17_ult_zero(<2 x i32> %x, <2 x i32> %y) {
214; CHECK-LABEL: @n17_ult_zero(
215; CHECK-NEXT:    [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 65536, i32 0>
216; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -1>
217; CHECK-NEXT:    ret <2 x i32> [[R]]
218;
219  %t = icmp ult <2 x i32> %x, <i32 65536, i32 0>
220  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -1>
221  ret <2 x i32> %r
222}
223define <2 x i32> @n18_ugt_allones(<2 x i32> %x, <2 x i32> %y) {
224; CHECK-LABEL: @n18_ugt_allones(
225; CHECK-NEXT:    [[T:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65534, i32 -1>
226; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 0>
227; CHECK-NEXT:    ret <2 x i32> [[R]]
228;
229  %t = icmp ugt <2 x i32> %x, <i32 65534, i32 -1>
230  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 0>
231  ret <2 x i32> %r
232}
233define <2 x i32> @n19_slt_int_min(<2 x i32> %x, <2 x i32> %y) {
234; CHECK-LABEL: @n19_slt_int_min(
235; CHECK-NEXT:    [[T:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 65536, i32 -2147483648>
236; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 2147483647>
237; CHECK-NEXT:    ret <2 x i32> [[R]]
238;
239  %t = icmp slt <2 x i32> %x, <i32 65536, i32 -2147483648>
240  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 2147483647>
241  ret <2 x i32> %r
242}
243define <2 x i32> @n20_sgt_int_max(<2 x i32> %x, <2 x i32> %y) {
244; CHECK-LABEL: @n20_sgt_int_max(
245; CHECK-NEXT:    [[T:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 65534, i32 2147483647>
246; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -2147483648>
247; CHECK-NEXT:    ret <2 x i32> [[R]]
248;
249  %t = icmp sgt <2 x i32> %x, <i32 65534, i32 2147483647>
250  %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -2147483648>
251  ret <2 x i32> %r
252}
253
254; We don't do anything for non-relational comparisons.
255define i32 @n21_equality(i32 %x, i32 %y) {
256; CHECK-LABEL: @n21_equality(
257; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
258; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 2147483647, i32 [[Y:%.*]]
259; CHECK-NEXT:    ret i32 [[R]]
260;
261  %t = icmp eq i32 %x, -2147483648
262  %r = select i1 %t, i32 2147483647, i32 %y
263  ret i32 %r
264}
265
266; There is nothing special about sign-bit-tests, we can fold them.
267define i32 @t22_sign_check(i32 %x, i32 %y) {
268; CHECK-LABEL: @t22_sign_check(
269; CHECK-NEXT:    [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], -1
270; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 -1
271; CHECK-NEXT:    ret i32 [[R]]
272;
273  %t = icmp slt i32 %x, 0
274  %r = select i1 %t, i32 -1, i32 %y
275  ret i32 %r
276}
277define i32 @t22_sign_check2(i32 %x, i32 %y) {
278; CHECK-LABEL: @t22_sign_check2(
279; CHECK-NEXT:    [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 0
280; CHECK-NEXT:    [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 0
281; CHECK-NEXT:    ret i32 [[R]]
282;
283  %t = icmp sgt i32 %x, -1
284  %r = select i1 %t, i32 0, i32 %y
285  ret i32 %r
286}
287
288; If the types don't match we currently don't do anything.
289define i32 @n23_type_mismatch(i64 %x, i32 %y) {
290; CHECK-LABEL: @n23_type_mismatch(
291; CHECK-NEXT:    [[T:%.*]] = icmp ult i64 [[X:%.*]], 65536
292; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
293; CHECK-NEXT:    ret i32 [[R]]
294;
295  %t = icmp ult i64 %x, 65536
296  %r = select i1 %t, i32 %y, i32 65535
297  ret i32 %r
298}
299
300; Don't do wrong tranform
301define i32 @n24_ult_65534(i32 %x, i32 %y) {
302; CHECK-LABEL: @n24_ult_65534(
303; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[X:%.*]], 65534
304; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
305; CHECK-NEXT:    ret i32 [[R]]
306;
307  %t = icmp ult i32 %x, 65534
308  %r = select i1 %t, i32 %y, i32 65535
309  ret i32 %r
310}
311
312; If we already have a match, it's good enough.
313define i32 @n25_all_good0(i32 %x, i32 %y) {
314; CHECK-LABEL: @n25_all_good0(
315; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
316; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 65535, i32 65536
317; CHECK-NEXT:    ret i32 [[R]]
318;
319  %t = icmp ult i32 %x, 65536
320  %r = select i1 %t, i32 65535, i32 65536
321  ret i32 %r
322}
323define i32 @n26_all_good1(i32 %x, i32 %y) {
324; CHECK-LABEL: @n26_all_good1(
325; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
326; CHECK-NEXT:    [[R:%.*]] = select i1 [[T]], i32 65536, i32 65535
327; CHECK-NEXT:    ret i32 [[R]]
328;
329  %t = icmp ult i32 %x, 65536
330  %r = select i1 %t, i32 65536, i32 65535
331  ret i32 %r
332}
333
334
335
336; CHECK: !0 = !{!"branch_weights", i32 1, i32 2000}
337