xref: /llvm-project/llvm/test/CodeGen/X86/srem-seteq.ll (revision 59fa435ea66629b4c45d9e6b62fa6cc1cdf5d5aa)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+cmov < %s | FileCheck %s --check-prefixes=CHECK,X86
3; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,X64
4
5;------------------------------------------------------------------------------;
6; Odd divisors
7;------------------------------------------------------------------------------;
8
9define i32 @test_srem_odd(i32 %X) nounwind {
10; X86-LABEL: test_srem_odd:
11; X86:       # %bb.0:
12; X86-NEXT:    imull $-858993459, {{[0-9]+}}(%esp), %ecx # imm = 0xCCCCCCCD
13; X86-NEXT:    addl $429496729, %ecx # imm = 0x19999999
14; X86-NEXT:    xorl %eax, %eax
15; X86-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
16; X86-NEXT:    setb %al
17; X86-NEXT:    retl
18;
19; X64-LABEL: test_srem_odd:
20; X64:       # %bb.0:
21; X64-NEXT:    imull $-858993459, %edi, %ecx # imm = 0xCCCCCCCD
22; X64-NEXT:    addl $429496729, %ecx # imm = 0x19999999
23; X64-NEXT:    xorl %eax, %eax
24; X64-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
25; X64-NEXT:    setb %al
26; X64-NEXT:    retq
27  %srem = srem i32 %X, 5
28  %cmp = icmp eq i32 %srem, 0
29  %ret = zext i1 %cmp to i32
30  ret i32 %ret
31}
32
33define i32 @test_srem_odd_25(i32 %X) nounwind {
34; X86-LABEL: test_srem_odd_25:
35; X86:       # %bb.0:
36; X86-NEXT:    imull $-1030792151, {{[0-9]+}}(%esp), %ecx # imm = 0xC28F5C29
37; X86-NEXT:    addl $85899345, %ecx # imm = 0x51EB851
38; X86-NEXT:    xorl %eax, %eax
39; X86-NEXT:    cmpl $171798691, %ecx # imm = 0xA3D70A3
40; X86-NEXT:    setb %al
41; X86-NEXT:    retl
42;
43; X64-LABEL: test_srem_odd_25:
44; X64:       # %bb.0:
45; X64-NEXT:    imull $-1030792151, %edi, %ecx # imm = 0xC28F5C29
46; X64-NEXT:    addl $85899345, %ecx # imm = 0x51EB851
47; X64-NEXT:    xorl %eax, %eax
48; X64-NEXT:    cmpl $171798691, %ecx # imm = 0xA3D70A3
49; X64-NEXT:    setb %al
50; X64-NEXT:    retq
51  %srem = srem i32 %X, 25
52  %cmp = icmp eq i32 %srem, 0
53  %ret = zext i1 %cmp to i32
54  ret i32 %ret
55}
56
57; This is like test_srem_odd, except the divisor has bit 30 set.
58define i32 @test_srem_odd_bit30(i32 %X) nounwind {
59; X86-LABEL: test_srem_odd_bit30:
60; X86:       # %bb.0:
61; X86-NEXT:    imull $1789569707, {{[0-9]+}}(%esp), %ecx # imm = 0x6AAAAAAB
62; X86-NEXT:    incl %ecx
63; X86-NEXT:    xorl %eax, %eax
64; X86-NEXT:    cmpl $3, %ecx
65; X86-NEXT:    setb %al
66; X86-NEXT:    retl
67;
68; X64-LABEL: test_srem_odd_bit30:
69; X64:       # %bb.0:
70; X64-NEXT:    imull $1789569707, %edi, %ecx # imm = 0x6AAAAAAB
71; X64-NEXT:    incl %ecx
72; X64-NEXT:    xorl %eax, %eax
73; X64-NEXT:    cmpl $3, %ecx
74; X64-NEXT:    setb %al
75; X64-NEXT:    retq
76  %srem = srem i32 %X, 1073741827
77  %cmp = icmp eq i32 %srem, 0
78  %ret = zext i1 %cmp to i32
79  ret i32 %ret
80}
81
82; This is like test_srem_odd, except the divisor has bit 31 set.
83define i32 @test_srem_odd_bit31(i32 %X) nounwind {
84; X86-LABEL: test_srem_odd_bit31:
85; X86:       # %bb.0:
86; X86-NEXT:    imull $-715827883, {{[0-9]+}}(%esp), %ecx # imm = 0xD5555555
87; X86-NEXT:    incl %ecx
88; X86-NEXT:    xorl %eax, %eax
89; X86-NEXT:    cmpl $3, %ecx
90; X86-NEXT:    setb %al
91; X86-NEXT:    retl
92;
93; X64-LABEL: test_srem_odd_bit31:
94; X64:       # %bb.0:
95; X64-NEXT:    imull $-715827883, %edi, %ecx # imm = 0xD5555555
96; X64-NEXT:    incl %ecx
97; X64-NEXT:    xorl %eax, %eax
98; X64-NEXT:    cmpl $3, %ecx
99; X64-NEXT:    setb %al
100; X64-NEXT:    retq
101  %srem = srem i32 %X, 2147483651
102  %cmp = icmp eq i32 %srem, 0
103  %ret = zext i1 %cmp to i32
104  ret i32 %ret
105}
106
107;------------------------------------------------------------------------------;
108; Even divisors
109;------------------------------------------------------------------------------;
110
111define i16 @test_srem_even(i16 %X) nounwind {
112; X86-LABEL: test_srem_even:
113; X86:       # %bb.0:
114; X86-NEXT:    imull $28087, {{[0-9]+}}(%esp), %eax # imm = 0x6DB7
115; X86-NEXT:    addl $4680, %eax # imm = 0x1248
116; X86-NEXT:    rorw %ax
117; X86-NEXT:    movzwl %ax, %ecx
118; X86-NEXT:    xorl %eax, %eax
119; X86-NEXT:    cmpl $4681, %ecx # imm = 0x1249
120; X86-NEXT:    setae %al
121; X86-NEXT:    # kill: def $ax killed $ax killed $eax
122; X86-NEXT:    retl
123;
124; X64-LABEL: test_srem_even:
125; X64:       # %bb.0:
126; X64-NEXT:    imull $28087, %edi, %eax # imm = 0x6DB7
127; X64-NEXT:    addl $4680, %eax # imm = 0x1248
128; X64-NEXT:    rorw %ax
129; X64-NEXT:    movzwl %ax, %ecx
130; X64-NEXT:    xorl %eax, %eax
131; X64-NEXT:    cmpl $4681, %ecx # imm = 0x1249
132; X64-NEXT:    setae %al
133; X64-NEXT:    # kill: def $ax killed $ax killed $eax
134; X64-NEXT:    retq
135  %srem = srem i16 %X, 14
136  %cmp = icmp ne i16 %srem, 0
137  %ret = zext i1 %cmp to i16
138  ret i16 %ret
139}
140
141define i32 @test_srem_even_100(i32 %X) nounwind {
142; X86-LABEL: test_srem_even_100:
143; X86:       # %bb.0:
144; X86-NEXT:    imull $-1030792151, {{[0-9]+}}(%esp), %ecx # imm = 0xC28F5C29
145; X86-NEXT:    addl $85899344, %ecx # imm = 0x51EB850
146; X86-NEXT:    rorl $2, %ecx
147; X86-NEXT:    xorl %eax, %eax
148; X86-NEXT:    cmpl $42949673, %ecx # imm = 0x28F5C29
149; X86-NEXT:    setb %al
150; X86-NEXT:    retl
151;
152; X64-LABEL: test_srem_even_100:
153; X64:       # %bb.0:
154; X64-NEXT:    imull $-1030792151, %edi, %ecx # imm = 0xC28F5C29
155; X64-NEXT:    addl $85899344, %ecx # imm = 0x51EB850
156; X64-NEXT:    rorl $2, %ecx
157; X64-NEXT:    xorl %eax, %eax
158; X64-NEXT:    cmpl $42949673, %ecx # imm = 0x28F5C29
159; X64-NEXT:    setb %al
160; X64-NEXT:    retq
161  %srem = srem i32 %X, 100
162  %cmp = icmp eq i32 %srem, 0
163  %ret = zext i1 %cmp to i32
164  ret i32 %ret
165}
166
167; This is like test_srem_even, except the divisor has bit 30 set.
168define i32 @test_srem_even_bit30(i32 %X) nounwind {
169; X86-LABEL: test_srem_even_bit30:
170; X86:       # %bb.0:
171; X86-NEXT:    imull $-51622203, {{[0-9]+}}(%esp), %ecx # imm = 0xFCEC4EC5
172; X86-NEXT:    addl $8, %ecx
173; X86-NEXT:    rorl $3, %ecx
174; X86-NEXT:    xorl %eax, %eax
175; X86-NEXT:    cmpl $3, %ecx
176; X86-NEXT:    setb %al
177; X86-NEXT:    retl
178;
179; X64-LABEL: test_srem_even_bit30:
180; X64:       # %bb.0:
181; X64-NEXT:    imull $-51622203, %edi, %ecx # imm = 0xFCEC4EC5
182; X64-NEXT:    addl $8, %ecx
183; X64-NEXT:    rorl $3, %ecx
184; X64-NEXT:    xorl %eax, %eax
185; X64-NEXT:    cmpl $3, %ecx
186; X64-NEXT:    setb %al
187; X64-NEXT:    retq
188  %srem = srem i32 %X, 1073741928
189  %cmp = icmp eq i32 %srem, 0
190  %ret = zext i1 %cmp to i32
191  ret i32 %ret
192}
193
194; This is like test_srem_odd, except the divisor has bit 31 set.
195define i32 @test_srem_even_bit31(i32 %X) nounwind {
196; X86-LABEL: test_srem_even_bit31:
197; X86:       # %bb.0:
198; X86-NEXT:    imull $-989526779, {{[0-9]+}}(%esp), %ecx # imm = 0xC5050505
199; X86-NEXT:    addl $2, %ecx
200; X86-NEXT:    rorl %ecx
201; X86-NEXT:    xorl %eax, %eax
202; X86-NEXT:    cmpl $3, %ecx
203; X86-NEXT:    setb %al
204; X86-NEXT:    retl
205;
206; X64-LABEL: test_srem_even_bit31:
207; X64:       # %bb.0:
208; X64-NEXT:    imull $-989526779, %edi, %ecx # imm = 0xC5050505
209; X64-NEXT:    addl $2, %ecx
210; X64-NEXT:    rorl %ecx
211; X64-NEXT:    xorl %eax, %eax
212; X64-NEXT:    cmpl $3, %ecx
213; X64-NEXT:    setb %al
214; X64-NEXT:    retq
215  %srem = srem i32 %X, 2147483750
216  %cmp = icmp eq i32 %srem, 0
217  %ret = zext i1 %cmp to i32
218  ret i32 %ret
219}
220
221;------------------------------------------------------------------------------;
222; Special case
223;------------------------------------------------------------------------------;
224
225; 'NE' predicate is fine too.
226define i32 @test_srem_odd_setne(i32 %X) nounwind {
227; X86-LABEL: test_srem_odd_setne:
228; X86:       # %bb.0:
229; X86-NEXT:    imull $-858993459, {{[0-9]+}}(%esp), %ecx # imm = 0xCCCCCCCD
230; X86-NEXT:    addl $429496729, %ecx # imm = 0x19999999
231; X86-NEXT:    xorl %eax, %eax
232; X86-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
233; X86-NEXT:    setae %al
234; X86-NEXT:    retl
235;
236; X64-LABEL: test_srem_odd_setne:
237; X64:       # %bb.0:
238; X64-NEXT:    imull $-858993459, %edi, %ecx # imm = 0xCCCCCCCD
239; X64-NEXT:    addl $429496729, %ecx # imm = 0x19999999
240; X64-NEXT:    xorl %eax, %eax
241; X64-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
242; X64-NEXT:    setae %al
243; X64-NEXT:    retq
244  %srem = srem i32 %X, 5
245  %cmp = icmp ne i32 %srem, 0
246  %ret = zext i1 %cmp to i32
247  ret i32 %ret
248}
249
250; The fold is only valid for positive divisors, negative-ones should be negated.
251define i32 @test_srem_negative_odd(i32 %X) nounwind {
252; X86-LABEL: test_srem_negative_odd:
253; X86:       # %bb.0:
254; X86-NEXT:    imull $-858993459, {{[0-9]+}}(%esp), %ecx # imm = 0xCCCCCCCD
255; X86-NEXT:    addl $429496729, %ecx # imm = 0x19999999
256; X86-NEXT:    xorl %eax, %eax
257; X86-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
258; X86-NEXT:    setae %al
259; X86-NEXT:    retl
260;
261; X64-LABEL: test_srem_negative_odd:
262; X64:       # %bb.0:
263; X64-NEXT:    imull $-858993459, %edi, %ecx # imm = 0xCCCCCCCD
264; X64-NEXT:    addl $429496729, %ecx # imm = 0x19999999
265; X64-NEXT:    xorl %eax, %eax
266; X64-NEXT:    cmpl $858993459, %ecx # imm = 0x33333333
267; X64-NEXT:    setae %al
268; X64-NEXT:    retq
269  %srem = srem i32 %X, -5
270  %cmp = icmp ne i32 %srem, 0
271  %ret = zext i1 %cmp to i32
272  ret i32 %ret
273}
274define i32 @test_srem_negative_even(i32 %X) nounwind {
275; X86-LABEL: test_srem_negative_even:
276; X86:       # %bb.0:
277; X86-NEXT:    imull $-1227133513, {{[0-9]+}}(%esp), %ecx # imm = 0xB6DB6DB7
278; X86-NEXT:    addl $306783378, %ecx # imm = 0x12492492
279; X86-NEXT:    rorl %ecx
280; X86-NEXT:    xorl %eax, %eax
281; X86-NEXT:    cmpl $306783379, %ecx # imm = 0x12492493
282; X86-NEXT:    setae %al
283; X86-NEXT:    retl
284;
285; X64-LABEL: test_srem_negative_even:
286; X64:       # %bb.0:
287; X64-NEXT:    imull $-1227133513, %edi, %ecx # imm = 0xB6DB6DB7
288; X64-NEXT:    addl $306783378, %ecx # imm = 0x12492492
289; X64-NEXT:    rorl %ecx
290; X64-NEXT:    xorl %eax, %eax
291; X64-NEXT:    cmpl $306783379, %ecx # imm = 0x12492493
292; X64-NEXT:    setae %al
293; X64-NEXT:    retq
294  %srem = srem i32 %X, -14
295  %cmp = icmp ne i32 %srem, 0
296  %ret = zext i1 %cmp to i32
297  ret i32 %ret
298}
299
300;------------------------------------------------------------------------------;
301; Negative tests
302;------------------------------------------------------------------------------;
303
304; We can lower remainder of division by one much better elsewhere.
305define i32 @test_srem_one(i32 %X) nounwind {
306; CHECK-LABEL: test_srem_one:
307; CHECK:       # %bb.0:
308; CHECK-NEXT:    movl $1, %eax
309; CHECK-NEXT:    ret{{[l|q]}}
310  %srem = srem i32 %X, 1
311  %cmp = icmp eq i32 %srem, 0
312  %ret = zext i1 %cmp to i32
313  ret i32 %ret
314}
315
316; We can lower remainder of division by powers of two much better elsewhere.
317define i32 @test_srem_pow2(i32 %X) nounwind {
318; X86-LABEL: test_srem_pow2:
319; X86:       # %bb.0:
320; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
321; X86-NEXT:    leal 15(%ecx), %edx
322; X86-NEXT:    testl %ecx, %ecx
323; X86-NEXT:    cmovnsl %ecx, %edx
324; X86-NEXT:    andl $-16, %edx
325; X86-NEXT:    xorl %eax, %eax
326; X86-NEXT:    cmpl %edx, %ecx
327; X86-NEXT:    sete %al
328; X86-NEXT:    retl
329;
330; X64-LABEL: test_srem_pow2:
331; X64:       # %bb.0:
332; X64-NEXT:    # kill: def $edi killed $edi def $rdi
333; X64-NEXT:    leal 15(%rdi), %ecx
334; X64-NEXT:    testl %edi, %edi
335; X64-NEXT:    cmovnsl %edi, %ecx
336; X64-NEXT:    andl $-16, %ecx
337; X64-NEXT:    xorl %eax, %eax
338; X64-NEXT:    cmpl %ecx, %edi
339; X64-NEXT:    sete %al
340; X64-NEXT:    retq
341  %srem = srem i32 %X, 16
342  %cmp = icmp eq i32 %srem, 0
343  %ret = zext i1 %cmp to i32
344  ret i32 %ret
345}
346
347; The fold is only valid for positive divisors, and we can't negate INT_MIN.
348define i32 @test_srem_int_min(i32 %X) nounwind {
349; X86-LABEL: test_srem_int_min:
350; X86:       # %bb.0:
351; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
352; X86-NEXT:    leal 2147483647(%ecx), %edx
353; X86-NEXT:    testl %ecx, %ecx
354; X86-NEXT:    cmovnsl %ecx, %edx
355; X86-NEXT:    andl $-2147483648, %edx # imm = 0x80000000
356; X86-NEXT:    xorl %eax, %eax
357; X86-NEXT:    addl %ecx, %edx
358; X86-NEXT:    sete %al
359; X86-NEXT:    retl
360;
361; X64-LABEL: test_srem_int_min:
362; X64:       # %bb.0:
363; X64-NEXT:    # kill: def $edi killed $edi def $rdi
364; X64-NEXT:    leal 2147483647(%rdi), %ecx
365; X64-NEXT:    testl %edi, %edi
366; X64-NEXT:    cmovnsl %edi, %ecx
367; X64-NEXT:    andl $-2147483648, %ecx # imm = 0x80000000
368; X64-NEXT:    xorl %eax, %eax
369; X64-NEXT:    addl %edi, %ecx
370; X64-NEXT:    sete %al
371; X64-NEXT:    retq
372  %srem = srem i32 %X, 2147483648
373  %cmp = icmp eq i32 %srem, 0
374  %ret = zext i1 %cmp to i32
375  ret i32 %ret
376}
377
378; We can lower remainder of division by all-ones much better elsewhere.
379define i32 @test_srem_allones(i32 %X) nounwind {
380; CHECK-LABEL: test_srem_allones:
381; CHECK:       # %bb.0:
382; CHECK-NEXT:    movl $1, %eax
383; CHECK-NEXT:    ret{{[l|q]}}
384  %srem = srem i32 %X, 4294967295
385  %cmp = icmp eq i32 %srem, 0
386  %ret = zext i1 %cmp to i32
387  ret i32 %ret
388}
389