Use Align for TFL::TransientStackAlignment
[llvm-core.git] / test / CodeGen / X86 / cmovcmov.ll
blobb27eccbb2cdbf91ff20d898650bfada03fcf674a
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=CHECK --check-prefix=CMOV
3 ; RUN: llc < %s -mtriple=i686-unknown-linux | FileCheck %s --check-prefix=CHECK --check-prefix=NOCMOV
5 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
7 ; Test 2xCMOV patterns exposed after legalization.
8 ; One way to do that is with (select (fcmp une/oeq)), which gets
9 ; legalized to setp/setne.
11 define i32 @test_select_fcmp_oeq_i32(float %a, float %b, i32 %c, i32 %d) nounwind {
12 ; CMOV-LABEL: test_select_fcmp_oeq_i32:
13 ; CMOV:       # %bb.0: # %entry
14 ; CMOV-NEXT:    movl %edi, %eax
15 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
16 ; CMOV-NEXT:    cmovnel %esi, %eax
17 ; CMOV-NEXT:    cmovpl %esi, %eax
18 ; CMOV-NEXT:    retq
20 ; NOCMOV-LABEL: test_select_fcmp_oeq_i32:
21 ; NOCMOV:       # %bb.0: # %entry
22 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
23 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
24 ; NOCMOV-NEXT:    fucompp
25 ; NOCMOV-NEXT:    fnstsw %ax
26 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
27 ; NOCMOV-NEXT:    sahf
28 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
29 ; NOCMOV-NEXT:    jne .LBB0_3
30 ; NOCMOV-NEXT:  # %bb.1: # %entry
31 ; NOCMOV-NEXT:    jp .LBB0_3
32 ; NOCMOV-NEXT:  # %bb.2: # %entry
33 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
34 ; NOCMOV-NEXT:  .LBB0_3: # %entry
35 ; NOCMOV-NEXT:    movl (%eax), %eax
36 ; NOCMOV-NEXT:    retl
37 entry:
38   %cmp = fcmp oeq float %a, %b
39   %r = select i1 %cmp, i32 %c, i32 %d
40   ret i32 %r
43 define i64 @test_select_fcmp_oeq_i64(float %a, float %b, i64 %c, i64 %d) nounwind {
44 ; CMOV-LABEL: test_select_fcmp_oeq_i64:
45 ; CMOV:       # %bb.0: # %entry
46 ; CMOV-NEXT:    movq %rdi, %rax
47 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
48 ; CMOV-NEXT:    cmovneq %rsi, %rax
49 ; CMOV-NEXT:    cmovpq %rsi, %rax
50 ; CMOV-NEXT:    retq
52 ; NOCMOV-LABEL: test_select_fcmp_oeq_i64:
53 ; NOCMOV:       # %bb.0: # %entry
54 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
55 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
56 ; NOCMOV-NEXT:    fucompp
57 ; NOCMOV-NEXT:    fnstsw %ax
58 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
59 ; NOCMOV-NEXT:    sahf
60 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %ecx
61 ; NOCMOV-NEXT:    jne .LBB1_3
62 ; NOCMOV-NEXT:  # %bb.1: # %entry
63 ; NOCMOV-NEXT:    jp .LBB1_3
64 ; NOCMOV-NEXT:  # %bb.2: # %entry
65 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %ecx
66 ; NOCMOV-NEXT:  .LBB1_3: # %entry
67 ; NOCMOV-NEXT:    movl (%ecx), %eax
68 ; NOCMOV-NEXT:    movl 4(%ecx), %edx
69 ; NOCMOV-NEXT:    retl
70 entry:
71   %cmp = fcmp oeq float %a, %b
72   %r = select i1 %cmp, i64 %c, i64 %d
73   ret i64 %r
76 define i64 @test_select_fcmp_une_i64(float %a, float %b, i64 %c, i64 %d) nounwind {
77 ; CMOV-LABEL: test_select_fcmp_une_i64:
78 ; CMOV:       # %bb.0: # %entry
79 ; CMOV-NEXT:    movq %rsi, %rax
80 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
81 ; CMOV-NEXT:    cmovneq %rdi, %rax
82 ; CMOV-NEXT:    cmovpq %rdi, %rax
83 ; CMOV-NEXT:    retq
85 ; NOCMOV-LABEL: test_select_fcmp_une_i64:
86 ; NOCMOV:       # %bb.0: # %entry
87 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
88 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
89 ; NOCMOV-NEXT:    fucompp
90 ; NOCMOV-NEXT:    fnstsw %ax
91 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
92 ; NOCMOV-NEXT:    sahf
93 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %ecx
94 ; NOCMOV-NEXT:    jne .LBB2_3
95 ; NOCMOV-NEXT:  # %bb.1: # %entry
96 ; NOCMOV-NEXT:    jp .LBB2_3
97 ; NOCMOV-NEXT:  # %bb.2: # %entry
98 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %ecx
99 ; NOCMOV-NEXT:  .LBB2_3: # %entry
100 ; NOCMOV-NEXT:    movl (%ecx), %eax
101 ; NOCMOV-NEXT:    movl 4(%ecx), %edx
102 ; NOCMOV-NEXT:    retl
103 entry:
104   %cmp = fcmp une float %a, %b
105   %r = select i1 %cmp, i64 %c, i64 %d
106   ret i64 %r
109 define double @test_select_fcmp_oeq_f64(float %a, float %b, double %c, double %d) nounwind {
110 ; CMOV-LABEL: test_select_fcmp_oeq_f64:
111 ; CMOV:       # %bb.0: # %entry
112 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
113 ; CMOV-NEXT:    jne .LBB3_3
114 ; CMOV-NEXT:  # %bb.1: # %entry
115 ; CMOV-NEXT:    jp .LBB3_3
116 ; CMOV-NEXT:  # %bb.2: # %entry
117 ; CMOV-NEXT:    movaps %xmm2, %xmm3
118 ; CMOV-NEXT:  .LBB3_3: # %entry
119 ; CMOV-NEXT:    movaps %xmm3, %xmm0
120 ; CMOV-NEXT:    retq
122 ; NOCMOV-LABEL: test_select_fcmp_oeq_f64:
123 ; NOCMOV:       # %bb.0: # %entry
124 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
125 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
126 ; NOCMOV-NEXT:    fucompp
127 ; NOCMOV-NEXT:    fnstsw %ax
128 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
129 ; NOCMOV-NEXT:    sahf
130 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
131 ; NOCMOV-NEXT:    jne .LBB3_3
132 ; NOCMOV-NEXT:  # %bb.1: # %entry
133 ; NOCMOV-NEXT:    jp .LBB3_3
134 ; NOCMOV-NEXT:  # %bb.2: # %entry
135 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
136 ; NOCMOV-NEXT:  .LBB3_3: # %entry
137 ; NOCMOV-NEXT:    fldl (%eax)
138 ; NOCMOV-NEXT:    retl
139 entry:
140   %cmp = fcmp oeq float %a, %b
141   %r = select i1 %cmp, double %c, double %d
142   ret double %r
145 define <4 x i32> @test_select_fcmp_oeq_v4i32(float %a, float %b, <4 x i32> %c, <4 x i32> %d) nounwind {
146 ; CMOV-LABEL: test_select_fcmp_oeq_v4i32:
147 ; CMOV:       # %bb.0: # %entry
148 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
149 ; CMOV-NEXT:    jne .LBB4_3
150 ; CMOV-NEXT:  # %bb.1: # %entry
151 ; CMOV-NEXT:    jp .LBB4_3
152 ; CMOV-NEXT:  # %bb.2: # %entry
153 ; CMOV-NEXT:    movaps %xmm2, %xmm3
154 ; CMOV-NEXT:  .LBB4_3: # %entry
155 ; CMOV-NEXT:    movaps %xmm3, %xmm0
156 ; CMOV-NEXT:    retq
158 ; NOCMOV-LABEL: test_select_fcmp_oeq_v4i32:
159 ; NOCMOV:       # %bb.0: # %entry
160 ; NOCMOV-NEXT:    pushl %edi
161 ; NOCMOV-NEXT:    pushl %esi
162 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
163 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
164 ; NOCMOV-NEXT:    fucompp
165 ; NOCMOV-NEXT:    fnstsw %ax
166 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
167 ; NOCMOV-NEXT:    sahf
168 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
169 ; NOCMOV-NEXT:    jne .LBB4_3
170 ; NOCMOV-NEXT:  # %bb.1: # %entry
171 ; NOCMOV-NEXT:    jp .LBB4_3
172 ; NOCMOV-NEXT:  # %bb.2: # %entry
173 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %eax
174 ; NOCMOV-NEXT:  .LBB4_3: # %entry
175 ; NOCMOV-NEXT:    movl (%eax), %ecx
176 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %edx
177 ; NOCMOV-NEXT:    jne .LBB4_6
178 ; NOCMOV-NEXT:  # %bb.4: # %entry
179 ; NOCMOV-NEXT:    jp .LBB4_6
180 ; NOCMOV-NEXT:  # %bb.5: # %entry
181 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %edx
182 ; NOCMOV-NEXT:  .LBB4_6: # %entry
183 ; NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
184 ; NOCMOV-NEXT:    movl (%edx), %edx
185 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %esi
186 ; NOCMOV-NEXT:    jne .LBB4_9
187 ; NOCMOV-NEXT:  # %bb.7: # %entry
188 ; NOCMOV-NEXT:    jp .LBB4_9
189 ; NOCMOV-NEXT:  # %bb.8: # %entry
190 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %esi
191 ; NOCMOV-NEXT:  .LBB4_9: # %entry
192 ; NOCMOV-NEXT:    movl (%esi), %esi
193 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %edi
194 ; NOCMOV-NEXT:    jne .LBB4_12
195 ; NOCMOV-NEXT:  # %bb.10: # %entry
196 ; NOCMOV-NEXT:    jp .LBB4_12
197 ; NOCMOV-NEXT:  # %bb.11: # %entry
198 ; NOCMOV-NEXT:    leal {{[0-9]+}}(%esp), %edi
199 ; NOCMOV-NEXT:  .LBB4_12: # %entry
200 ; NOCMOV-NEXT:    movl (%edi), %edi
201 ; NOCMOV-NEXT:    movl %edi, 12(%eax)
202 ; NOCMOV-NEXT:    movl %esi, 8(%eax)
203 ; NOCMOV-NEXT:    movl %edx, 4(%eax)
204 ; NOCMOV-NEXT:    movl %ecx, (%eax)
205 ; NOCMOV-NEXT:    popl %esi
206 ; NOCMOV-NEXT:    popl %edi
207 ; NOCMOV-NEXT:    retl $4
208 entry:
209   %cmp = fcmp oeq float %a, %b
210   %r = select i1 %cmp, <4 x i32> %c, <4 x i32> %d
211   ret <4 x i32> %r
214 ; Also make sure we catch the original code-sequence of interest:
216 define float @test_zext_fcmp_une(float %a, float %b) nounwind {
217 ; CMOV-LABEL: test_zext_fcmp_une:
218 ; CMOV:       # %bb.0: # %entry
219 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
220 ; CMOV-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
221 ; CMOV-NEXT:    jne .LBB5_3
222 ; CMOV-NEXT:  # %bb.1: # %entry
223 ; CMOV-NEXT:    jp .LBB5_3
224 ; CMOV-NEXT:  # %bb.2: # %entry
225 ; CMOV-NEXT:    xorps %xmm0, %xmm0
226 ; CMOV-NEXT:  .LBB5_3: # %entry
227 ; CMOV-NEXT:    retq
229 ; NOCMOV-LABEL: test_zext_fcmp_une:
230 ; NOCMOV:       # %bb.0: # %entry
231 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
232 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
233 ; NOCMOV-NEXT:    fucompp
234 ; NOCMOV-NEXT:    fnstsw %ax
235 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
236 ; NOCMOV-NEXT:    sahf
237 ; NOCMOV-NEXT:    fld1
238 ; NOCMOV-NEXT:    fldz
239 ; NOCMOV-NEXT:    jne .LBB5_1
240 ; NOCMOV-NEXT:  # %bb.2: # %entry
241 ; NOCMOV-NEXT:    jp .LBB5_5
242 ; NOCMOV-NEXT:  # %bb.3: # %entry
243 ; NOCMOV-NEXT:    fstp %st(1)
244 ; NOCMOV-NEXT:    jmp .LBB5_4
245 ; NOCMOV-NEXT:  .LBB5_1:
246 ; NOCMOV-NEXT:    fstp %st(0)
247 ; NOCMOV-NEXT:  .LBB5_4: # %entry
248 ; NOCMOV-NEXT:    fldz
249 ; NOCMOV-NEXT:  .LBB5_5: # %entry
250 ; NOCMOV-NEXT:    fstp %st(0)
251 ; NOCMOV-NEXT:    retl
252 entry:
253   %cmp = fcmp une float %a, %b
254   %conv1 = zext i1 %cmp to i32
255   %conv2 = sitofp i32 %conv1 to float
256   ret float %conv2
259 define float @test_zext_fcmp_oeq(float %a, float %b) nounwind {
260 ; CMOV-LABEL: test_zext_fcmp_oeq:
261 ; CMOV:       # %bb.0: # %entry
262 ; CMOV-NEXT:    ucomiss %xmm1, %xmm0
263 ; CMOV-NEXT:    xorps %xmm0, %xmm0
264 ; CMOV-NEXT:    jne .LBB6_3
265 ; CMOV-NEXT:  # %bb.1: # %entry
266 ; CMOV-NEXT:    jp .LBB6_3
267 ; CMOV-NEXT:  # %bb.2: # %entry
268 ; CMOV-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
269 ; CMOV-NEXT:  .LBB6_3: # %entry
270 ; CMOV-NEXT:    retq
272 ; NOCMOV-LABEL: test_zext_fcmp_oeq:
273 ; NOCMOV:       # %bb.0: # %entry
274 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
275 ; NOCMOV-NEXT:    flds {{[0-9]+}}(%esp)
276 ; NOCMOV-NEXT:    fucompp
277 ; NOCMOV-NEXT:    fnstsw %ax
278 ; NOCMOV-NEXT:    # kill: def $ah killed $ah killed $ax
279 ; NOCMOV-NEXT:    sahf
280 ; NOCMOV-NEXT:    fldz
281 ; NOCMOV-NEXT:    fld1
282 ; NOCMOV-NEXT:    jne .LBB6_1
283 ; NOCMOV-NEXT:  # %bb.2: # %entry
284 ; NOCMOV-NEXT:    jp .LBB6_5
285 ; NOCMOV-NEXT:  # %bb.3: # %entry
286 ; NOCMOV-NEXT:    fstp %st(1)
287 ; NOCMOV-NEXT:    jmp .LBB6_4
288 ; NOCMOV-NEXT:  .LBB6_1:
289 ; NOCMOV-NEXT:    fstp %st(0)
290 ; NOCMOV-NEXT:  .LBB6_4: # %entry
291 ; NOCMOV-NEXT:    fldz
292 ; NOCMOV-NEXT:  .LBB6_5: # %entry
293 ; NOCMOV-NEXT:    fstp %st(0)
294 ; NOCMOV-NEXT:    retl
295 entry:
296   %cmp = fcmp oeq float %a, %b
297   %conv1 = zext i1 %cmp to i32
298   %conv2 = sitofp i32 %conv1 to float
299   ret float %conv2
302 attributes #0 = { nounwind }
304 @g8 = global i8 0
306 ; The following test failed because llvm had a bug where a structure like:
308 ; %12 = CMOV_GR8 %7, %11 ... (lt)
309 ; %13 = CMOV_GR8 %12, %11 ... (gt)
311 ; was lowered to:
313 ; The first two cmovs got expanded to:
314 ; %bb.0:
315 ;   JCC_1 %bb.9, 12
316 ; %bb.7:
317 ;   JCC_1 %bb.9, 15
318 ; %bb.8:
319 ; %bb.9:
320 ;   %12 = phi(%7, %bb.8, %11, %bb.0, %12, %bb.7)
321 ;   %13 = COPY %12
322 ; Which was invalid as %12 is not the same value as %13
324 define void @no_cascade_opt(i32 %v0, i32 %v1, i32 %v2, i32 %v3) nounwind {
325 ; CMOV-LABEL: no_cascade_opt:
326 ; CMOV:       # %bb.0: # %entry
327 ; CMOV-NEXT:    cmpl %edx, %esi
328 ; CMOV-NEXT:    movl $20, %eax
329 ; CMOV-NEXT:    cmovll %eax, %ecx
330 ; CMOV-NEXT:    cmovlel %ecx, %eax
331 ; CMOV-NEXT:    testl %edi, %edi
332 ; CMOV-NEXT:    cmovnel %ecx, %eax
333 ; CMOV-NEXT:    movb %al, {{.*}}(%rip)
334 ; CMOV-NEXT:    retq
336 ; NOCMOV-LABEL: no_cascade_opt:
337 ; NOCMOV:       # %bb.0: # %entry
338 ; NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
339 ; NOCMOV-NEXT:    cmpl {{[0-9]+}}(%esp), %eax
340 ; NOCMOV-NEXT:    movb $20, %al
341 ; NOCMOV-NEXT:    movb $20, %cl
342 ; NOCMOV-NEXT:    jge .LBB7_1
343 ; NOCMOV-NEXT:  # %bb.2: # %entry
344 ; NOCMOV-NEXT:    jle .LBB7_3
345 ; NOCMOV-NEXT:  .LBB7_4: # %entry
346 ; NOCMOV-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
347 ; NOCMOV-NEXT:    jne .LBB7_5
348 ; NOCMOV-NEXT:  .LBB7_6: # %entry
349 ; NOCMOV-NEXT:    movb %al, g8
350 ; NOCMOV-NEXT:    retl
351 ; NOCMOV-NEXT:  .LBB7_1: # %entry
352 ; NOCMOV-NEXT:    movb {{[0-9]+}}(%esp), %cl
353 ; NOCMOV-NEXT:    jg .LBB7_4
354 ; NOCMOV-NEXT:  .LBB7_3: # %entry
355 ; NOCMOV-NEXT:    movl %ecx, %eax
356 ; NOCMOV-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
357 ; NOCMOV-NEXT:    je .LBB7_6
358 ; NOCMOV-NEXT:  .LBB7_5: # %entry
359 ; NOCMOV-NEXT:    movl %ecx, %eax
360 ; NOCMOV-NEXT:    movb %al, g8
361 ; NOCMOV-NEXT:    retl
362 entry:
363   %c0 = icmp eq i32 %v0, 0
364   %c1 = icmp slt i32 %v1, %v2
365   %c2 = icmp sgt i32 %v1, %v2
366   %trunc = trunc i32 %v3 to i8
367   %sel0 = select i1 %c1, i8 20, i8 %trunc
368   %sel1 = select i1 %c2, i8 20, i8 %sel0
369   %sel2 = select i1 %c0, i8 %sel1, i8 %sel0
370   store volatile i8 %sel2, i8* @g8
371   ret void