llvm.org GIT mirror llvm / c18e8bc
[InstSimplify] add tests for possible sdiv/srem simplifications; NFC As noted in PR34517, the handling of signed div/rem is not on par with unsigned div/rem. Signed is harder to reason about, but it should be possible to handle at least some of these using the same technique that we use for unsigned: use icmp logic to see if there's a relationship between the quotient and divisor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312938 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 2 years ago
1 changed file(s) with 354 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 ; RUN: opt < %s -instsimplify -S | FileCheck %s
1
2 define i32 @sdiv_sext_big_divisor(i8 %x) {
3 ; CHECK-LABEL: @sdiv_sext_big_divisor(
4 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
5 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 129
6 ; CHECK-NEXT: ret i32 [[DIV]]
7 ;
8 %conv = sext i8 %x to i32
9 %div = sdiv i32 %conv, 129
10 ret i32 %div
11 }
12
13 define i32 @not_sdiv_sext_big_divisor(i8 %x) {
14 ; CHECK-LABEL: @not_sdiv_sext_big_divisor(
15 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
16 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 128
17 ; CHECK-NEXT: ret i32 [[DIV]]
18 ;
19 %conv = sext i8 %x to i32
20 %div = sdiv i32 %conv, 128
21 ret i32 %div
22 }
23
24 define i32 @sdiv_sext_small_divisor(i8 %x) {
25 ; CHECK-LABEL: @sdiv_sext_small_divisor(
26 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
27 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -129
28 ; CHECK-NEXT: ret i32 [[DIV]]
29 ;
30 %conv = sext i8 %x to i32
31 %div = sdiv i32 %conv, -129
32 ret i32 %div
33 }
34
35 define i32 @not_sdiv_sext_small_divisor(i8 %x) {
36 ; CHECK-LABEL: @not_sdiv_sext_small_divisor(
37 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
38 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -128
39 ; CHECK-NEXT: ret i32 [[DIV]]
40 ;
41 %conv = sext i8 %x to i32
42 %div = sdiv i32 %conv, -128
43 ret i32 %div
44 }
45
46 define i32 @sdiv_zext_big_divisor(i8 %x) {
47 ; CHECK-LABEL: @sdiv_zext_big_divisor(
48 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
49 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 256
50 ; CHECK-NEXT: ret i32 [[DIV]]
51 ;
52 %conv = zext i8 %x to i32
53 %div = sdiv i32 %conv, 256
54 ret i32 %div
55 }
56
57 define i32 @not_sdiv_zext_big_divisor(i8 %x) {
58 ; CHECK-LABEL: @not_sdiv_zext_big_divisor(
59 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
60 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 255
61 ; CHECK-NEXT: ret i32 [[DIV]]
62 ;
63 %conv = zext i8 %x to i32
64 %div = sdiv i32 %conv, 255
65 ret i32 %div
66 }
67
68 define i32 @sdiv_zext_small_divisor(i8 %x) {
69 ; CHECK-LABEL: @sdiv_zext_small_divisor(
70 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
71 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -256
72 ; CHECK-NEXT: ret i32 [[DIV]]
73 ;
74 %conv = zext i8 %x to i32
75 %div = sdiv i32 %conv, -256
76 ret i32 %div
77 }
78
79 define i32 @not_sdiv_zext_small_divisor(i8 %x) {
80 ; CHECK-LABEL: @not_sdiv_zext_small_divisor(
81 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
82 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -255
83 ; CHECK-NEXT: ret i32 [[DIV]]
84 ;
85 %conv = zext i8 %x to i32
86 %div = sdiv i32 %conv, -255
87 ret i32 %div
88 }
89
90 define i32 @sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
91 ; CHECK-LABEL: @sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(
92 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
93 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], 254
94 ; CHECK-NEXT: ret i32 [[DIV]]
95 ;
96 %and = and i32 %x, 253
97 %div = sdiv i32 %and, 254
98 ret i32 %div
99 }
100
101 define i32 @not_sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
102 ; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(
103 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
104 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], 253
105 ; CHECK-NEXT: ret i32 [[DIV]]
106 ;
107 %and = and i32 %x, 253
108 %div = sdiv i32 %and, 253
109 ret i32 %div
110 }
111
112 define i32 @sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
113 ; CHECK-LABEL: @sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(
114 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
115 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], -254
116 ; CHECK-NEXT: ret i32 [[DIV]]
117 ;
118 %and = and i32 %x, 253
119 %div = sdiv i32 %and, -254
120 ret i32 %div
121 }
122
123 define i32 @not_sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
124 ; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(
125 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
126 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], -253
127 ; CHECK-NEXT: ret i32 [[DIV]]
128 ;
129 %and = and i32 %x, 253
130 %div = sdiv i32 %and, -253
131 ret i32 %div
132 }
133
134 define i32 @sdiv_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) {
135 ; CHECK-LABEL: @sdiv_quotient_known_smaller_than_pos_divisor_set_bits(
136 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
137 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], 254
138 ; CHECK-NEXT: ret i32 [[DIV]]
139 ;
140 %or = or i32 %x, -253
141 %div = sdiv i32 %or, 254
142 ret i32 %div
143 }
144
145 define i32 @not_sdiv_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) {
146 ; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_pos_divisor_set_bits(
147 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
148 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], 253
149 ; CHECK-NEXT: ret i32 [[DIV]]
150 ;
151 %or = or i32 %x, -253
152 %div = sdiv i32 %or, 253
153 ret i32 %div
154 }
155
156 define i32 @sdiv_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) {
157 ; CHECK-LABEL: @sdiv_quotient_known_smaller_than_neg_divisor_set_bits(
158 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
159 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], -254
160 ; CHECK-NEXT: ret i32 [[DIV]]
161 ;
162 %or = or i32 %x, -253
163 %div = sdiv i32 %or, -254
164 ret i32 %div
165 }
166
167 define i32 @not_sdiv_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) {
168 ; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_neg_divisor_set_bits(
169 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
170 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], -253
171 ; CHECK-NEXT: ret i32 [[DIV]]
172 ;
173 %or = or i32 %x, -253
174 %div = sdiv i32 %or, -253
175 ret i32 %div
176 }
177
178 define i32 @srem_sext_big_divisor(i8 %x) {
179 ; CHECK-LABEL: @srem_sext_big_divisor(
180 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
181 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 129
182 ; CHECK-NEXT: ret i32 [[REM]]
183 ;
184 %conv = sext i8 %x to i32
185 %rem = srem i32 %conv, 129
186 ret i32 %rem
187 }
188
189 define i32 @not_srem_sext_big_divisor(i8 %x) {
190 ; CHECK-LABEL: @not_srem_sext_big_divisor(
191 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
192 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 128
193 ; CHECK-NEXT: ret i32 [[REM]]
194 ;
195 %conv = sext i8 %x to i32
196 %rem = srem i32 %conv, 128
197 ret i32 %rem
198 }
199
200 define i32 @srem_sext_small_divisor(i8 %x) {
201 ; CHECK-LABEL: @srem_sext_small_divisor(
202 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
203 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -129
204 ; CHECK-NEXT: ret i32 [[REM]]
205 ;
206 %conv = sext i8 %x to i32
207 %rem = srem i32 %conv, -129
208 ret i32 %rem
209 }
210
211 define i32 @not_srem_sext_small_divisor(i8 %x) {
212 ; CHECK-LABEL: @not_srem_sext_small_divisor(
213 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32
214 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -128
215 ; CHECK-NEXT: ret i32 [[REM]]
216 ;
217 %conv = sext i8 %x to i32
218 %rem = srem i32 %conv, -128
219 ret i32 %rem
220 }
221
222 define i32 @srem_zext_big_divisor(i8 %x) {
223 ; CHECK-LABEL: @srem_zext_big_divisor(
224 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
225 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 256
226 ; CHECK-NEXT: ret i32 [[REM]]
227 ;
228 %conv = zext i8 %x to i32
229 %rem = srem i32 %conv, 256
230 ret i32 %rem
231 }
232
233 define i32 @not_srem_zext_big_divisor(i8 %x) {
234 ; CHECK-LABEL: @not_srem_zext_big_divisor(
235 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
236 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 255
237 ; CHECK-NEXT: ret i32 [[REM]]
238 ;
239 %conv = zext i8 %x to i32
240 %rem = srem i32 %conv, 255
241 ret i32 %rem
242 }
243
244 define i32 @srem_zext_small_divisor(i8 %x) {
245 ; CHECK-LABEL: @srem_zext_small_divisor(
246 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
247 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -256
248 ; CHECK-NEXT: ret i32 [[REM]]
249 ;
250 %conv = zext i8 %x to i32
251 %rem = srem i32 %conv, -256
252 ret i32 %rem
253 }
254
255 define i32 @not_srem_zext_small_divisor(i8 %x) {
256 ; CHECK-LABEL: @not_srem_zext_small_divisor(
257 ; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32
258 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -255
259 ; CHECK-NEXT: ret i32 [[REM]]
260 ;
261 %conv = zext i8 %x to i32
262 %rem = srem i32 %conv, -255
263 ret i32 %rem
264 }
265
266 define i32 @srem_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
267 ; CHECK-LABEL: @srem_quotient_known_smaller_than_pos_divisor_clear_bits(
268 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
269 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], 254
270 ; CHECK-NEXT: ret i32 [[REM]]
271 ;
272 %and = and i32 %x, 253
273 %rem = srem i32 %and, 254
274 ret i32 %rem
275 }
276
277 define i32 @not_srem_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
278 ; CHECK-LABEL: @not_srem_quotient_known_smaller_than_pos_divisor_clear_bits(
279 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
280 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], 253
281 ; CHECK-NEXT: ret i32 [[REM]]
282 ;
283 %and = and i32 %x, 253
284 %rem = srem i32 %and, 253
285 ret i32 %rem
286 }
287
288 define i32 @srem_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
289 ; CHECK-LABEL: @srem_quotient_known_smaller_than_neg_divisor_clear_bits(
290 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
291 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], -254
292 ; CHECK-NEXT: ret i32 [[REM]]
293 ;
294 %and = and i32 %x, 253
295 %rem = srem i32 %and, -254
296 ret i32 %rem
297 }
298
299 define i32 @not_srem_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
300 ; CHECK-LABEL: @not_srem_quotient_known_smaller_than_neg_divisor_clear_bits(
301 ; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253
302 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], -253
303 ; CHECK-NEXT: ret i32 [[REM]]
304 ;
305 %and = and i32 %x, 253
306 %rem = srem i32 %and, -253
307 ret i32 %rem
308 }
309
310 define i32 @srem_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) {
311 ; CHECK-LABEL: @srem_quotient_known_smaller_than_pos_divisor_set_bits(
312 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
313 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], 254
314 ; CHECK-NEXT: ret i32 [[REM]]
315 ;
316 %or = or i32 %x, -253
317 %rem = srem i32 %or, 254
318 ret i32 %rem
319 }
320
321 define i32 @not_srem_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) {
322 ; CHECK-LABEL: @not_srem_quotient_known_smaller_than_pos_divisor_set_bits(
323 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
324 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], 253
325 ; CHECK-NEXT: ret i32 [[REM]]
326 ;
327 %or = or i32 %x, -253
328 %rem = srem i32 %or, 253
329 ret i32 %rem
330 }
331
332 define i32 @srem_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) {
333 ; CHECK-LABEL: @srem_quotient_known_smaller_than_neg_divisor_set_bits(
334 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
335 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], -254
336 ; CHECK-NEXT: ret i32 [[REM]]
337 ;
338 %or = or i32 %x, -253
339 %rem = srem i32 %or, -254
340 ret i32 %rem
341 }
342
343 define i32 @not_srem_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) {
344 ; CHECK-LABEL: @not_srem_quotient_known_smaller_than_neg_divisor_set_bits(
345 ; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253
346 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], -253
347 ; CHECK-NEXT: ret i32 [[REM]]
348 ;
349 %or = or i32 %x, -253
350 %rem = srem i32 %or, -253
351 ret i32 %rem
352 }
353