1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
4 define i32 @zero_dividend(i32 %A) {
5 ; CHECK-LABEL: @zero_dividend(
6 ; CHECK-NEXT: ret i32 0
12 define <2 x i32> @zero_dividend_vector(<2 x i32> %A) {
13 ; CHECK-LABEL: @zero_dividend_vector(
14 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
16 %B = udiv <2 x i32> zeroinitializer, %A
20 define <2 x i32> @zero_dividend_vector_undef_elt(<2 x i32> %A) {
21 ; CHECK-LABEL: @zero_dividend_vector_undef_elt(
22 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
24 %B = sdiv <2 x i32> <i32 0, i32 undef>, %A
28 ; Division-by-zero is poison. UB in any vector lane means the whole op is poison.
30 define <2 x i8> @sdiv_zero_elt_vec_constfold(<2 x i8> %x) {
31 ; CHECK-LABEL: @sdiv_zero_elt_vec_constfold(
32 ; CHECK-NEXT: ret <2 x i8> poison
34 %div = sdiv <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
38 define <2 x i8> @udiv_zero_elt_vec_constfold(<2 x i8> %x) {
39 ; CHECK-LABEL: @udiv_zero_elt_vec_constfold(
40 ; CHECK-NEXT: ret <2 x i8> poison
42 %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
46 define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
47 ; CHECK-LABEL: @sdiv_zero_elt_vec(
48 ; CHECK-NEXT: ret <2 x i8> poison
50 %div = sdiv <2 x i8> %x, <i8 -42, i8 0>
54 define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) {
55 ; CHECK-LABEL: @udiv_zero_elt_vec(
56 ; CHECK-NEXT: ret <2 x i8> poison
58 %div = udiv <2 x i8> %x, <i8 0, i8 42>
62 define <2 x i8> @sdiv_undef_elt_vec(<2 x i8> %x) {
63 ; CHECK-LABEL: @sdiv_undef_elt_vec(
64 ; CHECK-NEXT: ret <2 x i8> poison
66 %div = sdiv <2 x i8> %x, <i8 -42, i8 undef>
70 define <2 x i8> @udiv_undef_elt_vec(<2 x i8> %x) {
71 ; CHECK-LABEL: @udiv_undef_elt_vec(
72 ; CHECK-NEXT: ret <2 x i8> poison
74 %div = udiv <2 x i8> %x, <i8 undef, i8 42>
78 ; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
79 ; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
80 ; Therefore, assume that all elements of 'y' must be 1.
82 define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
83 ; CHECK-LABEL: @sdiv_bool_vec(
84 ; CHECK-NEXT: ret <2 x i1> [[X:%.*]]
86 %div = sdiv <2 x i1> %x, %y
90 define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
91 ; CHECK-LABEL: @udiv_bool_vec(
92 ; CHECK-NEXT: ret <2 x i1> [[X:%.*]]
94 %div = udiv <2 x i1> %x, %y
98 define i32 @zext_bool_udiv_divisor(i1 %x, i32 %y) {
99 ; CHECK-LABEL: @zext_bool_udiv_divisor(
100 ; CHECK-NEXT: ret i32 [[Y:%.*]]
102 %ext = zext i1 %x to i32
103 %r = udiv i32 %y, %ext
107 define <2 x i32> @zext_bool_sdiv_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
108 ; CHECK-LABEL: @zext_bool_sdiv_divisor_vec(
109 ; CHECK-NEXT: ret <2 x i32> [[Y:%.*]]
111 %ext = zext <2 x i1> %x to <2 x i32>
112 %r = sdiv <2 x i32> %y, %ext
116 define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
117 ; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor(
118 ; CHECK-NEXT: ret i32 0
120 %and = and i32 %x, 250
121 %div = udiv i32 %and, 251
125 define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
126 ; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor(
127 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 251
128 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], 251
129 ; CHECK-NEXT: ret i32 [[DIV]]
131 %and = and i32 %x, 251
132 %div = udiv i32 %and, 251
136 define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
137 ; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor(
138 ; CHECK-NEXT: ret i32 0
141 %div = udiv i32 250, %or
145 define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
146 ; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor(
147 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], 251
148 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 251, [[OR]]
149 ; CHECK-NEXT: ret i32 [[DIV]]
152 %div = udiv i32 251, %or
156 define i8 @udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) {
157 ; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor2(
158 ; CHECK-NEXT: ret i8 0
160 %t0 = zext i1 %b to i8
161 %xor = xor i8 %t0, 12
162 %r = udiv i8 %xor, 14
166 ; negative test - dividend can equal 13
168 define i8 @not_udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) {
169 ; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor2(
170 ; CHECK-NEXT: [[T0:%.*]] = zext i1 [[B:%.*]] to i8
171 ; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[T0]], 12
172 ; CHECK-NEXT: [[R:%.*]] = udiv i8 [[XOR]], 13
173 ; CHECK-NEXT: ret i8 [[R]]
175 %t0 = zext i1 %b to i8
176 %xor = xor i8 %t0, 12
177 %r = udiv i8 %xor, 13
181 ; This would require computing known bits on both x and y. Is it worth doing?
183 define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
184 ; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor(
185 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 250
186 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 251
187 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
188 ; CHECK-NEXT: ret i32 [[DIV]]
190 %and = and i32 %x, 250
192 %div = udiv i32 %and, %or
196 define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
197 ; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor(
198 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 251
199 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 251
200 ; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
201 ; CHECK-NEXT: ret i32 [[DIV]]
203 %and = and i32 %x, 251
205 %div = udiv i32 %and, %or
209 declare i32 @external()
212 ; CHECK-LABEL: @div1(
213 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @external(), !range [[RNG0:![0-9]+]]
214 ; CHECK-NEXT: ret i32 0
216 %call = call i32 @external(), !range !0
217 %urem = udiv i32 %call, 3
221 define i8 @sdiv_minusone_divisor() {
222 ; CHECK-LABEL: @sdiv_minusone_divisor(
223 ; CHECK-NEXT: ret i8 poison
225 %v = sdiv i8 -128, -1
229 @g = external global i64
230 @g2 = external global i64
232 define i64 @const_sdiv_one() {
233 ; CHECK-LABEL: @const_sdiv_one(
234 ; CHECK-NEXT: ret i64 ptrtoint (ptr @g to i64)
236 %div = sdiv i64 ptrtoint (ptr @g to i64), 1
240 define i64 @const_srem_one() {
241 ; CHECK-LABEL: @const_srem_one(
242 ; CHECK-NEXT: ret i64 0
244 %rem = srem i64 ptrtoint (ptr @g to i64), 1
248 define i64 @const_udiv_one() {
249 ; CHECK-LABEL: @const_udiv_one(
250 ; CHECK-NEXT: ret i64 ptrtoint (ptr @g to i64)
252 %div = udiv i64 ptrtoint (ptr @g to i64), 1
256 define i64 @const_urem_one() {
257 ; CHECK-LABEL: @const_urem_one(
258 ; CHECK-NEXT: ret i64 0
260 %rem = urem i64 ptrtoint (ptr @g to i64), 1
264 define i64 @const_sdiv_zero() {
265 ; CHECK-LABEL: @const_sdiv_zero(
266 ; CHECK-NEXT: ret i64 0
268 %div = sdiv i64 0, ptrtoint (ptr @g to i64)
272 define i64 @const_srem_zero() {
273 ; CHECK-LABEL: @const_srem_zero(
274 ; CHECK-NEXT: ret i64 0
276 %rem = srem i64 0, ptrtoint (ptr @g to i64)
280 define i64 @const_udiv_zero() {
281 ; CHECK-LABEL: @const_udiv_zero(
282 ; CHECK-NEXT: ret i64 0
284 %div = udiv i64 0, ptrtoint (ptr @g to i64)
288 define i64 @const_urem_zero() {
289 ; CHECK-LABEL: @const_urem_zero(
290 ; CHECK-NEXT: ret i64 0
292 %rem = urem i64 0, ptrtoint (ptr @g to i64)
296 define i64 @const_sdiv_zero_negone() {
297 ; CHECK-LABEL: @const_sdiv_zero_negone(
298 ; CHECK-NEXT: ret i64 0
300 %div = sdiv i64 0, -1
304 define i1 @const_sdiv_i1() {
305 ; CHECK-LABEL: @const_sdiv_i1(
306 ; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1)
308 %div = sdiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
312 define i1 @const_srem_1() {
313 ; CHECK-LABEL: @const_srem_1(
314 ; CHECK-NEXT: ret i1 false
316 %rem = srem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
320 define i1 @const_udiv_i1() {
321 ; CHECK-LABEL: @const_udiv_i1(
322 ; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1)
324 %div = udiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
328 define i1 @const_urem_1() {
329 ; CHECK-LABEL: @const_urem_1(
330 ; CHECK-NEXT: ret i1 false
332 %rem = urem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
336 ; Can't divide evenly, so create poison.
338 define i8 @sdiv_exact_trailing_zeros(i8 %x) {
339 ; CHECK-LABEL: @sdiv_exact_trailing_zeros(
340 ; CHECK-NEXT: ret i8 poison
342 %o = or i8 %x, 1 ; odd number
343 %r = sdiv exact i8 %o, -42 ; can't divide exactly
347 ; Negative test - could divide evenly.
349 define i8 @sdiv_exact_trailing_zeros_eq(i8 %x) {
350 ; CHECK-LABEL: @sdiv_exact_trailing_zeros_eq(
351 ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 2
352 ; CHECK-NEXT: [[R:%.*]] = sdiv exact i8 [[O]], -42
353 ; CHECK-NEXT: ret i8 [[R]]
356 %r = sdiv exact i8 %o, -42
360 ; Negative test - must be exact div.
362 define i8 @sdiv_trailing_zeros(i8 %x) {
363 ; CHECK-LABEL: @sdiv_trailing_zeros(
364 ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1
365 ; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[O]], -12
366 ; CHECK-NEXT: ret i8 [[R]]
373 ; TODO: Match non-splat vector constants.
375 define <2 x i8> @sdiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
376 ; CHECK-LABEL: @sdiv_exact_trailing_zeros_nonuniform_vector(
377 ; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 1>
378 ; CHECK-NEXT: [[R:%.*]] = sdiv exact <2 x i8> [[O]], <i8 12, i8 2>
379 ; CHECK-NEXT: ret <2 x i8> [[R]]
381 %o = or <2 x i8> %x, <i8 3, i8 1>
382 %r = sdiv exact <2 x i8> %o, <i8 12, i8 2>
386 ; Can't divide evenly, so create poison.
388 define <2 x i8> @udiv_exact_trailing_zeros(<2 x i8> %x) {
389 ; CHECK-LABEL: @udiv_exact_trailing_zeros(
390 ; CHECK-NEXT: ret <2 x i8> poison
392 %o = or <2 x i8> %x, <i8 3, i8 3>
393 %r = udiv exact <2 x i8> %o, <i8 12, i8 12> ; can't divide exactly
397 ; Negative test - could divide evenly.
399 define <2 x i8> @udiv_exact_trailing_zeros_eq(<2 x i8> %x) {
400 ; CHECK-LABEL: @udiv_exact_trailing_zeros_eq(
401 ; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 28, i8 28>
402 ; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 12>
403 ; CHECK-NEXT: ret <2 x i8> [[R]]
405 %o = or <2 x i8> %x, <i8 28, i8 28>
406 %r = udiv exact <2 x i8> %o, <i8 12, i8 12>
410 ; Negative test - must be exact div.
412 define i8 @udiv_trailing_zeros(i8 %x) {
413 ; CHECK-LABEL: @udiv_trailing_zeros(
414 ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1
415 ; CHECK-NEXT: [[R:%.*]] = udiv i8 [[O]], 12
416 ; CHECK-NEXT: ret i8 [[R]]
423 ; Negative test - only the first element is poison
425 define <2 x i8> @udiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
426 ; CHECK-LABEL: @udiv_exact_trailing_zeros_nonuniform_vector(
427 ; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 3>
428 ; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 1>
429 ; CHECK-NEXT: ret <2 x i8> [[R]]
431 %o = or <2 x i8> %x, <i8 3, i8 3>
432 %r = udiv exact <2 x i8> %o, <i8 12, i8 1>
438 define i32 @sdiv_one_srem_divisor(i32 %a, i32 %b) {
439 ; CHECK-LABEL: @sdiv_one_srem_divisor(
440 ; CHECK-NEXT: ret i32 [[A:%.*]]
442 %srem = srem i32 1, %b
443 %sdiv = sdiv i32 %a, %srem
447 define i32 @sdiv_one_urem_divisor(i32 %a, i32 %b) {
448 ; CHECK-LABEL: @sdiv_one_urem_divisor(
449 ; CHECK-NEXT: ret i32 [[A:%.*]]
451 %urem = urem i32 1, %b
452 %sdiv = sdiv i32 %a, %urem
456 define i32 @udiv_one_srem_divisor(i32 %a, i32 %b) {
457 ; CHECK-LABEL: @udiv_one_srem_divisor(
458 ; CHECK-NEXT: ret i32 [[A:%.*]]
460 %srem = srem i32 1, %b
461 %udiv = udiv i32 %a, %srem
465 define i32 @udiv_one_urem_divisor(i32 %a, i32 %b) {
466 ; CHECK-LABEL: @udiv_one_urem_divisor(
467 ; CHECK-NEXT: ret i32 [[A:%.*]]
469 %urem = urem i32 1, %b
470 %udiv = udiv i32 %a, %urem
474 define i32 @srem_one_srem_divisor(i32 %a, i32 %b) {
475 ; CHECK-LABEL: @srem_one_srem_divisor(
476 ; CHECK-NEXT: ret i32 0
478 %srem = srem i32 1, %b
479 %srem1 = srem i32 %a, %srem
483 define i32 @urem_one_srem_divisor(i32 %a, i32 %b) {
484 ; CHECK-LABEL: @urem_one_srem_divisor(
485 ; CHECK-NEXT: ret i32 0
487 %srem = srem i32 1, %b
488 %urem = urem i32 %a, %srem
492 define i32 @srem_one_urem_divisor(i32 %a, i32 %b) {
493 ; CHECK-LABEL: @srem_one_urem_divisor(
494 ; CHECK-NEXT: ret i32 0
496 %urem = urem i32 1, %b
497 %srem = srem i32 %a, %urem
501 define i32 @urem_one_urem_divisor(i32 %a, i32 %b) {
502 ; CHECK-LABEL: @urem_one_urem_divisor(
503 ; CHECK-NEXT: ret i32 0
505 %urem = urem i32 1, %b
506 %urem1 = urem i32 %a, %urem
510 define <2 x i8> @sdiv_one_vec_srem_divisor(<2 x i8> %a, <2 x i8> %b) {
511 ; CHECK-LABEL: @sdiv_one_vec_srem_divisor(
512 ; CHECK-NEXT: ret <2 x i8> [[A:%.*]]
514 %srem = srem <2 x i8> <i8 1, i8 1>, %b
515 %sdiv = sdiv <2 x i8> %a, %srem
519 define i32 @sdiv_and_one_divisor(i32 %x, i32 %y) {
520 ; CHECK-LABEL: @sdiv_and_one_divisor(
521 ; CHECK-NEXT: ret i32 [[Y:%.*]]
524 %res = sdiv i32 %y, %and
528 define <2 x i8> @sdiv_and_one_vec_divisor(<2 x i8> %x, <2 x i8> %y) {
529 ; CHECK-LABEL: @sdiv_and_one_vec_divisor(
530 ; CHECK-NEXT: ret <2 x i8> [[Y:%.*]]
532 %and = and <2 x i8> %x, <i8 1, i8 1>
533 %res = sdiv <2 x i8> %y, %and
537 define i32 @sdiv_neg_or_divisor(i32 %x, i32 %y) {
538 ; CHECK-LABEL: @sdiv_neg_or_divisor(
539 ; CHECK-NEXT: ret i32 [[Y:%.*]]
542 %neg = xor i32 %or, -1
543 %res = sdiv i32 %y, %neg
547 define i32 @sdiv_neg_or_multi_one_bit_divisor(i32 %x, i32 %y) {
548 ; CHECK-LABEL: @sdiv_neg_or_multi_one_bit_divisor(
549 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -3
550 ; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[OR]], -1
551 ; CHECK-NEXT: [[RES:%.*]] = sdiv i32 [[Y:%.*]], [[NEG]]
552 ; CHECK-NEXT: ret i32 [[RES]]
555 %neg = xor i32 %or, -1
556 %res = sdiv i32 %y, %neg
560 define <2 x i8> @sdiv_vec_multi_one_bit_divisor(<2 x i8> %x, <2 x i8> %y) {
561 ; CHECK-LABEL: @sdiv_vec_multi_one_bit_divisor(
562 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 1, i8 3>
563 ; CHECK-NEXT: [[RES:%.*]] = sdiv <2 x i8> [[Y:%.*]], [[AND]]
564 ; CHECK-NEXT: ret <2 x i8> [[RES]]
566 %and = and <2 x i8> %x, <i8 1, i8 3>
567 %res = sdiv <2 x i8> %y, %and