xref: /llvm-project/llvm/test/Transforms/InstSimplify/div.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4define i32 @zero_dividend(i32 %A) {
5; CHECK-LABEL: @zero_dividend(
6; CHECK-NEXT:    ret i32 0
7;
8  %B = sdiv i32 0, %A
9  ret i32 %B
10}
11
12define <2 x i32> @zero_dividend_vector(<2 x i32> %A) {
13; CHECK-LABEL: @zero_dividend_vector(
14; CHECK-NEXT:    ret <2 x i32> zeroinitializer
15;
16  %B = udiv <2 x i32> zeroinitializer, %A
17  ret <2 x i32> %B
18}
19
20define <2 x i32> @zero_dividend_vector_poison_elt(<2 x i32> %A) {
21; CHECK-LABEL: @zero_dividend_vector_poison_elt(
22; CHECK-NEXT:    ret <2 x i32> zeroinitializer
23;
24  %B = sdiv <2 x i32> <i32 0, i32 poison>, %A
25  ret <2 x i32> %B
26}
27
28; Division-by-zero is poison. UB in any vector lane means the whole op is poison.
29
30define <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> <i8 poison, i8 0>
33;
34  %div = sdiv <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
35  ret <2 x i8> %div
36}
37
38define <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> <i8 0, i8 poison>
41;
42  %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
43  ret <2 x i8> %div
44}
45
46define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
47; CHECK-LABEL: @sdiv_zero_elt_vec(
48; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 -42, i8 0>
49; CHECK-NEXT:    ret <2 x i8> [[DIV]]
50;
51  %div = sdiv <2 x i8> %x, <i8 -42, i8 0>
52  ret <2 x i8> %div
53}
54
55define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) {
56; CHECK-LABEL: @udiv_zero_elt_vec(
57; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 0, i8 42>
58; CHECK-NEXT:    ret <2 x i8> [[DIV]]
59;
60  %div = udiv <2 x i8> %x, <i8 0, i8 42>
61  ret <2 x i8> %div
62}
63
64define <2 x i8> @sdiv_poison_elt_vec(<2 x i8> %x) {
65; CHECK-LABEL: @sdiv_poison_elt_vec(
66; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 -42, i8 poison>
67; CHECK-NEXT:    ret <2 x i8> [[DIV]]
68;
69  %div = sdiv <2 x i8> %x, <i8 -42, i8 poison>
70  ret <2 x i8> %div
71}
72
73define <2 x i8> @udiv_poison_elt_vec(<2 x i8> %x) {
74; CHECK-LABEL: @udiv_poison_elt_vec(
75; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 poison, i8 42>
76; CHECK-NEXT:    ret <2 x i8> [[DIV]]
77;
78  %div = udiv <2 x i8> %x, <i8 poison, i8 42>
79  ret <2 x i8> %div
80}
81
82; Division-by-zero is poison. UB in any vector lane means the whole op is poison.
83; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
84; Therefore, assume that all elements of 'y' must be 1.
85
86define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
87; CHECK-LABEL: @sdiv_bool_vec(
88; CHECK-NEXT:    ret <2 x i1> [[X:%.*]]
89;
90  %div = sdiv <2 x i1> %x, %y
91  ret <2 x i1> %div
92}
93
94define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
95; CHECK-LABEL: @udiv_bool_vec(
96; CHECK-NEXT:    ret <2 x i1> [[X:%.*]]
97;
98  %div = udiv <2 x i1> %x, %y
99  ret <2 x i1> %div
100}
101
102define i32 @zext_bool_udiv_divisor(i1 %x, i32 %y) {
103; CHECK-LABEL: @zext_bool_udiv_divisor(
104; CHECK-NEXT:    ret i32 [[Y:%.*]]
105;
106  %ext = zext i1 %x to i32
107  %r = udiv i32 %y, %ext
108  ret i32 %r
109}
110
111define <2 x i32> @zext_bool_sdiv_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
112; CHECK-LABEL: @zext_bool_sdiv_divisor_vec(
113; CHECK-NEXT:    ret <2 x i32> [[Y:%.*]]
114;
115  %ext = zext <2 x i1> %x to <2 x i32>
116  %r = sdiv <2 x i32> %y, %ext
117  ret <2 x i32> %r
118}
119
120define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
121; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor(
122; CHECK-NEXT:    ret i32 0
123;
124  %and = and i32 %x, 250
125  %div = udiv i32 %and, 251
126  ret i32 %div
127}
128
129define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
130; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor(
131; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
132; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], 251
133; CHECK-NEXT:    ret i32 [[DIV]]
134;
135  %and = and i32 %x, 251
136  %div = udiv i32 %and, 251
137  ret i32 %div
138}
139
140define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
141; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor(
142; CHECK-NEXT:    ret i32 0
143;
144  %or = or i32 %x, 251
145  %div = udiv i32 250, %or
146  ret i32 %div
147}
148
149define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
150; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor(
151; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], 251
152; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 251, [[OR]]
153; CHECK-NEXT:    ret i32 [[DIV]]
154;
155  %or = or i32 %x, 251
156  %div = udiv i32 251, %or
157  ret i32 %div
158}
159
160define i8 @udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) {
161; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor2(
162; CHECK-NEXT:    ret i8 0
163;
164  %t0 = zext i1 %b to i8
165  %xor = xor i8 %t0, 12
166  %r = udiv i8 %xor, 14
167  ret i8 %r
168}
169
170; negative test - dividend can equal 13
171
172define i8 @not_udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) {
173; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor2(
174; CHECK-NEXT:    [[T0:%.*]] = zext i1 [[B:%.*]] to i8
175; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[T0]], 12
176; CHECK-NEXT:    [[R:%.*]] = udiv i8 [[XOR]], 13
177; CHECK-NEXT:    ret i8 [[R]]
178;
179  %t0 = zext i1 %b to i8
180  %xor = xor i8 %t0, 12
181  %r = udiv i8 %xor, 13
182  ret i8 %r
183}
184
185; This would require computing known bits on both x and y. Is it worth doing?
186
187define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
188; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor(
189; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
190; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
191; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
192; CHECK-NEXT:    ret i32 [[DIV]]
193;
194  %and = and i32 %x, 250
195  %or = or i32 %y, 251
196  %div = udiv i32 %and, %or
197  ret i32 %div
198}
199
200define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
201; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor(
202; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
203; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
204; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
205; CHECK-NEXT:    ret i32 [[DIV]]
206;
207  %and = and i32 %x, 251
208  %or = or i32 %y, 251
209  %div = udiv i32 %and, %or
210  ret i32 %div
211}
212
213declare i32 @external()
214
215define i32 @div1() {
216; CHECK-LABEL: @div1(
217; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range [[RNG0:![0-9]+]]
218; CHECK-NEXT:    ret i32 0
219;
220  %call = call i32 @external(), !range !0
221  %urem = udiv i32 %call, 3
222  ret i32 %urem
223}
224
225define i8 @sdiv_minusone_divisor() {
226; CHECK-LABEL: @sdiv_minusone_divisor(
227; CHECK-NEXT:    ret i8 poison
228;
229  %v = sdiv i8 -128, -1
230  ret i8 %v
231}
232
233@g = external global i64
234@g2 = external global i64
235
236define i64 @const_sdiv_one() {
237; CHECK-LABEL: @const_sdiv_one(
238; CHECK-NEXT:    ret i64 ptrtoint (ptr @g to i64)
239;
240  %div = sdiv i64 ptrtoint (ptr @g to i64), 1
241  ret i64 %div
242}
243
244define i64 @const_srem_one() {
245; CHECK-LABEL: @const_srem_one(
246; CHECK-NEXT:    ret i64 0
247;
248  %rem = srem i64 ptrtoint (ptr @g to i64), 1
249  ret i64 %rem
250}
251
252define i64 @const_udiv_one() {
253; CHECK-LABEL: @const_udiv_one(
254; CHECK-NEXT:    ret i64 ptrtoint (ptr @g to i64)
255;
256  %div = udiv i64 ptrtoint (ptr @g to i64), 1
257  ret i64 %div
258}
259
260define i64 @const_urem_one() {
261; CHECK-LABEL: @const_urem_one(
262; CHECK-NEXT:    ret i64 0
263;
264  %rem = urem i64 ptrtoint (ptr @g to i64), 1
265  ret i64 %rem
266}
267
268define i64 @const_sdiv_zero() {
269; CHECK-LABEL: @const_sdiv_zero(
270; CHECK-NEXT:    ret i64 0
271;
272  %div = sdiv i64 0, ptrtoint (ptr @g to i64)
273  ret i64 %div
274}
275
276define i64 @const_srem_zero() {
277; CHECK-LABEL: @const_srem_zero(
278; CHECK-NEXT:    ret i64 0
279;
280  %rem = srem i64 0, ptrtoint (ptr @g to i64)
281  ret i64 %rem
282}
283
284define i64 @const_udiv_zero() {
285; CHECK-LABEL: @const_udiv_zero(
286; CHECK-NEXT:    ret i64 0
287;
288  %div = udiv i64 0, ptrtoint (ptr @g to i64)
289  ret i64 %div
290}
291
292define i64 @const_urem_zero() {
293; CHECK-LABEL: @const_urem_zero(
294; CHECK-NEXT:    ret i64 0
295;
296  %rem = urem i64 0, ptrtoint (ptr @g to i64)
297  ret i64 %rem
298}
299
300define i64 @const_sdiv_zero_negone() {
301; CHECK-LABEL: @const_sdiv_zero_negone(
302; CHECK-NEXT:    ret i64 0
303;
304  %div = sdiv i64 0, -1
305  ret i64 %div
306}
307
308define i1 @const_sdiv_i1() {
309; CHECK-LABEL: @const_sdiv_i1(
310; CHECK-NEXT:    ret i1 ptrtoint (ptr @g to i1)
311;
312  %div = sdiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
313  ret i1 %div
314}
315
316define i1 @const_srem_1() {
317; CHECK-LABEL: @const_srem_1(
318; CHECK-NEXT:    ret i1 false
319;
320  %rem = srem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
321  ret i1 %rem
322}
323
324define i1 @const_udiv_i1() {
325; CHECK-LABEL: @const_udiv_i1(
326; CHECK-NEXT:    ret i1 ptrtoint (ptr @g to i1)
327;
328  %div = udiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
329  ret i1 %div
330}
331
332define i1 @const_urem_1() {
333; CHECK-LABEL: @const_urem_1(
334; CHECK-NEXT:    ret i1 false
335;
336  %rem = urem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1)
337  ret i1 %rem
338}
339
340; Can't divide evenly, so create poison.
341
342define i8 @sdiv_exact_trailing_zeros(i8 %x) {
343; CHECK-LABEL: @sdiv_exact_trailing_zeros(
344; CHECK-NEXT:    ret i8 poison
345;
346  %o = or i8 %x, 1           ; odd number
347  %r = sdiv exact i8 %o, -42 ; can't divide exactly
348  ret i8 %r
349}
350
351; Negative test - could divide evenly.
352
353define i8 @sdiv_exact_trailing_zeros_eq(i8 %x) {
354; CHECK-LABEL: @sdiv_exact_trailing_zeros_eq(
355; CHECK-NEXT:    [[O:%.*]] = or i8 [[X:%.*]], 2
356; CHECK-NEXT:    [[R:%.*]] = sdiv exact i8 [[O]], -42
357; CHECK-NEXT:    ret i8 [[R]]
358;
359  %o = or i8 %x, 2
360  %r = sdiv exact i8 %o, -42
361  ret i8 %r
362}
363
364; Negative test - must be exact div.
365
366define i8 @sdiv_trailing_zeros(i8 %x) {
367; CHECK-LABEL: @sdiv_trailing_zeros(
368; CHECK-NEXT:    [[O:%.*]] = or i8 [[X:%.*]], 1
369; CHECK-NEXT:    [[R:%.*]] = sdiv i8 [[O]], -12
370; CHECK-NEXT:    ret i8 [[R]]
371;
372  %o = or i8 %x, 1
373  %r = sdiv i8 %o, -12
374  ret i8 %r
375}
376
377; TODO: Match non-splat vector constants.
378
379define <2 x i8> @sdiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
380; CHECK-LABEL: @sdiv_exact_trailing_zeros_nonuniform_vector(
381; CHECK-NEXT:    [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 1>
382; CHECK-NEXT:    [[R:%.*]] = sdiv exact <2 x i8> [[O]], <i8 12, i8 2>
383; CHECK-NEXT:    ret <2 x i8> [[R]]
384;
385  %o = or <2 x i8> %x, <i8 3, i8 1>
386  %r = sdiv exact <2 x i8> %o, <i8 12, i8 2>
387  ret <2 x i8> %r
388}
389
390; Can't divide evenly, so create poison.
391
392define <2 x i8> @udiv_exact_trailing_zeros(<2 x i8> %x) {
393; CHECK-LABEL: @udiv_exact_trailing_zeros(
394; CHECK-NEXT:    ret <2 x i8> poison
395;
396  %o = or <2 x i8> %x, <i8 3, i8 3>
397  %r = udiv exact <2 x i8> %o, <i8 12, i8 12>  ; can't divide exactly
398  ret <2 x i8> %r
399}
400
401; Negative test - could divide evenly.
402
403define <2 x i8> @udiv_exact_trailing_zeros_eq(<2 x i8> %x) {
404; CHECK-LABEL: @udiv_exact_trailing_zeros_eq(
405; CHECK-NEXT:    [[O:%.*]] = or <2 x i8> [[X:%.*]], splat (i8 28)
406; CHECK-NEXT:    [[R:%.*]] = udiv exact <2 x i8> [[O]], splat (i8 12)
407; CHECK-NEXT:    ret <2 x i8> [[R]]
408;
409  %o = or <2 x i8> %x, <i8 28, i8 28>
410  %r = udiv exact <2 x i8> %o, <i8 12, i8 12>
411  ret <2 x i8> %r
412}
413
414; Negative test - must be exact div.
415
416define i8 @udiv_trailing_zeros(i8 %x) {
417; CHECK-LABEL: @udiv_trailing_zeros(
418; CHECK-NEXT:    [[O:%.*]] = or i8 [[X:%.*]], 1
419; CHECK-NEXT:    [[R:%.*]] = udiv i8 [[O]], 12
420; CHECK-NEXT:    ret i8 [[R]]
421;
422  %o = or i8 %x, 1
423  %r = udiv i8 %o, 12
424  ret i8 %r
425}
426
427; Negative test - only the first element is poison
428
429define <2 x i8> @udiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
430; CHECK-LABEL: @udiv_exact_trailing_zeros_nonuniform_vector(
431; CHECK-NEXT:    [[O:%.*]] = or <2 x i8> [[X:%.*]], splat (i8 3)
432; CHECK-NEXT:    [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 1>
433; CHECK-NEXT:    ret <2 x i8> [[R]]
434;
435  %o = or <2 x i8> %x, <i8 3, i8 3>
436  %r = udiv exact <2 x i8> %o, <i8 12, i8 1>
437  ret <2 x i8> %r
438}
439
440!0 = !{i32 0, i32 3}
441
442define i32 @sdiv_one_srem_divisor(i32 %a, i32 %b) {
443; CHECK-LABEL: @sdiv_one_srem_divisor(
444; CHECK-NEXT:    ret i32 [[A:%.*]]
445;
446  %srem = srem i32 1, %b
447  %sdiv = sdiv i32 %a, %srem
448  ret i32 %sdiv
449}
450
451define i32 @sdiv_one_urem_divisor(i32 %a, i32 %b) {
452; CHECK-LABEL: @sdiv_one_urem_divisor(
453; CHECK-NEXT:    ret i32 [[A:%.*]]
454;
455  %urem = urem i32 1, %b
456  %sdiv = sdiv i32 %a, %urem
457  ret i32 %sdiv
458}
459
460define i32 @udiv_one_srem_divisor(i32 %a, i32 %b) {
461; CHECK-LABEL: @udiv_one_srem_divisor(
462; CHECK-NEXT:    ret i32 [[A:%.*]]
463;
464  %srem = srem i32 1, %b
465  %udiv = udiv i32 %a, %srem
466  ret i32 %udiv
467}
468
469define i32 @udiv_one_urem_divisor(i32 %a, i32 %b) {
470; CHECK-LABEL: @udiv_one_urem_divisor(
471; CHECK-NEXT:    ret i32 [[A:%.*]]
472;
473  %urem = urem i32 1, %b
474  %udiv = udiv i32 %a, %urem
475  ret i32 %udiv
476}
477
478define i32 @srem_one_srem_divisor(i32 %a, i32 %b) {
479; CHECK-LABEL: @srem_one_srem_divisor(
480; CHECK-NEXT:    ret i32 0
481;
482  %srem = srem i32 1, %b
483  %srem1 = srem i32 %a, %srem
484  ret i32 %srem1
485}
486
487define i32 @urem_one_srem_divisor(i32 %a, i32 %b) {
488; CHECK-LABEL: @urem_one_srem_divisor(
489; CHECK-NEXT:    ret i32 0
490;
491  %srem = srem i32 1, %b
492  %urem = urem i32 %a, %srem
493  ret i32 %urem
494}
495
496define i32 @srem_one_urem_divisor(i32 %a, i32 %b) {
497; CHECK-LABEL: @srem_one_urem_divisor(
498; CHECK-NEXT:    ret i32 0
499;
500  %urem = urem i32 1, %b
501  %srem = srem i32 %a, %urem
502  ret i32 %srem
503}
504
505define i32 @urem_one_urem_divisor(i32 %a, i32 %b) {
506; CHECK-LABEL: @urem_one_urem_divisor(
507; CHECK-NEXT:    ret i32 0
508;
509  %urem = urem i32 1, %b
510  %urem1 = urem i32 %a, %urem
511  ret i32 %urem1
512}
513
514define <2 x i8> @sdiv_one_vec_srem_divisor(<2 x i8> %a, <2 x i8> %b) {
515; CHECK-LABEL: @sdiv_one_vec_srem_divisor(
516; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
517;
518  %srem = srem <2 x i8> <i8 1, i8 1>, %b
519  %sdiv = sdiv <2 x i8> %a, %srem
520  ret <2 x i8> %sdiv
521}
522
523define i32 @sdiv_and_one_divisor(i32 %x, i32 %y) {
524; CHECK-LABEL: @sdiv_and_one_divisor(
525; CHECK-NEXT:    ret i32 [[Y:%.*]]
526;
527  %and = and i32 %x, 1
528  %res = sdiv i32 %y, %and
529  ret i32 %res
530}
531
532define <2 x i8> @sdiv_and_one_vec_divisor(<2 x i8> %x, <2 x i8> %y) {
533; CHECK-LABEL: @sdiv_and_one_vec_divisor(
534; CHECK-NEXT:    ret <2 x i8> [[Y:%.*]]
535;
536  %and = and <2 x i8> %x, <i8 1, i8 1>
537  %res = sdiv <2 x i8> %y, %and
538  ret <2 x i8> %res
539}
540
541define i32 @sdiv_neg_or_divisor(i32 %x, i32 %y) {
542; CHECK-LABEL: @sdiv_neg_or_divisor(
543; CHECK-NEXT:    ret i32 [[Y:%.*]]
544;
545  %or = or i32 %x, -2
546  %neg = xor i32 %or, -1
547  %res = sdiv i32 %y, %neg
548  ret i32 %res
549}
550
551define i32 @sdiv_neg_or_multi_one_bit_divisor(i32 %x, i32 %y) {
552; CHECK-LABEL: @sdiv_neg_or_multi_one_bit_divisor(
553; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -3
554; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[OR]], -1
555; CHECK-NEXT:    [[RES:%.*]] = sdiv i32 [[Y:%.*]], [[NEG]]
556; CHECK-NEXT:    ret i32 [[RES]]
557;
558  %or = or i32 %x, -3
559  %neg = xor i32 %or, -1
560  %res = sdiv i32 %y, %neg
561  ret i32 %res
562}
563
564define <2 x i8> @sdiv_vec_multi_one_bit_divisor(<2 x i8> %x, <2 x i8> %y) {
565; CHECK-LABEL: @sdiv_vec_multi_one_bit_divisor(
566; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 1, i8 3>
567; CHECK-NEXT:    [[RES:%.*]] = sdiv <2 x i8> [[Y:%.*]], [[AND]]
568; CHECK-NEXT:    ret <2 x i8> [[RES]]
569;
570  %and = and <2 x i8> %x, <i8 1, i8 3>
571  %res = sdiv <2 x i8> %y, %and
572  ret <2 x i8> %res
573}
574
575define i8 @udiv_exact_mul_nsw(i8 %x) {
576; CHECK-LABEL: @udiv_exact_mul_nsw(
577; CHECK-NEXT:    ret i8 [[X:%.*]]
578;
579  %a = mul nsw i8 %x, 24
580  %b = udiv exact i8 %a, 24
581  ret i8 %b
582}
583
584define i8 @sdiv_exact_mul_nuw(i8 %x) {
585; CHECK-LABEL: @sdiv_exact_mul_nuw(
586; CHECK-NEXT:    ret i8 [[X:%.*]]
587;
588  %a = mul nuw i8 %x, 24
589  %b = sdiv exact i8 %a, 24
590  ret i8 %b
591}
592
593; Negative tests
594
595define i8 @udiv_exact_mul_nsw_mismatch(i8 %x) {
596; CHECK-LABEL: @udiv_exact_mul_nsw_mismatch(
597; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], 24
598; CHECK-NEXT:    [[B:%.*]] = udiv exact i8 [[A]], 12
599; CHECK-NEXT:    ret i8 [[B]]
600;
601  %a = mul nsw i8 %x, 24
602  %b = udiv exact i8 %a, 12
603  ret i8 %b
604}
605
606define i8 @udiv_exact_mul_nsw_power_of_2(i8 %x) {
607; CHECK-LABEL: @udiv_exact_mul_nsw_power_of_2(
608; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], 8
609; CHECK-NEXT:    [[B:%.*]] = udiv exact i8 [[A]], 8
610; CHECK-NEXT:    ret i8 [[B]]
611;
612  %a = mul nsw i8 %x, 8
613  %b = udiv exact i8 %a, 8
614  ret i8 %b
615}
616
617define i8 @sdiv_exact_mul_nuw_power_of_2(i8 %x) {
618; CHECK-LABEL: @sdiv_exact_mul_nuw_power_of_2(
619; CHECK-NEXT:    [[A:%.*]] = mul nuw i8 [[X:%.*]], 8
620; CHECK-NEXT:    [[B:%.*]] = sdiv exact i8 [[A]], 8
621; CHECK-NEXT:    ret i8 [[B]]
622;
623  %a = mul nuw i8 %x, 8
624  %b = sdiv exact i8 %a, 8
625  ret i8 %b
626}
627
628define i8 @udiv_exact_mul(i8 %x) {
629; CHECK-LABEL: @udiv_exact_mul(
630; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 24
631; CHECK-NEXT:    [[B:%.*]] = udiv exact i8 [[A]], 24
632; CHECK-NEXT:    ret i8 [[B]]
633;
634  %a = mul i8 %x, 24
635  %b = udiv exact i8 %a, 24
636  ret i8 %b
637}
638
639define i8 @sdiv_exact_mul(i8 %x) {
640; CHECK-LABEL: @sdiv_exact_mul(
641; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 24
642; CHECK-NEXT:    [[B:%.*]] = sdiv exact i8 [[A]], 24
643; CHECK-NEXT:    ret i8 [[B]]
644;
645  %a = mul i8 %x, 24
646  %b = sdiv exact i8 %a, 24
647  ret i8 %b
648}
649
650define i8 @udiv_mul_nsw(i8 %x) {
651; CHECK-LABEL: @udiv_mul_nsw(
652; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], 24
653; CHECK-NEXT:    [[B:%.*]] = udiv i8 [[A]], 24
654; CHECK-NEXT:    ret i8 [[B]]
655;
656  %a = mul nsw i8 %x, 24
657  %b = udiv i8 %a, 24
658  ret i8 %b
659}
660
661define i8 @sdiv_mul_nuw(i8 %x) {
662; CHECK-LABEL: @sdiv_mul_nuw(
663; CHECK-NEXT:    [[A:%.*]] = mul nuw i8 [[X:%.*]], 24
664; CHECK-NEXT:    [[B:%.*]] = sdiv i8 [[A]], 24
665; CHECK-NEXT:    ret i8 [[B]]
666;
667  %a = mul nuw i8 %x, 24
668  %b = sdiv i8 %a, 24
669  ret i8 %b
670}
671