1; NOTE: Assertions have been autogenerated by update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
5
6define <2 x i8> @srem_zero_elt_vec_constfold(<2 x i8> %x) {
7; CHECK-LABEL: @srem_zero_elt_vec_constfold(
8; CHECK-NEXT:    ret <2 x i8> undef
9;
10  %rem = srem <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
11  ret <2 x i8> %rem
12}
13
14define <2 x i8> @urem_zero_elt_vec_constfold(<2 x i8> %x) {
15; CHECK-LABEL: @urem_zero_elt_vec_constfold(
16; CHECK-NEXT:    ret <2 x i8> undef
17;
18  %rem = urem <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
19  ret <2 x i8> %rem
20}
21
22define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) {
23; CHECK-LABEL: @srem_zero_elt_vec(
24; CHECK-NEXT:    ret <2 x i8> undef
25;
26  %rem = srem <2 x i8> %x, <i8 -42, i8 0>
27  ret <2 x i8> %rem
28}
29
30define <2 x i8> @urem_zero_elt_vec(<2 x i8> %x) {
31; CHECK-LABEL: @urem_zero_elt_vec(
32; CHECK-NEXT:    ret <2 x i8> undef
33;
34  %rem = urem <2 x i8> %x, <i8 0, i8 42>
35  ret <2 x i8> %rem
36}
37
38; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
39; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
40; Therefore, assume that all elements of 'y' must be 1.
41
42define <2 x i1> @srem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
43; CHECK-LABEL: @srem_bool_vec(
44; CHECK-NEXT:    ret <2 x i1> zeroinitializer
45;
46  %rem = srem <2 x i1> %x, %y
47  ret <2 x i1> %rem
48}
49
50define <2 x i1> @urem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
51; CHECK-LABEL: @urem_bool_vec(
52; CHECK-NEXT:    ret <2 x i1> zeroinitializer
53;
54  %rem = urem <2 x i1> %x, %y
55  ret <2 x i1> %rem
56}
57
58define i32 @select1(i32 %x, i1 %b) {
59; CHECK-LABEL: @select1(
60; CHECK-NEXT:    ret i32 0
61;
62  %rhs = select i1 %b, i32 %x, i32 1
63  %rem = srem i32 %x, %rhs
64  ret i32 %rem
65}
66
67define i32 @select2(i32 %x, i1 %b) {
68; CHECK-LABEL: @select2(
69; CHECK-NEXT:    ret i32 0
70;
71  %rhs = select i1 %b, i32 %x, i32 1
72  %rem = urem i32 %x, %rhs
73  ret i32 %rem
74}
75
76define i32 @rem1(i32 %x, i32 %n) {
77; CHECK-LABEL: @rem1(
78; CHECK-NEXT:    [[MOD:%.*]] = srem i32 %x, %n
79; CHECK-NEXT:    ret i32 [[MOD]]
80;
81  %mod = srem i32 %x, %n
82  %mod1 = srem i32 %mod, %n
83  ret i32 %mod1
84}
85
86define i32 @rem2(i32 %x, i32 %n) {
87; CHECK-LABEL: @rem2(
88; CHECK-NEXT:    [[MOD:%.*]] = urem i32 %x, %n
89; CHECK-NEXT:    ret i32 [[MOD]]
90;
91  %mod = urem i32 %x, %n
92  %mod1 = urem i32 %mod, %n
93  ret i32 %mod1
94}
95
96define i32 @rem3(i32 %x, i32 %n) {
97; CHECK-LABEL: @rem3(
98; CHECK-NEXT:    [[MOD:%.*]] = srem i32 %x, %n
99; CHECK-NEXT:    [[MOD1:%.*]] = urem i32 [[MOD]], %n
100; CHECK-NEXT:    ret i32 [[MOD1]]
101;
102  %mod = srem i32 %x, %n
103  %mod1 = urem i32 %mod, %n
104  ret i32 %mod1
105}
106
107define i32 @urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
108; CHECK-LABEL: @urem_dividend_known_smaller_than_constant_divisor(
109; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 250
110; CHECK-NEXT:    ret i32 [[AND]]
111;
112  %and = and i32 %x, 250
113  %r = urem i32 %and, 251
114  ret i32 %r
115}
116
117define i32 @not_urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
118; CHECK-LABEL: @not_urem_dividend_known_smaller_than_constant_divisor(
119; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 251
120; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], 251
121; CHECK-NEXT:    ret i32 [[R]]
122;
123  %and = and i32 %x, 251
124  %r = urem i32 %and, 251
125  ret i32 %r
126}
127
128define i32 @urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
129; CHECK-LABEL: @urem_constant_dividend_known_smaller_than_divisor(
130; CHECK-NEXT:    ret i32 250
131;
132  %or = or i32 %x, 251
133  %r = urem i32 250, %or
134  ret i32 %r
135}
136
137define i32 @not_urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
138; CHECK-LABEL: @not_urem_constant_dividend_known_smaller_than_divisor(
139; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 251
140; CHECK-NEXT:    [[R:%.*]] = urem i32 251, [[OR]]
141; CHECK-NEXT:    ret i32 [[R]]
142;
143  %or = or i32 %x, 251
144  %r = urem i32 251, %or
145  ret i32 %r
146}
147
148; This would require computing known bits on both x and y. Is it worth doing?
149
150define i32 @urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
151; CHECK-LABEL: @urem_dividend_known_smaller_than_divisor(
152; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 250
153; CHECK-NEXT:    [[OR:%.*]] = or i32 %y, 251
154; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
155; CHECK-NEXT:    ret i32 [[R]]
156;
157  %and = and i32 %x, 250
158  %or = or i32 %y, 251
159  %r = urem i32 %and, %or
160  ret i32 %r
161}
162
163define i32 @not_urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
164; CHECK-LABEL: @not_urem_dividend_known_smaller_than_divisor(
165; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 251
166; CHECK-NEXT:    [[OR:%.*]] = or i32 %y, 251
167; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
168; CHECK-NEXT:    ret i32 [[R]]
169;
170  %and = and i32 %x, 251
171  %or = or i32 %y, 251
172  %r = urem i32 %and, %or
173  ret i32 %r
174}
175
176declare i32 @external()
177
178define i32 @rem4() {
179; CHECK-LABEL: @rem4(
180; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range !0
181; CHECK-NEXT:    ret i32 [[CALL]]
182;
183  %call = call i32 @external(), !range !0
184  %urem = urem i32 %call, 3
185  ret i32 %urem
186}
187
188!0 = !{i32 0, i32 3}
189