[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / 2004-11-27-SetCCForCastLargerAndConstant.ll
blob170114fb48d6d00bd0930554c34bd537844c9dda
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
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.
15 define 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]]
20   %Y = sext i8 %SB to i32
21   %C = icmp ult i32 %Y, 1024
22   ret i1 %C
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.
28 @a = common global i32** null
29 @b = common global [1 x i32] zeroinitializer
31 define 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]]
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
42 define <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]]
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
53 define i1 @lt_signed_to_large_signed(i8 %SB) {
54 ; CHECK-LABEL: @lt_signed_to_large_signed(
55 ; CHECK-NEXT:    ret i1 true
57   %Y = sext i8 %SB to i32
58   %C = icmp slt i32 %Y, 1024
59   ret i1 %C
62 define i1 @lt_signed_to_large_negative(i8 %SB) {
63 ; CHECK-LABEL: @lt_signed_to_large_negative(
64 ; CHECK-NEXT:    ret i1 false
66   %Y = sext i8 %SB to i32
67   %C = icmp slt i32 %Y, -1024
68   ret i1 %C
71 define 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]]
76   %Y = sext i8 %SB to i32
77   %C = icmp ult i32 %Y, 17
78   ret i1 %C
81 define 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]]
86   %Y = sext i8 %SB to i32
87   %C = icmp slt i32 %Y, 17
88   ret i1 %C
90 define 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]]
95   %Y = sext i8 %SB to i32
96   %C = icmp slt i32 %Y, -17
97   ret i1 %C
100 define i1 @lt_unsigned_to_large_unsigned(i8 %SB) {
101 ; CHECK-LABEL: @lt_unsigned_to_large_unsigned(
102 ; CHECK-NEXT:    ret i1 true
104   %Y = zext i8 %SB to i32
105   %C = icmp ult i32 %Y, 1024
106   ret i1 %C
109 define i1 @lt_unsigned_to_large_signed(i8 %SB) {
110 ; CHECK-LABEL: @lt_unsigned_to_large_signed(
111 ; CHECK-NEXT:    ret i1 true
113   %Y = zext i8 %SB to i32
114   %C = icmp slt i32 %Y, 1024
115   ret i1 %C
118 define i1 @lt_unsigned_to_large_negative(i8 %SB) {
119 ; CHECK-LABEL: @lt_unsigned_to_large_negative(
120 ; CHECK-NEXT:    ret i1 false
122   %Y = zext i8 %SB to i32
123   %C = icmp slt i32 %Y, -1024
124   ret i1 %C
127 define 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]]
132   %Y = zext i8 %SB to i32
133   %C = icmp ult i32 %Y, 17
134   ret i1 %C
137 define 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]]
142   %Y = zext i8 %SB to i32
143   %C = icmp slt i32 %Y, 17
144   ret i1 %C
147 define i1 @lt_unsigned_to_small_negative(i8 %SB) {
148 ; CHECK-LABEL: @lt_unsigned_to_small_negative(
149 ; CHECK-NEXT:    ret i1 false
151   %Y = zext i8 %SB to i32
152   %C = icmp slt i32 %Y, -17
153   ret i1 %C
156 define 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]]
161   %Y = sext i8 %SB to i32
162   %C = icmp ugt i32 %Y, 1024
163   ret i1 %C
166 define i1 @gt_signed_to_large_signed(i8 %SB) {
167 ; CHECK-LABEL: @gt_signed_to_large_signed(
168 ; CHECK-NEXT:    ret i1 false
170   %Y = sext i8 %SB to i32
171   %C = icmp sgt i32 %Y, 1024
172   ret i1 %C
175 define i1 @gt_signed_to_large_negative(i8 %SB) {
176 ; CHECK-LABEL: @gt_signed_to_large_negative(
177 ; CHECK-NEXT:    ret i1 true
179   %Y = sext i8 %SB to i32
180   %C = icmp sgt i32 %Y, -1024
181   ret i1 %C
184 define 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]]
189   %Y = sext i8 %SB to i32
190   %C = icmp ugt i32 %Y, 17
191   ret i1 %C
194 define 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]]
199   %Y = sext i8 %SB to i32
200   %C = icmp sgt i32 %Y, 17
201   ret i1 %C
204 define 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]]
209   %Y = sext i8 %SB to i32
210   %C = icmp sgt i32 %Y, -17
211   ret i1 %C
214 define i1 @gt_unsigned_to_large_unsigned(i8 %SB) {
215 ; CHECK-LABEL: @gt_unsigned_to_large_unsigned(
216 ; CHECK-NEXT:    ret i1 false
218   %Y = zext i8 %SB to i32
219   %C = icmp ugt i32 %Y, 1024
220   ret i1 %C
223 define i1 @gt_unsigned_to_large_signed(i8 %SB) {
224 ; CHECK-LABEL: @gt_unsigned_to_large_signed(
225 ; CHECK-NEXT:    ret i1 false
227   %Y = zext i8 %SB to i32
228   %C = icmp sgt i32 %Y, 1024
229   ret i1 %C
232 define i1 @gt_unsigned_to_large_negative(i8 %SB) {
233 ; CHECK-LABEL: @gt_unsigned_to_large_negative(
234 ; CHECK-NEXT:    ret i1 true
236   %Y = zext i8 %SB to i32
237   %C = icmp sgt i32 %Y, -1024
238   ret i1 %C
241 define 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]]
246   %Y = zext i8 %SB to i32
247   %C = icmp ugt i32 %Y, 17
248   ret i1 %C
251 define 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]]
256   %Y = zext i8 %SB to i32
257   %C = icmp sgt i32 %Y, 17
258   ret i1 %C
261 define i1 @gt_unsigned_to_small_negative(i8 %SB) {
262 ; CHECK-LABEL: @gt_unsigned_to_small_negative(
263 ; CHECK-NEXT:    ret i1 true
265   %Y = zext i8 %SB to i32
266   %C = icmp sgt i32 %Y, -17
267   ret i1 %C
270 define 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]]
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
282 define <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]]
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
294 define 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]]
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
306 define 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]]
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
318 define 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]]
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
330 define 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]]
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
342 define 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]]
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
354 define 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]]
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
366 define 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]]
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
378 define 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]]
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
390 define 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]]
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
402 ; TODO: This can be reduced.
404 define 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]]
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
417 declare void @use(i25)
419 define 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]]
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
434 define 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]]
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
449 ; Negative test - extra uses on both casts is too much.
451 define 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]]
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