Skip to content

Commit 9405b67

Browse files
committed
[X86] Add test coverage for PR33879 (Issue llvm#33226)
Ensure we only use the eflags results from shift instructions when it won't cause stalls shift by variable causes stalls as it has to preserve eflags when the shift amount was zero, so we're better off using a separate test
1 parent 71a7192 commit 9405b67

File tree

1 file changed

+388
-0
lines changed

1 file changed

+388
-0
lines changed

llvm/test/CodeGen/X86/shift-eflags.ll

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
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
7+
define 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
21+
define 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
35+
define 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
49+
define 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
63+
define 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
77+
define 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
91+
define 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
105+
define 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
119+
define 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
133+
define 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
147+
define 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
161+
define 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 seperate test
175+
define 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 seperate test
192+
define 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 seperate test
209+
define 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 seperate test
226+
define 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 seperate test
243+
define 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 seperate test
260+
define 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 seperate test
277+
define 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 seperate test
296+
define 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 seperate test
315+
define 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 seperate test
334+
define 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 seperate test
353+
define 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 seperate test
372+
define 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+
}

0 commit comments

Comments
 (0)