1; RUN: opt < %s -instsimplify -S | FileCheck %s
2
3; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
4
5define <2 x i8> @sdiv_zero_elt_vec_constfold(<2 x i8> %x) {
6; CHECK-LABEL: @sdiv_zero_elt_vec_constfold(
7; CHECK-NEXT:    ret <2 x i8> undef
8;
9  %div = sdiv <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
10  ret <2 x i8> %div
11}
12
13define <2 x i8> @udiv_zero_elt_vec_constfold(<2 x i8> %x) {
14; CHECK-LABEL: @udiv_zero_elt_vec_constfold(
15; CHECK-NEXT:    ret <2 x i8> undef
16;
17  %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
18  ret <2 x i8> %div
19}
20
21define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
22; CHECK-LABEL: @sdiv_zero_elt_vec(
23; CHECK-NEXT:    ret <2 x i8> undef
24;
25  %div = sdiv <2 x i8> %x, <i8 -42, i8 0>
26  ret <2 x i8> %div
27}
28
29define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) {
30; CHECK-LABEL: @udiv_zero_elt_vec(
31; CHECK-NEXT:    ret <2 x i8> undef
32;
33  %div = udiv <2 x i8> %x, <i8 0, i8 42>
34  ret <2 x i8> %div
35}
36
37; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
38; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
39; Therefore, assume that all elements of 'y' must be 1.
40
41define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
42; CHECK-LABEL: @sdiv_bool_vec(
43; CHECK-NEXT:    ret <2 x i1> %x
44;
45  %div = sdiv <2 x i1> %x, %y
46  ret <2 x i1> %div
47}
48
49define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
50; CHECK-LABEL: @udiv_bool_vec(
51; CHECK-NEXT:    ret <2 x i1> %x
52;
53  %div = udiv <2 x i1> %x, %y
54  ret <2 x i1> %div
55}
56
57define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
58; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor(
59; CHECK-NEXT:    ret i32 0
60;
61  %and = and i32 %x, 250
62  %div = udiv i32 %and, 251
63  ret i32 %div
64}
65
66define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
67; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor(
68; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 251
69; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], 251
70; CHECK-NEXT:    ret i32 [[DIV]]
71;
72  %and = and i32 %x, 251
73  %div = udiv i32 %and, 251
74  ret i32 %div
75}
76
77define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
78; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor(
79; CHECK-NEXT:    ret i32 0
80;
81  %or = or i32 %x, 251
82  %div = udiv i32 250, %or
83  ret i32 %div
84}
85
86define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
87; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor(
88; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 251
89; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 251, [[OR]]
90; CHECK-NEXT:    ret i32 [[DIV]]
91;
92  %or = or i32 %x, 251
93  %div = udiv i32 251, %or
94  ret i32 %div
95}
96
97; This would require computing known bits on both x and y. Is it worth doing?
98
99define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
100; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor(
101; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 250
102; CHECK-NEXT:    [[OR:%.*]] = or i32 %y, 251
103; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
104; CHECK-NEXT:    ret i32 [[DIV]]
105;
106  %and = and i32 %x, 250
107  %or = or i32 %y, 251
108  %div = udiv i32 %and, %or
109  ret i32 %div
110}
111
112define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
113; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor(
114; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 251
115; CHECK-NEXT:    [[OR:%.*]] = or i32 %y, 251
116; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
117; CHECK-NEXT:    ret i32 [[DIV]]
118;
119  %and = and i32 %x, 251
120  %or = or i32 %y, 251
121  %div = udiv i32 %and, %or
122  ret i32 %div
123}
124
125declare i32 @external()
126
127define i32 @div1() {
128; CHECK-LABEL: @div1(
129; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range !0
130; CHECK-NEXT:    ret i32 0
131;
132  %call = call i32 @external(), !range !0
133  %urem = udiv i32 %call, 3
134  ret i32 %urem
135}
136
137!0 = !{i32 0, i32 3}
138