1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instsimplify -S | FileCheck %s
4 define <2 x i8> @vsel_tvec(<2 x i8> %x, <2 x i8> %y) {
5 ; CHECK-LABEL: @vsel_tvec(
6 ; CHECK-NEXT: ret <2 x i8> %x
8 %s = select <2 x i1><i1 true, i1 true>, <2 x i8> %x, <2 x i8> %y
12 define <2 x i8> @vsel_fvec(<2 x i8> %x, <2 x i8> %y) {
13 ; CHECK-LABEL: @vsel_fvec(
14 ; CHECK-NEXT: ret <2 x i8> %y
16 %s = select <2 x i1><i1 false, i1 false>, <2 x i8> %x, <2 x i8> %y
20 define <2 x i8> @vsel_mixedvec() {
21 ; CHECK-LABEL: @vsel_mixedvec(
22 ; CHECK-NEXT: ret <2 x i8> <i8 0, i8 3>
24 %s = select <2 x i1><i1 true, i1 false>, <2 x i8> <i8 0, i8 1>, <2 x i8> <i8 2, i8 3>
28 ; FIXME: Allow for undef elements in a constant vector condition.
30 define <3 x i8> @vsel_undef_true_op(<3 x i8> %x, <3 x i8> %y) {
31 ; CHECK-LABEL: @vsel_undef_true_op(
32 ; CHECK-NEXT: [[S:%.*]] = select <3 x i1> <i1 true, i1 undef, i1 true>, <3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]
33 ; CHECK-NEXT: ret <3 x i8> [[S]]
35 %s = select <3 x i1><i1 1, i1 undef, i1 1>, <3 x i8> %x, <3 x i8> %y
39 define <3 x i4> @vsel_undef_false_op(<3 x i4> %x, <3 x i4> %y) {
40 ; CHECK-LABEL: @vsel_undef_false_op(
41 ; CHECK-NEXT: [[S:%.*]] = select <3 x i1> <i1 false, i1 undef, i1 undef>, <3 x i4> [[X:%.*]], <3 x i4> [[Y:%.*]]
42 ; CHECK-NEXT: ret <3 x i4> [[S]]
44 %s = select <3 x i1><i1 0, i1 undef, i1 undef>, <3 x i4> %x, <3 x i4> %y
48 define i32 @test1(i32 %x) {
49 ; CHECK-LABEL: @test1(
50 ; CHECK-NEXT: ret i32 %x
53 %cmp = icmp eq i32 %and, 0
54 %and1 = and i32 %x, -2
55 %and1.x = select i1 %cmp, i32 %and1, i32 %x
59 define i32 @test2(i32 %x) {
60 ; CHECK-LABEL: @test2(
61 ; CHECK-NEXT: ret i32 %x
64 %cmp = icmp ne i32 %and, 0
65 %and1 = and i32 %x, -2
66 %and1.x = select i1 %cmp, i32 %x, i32 %and1
70 define i32 @test3(i32 %x) {
71 ; CHECK-LABEL: @test3(
72 ; CHECK-NEXT: [[AND1:%.*]] = and i32 %x, -2
73 ; CHECK-NEXT: ret i32 [[AND1]]
76 %cmp = icmp ne i32 %and, 0
77 %and1 = and i32 %x, -2
78 %and1.x = select i1 %cmp, i32 %and1, i32 %x
82 define i32 @test4(i32 %X) {
83 ; CHECK-LABEL: @test4(
84 ; CHECK-NEXT: [[OR:%.*]] = or i32 %X, -2147483648
85 ; CHECK-NEXT: ret i32 [[OR]]
87 %cmp = icmp slt i32 %X, 0
88 %or = or i32 %X, -2147483648
89 %cond = select i1 %cmp, i32 %X, i32 %or
93 ; Same as above, but the compare isn't canonical
94 define i32 @test4noncanon(i32 %X) {
95 ; CHECK-LABEL: @test4noncanon(
96 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
97 ; CHECK-NEXT: ret i32 [[OR]]
99 %cmp = icmp sle i32 %X, -1
100 %or = or i32 %X, -2147483648
101 %cond = select i1 %cmp, i32 %X, i32 %or
105 define i32 @test5(i32 %X) {
106 ; CHECK-LABEL: @test5(
107 ; CHECK-NEXT: ret i32 %X
109 %cmp = icmp slt i32 %X, 0
110 %or = or i32 %X, -2147483648
111 %cond = select i1 %cmp, i32 %or, i32 %X
115 define i32 @test6(i32 %X) {
116 ; CHECK-LABEL: @test6(
117 ; CHECK-NEXT: [[AND:%.*]] = and i32 %X, 2147483647
118 ; CHECK-NEXT: ret i32 [[AND]]
120 %cmp = icmp slt i32 %X, 0
121 %and = and i32 %X, 2147483647
122 %cond = select i1 %cmp, i32 %and, i32 %X
126 define i32 @test7(i32 %X) {
127 ; CHECK-LABEL: @test7(
128 ; CHECK-NEXT: ret i32 %X
130 %cmp = icmp slt i32 %X, 0
131 %and = and i32 %X, 2147483647
132 %cond = select i1 %cmp, i32 %X, i32 %and
136 define i32 @test8(i32 %X) {
137 ; CHECK-LABEL: @test8(
138 ; CHECK-NEXT: ret i32 %X
140 %cmp = icmp sgt i32 %X, -1
141 %or = or i32 %X, -2147483648
142 %cond = select i1 %cmp, i32 %X, i32 %or
146 define i32 @test9(i32 %X) {
147 ; CHECK-LABEL: @test9(
148 ; CHECK-NEXT: [[OR:%.*]] = or i32 %X, -2147483648
149 ; CHECK-NEXT: ret i32 [[OR]]
151 %cmp = icmp sgt i32 %X, -1
152 %or = or i32 %X, -2147483648
153 %cond = select i1 %cmp, i32 %or, i32 %X
157 ; Same as above, but the compare isn't canonical
158 define i32 @test9noncanon(i32 %X) {
159 ; CHECK-LABEL: @test9noncanon(
160 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
161 ; CHECK-NEXT: ret i32 [[OR]]
163 %cmp = icmp sge i32 %X, 0
164 %or = or i32 %X, -2147483648
165 %cond = select i1 %cmp, i32 %or, i32 %X
169 define i32 @test10(i32 %X) {
170 ; CHECK-LABEL: @test10(
171 ; CHECK-NEXT: ret i32 %X
173 %cmp = icmp sgt i32 %X, -1
174 %and = and i32 %X, 2147483647
175 %cond = select i1 %cmp, i32 %and, i32 %X
179 define i32 @test11(i32 %X) {
180 ; CHECK-LABEL: @test11(
181 ; CHECK-NEXT: [[AND:%.*]] = and i32 %X, 2147483647
182 ; CHECK-NEXT: ret i32 [[AND]]
184 %cmp = icmp sgt i32 %X, -1
185 %and = and i32 %X, 2147483647
186 %cond = select i1 %cmp, i32 %X, i32 %and
190 define <2 x i8> @test11vec(<2 x i8> %X) {
191 ; CHECK-LABEL: @test11vec(
192 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> %X, <i8 127, i8 127>
193 ; CHECK-NEXT: ret <2 x i8> [[AND]]
195 %cmp = icmp sgt <2 x i8> %X, <i8 -1, i8 -1>
196 %and = and <2 x i8> %X, <i8 127, i8 127>
197 %sel = select <2 x i1> %cmp, <2 x i8> %X, <2 x i8> %and
201 define i32 @test12(i32 %X) {
202 ; CHECK-LABEL: @test12(
203 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
204 ; CHECK-NEXT: ret i32 [[AND]]
206 %cmp = icmp ult i32 %X, 4
208 %cond = select i1 %cmp, i32 %X, i32 %and
212 ; Same as above, but the compare isn't canonical
213 define i32 @test12noncanon(i32 %X) {
214 ; CHECK-LABEL: @test12noncanon(
215 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
216 ; CHECK-NEXT: ret i32 [[AND]]
218 %cmp = icmp ule i32 %X, 3
220 %cond = select i1 %cmp, i32 %X, i32 %and
224 define i32 @test13(i32 %X) {
225 ; CHECK-LABEL: @test13(
226 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
227 ; CHECK-NEXT: ret i32 [[AND]]
229 %cmp = icmp ugt i32 %X, 3
231 %cond = select i1 %cmp, i32 %and, i32 %X
235 ; Same as above, but the compare isn't canonical
236 define i32 @test13noncanon(i32 %X) {
237 ; CHECK-LABEL: @test13noncanon(
238 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
239 ; CHECK-NEXT: ret i32 [[AND]]
241 %cmp = icmp uge i32 %X, 4
243 %cond = select i1 %cmp, i32 %and, i32 %X
247 define i32 @select_icmp_and_8_eq_0_or_8(i32 %x) {
248 ; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8(
249 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 8
250 ; CHECK-NEXT: ret i32 [[OR]]
253 %cmp = icmp eq i32 %and, 0
255 %sel = select i1 %cmp, i32 %or, i32 %x
259 define i32 @select_icmp_and_8_eq_0_or_8_alt(i32 %x) {
260 ; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8_alt(
261 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 8
262 ; CHECK-NEXT: ret i32 [[OR]]
265 %cmp = icmp ne i32 %and, 0
267 %sel = select i1 %cmp, i32 %x, i32 %or
271 define i32 @select_icmp_and_8_ne_0_or_8(i32 %x) {
272 ; CHECK-LABEL: @select_icmp_and_8_ne_0_or_8(
273 ; CHECK-NEXT: ret i32 %x
276 %cmp = icmp ne i32 %and, 0
278 %sel = select i1 %cmp, i32 %or, i32 %x
282 define i32 @select_icmp_and_8_ne_0_or_8_alt(i32 %x) {
283 ; CHECK-LABEL: @select_icmp_and_8_ne_0_or_8_alt(
284 ; CHECK-NEXT: ret i32 %x
287 %cmp = icmp eq i32 %and, 0
289 %sel = select i1 %cmp, i32 %x, i32 %or
293 define i32 @select_icmp_and_8_eq_0_and_not_8(i32 %x) {
294 ; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8(
295 ; CHECK-NEXT: [[AND1:%.*]] = and i32 %x, -9
296 ; CHECK-NEXT: ret i32 [[AND1]]
299 %cmp = icmp eq i32 %and, 0
300 %and1 = and i32 %x, -9
301 %sel = select i1 %cmp, i32 %x, i32 %and1
305 define i32 @select_icmp_and_8_eq_0_and_not_8_alt(i32 %x) {
306 ; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8_alt(
307 ; CHECK-NEXT: [[AND1:%.*]] = and i32 %x, -9
308 ; CHECK-NEXT: ret i32 [[AND1]]
311 %cmp = icmp ne i32 %and, 0
312 %and1 = and i32 %x, -9
313 %sel = select i1 %cmp, i32 %and1, i32 %x
317 define i32 @select_icmp_and_8_ne_0_and_not_8(i32 %x) {
318 ; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8(
319 ; CHECK-NEXT: ret i32 %x
322 %cmp = icmp ne i32 %and, 0
323 %and1 = and i32 %x, -9
324 %sel = select i1 %cmp, i32 %x, i32 %and1
328 define i32 @select_icmp_and_8_ne_0_and_not_8_alt(i32 %x) {
329 ; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8_alt(
330 ; CHECK-NEXT: ret i32 %x
333 %cmp = icmp eq i32 %and, 0
334 %and1 = and i32 %x, -9
335 %sel = select i1 %cmp, i32 %and1, i32 %x
339 ; PR28466: https://llvm.org/bugs/show_bug.cgi?id=28466
340 ; Each of the previous 8 patterns has a variant that replaces the
341 ; 'and' with a 'trunc' and the icmp eq/ne with icmp slt/sgt.
343 define i32 @select_icmp_trunc_8_ne_0_or_128(i32 %x) {
344 ; CHECK-LABEL: @select_icmp_trunc_8_ne_0_or_128(
345 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 128
346 ; CHECK-NEXT: ret i32 [[OR]]
348 %trunc = trunc i32 %x to i8
349 %cmp = icmp sgt i8 %trunc, -1
351 %sel = select i1 %cmp, i32 %or, i32 %x
355 define i32 @select_icmp_trunc_8_ne_0_or_128_alt(i32 %x) {
356 ; CHECK-LABEL: @select_icmp_trunc_8_ne_0_or_128_alt(
357 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, 128
358 ; CHECK-NEXT: ret i32 [[OR]]
360 %trunc = trunc i32 %x to i8
361 %cmp = icmp slt i8 %trunc, 0
363 %sel = select i1 %cmp, i32 %x, i32 %or
367 define i32 @select_icmp_trunc_8_eq_0_or_128(i32 %x) {
368 ; CHECK-LABEL: @select_icmp_trunc_8_eq_0_or_128(
369 ; CHECK-NEXT: ret i32 %x
371 %trunc = trunc i32 %x to i8
372 %cmp = icmp slt i8 %trunc, 0
374 %sel = select i1 %cmp, i32 %or, i32 %x
378 define i32 @select_icmp_trunc_8_eq_0_or_128_alt(i32 %x) {
379 ; CHECK-LABEL: @select_icmp_trunc_8_eq_0_or_128_alt(
380 ; CHECK-NEXT: ret i32 %x
382 %trunc = trunc i32 %x to i8
383 %cmp = icmp sgt i8 %trunc, -1
385 %sel = select i1 %cmp, i32 %x, i32 %or
389 define i32 @select_icmp_trunc_8_eq_0_and_not_8(i32 %x) {
390 ; CHECK-LABEL: @select_icmp_trunc_8_eq_0_and_not_8(
391 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, -9
392 ; CHECK-NEXT: ret i32 [[AND]]
394 %trunc = trunc i32 %x to i4
395 %cmp = icmp sgt i4 %trunc, -1
396 %and = and i32 %x, -9
397 %sel = select i1 %cmp, i32 %x, i32 %and
401 define i32 @select_icmp_trunc_8_eq_0_and_not_8_alt(i32 %x) {
402 ; CHECK-LABEL: @select_icmp_trunc_8_eq_0_and_not_8_alt(
403 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, -9
404 ; CHECK-NEXT: ret i32 [[AND]]
406 %trunc = trunc i32 %x to i4
407 %cmp = icmp slt i4 %trunc, 0
408 %and = and i32 %x, -9
409 %sel = select i1 %cmp, i32 %and, i32 %x
413 define i32 @select_icmp_trunc_8_ne_0_and_not_8(i32 %x) {
414 ; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8(
415 ; CHECK-NEXT: ret i32 %x
417 %trunc = trunc i32 %x to i4
418 %cmp = icmp slt i4 %trunc, 0
419 %and = and i32 %x, -9
420 %sel = select i1 %cmp, i32 %x, i32 %and
424 define i32 @select_icmp_trunc_8_ne_0_and_not_8_alt(i32 %x) {
425 ; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8_alt(
426 ; CHECK-NEXT: ret i32 %x
428 %trunc = trunc i32 %x to i4
429 %cmp = icmp sgt i4 %trunc, -1
430 %and = and i32 %x, -9
431 %sel = select i1 %cmp, i32 %and, i32 %x
435 ; Make sure that at least a few of the same patterns are repeated with vector types.
437 define <2 x i32> @select_icmp_and_8_ne_0_and_not_8_vec(<2 x i32> %x) {
438 ; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8_vec(
439 ; CHECK-NEXT: ret <2 x i32> %x
441 %and = and <2 x i32> %x, <i32 8, i32 8>
442 %cmp = icmp ne <2 x i32> %and, zeroinitializer
443 %and1 = and <2 x i32> %x, <i32 -9, i32 -9>
444 %sel = select <2 x i1> %cmp, <2 x i32> %x, <2 x i32> %and1
448 define <2 x i32> @select_icmp_trunc_8_ne_0_and_not_8_alt_vec(<2 x i32> %x) {
449 ; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8_alt_vec(
450 ; CHECK-NEXT: ret <2 x i32> %x
452 %trunc = trunc <2 x i32> %x to <2 x i4>
453 %cmp = icmp sgt <2 x i4> %trunc, <i4 -1, i4 -1>
454 %and = and <2 x i32> %x, <i32 -9, i32 -9>
455 %sel = select <2 x i1> %cmp, <2 x i32> %and, <2 x i32> %x
459 ; Insert a bit from x into y? This should be possible in InstCombine, but not InstSimplify?
461 define i32 @select_icmp_x_and_8_eq_0_y_and_not_8(i32 %x, i32 %y) {
462 ; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_and_not_8(
463 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 8
464 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
465 ; CHECK-NEXT: [[AND1:%.*]] = and i32 %y, -9
466 ; CHECK-NEXT: [[Y_AND1:%.*]] = select i1 [[CMP]], i32 %y, i32 [[AND1]]
467 ; CHECK-NEXT: ret i32 [[Y_AND1]]
470 %cmp = icmp eq i32 %and, 0
471 %and1 = and i32 %y, -9
472 %y.and1 = select i1 %cmp, i32 %y, i32 %and1
476 define i64 @select_icmp_x_and_8_eq_0_y64_and_not_8(i32 %x, i64 %y) {
477 ; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y64_and_not_8(
478 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 8
479 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
480 ; CHECK-NEXT: [[AND1:%.*]] = and i64 %y, -9
481 ; CHECK-NEXT: [[Y_AND1:%.*]] = select i1 [[CMP]], i64 %y, i64 [[AND1]]
482 ; CHECK-NEXT: ret i64 [[Y_AND1]]
485 %cmp = icmp eq i32 %and, 0
486 %and1 = and i64 %y, -9
487 %y.and1 = select i1 %cmp, i64 %y, i64 %and1
491 define i64 @select_icmp_x_and_8_ne_0_y64_and_not_8(i32 %x, i64 %y) {
492 ; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y64_and_not_8(
493 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 8
494 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
495 ; CHECK-NEXT: [[AND1:%.*]] = and i64 %y, -9
496 ; CHECK-NEXT: [[AND1_Y:%.*]] = select i1 [[CMP]], i64 [[AND1]], i64 %y
497 ; CHECK-NEXT: ret i64 [[AND1_Y]]
500 %cmp = icmp eq i32 %and, 0
501 %and1 = and i64 %y, -9
502 %and1.y = select i1 %cmp, i64 %and1, i64 %y
506 ; Don't crash on a pointer or aggregate type.
508 define i32* @select_icmp_pointers(i32* %x, i32* %y) {
509 ; CHECK-LABEL: @select_icmp_pointers(
510 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32* %x, null
511 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32* %x, i32* %y
512 ; CHECK-NEXT: ret i32* [[SEL]]
514 %cmp = icmp slt i32* %x, null
515 %sel = select i1 %cmp, i32* %x, i32* %y
519 ; If the condition is known, we don't need to select, but we're not
520 ; doing this fold here to avoid compile-time cost.
522 declare void @llvm.assume(i1)
524 define i8 @assume_sel_cond(i1 %cond, i8 %x, i8 %y) {
525 ; CHECK-LABEL: @assume_sel_cond(
526 ; CHECK-NEXT: call void @llvm.assume(i1 %cond)
527 ; CHECK-NEXT: [[SEL:%.*]] = select i1 %cond, i8 %x, i8 %y
528 ; CHECK-NEXT: ret i8 [[SEL]]
530 call void @llvm.assume(i1 %cond)
531 %sel = select i1 %cond, i8 %x, i8 %y
535 define i8 @do_not_assume_sel_cond(i1 %cond, i8 %x, i8 %y) {
536 ; CHECK-LABEL: @do_not_assume_sel_cond(
537 ; CHECK-NEXT: [[NOTCOND:%.*]] = icmp eq i1 %cond, false
538 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOTCOND]])
539 ; CHECK-NEXT: [[SEL:%.*]] = select i1 %cond, i8 %x, i8 %y
540 ; CHECK-NEXT: ret i8 [[SEL]]
542 %notcond = icmp eq i1 %cond, false
543 call void @llvm.assume(i1 %notcond)
544 %sel = select i1 %cond, i8 %x, i8 %y
548 define i32* @select_icmp_eq_0_gep_operand(i32* %base, i64 %n) {
549 ; CHECK-LABEL: @select_icmp_eq_0_gep_operand(
550 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr
551 ; CHECK-NEXT: ret i32* [[GEP]]
552 %cond = icmp eq i64 %n, 0
553 %gep = getelementptr i32, i32* %base, i64 %n
554 %r = select i1 %cond, i32* %base, i32* %gep
558 define i32* @select_icmp_ne_0_gep_operand(i32* %base, i64 %n) {
559 ; CHECK-LABEL: @select_icmp_ne_0_gep_operand(
560 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr
561 ; CHECK-NEXT: ret i32* [[GEP]]
562 %cond = icmp ne i64 %n, 0
563 %gep = getelementptr i32, i32* %base, i64 %n
564 %r = select i1 %cond, i32* %gep, i32* %base