1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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_undef_elt(<2 x i32> %A) {
21; CHECK-LABEL: @zero_dividend_vector_undef_elt(
22; CHECK-NEXT:    ret <2 x i32> zeroinitializer
23;
24  %B = sdiv <2 x i32> <i32 0, i32 undef>, %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> poison
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> poison
41;
42  %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
43  ret <2 x i8> %div
44}
45
46; TODO: instsimplify should fold these to poison
47define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
48; CHECK-LABEL: @sdiv_zero_elt_vec(
49; CHECK-NEXT:    ret <2 x i8> undef
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:    ret <2 x i8> undef
58;
59  %div = udiv <2 x i8> %x, <i8 0, i8 42>
60  ret <2 x i8> %div
61}
62
63define <2 x i8> @sdiv_undef_elt_vec(<2 x i8> %x) {
64; CHECK-LABEL: @sdiv_undef_elt_vec(
65; CHECK-NEXT:    ret <2 x i8> undef
66;
67  %div = sdiv <2 x i8> %x, <i8 -42, i8 undef>
68  ret <2 x i8> %div
69}
70
71define <2 x i8> @udiv_undef_elt_vec(<2 x i8> %x) {
72; CHECK-LABEL: @udiv_undef_elt_vec(
73; CHECK-NEXT:    ret <2 x i8> undef
74;
75  %div = udiv <2 x i8> %x, <i8 undef, i8 42>
76  ret <2 x i8> %div
77}
78
79; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
80; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
81; Therefore, assume that all elements of 'y' must be 1.
82
83define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
84; CHECK-LABEL: @sdiv_bool_vec(
85; CHECK-NEXT:    ret <2 x i1> [[X:%.*]]
86;
87  %div = sdiv <2 x i1> %x, %y
88  ret <2 x i1> %div
89}
90
91define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) {
92; CHECK-LABEL: @udiv_bool_vec(
93; CHECK-NEXT:    ret <2 x i1> [[X:%.*]]
94;
95  %div = udiv <2 x i1> %x, %y
96  ret <2 x i1> %div
97}
98
99define i32 @zext_bool_udiv_divisor(i1 %x, i32 %y) {
100; CHECK-LABEL: @zext_bool_udiv_divisor(
101; CHECK-NEXT:    ret i32 [[Y:%.*]]
102;
103  %ext = zext i1 %x to i32
104  %r = udiv i32 %y, %ext
105  ret i32 %r
106}
107
108define <2 x i32> @zext_bool_sdiv_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
109; CHECK-LABEL: @zext_bool_sdiv_divisor_vec(
110; CHECK-NEXT:    ret <2 x i32> [[Y:%.*]]
111;
112  %ext = zext <2 x i1> %x to <2 x i32>
113  %r = sdiv <2 x i32> %y, %ext
114  ret <2 x i32> %r
115}
116
117define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
118; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor(
119; CHECK-NEXT:    ret i32 0
120;
121  %and = and i32 %x, 250
122  %div = udiv i32 %and, 251
123  ret i32 %div
124}
125
126define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) {
127; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor(
128; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
129; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], 251
130; CHECK-NEXT:    ret i32 [[DIV]]
131;
132  %and = and i32 %x, 251
133  %div = udiv i32 %and, 251
134  ret i32 %div
135}
136
137define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
138; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor(
139; CHECK-NEXT:    ret i32 0
140;
141  %or = or i32 %x, 251
142  %div = udiv i32 250, %or
143  ret i32 %div
144}
145
146define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) {
147; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor(
148; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], 251
149; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 251, [[OR]]
150; CHECK-NEXT:    ret i32 [[DIV]]
151;
152  %or = or i32 %x, 251
153  %div = udiv i32 251, %or
154  ret i32 %div
155}
156
157; This would require computing known bits on both x and y. Is it worth doing?
158
159define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
160; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor(
161; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
162; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
163; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
164; CHECK-NEXT:    ret i32 [[DIV]]
165;
166  %and = and i32 %x, 250
167  %or = or i32 %y, 251
168  %div = udiv i32 %and, %or
169  ret i32 %div
170}
171
172define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
173; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor(
174; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
175; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
176; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[AND]], [[OR]]
177; CHECK-NEXT:    ret i32 [[DIV]]
178;
179  %and = and i32 %x, 251
180  %or = or i32 %y, 251
181  %div = udiv i32 %and, %or
182  ret i32 %div
183}
184
185declare i32 @external()
186
187define i32 @div1() {
188; CHECK-LABEL: @div1(
189; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), [[RNG0:!range !.*]]
190; CHECK-NEXT:    ret i32 0
191;
192  %call = call i32 @external(), !range !0
193  %urem = udiv i32 %call, 3
194  ret i32 %urem
195}
196
197define i8 @sdiv_minusone_divisor() {
198; CHECK-LABEL: @sdiv_minusone_divisor(
199; CHECK-NEXT:    ret i8 poison
200;
201  %v = sdiv i8 -128, -1
202  ret i8 %v
203}
204
205; TODO: these should be poison
206define i32 @poison(i32 %x) {
207; CHECK-LABEL: @poison(
208; CHECK-NEXT:    ret i32 poison
209;
210  %v = udiv i32 %x, poison
211  ret i32 %v
212}
213
214define i32 @poison2(i32 %x) {
215; CHECK-LABEL: @poison2(
216; CHECK-NEXT:    ret i32 0
217;
218  %v = udiv i32 poison, %x
219  ret i32 %v
220}
221
222define <2 x i32> @poison3(<2 x i32> %x) {
223; CHECK-LABEL: @poison3(
224; CHECK-NEXT:    ret <2 x i32> undef
225;
226  %v = udiv <2 x i32> %x, <i32 poison, i32 1>
227  ret <2 x i32> %v
228}
229
230!0 = !{i32 0, i32 3}
231