1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; This tests the InstructionCombining optimization that reduces things like:
5;   %Y = sext i8 %X to i32
6;   %C = icmp ult i32 %Y, 1024
7; to
8;   %C = i1 true
9; It includes test cases for different constant values, signedness of the
10; cast operands, and types of setCC operators. In all cases, the cast should
11; be eliminated. In many cases the setCC is also eliminated based on the
12; constant value and the range of the casted value.
13;
14
15define i1 @lt_signed_to_large_unsigned(i8 %SB) {
16; CHECK-LABEL: @lt_signed_to_large_unsigned(
17; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[SB:%.*]], -1
18; CHECK-NEXT:    ret i1 [[C]]
19;
20  %Y = sext i8 %SB to i32
21  %C = icmp ult i32 %Y, 1024
22  ret i1 %C
23}
24
25; PR28011 - https://llvm.org/bugs/show_bug.cgi?id=28011
26; The above transform only applies to scalar integers; it shouldn't be attempted for constant expressions or vectors.
27
28@a = common global i32** null
29@b = common global [1 x i32] zeroinitializer
30
31define i1 @PR28011(i16 %a) {
32; CHECK-LABEL: @PR28011(
33; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
34; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[CONV]], or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1)
35; CHECK-NEXT:    ret i1 [[CMP]]
36;
37  %conv = sext i16 %a to i32
38  %cmp = icmp ne i32 %conv, or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1)
39  ret i1 %cmp
40}
41
42define <2 x i1> @lt_signed_to_large_unsigned_vec(<2 x i8> %SB) {
43; CHECK-LABEL: @lt_signed_to_large_unsigned_vec(
44; CHECK-NEXT:    [[Y:%.*]] = sext <2 x i8> [[SB:%.*]] to <2 x i32>
45; CHECK-NEXT:    [[C:%.*]] = icmp ult <2 x i32> [[Y]], <i32 1024, i32 2>
46; CHECK-NEXT:    ret <2 x i1> [[C]]
47;
48  %Y = sext <2 x i8> %SB to <2 x i32>
49  %C = icmp ult <2 x i32> %Y, <i32 1024, i32 2>
50  ret <2 x i1> %C
51}
52
53define i1 @lt_signed_to_large_signed(i8 %SB) {
54; CHECK-LABEL: @lt_signed_to_large_signed(
55; CHECK-NEXT:    ret i1 true
56;
57  %Y = sext i8 %SB to i32
58  %C = icmp slt i32 %Y, 1024
59  ret i1 %C
60}
61
62define i1 @lt_signed_to_large_negative(i8 %SB) {
63; CHECK-LABEL: @lt_signed_to_large_negative(
64; CHECK-NEXT:    ret i1 false
65;
66  %Y = sext i8 %SB to i32
67  %C = icmp slt i32 %Y, -1024
68  ret i1 %C
69}
70
71define i1 @lt_signed_to_small_unsigned(i8 %SB) {
72; CHECK-LABEL: @lt_signed_to_small_unsigned(
73; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
74; CHECK-NEXT:    ret i1 [[C]]
75;
76  %Y = sext i8 %SB to i32
77  %C = icmp ult i32 %Y, 17
78  ret i1 %C
79}
80
81define i1 @lt_signed_to_small_signed(i8 %SB) {
82; CHECK-LABEL: @lt_signed_to_small_signed(
83; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[SB:%.*]], 17
84; CHECK-NEXT:    ret i1 [[C]]
85;
86  %Y = sext i8 %SB to i32
87  %C = icmp slt i32 %Y, 17
88  ret i1 %C
89}
90define i1 @lt_signed_to_small_negative(i8 %SB) {
91; CHECK-LABEL: @lt_signed_to_small_negative(
92; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[SB:%.*]], -17
93; CHECK-NEXT:    ret i1 [[C]]
94;
95  %Y = sext i8 %SB to i32
96  %C = icmp slt i32 %Y, -17
97  ret i1 %C
98}
99
100define i1 @lt_unsigned_to_large_unsigned(i8 %SB) {
101; CHECK-LABEL: @lt_unsigned_to_large_unsigned(
102; CHECK-NEXT:    ret i1 true
103;
104  %Y = zext i8 %SB to i32
105  %C = icmp ult i32 %Y, 1024
106  ret i1 %C
107}
108
109define i1 @lt_unsigned_to_large_signed(i8 %SB) {
110; CHECK-LABEL: @lt_unsigned_to_large_signed(
111; CHECK-NEXT:    ret i1 true
112;
113  %Y = zext i8 %SB to i32
114  %C = icmp slt i32 %Y, 1024
115  ret i1 %C
116}
117
118define i1 @lt_unsigned_to_large_negative(i8 %SB) {
119; CHECK-LABEL: @lt_unsigned_to_large_negative(
120; CHECK-NEXT:    ret i1 false
121;
122  %Y = zext i8 %SB to i32
123  %C = icmp slt i32 %Y, -1024
124  ret i1 %C
125}
126
127define i1 @lt_unsigned_to_small_unsigned(i8 %SB) {
128; CHECK-LABEL: @lt_unsigned_to_small_unsigned(
129; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
130; CHECK-NEXT:    ret i1 [[C]]
131;
132  %Y = zext i8 %SB to i32
133  %C = icmp ult i32 %Y, 17
134  ret i1 %C
135}
136
137define i1 @lt_unsigned_to_small_signed(i8 %SB) {
138; CHECK-LABEL: @lt_unsigned_to_small_signed(
139; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
140; CHECK-NEXT:    ret i1 [[C]]
141;
142  %Y = zext i8 %SB to i32
143  %C = icmp slt i32 %Y, 17
144  ret i1 %C
145}
146
147define i1 @lt_unsigned_to_small_negative(i8 %SB) {
148; CHECK-LABEL: @lt_unsigned_to_small_negative(
149; CHECK-NEXT:    ret i1 false
150;
151  %Y = zext i8 %SB to i32
152  %C = icmp slt i32 %Y, -17
153  ret i1 %C
154}
155
156define i1 @gt_signed_to_large_unsigned(i8 %SB) {
157; CHECK-LABEL: @gt_signed_to_large_unsigned(
158; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[SB:%.*]], 0
159; CHECK-NEXT:    ret i1 [[C]]
160;
161  %Y = sext i8 %SB to i32
162  %C = icmp ugt i32 %Y, 1024
163  ret i1 %C
164}
165
166define i1 @gt_signed_to_large_signed(i8 %SB) {
167; CHECK-LABEL: @gt_signed_to_large_signed(
168; CHECK-NEXT:    ret i1 false
169;
170  %Y = sext i8 %SB to i32
171  %C = icmp sgt i32 %Y, 1024
172  ret i1 %C
173}
174
175define i1 @gt_signed_to_large_negative(i8 %SB) {
176; CHECK-LABEL: @gt_signed_to_large_negative(
177; CHECK-NEXT:    ret i1 true
178;
179  %Y = sext i8 %SB to i32
180  %C = icmp sgt i32 %Y, -1024
181  ret i1 %C
182}
183
184define i1 @gt_signed_to_small_unsigned(i8 %SB) {
185; CHECK-LABEL: @gt_signed_to_small_unsigned(
186; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
187; CHECK-NEXT:    ret i1 [[C]]
188;
189  %Y = sext i8 %SB to i32
190  %C = icmp ugt i32 %Y, 17
191  ret i1 %C
192}
193
194define i1 @gt_signed_to_small_signed(i8 %SB) {
195; CHECK-LABEL: @gt_signed_to_small_signed(
196; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[SB:%.*]], 17
197; CHECK-NEXT:    ret i1 [[C]]
198;
199  %Y = sext i8 %SB to i32
200  %C = icmp sgt i32 %Y, 17
201  ret i1 %C
202}
203
204define i1 @gt_signed_to_small_negative(i8 %SB) {
205; CHECK-LABEL: @gt_signed_to_small_negative(
206; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[SB:%.*]], -17
207; CHECK-NEXT:    ret i1 [[C]]
208;
209  %Y = sext i8 %SB to i32
210  %C = icmp sgt i32 %Y, -17
211  ret i1 %C
212}
213
214define i1 @gt_unsigned_to_large_unsigned(i8 %SB) {
215; CHECK-LABEL: @gt_unsigned_to_large_unsigned(
216; CHECK-NEXT:    ret i1 false
217;
218  %Y = zext i8 %SB to i32
219  %C = icmp ugt i32 %Y, 1024
220  ret i1 %C
221}
222
223define i1 @gt_unsigned_to_large_signed(i8 %SB) {
224; CHECK-LABEL: @gt_unsigned_to_large_signed(
225; CHECK-NEXT:    ret i1 false
226;
227  %Y = zext i8 %SB to i32
228  %C = icmp sgt i32 %Y, 1024
229  ret i1 %C
230}
231
232define i1 @gt_unsigned_to_large_negative(i8 %SB) {
233; CHECK-LABEL: @gt_unsigned_to_large_negative(
234; CHECK-NEXT:    ret i1 true
235;
236  %Y = zext i8 %SB to i32
237  %C = icmp sgt i32 %Y, -1024
238  ret i1 %C
239}
240
241define i1 @gt_unsigned_to_small_unsigned(i8 %SB) {
242; CHECK-LABEL: @gt_unsigned_to_small_unsigned(
243; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
244; CHECK-NEXT:    ret i1 [[C]]
245;
246  %Y = zext i8 %SB to i32
247  %C = icmp ugt i32 %Y, 17
248  ret i1 %C
249}
250
251define i1 @gt_unsigned_to_small_signed(i8 %SB) {
252; CHECK-LABEL: @gt_unsigned_to_small_signed(
253; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
254; CHECK-NEXT:    ret i1 [[C]]
255;
256  %Y = zext i8 %SB to i32
257  %C = icmp sgt i32 %Y, 17
258  ret i1 %C
259}
260
261define i1 @gt_unsigned_to_small_negative(i8 %SB) {
262; CHECK-LABEL: @gt_unsigned_to_small_negative(
263; CHECK-NEXT:    ret i1 true
264;
265  %Y = zext i8 %SB to i32
266  %C = icmp sgt i32 %Y, -17
267  ret i1 %C
268}
269
270define i1 @different_size_zext_zext_ugt(i7 %x, i4 %y) {
271; CHECK-LABEL: @different_size_zext_zext_ugt(
272; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
273; CHECK-NEXT:    [[R:%.*]] = icmp ult i7 [[TMP1]], [[X:%.*]]
274; CHECK-NEXT:    ret i1 [[R]]
275;
276  %zx = zext i7 %x to i25
277  %zy = zext i4 %y to i25
278  %r = icmp ugt i25 %zx, %zy
279  ret i1 %r
280}
281
282define <2 x i1> @different_size_zext_zext_ugt_commute(<2 x i4> %x, <2 x i7> %y) {
283; CHECK-LABEL: @different_size_zext_zext_ugt_commute(
284; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i4> [[X:%.*]] to <2 x i7>
285; CHECK-NEXT:    [[R:%.*]] = icmp ugt <2 x i7> [[TMP1]], [[Y:%.*]]
286; CHECK-NEXT:    ret <2 x i1> [[R]]
287;
288  %zx = zext <2 x i4> %x to <2 x i25>
289  %zy = zext <2 x i7> %y to <2 x i25>
290  %r = icmp ugt <2 x i25> %zx, %zy
291  ret <2 x i1> %r
292}
293
294define i1 @different_size_zext_zext_ult(i4 %x, i7 %y) {
295; CHECK-LABEL: @different_size_zext_zext_ult(
296; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7
297; CHECK-NEXT:    [[R:%.*]] = icmp ult i7 [[TMP1]], [[Y:%.*]]
298; CHECK-NEXT:    ret i1 [[R]]
299;
300  %zx = zext i4 %x to i25
301  %zy = zext i7 %y to i25
302  %r = icmp ult i25 %zx, %zy
303  ret i1 %r
304}
305
306define i1 @different_size_zext_zext_eq(i4 %x, i7 %y) {
307; CHECK-LABEL: @different_size_zext_zext_eq(
308; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7
309; CHECK-NEXT:    [[R:%.*]] = icmp eq i7 [[TMP1]], [[Y:%.*]]
310; CHECK-NEXT:    ret i1 [[R]]
311;
312  %zx = zext i4 %x to i25
313  %zy = zext i7 %y to i25
314  %r = icmp eq i25 %zx, %zy
315  ret i1 %r
316}
317
318define i1 @different_size_zext_zext_ne_commute(i7 %x, i4 %y) {
319; CHECK-LABEL: @different_size_zext_zext_ne_commute(
320; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
321; CHECK-NEXT:    [[R:%.*]] = icmp ne i7 [[TMP1]], [[X:%.*]]
322; CHECK-NEXT:    ret i1 [[R]]
323;
324  %zx = zext i7 %x to i25
325  %zy = zext i4 %y to i25
326  %r = icmp ne i25 %zx, %zy
327  ret i1 %r
328}
329
330define i1 @different_size_zext_zext_slt(i7 %x, i4 %y) {
331; CHECK-LABEL: @different_size_zext_zext_slt(
332; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
333; CHECK-NEXT:    [[R:%.*]] = icmp ugt i7 [[TMP1]], [[X:%.*]]
334; CHECK-NEXT:    ret i1 [[R]]
335;
336  %zx = zext i7 %x to i25
337  %zy = zext i4 %y to i25
338  %r = icmp slt i25 %zx, %zy
339  ret i1 %r
340}
341
342define i1 @different_size_zext_zext_sgt(i7 %x, i4 %y) {
343; CHECK-LABEL: @different_size_zext_zext_sgt(
344; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
345; CHECK-NEXT:    [[R:%.*]] = icmp ult i7 [[TMP1]], [[X:%.*]]
346; CHECK-NEXT:    ret i1 [[R]]
347;
348  %zx = zext i7 %x to i25
349  %zy = zext i4 %y to i25
350  %r = icmp sgt i25 %zx, %zy
351  ret i1 %r
352}
353
354define i1 @different_size_sext_sext_sgt(i7 %x, i4 %y) {
355; CHECK-LABEL: @different_size_sext_sext_sgt(
356; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
357; CHECK-NEXT:    [[R:%.*]] = icmp slt i7 [[TMP1]], [[X:%.*]]
358; CHECK-NEXT:    ret i1 [[R]]
359;
360  %sx = sext i7 %x to i25
361  %sy = sext i4 %y to i25
362  %r = icmp sgt i25 %sx, %sy
363  ret i1 %r
364}
365
366define i1 @different_size_sext_sext_sle(i7 %x, i4 %y) {
367; CHECK-LABEL: @different_size_sext_sext_sle(
368; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
369; CHECK-NEXT:    [[R:%.*]] = icmp sge i7 [[TMP1]], [[X:%.*]]
370; CHECK-NEXT:    ret i1 [[R]]
371;
372  %sx = sext i7 %x to i25
373  %sy = sext i4 %y to i25
374  %r = icmp sle i25 %sx, %sy
375  ret i1 %r
376}
377
378define i1 @different_size_sext_sext_eq(i7 %x, i4 %y) {
379; CHECK-LABEL: @different_size_sext_sext_eq(
380; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
381; CHECK-NEXT:    [[R:%.*]] = icmp eq i7 [[TMP1]], [[X:%.*]]
382; CHECK-NEXT:    ret i1 [[R]]
383;
384  %sx = sext i7 %x to i25
385  %sy = sext i4 %y to i25
386  %r = icmp eq i25 %sx, %sy
387  ret i1 %r
388}
389
390define i1 @different_size_sext_sext_ule(i7 %x, i4 %y) {
391; CHECK-LABEL: @different_size_sext_sext_ule(
392; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
393; CHECK-NEXT:    [[R:%.*]] = icmp uge i7 [[TMP1]], [[X:%.*]]
394; CHECK-NEXT:    ret i1 [[R]]
395;
396  %sx = sext i7 %x to i25
397  %sy = sext i4 %y to i25
398  %r = icmp ule i25 %sx, %sy
399  ret i1 %r
400}
401
402; TODO: This can be reduced.
403
404define i1 @different_size_sext_zext_ne(i7 %x, i4 %y) {
405; CHECK-LABEL: @different_size_sext_zext_ne(
406; CHECK-NEXT:    [[SX:%.*]] = sext i7 [[X:%.*]] to i25
407; CHECK-NEXT:    [[ZY:%.*]] = zext i4 [[Y:%.*]] to i25
408; CHECK-NEXT:    [[R:%.*]] = icmp ne i25 [[SX]], [[ZY]]
409; CHECK-NEXT:    ret i1 [[R]]
410;
411  %sx = sext i7 %x to i25
412  %zy = zext i4 %y to i25
413  %r = icmp ne i25 %sx, %zy
414  ret i1 %r
415}
416
417declare void @use(i25)
418
419define i1 @different_size_sext_sext_ule_extra_use1(i7 %x, i4 %y) {
420; CHECK-LABEL: @different_size_sext_sext_ule_extra_use1(
421; CHECK-NEXT:    [[SY:%.*]] = sext i4 [[Y:%.*]] to i25
422; CHECK-NEXT:    call void @use(i25 [[SY]])
423; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y]] to i7
424; CHECK-NEXT:    [[R:%.*]] = icmp uge i7 [[TMP1]], [[X:%.*]]
425; CHECK-NEXT:    ret i1 [[R]]
426;
427  %sx = sext i7 %x to i25
428  %sy = sext i4 %y to i25
429  call void @use(i25 %sy)
430  %r = icmp ule i25 %sx, %sy
431  ret i1 %r
432}
433
434define i1 @different_size_sext_sext_ule_extra_use2(i7 %x, i4 %y) {
435; CHECK-LABEL: @different_size_sext_sext_ule_extra_use2(
436; CHECK-NEXT:    [[SX:%.*]] = sext i7 [[X:%.*]] to i25
437; CHECK-NEXT:    call void @use(i25 [[SX]])
438; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
439; CHECK-NEXT:    [[R:%.*]] = icmp uge i7 [[TMP1]], [[X]]
440; CHECK-NEXT:    ret i1 [[R]]
441;
442  %sx = sext i7 %x to i25
443  call void @use(i25 %sx)
444  %sy = sext i4 %y to i25
445  %r = icmp ule i25 %sx, %sy
446  ret i1 %r
447}
448
449; Negative test - extra uses on both casts is too much.
450
451define i1 @different_size_sext_sext_ule_extra_use3(i7 %x, i4 %y) {
452; CHECK-LABEL: @different_size_sext_sext_ule_extra_use3(
453; CHECK-NEXT:    [[SX:%.*]] = sext i7 [[X:%.*]] to i25
454; CHECK-NEXT:    call void @use(i25 [[SX]])
455; CHECK-NEXT:    [[SY:%.*]] = sext i4 [[Y:%.*]] to i25
456; CHECK-NEXT:    call void @use(i25 [[SY]])
457; CHECK-NEXT:    [[R:%.*]] = icmp ule i25 [[SX]], [[SY]]
458; CHECK-NEXT:    ret i1 [[R]]
459;
460  %sx = sext i7 %x to i25
461  call void @use(i25 %sx)
462  %sy = sext i4 %y to i25
463  call void @use(i25 %sy)
464  %r = icmp ule i25 %sx, %sy
465  ret i1 %r
466}
467