Skip to content

Commit c18e8bc

Browse files
committed
[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
1 parent e4e1eed commit c18e8bc

File tree

1 file changed

+354
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)