xref: /llvm-project/llvm/test/CodeGen/AArch64/urem-seteq.ll (revision 2bb727297d9afb432455160f57e7e14a4a36db70)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
3
4;------------------------------------------------------------------------------;
5; Odd divisors
6;------------------------------------------------------------------------------;
7
8define i32 @test_urem_odd(i32 %X) nounwind {
9; CHECK-LABEL: test_urem_odd:
10; CHECK:       // %bb.0:
11; CHECK-NEXT:    mov w8, #52429 // =0xcccd
12; CHECK-NEXT:    mov w9, #13108 // =0x3334
13; CHECK-NEXT:    movk w8, #52428, lsl #16
14; CHECK-NEXT:    movk w9, #13107, lsl #16
15; CHECK-NEXT:    mul w8, w0, w8
16; CHECK-NEXT:    cmp w8, w9
17; CHECK-NEXT:    cset w0, lo
18; CHECK-NEXT:    ret
19  %urem = urem i32 %X, 5
20  %cmp = icmp eq i32 %urem, 0
21  %ret = zext i1 %cmp to i32
22  ret i32 %ret
23}
24
25define i32 @test_urem_odd_25(i32 %X) nounwind {
26; CHECK-LABEL: test_urem_odd_25:
27; CHECK:       // %bb.0:
28; CHECK-NEXT:    mov w8, #23593 // =0x5c29
29; CHECK-NEXT:    mov w9, #28836 // =0x70a4
30; CHECK-NEXT:    movk w8, #49807, lsl #16
31; CHECK-NEXT:    movk w9, #2621, lsl #16
32; CHECK-NEXT:    mul w8, w0, w8
33; CHECK-NEXT:    cmp w8, w9
34; CHECK-NEXT:    cset w0, lo
35; CHECK-NEXT:    ret
36  %urem = urem i32 %X, 25
37  %cmp = icmp eq i32 %urem, 0
38  %ret = zext i1 %cmp to i32
39  ret i32 %ret
40}
41
42; This is like test_urem_odd, except the divisor has bit 30 set.
43define i32 @test_urem_odd_bit30(i32 %X) nounwind {
44; CHECK-LABEL: test_urem_odd_bit30:
45; CHECK:       // %bb.0:
46; CHECK-NEXT:    mov w8, #43691 // =0xaaab
47; CHECK-NEXT:    movk w8, #27306, lsl #16
48; CHECK-NEXT:    mul w8, w0, w8
49; CHECK-NEXT:    cmp w8, #4
50; CHECK-NEXT:    cset w0, lo
51; CHECK-NEXT:    ret
52  %urem = urem i32 %X, 1073741827
53  %cmp = icmp eq i32 %urem, 0
54  %ret = zext i1 %cmp to i32
55  ret i32 %ret
56}
57
58; This is like test_urem_odd, except the divisor has bit 31 set.
59define i32 @test_urem_odd_bit31(i32 %X) nounwind {
60; CHECK-LABEL: test_urem_odd_bit31:
61; CHECK:       // %bb.0:
62; CHECK-NEXT:    mov w8, #43691 // =0xaaab
63; CHECK-NEXT:    movk w8, #10922, lsl #16
64; CHECK-NEXT:    mul w8, w0, w8
65; CHECK-NEXT:    cmp w8, #2
66; CHECK-NEXT:    cset w0, lo
67; CHECK-NEXT:    ret
68  %urem = urem i32 %X, 2147483651
69  %cmp = icmp eq i32 %urem, 0
70  %ret = zext i1 %cmp to i32
71  ret i32 %ret
72}
73
74;------------------------------------------------------------------------------;
75; Even divisors
76;------------------------------------------------------------------------------;
77
78define i16 @test_urem_even(i16 %X) nounwind {
79; CHECK-LABEL: test_urem_even:
80; CHECK:       // %bb.0:
81; CHECK-NEXT:    mov w8, #28087 // =0x6db7
82; CHECK-NEXT:    mul w8, w0, w8
83; CHECK-NEXT:    and w9, w8, #0xfffc
84; CHECK-NEXT:    lsr w9, w9, #1
85; CHECK-NEXT:    orr w8, w9, w8, lsl #15
86; CHECK-NEXT:    ubfx w8, w8, #1, #15
87; CHECK-NEXT:    cmp w8, #2340
88; CHECK-NEXT:    cset w0, hi
89; CHECK-NEXT:    ret
90  %urem = urem i16 %X, 14
91  %cmp = icmp ne i16 %urem, 0
92  %ret = zext i1 %cmp to i16
93  ret i16 %ret
94}
95
96define i32 @test_urem_even_100(i32 %X) nounwind {
97; CHECK-LABEL: test_urem_even_100:
98; CHECK:       // %bb.0:
99; CHECK-NEXT:    mov w8, #23593 // =0x5c29
100; CHECK-NEXT:    mov w9, #23593 // =0x5c29
101; CHECK-NEXT:    movk w8, #49807, lsl #16
102; CHECK-NEXT:    movk w9, #655, lsl #16
103; CHECK-NEXT:    mul w8, w0, w8
104; CHECK-NEXT:    ror w8, w8, #2
105; CHECK-NEXT:    cmp w8, w9
106; CHECK-NEXT:    cset w0, lo
107; CHECK-NEXT:    ret
108  %urem = urem i32 %X, 100
109  %cmp = icmp eq i32 %urem, 0
110  %ret = zext i1 %cmp to i32
111  ret i32 %ret
112}
113
114; This is like test_urem_even, except the divisor has bit 30 set.
115define i32 @test_urem_even_bit30(i32 %X) nounwind {
116; CHECK-LABEL: test_urem_even_bit30:
117; CHECK:       // %bb.0:
118; CHECK-NEXT:    mov w8, #20165 // =0x4ec5
119; CHECK-NEXT:    movk w8, #64748, lsl #16
120; CHECK-NEXT:    mul w8, w0, w8
121; CHECK-NEXT:    ror w8, w8, #3
122; CHECK-NEXT:    cmp w8, #4
123; CHECK-NEXT:    cset w0, lo
124; CHECK-NEXT:    ret
125  %urem = urem i32 %X, 1073741928
126  %cmp = icmp eq i32 %urem, 0
127  %ret = zext i1 %cmp to i32
128  ret i32 %ret
129}
130
131; This is like test_urem_odd, except the divisor has bit 31 set.
132define i32 @test_urem_even_bit31(i32 %X) nounwind {
133; CHECK-LABEL: test_urem_even_bit31:
134; CHECK:       // %bb.0:
135; CHECK-NEXT:    mov w8, #64251 // =0xfafb
136; CHECK-NEXT:    movk w8, #47866, lsl #16
137; CHECK-NEXT:    mul w8, w0, w8
138; CHECK-NEXT:    ror w8, w8, #1
139; CHECK-NEXT:    cmp w8, #2
140; CHECK-NEXT:    cset w0, lo
141; CHECK-NEXT:    ret
142  %urem = urem i32 %X, 2147483750
143  %cmp = icmp eq i32 %urem, 0
144  %ret = zext i1 %cmp to i32
145  ret i32 %ret
146}
147
148;------------------------------------------------------------------------------;
149; Special case
150;------------------------------------------------------------------------------;
151
152; 'NE' predicate is fine too.
153define i32 @test_urem_odd_setne(i32 %X) nounwind {
154; CHECK-LABEL: test_urem_odd_setne:
155; CHECK:       // %bb.0:
156; CHECK-NEXT:    mov w8, #52429 // =0xcccd
157; CHECK-NEXT:    mov w9, #858993459 // =0x33333333
158; CHECK-NEXT:    movk w8, #52428, lsl #16
159; CHECK-NEXT:    mul w8, w0, w8
160; CHECK-NEXT:    cmp w8, w9
161; CHECK-NEXT:    cset w0, hi
162; CHECK-NEXT:    ret
163  %urem = urem i32 %X, 5
164  %cmp = icmp ne i32 %urem, 0
165  %ret = zext i1 %cmp to i32
166  ret i32 %ret
167}
168
169; The fold is only valid for positive divisors, negative-ones should be negated.
170define i32 @test_urem_negative_odd(i32 %X) nounwind {
171; CHECK-LABEL: test_urem_negative_odd:
172; CHECK:       // %bb.0:
173; CHECK-NEXT:    mov w8, #858993459 // =0x33333333
174; CHECK-NEXT:    mul w8, w0, w8
175; CHECK-NEXT:    cmp w8, #1
176; CHECK-NEXT:    cset w0, hi
177; CHECK-NEXT:    ret
178  %urem = urem i32 %X, -5
179  %cmp = icmp ne i32 %urem, 0
180  %ret = zext i1 %cmp to i32
181  ret i32 %ret
182}
183define i32 @test_urem_negative_even(i32 %X) nounwind {
184; CHECK-LABEL: test_urem_negative_even:
185; CHECK:       // %bb.0:
186; CHECK-NEXT:    mov w8, #37449 // =0x9249
187; CHECK-NEXT:    movk w8, #51492, lsl #16
188; CHECK-NEXT:    mul w8, w0, w8
189; CHECK-NEXT:    ror w8, w8, #1
190; CHECK-NEXT:    cmp w8, #1
191; CHECK-NEXT:    cset w0, hi
192; CHECK-NEXT:    ret
193  %urem = urem i32 %X, -14
194  %cmp = icmp ne i32 %urem, 0
195  %ret = zext i1 %cmp to i32
196  ret i32 %ret
197}
198
199;------------------------------------------------------------------------------;
200; Negative tests
201;------------------------------------------------------------------------------;
202
203; We can lower remainder of division by one much better elsewhere.
204define i32 @test_urem_one(i32 %X) nounwind {
205; CHECK-LABEL: test_urem_one:
206; CHECK:       // %bb.0:
207; CHECK-NEXT:    mov w0, #1 // =0x1
208; CHECK-NEXT:    ret
209  %urem = urem i32 %X, 1
210  %cmp = icmp eq i32 %urem, 0
211  %ret = zext i1 %cmp to i32
212  ret i32 %ret
213}
214
215; We can lower remainder of division by powers of two much better elsewhere.
216define i32 @test_urem_pow2(i32 %X) nounwind {
217; CHECK-LABEL: test_urem_pow2:
218; CHECK:       // %bb.0:
219; CHECK-NEXT:    tst w0, #0xf
220; CHECK-NEXT:    cset w0, eq
221; CHECK-NEXT:    ret
222  %urem = urem i32 %X, 16
223  %cmp = icmp eq i32 %urem, 0
224  %ret = zext i1 %cmp to i32
225  ret i32 %ret
226}
227
228; The fold is only valid for positive divisors, and we can't negate INT_MIN.
229define i32 @test_urem_int_min(i32 %X) nounwind {
230; CHECK-LABEL: test_urem_int_min:
231; CHECK:       // %bb.0:
232; CHECK-NEXT:    tst w0, #0x7fffffff
233; CHECK-NEXT:    cset w0, eq
234; CHECK-NEXT:    ret
235  %urem = urem i32 %X, 2147483648
236  %cmp = icmp eq i32 %urem, 0
237  %ret = zext i1 %cmp to i32
238  ret i32 %ret
239}
240
241; We can lower remainder of division by all-ones much better elsewhere.
242define i32 @test_urem_allones(i32 %X) nounwind {
243; CHECK-LABEL: test_urem_allones:
244; CHECK:       // %bb.0:
245; CHECK-NEXT:    neg w8, w0
246; CHECK-NEXT:    cmp w8, #2
247; CHECK-NEXT:    cset w0, lo
248; CHECK-NEXT:    ret
249  %urem = urem i32 %X, 4294967295
250  %cmp = icmp eq i32 %urem, 0
251  %ret = zext i1 %cmp to i32
252  ret i32 %ret
253}
254