1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=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
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
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 ptr null
29 @b = common global [1 x i32] zeroinitializer
31 define i1 @PR28011(i16 %a) {
32 ; CHECK-LABEL: @PR28011(
33 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[A:%.*]], 1
34 ; CHECK-NEXT: ret i1 [[CMP]]
36 %conv = sext i16 %a to i32
37 %cmp2 = icmp ne ptr @b, @a
38 %ext = zext i1 %cmp2 to i32
40 %cmp = icmp ne i32 %conv, %or
44 define <2 x i1> @lt_signed_to_large_unsigned_vec(<2 x i8> %SB) {
45 ; CHECK-LABEL: @lt_signed_to_large_unsigned_vec(
46 ; CHECK-NEXT: [[Y:%.*]] = sext <2 x i8> [[SB:%.*]] to <2 x i32>
47 ; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i32> [[Y]], <i32 1024, i32 2>
48 ; CHECK-NEXT: ret <2 x i1> [[C]]
50 %Y = sext <2 x i8> %SB to <2 x i32>
51 %C = icmp ult <2 x i32> %Y, <i32 1024, i32 2>
55 define i1 @lt_signed_to_large_signed(i8 %SB) {
56 ; CHECK-LABEL: @lt_signed_to_large_signed(
57 ; CHECK-NEXT: ret i1 true
59 %Y = sext i8 %SB to i32
60 %C = icmp slt i32 %Y, 1024
64 define i1 @lt_signed_to_large_negative(i8 %SB) {
65 ; CHECK-LABEL: @lt_signed_to_large_negative(
66 ; CHECK-NEXT: ret i1 false
68 %Y = sext i8 %SB to i32
69 %C = icmp slt i32 %Y, -1024
73 define i1 @lt_signed_to_small_unsigned(i8 %SB) {
74 ; CHECK-LABEL: @lt_signed_to_small_unsigned(
75 ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
76 ; CHECK-NEXT: ret i1 [[C]]
78 %Y = sext i8 %SB to i32
79 %C = icmp ult i32 %Y, 17
83 define i1 @lt_signed_to_small_signed(i8 %SB) {
84 ; CHECK-LABEL: @lt_signed_to_small_signed(
85 ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], 17
86 ; CHECK-NEXT: ret i1 [[C]]
88 %Y = sext i8 %SB to i32
89 %C = icmp slt i32 %Y, 17
92 define i1 @lt_signed_to_small_negative(i8 %SB) {
93 ; CHECK-LABEL: @lt_signed_to_small_negative(
94 ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], -17
95 ; CHECK-NEXT: ret i1 [[C]]
97 %Y = sext i8 %SB to i32
98 %C = icmp slt i32 %Y, -17
102 define i1 @lt_unsigned_to_large_unsigned(i8 %SB) {
103 ; CHECK-LABEL: @lt_unsigned_to_large_unsigned(
104 ; CHECK-NEXT: ret i1 true
106 %Y = zext i8 %SB to i32
107 %C = icmp ult i32 %Y, 1024
111 define i1 @lt_unsigned_to_large_signed(i8 %SB) {
112 ; CHECK-LABEL: @lt_unsigned_to_large_signed(
113 ; CHECK-NEXT: ret i1 true
115 %Y = zext i8 %SB to i32
116 %C = icmp slt i32 %Y, 1024
120 define i1 @lt_unsigned_to_large_negative(i8 %SB) {
121 ; CHECK-LABEL: @lt_unsigned_to_large_negative(
122 ; CHECK-NEXT: ret i1 false
124 %Y = zext i8 %SB to i32
125 %C = icmp slt i32 %Y, -1024
129 define i1 @lt_unsigned_to_small_unsigned(i8 %SB) {
130 ; CHECK-LABEL: @lt_unsigned_to_small_unsigned(
131 ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
132 ; CHECK-NEXT: ret i1 [[C]]
134 %Y = zext i8 %SB to i32
135 %C = icmp ult i32 %Y, 17
139 define i1 @lt_unsigned_to_small_signed(i8 %SB) {
140 ; CHECK-LABEL: @lt_unsigned_to_small_signed(
141 ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17
142 ; CHECK-NEXT: ret i1 [[C]]
144 %Y = zext i8 %SB to i32
145 %C = icmp slt i32 %Y, 17
149 define i1 @lt_unsigned_to_small_negative(i8 %SB) {
150 ; CHECK-LABEL: @lt_unsigned_to_small_negative(
151 ; CHECK-NEXT: ret i1 false
153 %Y = zext i8 %SB to i32
154 %C = icmp slt i32 %Y, -17
158 define i1 @gt_signed_to_large_unsigned(i8 %SB) {
159 ; CHECK-LABEL: @gt_signed_to_large_unsigned(
160 ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], 0
161 ; CHECK-NEXT: ret i1 [[C]]
163 %Y = sext i8 %SB to i32
164 %C = icmp ugt i32 %Y, 1024
168 define i1 @gt_signed_to_large_signed(i8 %SB) {
169 ; CHECK-LABEL: @gt_signed_to_large_signed(
170 ; CHECK-NEXT: ret i1 false
172 %Y = sext i8 %SB to i32
173 %C = icmp sgt i32 %Y, 1024
177 define i1 @gt_signed_to_large_negative(i8 %SB) {
178 ; CHECK-LABEL: @gt_signed_to_large_negative(
179 ; CHECK-NEXT: ret i1 true
181 %Y = sext i8 %SB to i32
182 %C = icmp sgt i32 %Y, -1024
186 define i1 @gt_signed_to_small_unsigned(i8 %SB) {
187 ; CHECK-LABEL: @gt_signed_to_small_unsigned(
188 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
189 ; CHECK-NEXT: ret i1 [[C]]
191 %Y = sext i8 %SB to i32
192 %C = icmp ugt i32 %Y, 17
196 define i1 @gt_signed_to_small_signed(i8 %SB) {
197 ; CHECK-LABEL: @gt_signed_to_small_signed(
198 ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[SB:%.*]], 17
199 ; CHECK-NEXT: ret i1 [[C]]
201 %Y = sext i8 %SB to i32
202 %C = icmp sgt i32 %Y, 17
206 define i1 @gt_signed_to_small_negative(i8 %SB) {
207 ; CHECK-LABEL: @gt_signed_to_small_negative(
208 ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[SB:%.*]], -17
209 ; CHECK-NEXT: ret i1 [[C]]
211 %Y = sext i8 %SB to i32
212 %C = icmp sgt i32 %Y, -17
216 define i1 @gt_unsigned_to_large_unsigned(i8 %SB) {
217 ; CHECK-LABEL: @gt_unsigned_to_large_unsigned(
218 ; CHECK-NEXT: ret i1 false
220 %Y = zext i8 %SB to i32
221 %C = icmp ugt i32 %Y, 1024
225 define i1 @gt_unsigned_to_large_signed(i8 %SB) {
226 ; CHECK-LABEL: @gt_unsigned_to_large_signed(
227 ; CHECK-NEXT: ret i1 false
229 %Y = zext i8 %SB to i32
230 %C = icmp sgt i32 %Y, 1024
234 define i1 @gt_unsigned_to_large_negative(i8 %SB) {
235 ; CHECK-LABEL: @gt_unsigned_to_large_negative(
236 ; CHECK-NEXT: ret i1 true
238 %Y = zext i8 %SB to i32
239 %C = icmp sgt i32 %Y, -1024
243 define i1 @gt_unsigned_to_small_unsigned(i8 %SB) {
244 ; CHECK-LABEL: @gt_unsigned_to_small_unsigned(
245 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
246 ; CHECK-NEXT: ret i1 [[C]]
248 %Y = zext i8 %SB to i32
249 %C = icmp ugt i32 %Y, 17
253 define i1 @gt_unsigned_to_small_signed(i8 %SB) {
254 ; CHECK-LABEL: @gt_unsigned_to_small_signed(
255 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17
256 ; CHECK-NEXT: ret i1 [[C]]
258 %Y = zext i8 %SB to i32
259 %C = icmp sgt i32 %Y, 17
263 define i1 @gt_unsigned_to_small_negative(i8 %SB) {
264 ; CHECK-LABEL: @gt_unsigned_to_small_negative(
265 ; CHECK-NEXT: ret i1 true
267 %Y = zext i8 %SB to i32
268 %C = icmp sgt i32 %Y, -17
272 define i1 @different_size_zext_zext_ugt(i7 %x, i4 %y) {
273 ; CHECK-LABEL: @different_size_zext_zext_ugt(
274 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
275 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i7 [[X:%.*]], [[TMP1]]
276 ; CHECK-NEXT: ret i1 [[R]]
278 %zx = zext i7 %x to i25
279 %zy = zext i4 %y to i25
280 %r = icmp ugt i25 %zx, %zy
284 define <2 x i1> @different_size_zext_zext_ugt_commute(<2 x i4> %x, <2 x i7> %y) {
285 ; CHECK-LABEL: @different_size_zext_zext_ugt_commute(
286 ; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i4> [[X:%.*]] to <2 x i7>
287 ; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i7> [[Y:%.*]], [[TMP1]]
288 ; CHECK-NEXT: ret <2 x i1> [[R]]
290 %zx = zext <2 x i4> %x to <2 x i25>
291 %zy = zext <2 x i7> %y to <2 x i25>
292 %r = icmp ugt <2 x i25> %zx, %zy
296 define i1 @different_size_zext_zext_ult(i4 %x, i7 %y) {
297 ; CHECK-LABEL: @different_size_zext_zext_ult(
298 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7
299 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i7 [[Y:%.*]], [[TMP1]]
300 ; CHECK-NEXT: ret i1 [[R]]
302 %zx = zext i4 %x to i25
303 %zy = zext i7 %y to i25
304 %r = icmp ult i25 %zx, %zy
308 define i1 @different_size_zext_zext_eq(i4 %x, i7 %y) {
309 ; CHECK-LABEL: @different_size_zext_zext_eq(
310 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7
311 ; CHECK-NEXT: [[R:%.*]] = icmp eq i7 [[Y:%.*]], [[TMP1]]
312 ; CHECK-NEXT: ret i1 [[R]]
314 %zx = zext i4 %x to i25
315 %zy = zext i7 %y to i25
316 %r = icmp eq i25 %zx, %zy
320 define i1 @different_size_zext_zext_ne_commute(i7 %x, i4 %y) {
321 ; CHECK-LABEL: @different_size_zext_zext_ne_commute(
322 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
323 ; CHECK-NEXT: [[R:%.*]] = icmp ne i7 [[X:%.*]], [[TMP1]]
324 ; CHECK-NEXT: ret i1 [[R]]
326 %zx = zext i7 %x to i25
327 %zy = zext i4 %y to i25
328 %r = icmp ne i25 %zx, %zy
332 define i1 @different_size_zext_zext_slt(i7 %x, i4 %y) {
333 ; CHECK-LABEL: @different_size_zext_zext_slt(
334 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
335 ; CHECK-NEXT: [[R:%.*]] = icmp ult i7 [[X:%.*]], [[TMP1]]
336 ; CHECK-NEXT: ret i1 [[R]]
338 %zx = zext i7 %x to i25
339 %zy = zext i4 %y to i25
340 %r = icmp slt i25 %zx, %zy
344 define i1 @different_size_zext_zext_sgt(i7 %x, i4 %y) {
345 ; CHECK-LABEL: @different_size_zext_zext_sgt(
346 ; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7
347 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i7 [[X:%.*]], [[TMP1]]
348 ; CHECK-NEXT: ret i1 [[R]]
350 %zx = zext i7 %x to i25
351 %zy = zext i4 %y to i25
352 %r = icmp sgt i25 %zx, %zy
356 define i1 @different_size_sext_sext_sgt(i7 %x, i4 %y) {
357 ; CHECK-LABEL: @different_size_sext_sext_sgt(
358 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
359 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i7 [[X:%.*]], [[TMP1]]
360 ; CHECK-NEXT: ret i1 [[R]]
362 %sx = sext i7 %x to i25
363 %sy = sext i4 %y to i25
364 %r = icmp sgt i25 %sx, %sy
368 define i1 @different_size_sext_sext_sle(i7 %x, i4 %y) {
369 ; CHECK-LABEL: @different_size_sext_sext_sle(
370 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
371 ; CHECK-NEXT: [[R:%.*]] = icmp sle i7 [[X:%.*]], [[TMP1]]
372 ; CHECK-NEXT: ret i1 [[R]]
374 %sx = sext i7 %x to i25
375 %sy = sext i4 %y to i25
376 %r = icmp sle i25 %sx, %sy
380 define i1 @different_size_sext_sext_eq(i7 %x, i4 %y) {
381 ; CHECK-LABEL: @different_size_sext_sext_eq(
382 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
383 ; CHECK-NEXT: [[R:%.*]] = icmp eq i7 [[X:%.*]], [[TMP1]]
384 ; CHECK-NEXT: ret i1 [[R]]
386 %sx = sext i7 %x to i25
387 %sy = sext i4 %y to i25
388 %r = icmp eq i25 %sx, %sy
392 define i1 @different_size_sext_sext_ule(i7 %x, i4 %y) {
393 ; CHECK-LABEL: @different_size_sext_sext_ule(
394 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
395 ; CHECK-NEXT: [[R:%.*]] = icmp ule i7 [[X:%.*]], [[TMP1]]
396 ; CHECK-NEXT: ret i1 [[R]]
398 %sx = sext i7 %x to i25
399 %sy = sext i4 %y to i25
400 %r = icmp ule i25 %sx, %sy
404 ; TODO: This can be reduced.
406 define i1 @different_size_sext_zext_ne(i7 %x, i4 %y) {
407 ; CHECK-LABEL: @different_size_sext_zext_ne(
408 ; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25
409 ; CHECK-NEXT: [[ZY:%.*]] = zext i4 [[Y:%.*]] to i25
410 ; CHECK-NEXT: [[R:%.*]] = icmp ne i25 [[SX]], [[ZY]]
411 ; CHECK-NEXT: ret i1 [[R]]
413 %sx = sext i7 %x to i25
414 %zy = zext i4 %y to i25
415 %r = icmp ne i25 %sx, %zy
419 declare void @use(i25)
421 define i1 @different_size_sext_sext_ule_extra_use1(i7 %x, i4 %y) {
422 ; CHECK-LABEL: @different_size_sext_sext_ule_extra_use1(
423 ; CHECK-NEXT: [[SY:%.*]] = sext i4 [[Y:%.*]] to i25
424 ; CHECK-NEXT: call void @use(i25 [[SY]])
425 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y]] to i7
426 ; CHECK-NEXT: [[R:%.*]] = icmp ule i7 [[X:%.*]], [[TMP1]]
427 ; CHECK-NEXT: ret i1 [[R]]
429 %sx = sext i7 %x to i25
430 %sy = sext i4 %y to i25
431 call void @use(i25 %sy)
432 %r = icmp ule i25 %sx, %sy
436 define i1 @different_size_sext_sext_ule_extra_use2(i7 %x, i4 %y) {
437 ; CHECK-LABEL: @different_size_sext_sext_ule_extra_use2(
438 ; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25
439 ; CHECK-NEXT: call void @use(i25 [[SX]])
440 ; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
441 ; CHECK-NEXT: [[R:%.*]] = icmp ule i7 [[X]], [[TMP1]]
442 ; CHECK-NEXT: ret i1 [[R]]
444 %sx = sext i7 %x to i25
445 call void @use(i25 %sx)
446 %sy = sext i4 %y to i25
447 %r = icmp ule i25 %sx, %sy
451 ; Negative test - extra uses on both casts is too much.
453 define i1 @different_size_sext_sext_ule_extra_use3(i7 %x, i4 %y) {
454 ; CHECK-LABEL: @different_size_sext_sext_ule_extra_use3(
455 ; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25
456 ; CHECK-NEXT: call void @use(i25 [[SX]])
457 ; CHECK-NEXT: [[SY:%.*]] = sext i4 [[Y:%.*]] to i25
458 ; CHECK-NEXT: call void @use(i25 [[SY]])
459 ; CHECK-NEXT: [[R:%.*]] = icmp ule i25 [[SX]], [[SY]]
460 ; CHECK-NEXT: ret i1 [[R]]
462 %sx = sext i7 %x to i25
463 call void @use(i25 %sx)
464 %sy = sext i4 %y to i25
465 call void @use(i25 %sy)
466 %r = icmp ule i25 %sx, %sy