xref: /llvm-project/llvm/test/CodeGen/X86/shift-eflags.ll (revision d4a0154902fb9b0611ed857134b26a64a1d5ad1e)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
3
4; PR33879 - use shift eflags result when it won't cause stalls
5
6; ashr by constant - use sarl eflags result
7define i32 @ashr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
8; CHECK-LABEL: ashr_const:
9; CHECK:       # %bb.0:
10; CHECK-NEXT:    movl %edx, %eax
11; CHECK-NEXT:    sarl $14, %edi
12; CHECK-NEXT:    cmovnel %ecx, %eax
13; CHECK-NEXT:    retq
14  %s = ashr i32 %a0, 14
15  %c = icmp eq i32 %s, 0
16  %r = select i1 %c, i32 %a2, i32 %a3
17  ret i32 %r
18}
19
20; lshr by constant - simplify to test
21define i32 @lshr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
22; CHECK-LABEL: lshr_const:
23; CHECK:       # %bb.0:
24; CHECK-NEXT:    movl %edx, %eax
25; CHECK-NEXT:    testl $-16384, %edi # imm = 0xC000
26; CHECK-NEXT:    cmovnel %ecx, %eax
27; CHECK-NEXT:    retq
28  %s = lshr i32 %a0, 14
29  %c = icmp eq i32 %s, 0
30  %r = select i1 %c, i32 %a2, i32 %a3
31  ret i32 %r
32}
33
34; shl by constant - simplify to test
35define i32 @shl_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
36; CHECK-LABEL: shl_const:
37; CHECK:       # %bb.0:
38; CHECK-NEXT:    movl %edx, %eax
39; CHECK-NEXT:    testl $262143, %edi # imm = 0x3FFFF
40; CHECK-NEXT:    cmovnel %ecx, %eax
41; CHECK-NEXT:    retq
42  %s = shl i32 %a0, 14
43  %c = icmp eq i32 %s, 0
44  %r = select i1 %c, i32 %a2, i32 %a3
45  ret i32 %r
46}
47
48; ashr by constant and using shift result - use sarl eflags result
49define i32 @ashr_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
50; CHECK-LABEL: ashr_const_self_select:
51; CHECK:       # %bb.0:
52; CHECK-NEXT:    movl %edi, %eax
53; CHECK-NEXT:    sarl $14, %eax
54; CHECK-NEXT:    cmovnel %edx, %eax
55; CHECK-NEXT:    retq
56  %s = ashr i32 %a0, 14
57  %c = icmp eq i32 %s, 0
58  %r = select i1 %c, i32 %s, i32 %a2
59  ret i32 %r
60}
61
62; lshr by constant and using shift result - use shrl eflags result
63define i32 @lshr_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
64; CHECK-LABEL: lshr_const_self_select:
65; CHECK:       # %bb.0:
66; CHECK-NEXT:    movl %edi, %eax
67; CHECK-NEXT:    shrl $14, %eax
68; CHECK-NEXT:    cmovnel %edx, %eax
69; CHECK-NEXT:    retq
70  %s = lshr i32 %a0, 14
71  %c = icmp eq i32 %s, 0
72  %r = select i1 %c, i32 %s, i32 %a2
73  ret i32 %r
74}
75
76; lshr by constant and using result - use shll eflags result
77define i32 @shl_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
78; CHECK-LABEL: shl_const_self_select:
79; CHECK:       # %bb.0:
80; CHECK-NEXT:    movl %edi, %eax
81; CHECK-NEXT:    shll $14, %eax
82; CHECK-NEXT:    cmovnel %edx, %eax
83; CHECK-NEXT:    retq
84  %s = shl i32 %a0, 14
85  %c = icmp eq i32 %s, 0
86  %r = select i1 %c, i32 %s, i32 %a2
87  ret i32 %r
88}
89
90; ashr by 1 - use sarl eflags result
91define i32 @ashr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
92; CHECK-LABEL: ashr_const1:
93; CHECK:       # %bb.0:
94; CHECK-NEXT:    movl %edx, %eax
95; CHECK-NEXT:    sarl %edi
96; CHECK-NEXT:    cmovnel %ecx, %eax
97; CHECK-NEXT:    retq
98  %s = ashr i32 %a0, 1
99  %c = icmp eq i32 %s, 0
100  %r = select i1 %c, i32 %a2, i32 %a3
101  ret i32 %r
102}
103
104; lshr by 1 - simplify to test
105define i32 @lshr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
106; CHECK-LABEL: lshr_const1:
107; CHECK:       # %bb.0:
108; CHECK-NEXT:    movl %edx, %eax
109; CHECK-NEXT:    testl $-2, %edi
110; CHECK-NEXT:    cmovnel %ecx, %eax
111; CHECK-NEXT:    retq
112  %s = lshr i32 %a0, 1
113  %c = icmp eq i32 %s, 0
114  %r = select i1 %c, i32 %a2, i32 %a3
115  ret i32 %r
116}
117
118; shl by 1 - simplify to test
119define i32 @shl_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
120; CHECK-LABEL: shl_const1:
121; CHECK:       # %bb.0:
122; CHECK-NEXT:    movl %edx, %eax
123; CHECK-NEXT:    testl $2147483647, %edi # imm = 0x7FFFFFFF
124; CHECK-NEXT:    cmovnel %ecx, %eax
125; CHECK-NEXT:    retq
126  %s = shl i32 %a0, 1
127  %c = icmp eq i32 %s, 0
128  %r = select i1 %c, i32 %a2, i32 %a3
129  ret i32 %r
130}
131
132; ashr by 1 and using shift result - use sarl eflags result
133define i32 @ashr_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
134; CHECK-LABEL: ashr_const1_self_select:
135; CHECK:       # %bb.0:
136; CHECK-NEXT:    movl %edi, %eax
137; CHECK-NEXT:    sarl %eax
138; CHECK-NEXT:    cmovnel %edx, %eax
139; CHECK-NEXT:    retq
140  %s = ashr i32 %a0, 1
141  %c = icmp eq i32 %s, 0
142  %r = select i1 %c, i32 %s, i32 %a2
143  ret i32 %r
144}
145
146; lshr by 1 and using shift result - use shrl eflags result
147define i32 @lshr_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
148; CHECK-LABEL: lshr_const1_self_select:
149; CHECK:       # %bb.0:
150; CHECK-NEXT:    movl %edi, %eax
151; CHECK-NEXT:    shrl %eax
152; CHECK-NEXT:    cmovnel %edx, %eax
153; CHECK-NEXT:    retq
154  %s = lshr i32 %a0, 1
155  %c = icmp eq i32 %s, 0
156  %r = select i1 %c, i32 %s, i32 %a2
157  ret i32 %r
158}
159
160; lshr by 1 and using result - use addl eflags result
161define i32 @shl_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
162; CHECK-LABEL: shl_const1_self_select:
163; CHECK:       # %bb.0:
164; CHECK-NEXT:    movl %edi, %eax
165; CHECK-NEXT:    addl %edi, %eax
166; CHECK-NEXT:    cmovnel %edx, %eax
167; CHECK-NEXT:    retq
168  %s = shl i32 %a0, 1
169  %c = icmp eq i32 %s, 0
170  %r = select i1 %c, i32 %s, i32 %a2
171  ret i32 %r
172}
173
174; ashr by variable - use separate test
175define i32 @ashr_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
176; CHECK-LABEL: ashr_var:
177; CHECK:       # %bb.0:
178; CHECK-NEXT:    movl %ecx, %eax
179; CHECK-NEXT:    movl %esi, %ecx
180; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
181; CHECK-NEXT:    sarl %cl, %edi
182; CHECK-NEXT:    testl %edi, %edi
183; CHECK-NEXT:    cmovel %edx, %eax
184; CHECK-NEXT:    retq
185  %s = ashr i32 %a0, %a1
186  %c = icmp eq i32 %s, 0
187  %r = select i1 %c, i32 %a2, i32 %a3
188  ret i32 %r
189}
190
191; lshr by variable - use separate test
192define i32 @lshr_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
193; CHECK-LABEL: lshr_var:
194; CHECK:       # %bb.0:
195; CHECK-NEXT:    movl %ecx, %eax
196; CHECK-NEXT:    movl %esi, %ecx
197; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
198; CHECK-NEXT:    shrl %cl, %edi
199; CHECK-NEXT:    testl %edi, %edi
200; CHECK-NEXT:    cmovel %edx, %eax
201; CHECK-NEXT:    retq
202  %s = lshr i32 %a0, %a1
203  %c = icmp eq i32 %s, 0
204  %r = select i1 %c, i32 %a2, i32 %a3
205  ret i32 %r
206}
207
208; shl by variable - use separate test
209define i32 @shl_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
210; CHECK-LABEL: shl_var:
211; CHECK:       # %bb.0:
212; CHECK-NEXT:    movl %ecx, %eax
213; CHECK-NEXT:    movl %esi, %ecx
214; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
215; CHECK-NEXT:    shll %cl, %edi
216; CHECK-NEXT:    testl %edi, %edi
217; CHECK-NEXT:    cmovel %edx, %eax
218; CHECK-NEXT:    retq
219  %s = shl i32 %a0, %a1
220  %c = icmp eq i32 %s, 0
221  %r = select i1 %c, i32 %a2, i32 %a3
222  ret i32 %r
223}
224
225; ashr by variable and using result - use separate test
226define i32 @ashr_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
227; CHECK-LABEL: ashr_var_self_select:
228; CHECK:       # %bb.0:
229; CHECK-NEXT:    movl %esi, %ecx
230; CHECK-NEXT:    movl %edi, %eax
231; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
232; CHECK-NEXT:    sarl %cl, %eax
233; CHECK-NEXT:    testl %eax, %eax
234; CHECK-NEXT:    cmovnel %edx, %eax
235; CHECK-NEXT:    retq
236  %s = ashr i32 %a0, %a1
237  %c = icmp eq i32 %s, 0
238  %r = select i1 %c, i32 %s, i32 %a2
239  ret i32 %r
240}
241
242; lshr by variable and using result - use separate test
243define i32 @lshr_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
244; CHECK-LABEL: lshr_var_self_select:
245; CHECK:       # %bb.0:
246; CHECK-NEXT:    movl %esi, %ecx
247; CHECK-NEXT:    movl %edi, %eax
248; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
249; CHECK-NEXT:    shrl %cl, %eax
250; CHECK-NEXT:    testl %eax, %eax
251; CHECK-NEXT:    cmovnel %edx, %eax
252; CHECK-NEXT:    retq
253  %s = lshr i32 %a0, %a1
254  %c = icmp eq i32 %s, 0
255  %r = select i1 %c, i32 %s, i32 %a2
256  ret i32 %r
257}
258
259; shl by variable and using result - use separate test
260define i32 @shl_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
261; CHECK-LABEL: shl_var_self_select:
262; CHECK:       # %bb.0:
263; CHECK-NEXT:    movl %esi, %ecx
264; CHECK-NEXT:    movl %edi, %eax
265; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
266; CHECK-NEXT:    shll %cl, %eax
267; CHECK-NEXT:    testl %eax, %eax
268; CHECK-NEXT:    cmovnel %edx, %eax
269; CHECK-NEXT:    retq
270  %s = shl i32 %a0, %a1
271  %c = icmp eq i32 %s, 0
272  %r = select i1 %c, i32 %s, i32 %a2
273  ret i32 %r
274}
275
276; ashr by non-zero variable - use separate test
277define i32 @ashr_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
278; CHECK-LABEL: ashr_var_amt_never_zero:
279; CHECK:       # %bb.0:
280; CHECK-NEXT:    movl %ecx, %eax
281; CHECK-NEXT:    movl %esi, %ecx
282; CHECK-NEXT:    orb $1, %cl
283; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
284; CHECK-NEXT:    sarl %cl, %edi
285; CHECK-NEXT:    testl %edi, %edi
286; CHECK-NEXT:    cmovel %edx, %eax
287; CHECK-NEXT:    retq
288  %a = or i32 %a1, 1
289  %s = ashr i32 %a0, %a
290  %c = icmp eq i32 %s, 0
291  %r = select i1 %c, i32 %a2, i32 %a3
292  ret i32 %r
293}
294
295; lshr by non-zero variable - use separate test
296define i32 @lshr_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
297; CHECK-LABEL: lshr_var_amt_never_zero:
298; CHECK:       # %bb.0:
299; CHECK-NEXT:    movl %ecx, %eax
300; CHECK-NEXT:    movl %esi, %ecx
301; CHECK-NEXT:    orb $1, %cl
302; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
303; CHECK-NEXT:    shrl %cl, %edi
304; CHECK-NEXT:    testl %edi, %edi
305; CHECK-NEXT:    cmovel %edx, %eax
306; CHECK-NEXT:    retq
307  %a = or i32 %a1, 1
308  %s = lshr i32 %a0, %a
309  %c = icmp eq i32 %s, 0
310  %r = select i1 %c, i32 %a2, i32 %a3
311  ret i32 %r
312}
313
314; shl by non-zero variable - use separate test
315define i32 @shl_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
316; CHECK-LABEL: shl_var_amt_never_zero:
317; CHECK:       # %bb.0:
318; CHECK-NEXT:    movl %ecx, %eax
319; CHECK-NEXT:    movl %esi, %ecx
320; CHECK-NEXT:    orb $1, %cl
321; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
322; CHECK-NEXT:    shll %cl, %edi
323; CHECK-NEXT:    testl %edi, %edi
324; CHECK-NEXT:    cmovel %edx, %eax
325; CHECK-NEXT:    retq
326  %a = or i32 %a1, 1
327  %s = shl i32 %a0, %a
328  %c = icmp eq i32 %s, 0
329  %r = select i1 %c, i32 %a2, i32 %a3
330  ret i32 %r
331}
332
333; ashr by non-zero variable and using result - use separate test
334define i32 @ashr_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
335; CHECK-LABEL: ashr_var_self_select_amt_never_zero:
336; CHECK:       # %bb.0:
337; CHECK-NEXT:    movl %esi, %ecx
338; CHECK-NEXT:    movl %edi, %eax
339; CHECK-NEXT:    orb $1, %cl
340; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
341; CHECK-NEXT:    shrl %cl, %eax
342; CHECK-NEXT:    testl %eax, %eax
343; CHECK-NEXT:    cmovnel %edx, %eax
344; CHECK-NEXT:    retq
345  %a = or i32 %a1, 1
346  %s = lshr i32 %a0, %a
347  %c = icmp eq i32 %s, 0
348  %r = select i1 %c, i32 %s, i32 %a2
349  ret i32 %r
350}
351
352; lshr by non-zero variable and using result - use separate test
353define i32 @lshr_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
354; CHECK-LABEL: lshr_var_self_select_amt_never_zero:
355; CHECK:       # %bb.0:
356; CHECK-NEXT:    movl %esi, %ecx
357; CHECK-NEXT:    movl %edi, %eax
358; CHECK-NEXT:    orb $1, %cl
359; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
360; CHECK-NEXT:    shrl %cl, %eax
361; CHECK-NEXT:    testl %eax, %eax
362; CHECK-NEXT:    cmovnel %edx, %eax
363; CHECK-NEXT:    retq
364  %a = or i32 %a1, 1
365  %s = lshr i32 %a0, %a
366  %c = icmp eq i32 %s, 0
367  %r = select i1 %c, i32 %s, i32 %a2
368  ret i32 %r
369}
370
371; shl by non-zero variable and using result - use separate test
372define i32 @shl_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
373; CHECK-LABEL: shl_var_self_select_amt_never_zero:
374; CHECK:       # %bb.0:
375; CHECK-NEXT:    movl %esi, %ecx
376; CHECK-NEXT:    movl %edi, %eax
377; CHECK-NEXT:    orb $1, %cl
378; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
379; CHECK-NEXT:    shrl %cl, %eax
380; CHECK-NEXT:    testl %eax, %eax
381; CHECK-NEXT:    cmovnel %edx, %eax
382; CHECK-NEXT:    retq
383  %a = or i32 %a1, 1
384  %s = lshr i32 %a0, %a
385  %c = icmp eq i32 %s, 0
386  %r = select i1 %c, i32 %s, i32 %a2
387  ret i32 %r
388}
389