1 ; RUN: llc < %s -mtriple=i686-windows | FileCheck %s -check-prefix=NORMAL
2 ; RUN: llc < %s -mtriple=i686-windows -no-x86-call-frame-opt | FileCheck %s -check-prefix=NOPUSH
3 ; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64
4 ; RUN: llc < %s -mtriple=i686-windows -stackrealign -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED
5 ; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX
7 %class.Class = type { i32 }
8 %struct.s = type { i64 }
10 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
11 declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)
12 declare x86_thiscallcc void @thiscall(%class.Class* %class, i32 %a, i32 %b, i32 %c, i32 %d)
13 declare void @oneparam(i32 %a)
14 declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
15 declare void @eightparams16(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h)
16 declare void @eightparams64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)
17 declare void @struct(%struct.s* byval %a, i32 %b, i32 %c, i32 %d)
18 declare void @inalloca(<{ %struct.s }>* inalloca)
20 declare i8* @llvm.stacksave()
21 declare void @llvm.stackrestore(i8*)
23 ; We should get pushes for x86, even though there is a reserved call frame.
24 ; Make sure we don't touch x86-64, and that turning it off works.
25 ; NORMAL-LABEL: test1:
26 ; NORMAL-NOT: subl {{.*}} %esp
28 ; NORMAL-NEXT: pushl $3
29 ; NORMAL-NEXT: pushl $2
30 ; NORMAL-NEXT: pushl $1
32 ; NORMAL-NEXT: addl $16, %esp
35 ; X64-NEXT: movl $2, %edx
36 ; X64-NEXT: movl $3, %r8d
37 ; X64-NEXT: movl $4, %r9d
38 ; X64-NEXT: callq good
39 ; NOPUSH-LABEL: test1:
40 ; NOPUSH: subl $16, %esp
41 ; NOPUSH-NEXT: movl $4, 12(%esp)
42 ; NOPUSH-NEXT: movl $3, 8(%esp)
43 ; NOPUSH-NEXT: movl $2, 4(%esp)
44 ; NOPUSH-NEXT: movl $1, (%esp)
46 ; NOPUSH-NEXT: addl $16, %esp
47 define void @test1() {
49 call void @good(i32 1, i32 2, i32 3, i32 4)
53 ; If we have a reserved frame, we should have pushes
54 ; NORMAL-LABEL: test2:
55 ; NORMAL-NOT: subl {{.*}} %esp
57 ; NORMAL-NEXT: pushl $3
58 ; NORMAL-NEXT: pushl $2
59 ; NORMAL-NEXT: pushl $1
61 define void @test2(i32 %k) {
63 %a = alloca i32, i32 %k
64 call void @good(i32 1, i32 2, i32 3, i32 4)
68 ; Again, we expect a sequence of 4 immediate pushes
69 ; Checks that we generate the right pushes for >8bit immediates
70 ; NORMAL-LABEL: test2b:
71 ; NORMAL-NOT: subl {{.*}} %esp
73 ; NORMAL-NEXT: pushl $3072
74 ; NORMAL-NEXT: pushl $2048
75 ; NORMAL-NEXT: pushl $1024
77 ; NORMAL-NEXT: addl $16, %esp
78 define void @test2b() optsize {
80 call void @good(i32 1024, i32 2048, i32 3072, i32 4096)
84 ; The first push should push a register
85 ; NORMAL-LABEL: test3:
86 ; NORMAL-NOT: subl {{.*}} %esp
88 ; NORMAL-NEXT: pushl $3
89 ; NORMAL-NEXT: pushl $2
90 ; NORMAL-NEXT: pushl %e{{..}}
92 ; NORMAL-NEXT: addl $16, %esp
93 define void @test3(i32 %k) optsize {
96 call void @good(i32 %f, i32 2, i32 3, i32 4)
100 ; We support weird calling conventions
101 ; NORMAL-LABEL: test4:
102 ; NORMAL: movl $2, %eax
103 ; NORMAL-NEXT: pushl $4
104 ; NORMAL-NEXT: pushl $3
105 ; NORMAL-NEXT: pushl $1
107 ; NORMAL-NEXT: addl $12, %esp
108 define void @test4() optsize {
110 call void @inreg(i32 1, i32 2, i32 3, i32 4)
114 ; NORMAL-LABEL: test4b:
115 ; NORMAL: movl 4(%esp), %ecx
116 ; NORMAL-NEXT: pushl $4
117 ; NORMAL-NEXT: pushl $3
118 ; NORMAL-NEXT: pushl $2
119 ; NORMAL-NEXT: pushl $1
122 define void @test4b(%class.Class* %f) optsize {
124 call x86_thiscallcc void @thiscall(%class.Class* %f, i32 1, i32 2, i32 3, i32 4)
128 ; When there is no reserved call frame, check that additional alignment
129 ; is added when the pushes don't add up to the required alignment.
130 ; ALIGNED-LABEL: test5:
131 ; ALIGNED: subl $16, %esp
132 ; ALIGNED-NEXT: pushl $4
133 ; ALIGNED-NEXT: pushl $3
134 ; ALIGNED-NEXT: pushl $2
135 ; ALIGNED-NEXT: pushl $1
137 define void @test5(i32 %k) {
139 %a = alloca i32, i32 %k
140 call void @good(i32 1, i32 2, i32 3, i32 4)
144 ; When the alignment adds up, do the transformation
145 ; ALIGNED-LABEL: test5b:
147 ; ALIGNED-NEXT: pushl $7
148 ; ALIGNED-NEXT: pushl $6
149 ; ALIGNED-NEXT: pushl $5
150 ; ALIGNED-NEXT: pushl $4
151 ; ALIGNED-NEXT: pushl $3
152 ; ALIGNED-NEXT: pushl $2
153 ; ALIGNED-NEXT: pushl $1
155 define void @test5b() optsize {
157 call void @eightparams(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8)
161 ; When having to compensate for the alignment isn't worth it,
163 ; ALIGNED-LABEL: test5c:
164 ; ALIGNED: movl $1, (%esp)
166 define void @test5c() optsize {
168 call void @oneparam(i32 1)
172 ; Check that pushing the addresses of globals (Or generally, things that
173 ; aren't exactly immediates) isn't broken.
175 ; NORMAL-LABEL: test6:
176 ; NORMAL: pushl $_ext
179 @ext = external constant i8
181 define void @test6() {
182 call void @f(i8* @ext)
189 ; Check that we fold simple cases into the push
190 ; NORMAL-LABEL: test7:
191 ; NORMAL-NOT: subl {{.*}} %esp
192 ; NORMAL: movl 4(%esp), [[EAX:%e..]]
193 ; NORMAL-NEXT: pushl $4
194 ; NORMAL-NEXT: pushl ([[EAX]])
195 ; NORMAL-NEXT: pushl $2
196 ; NORMAL-NEXT: pushl $1
198 ; NORMAL-NEXT: addl $16, %esp
199 define void @test7(i32* %ptr) optsize {
201 %val = load i32, i32* %ptr
202 call void @good(i32 1, i32 2, i32 %val, i32 4)
206 ; Fold stack-relative loads into the push, with correct offset
207 ; In particular, at the second push, %b was at 12(%esp) and
208 ; %a wast at 8(%esp), but the second push bumped %esp, so %a
209 ; is now it at 12(%esp)
210 ; NORMAL-LABEL: test8:
212 ; NORMAL-NEXT: pushl 12(%esp)
213 ; NORMAL-NEXT: pushl 12(%esp)
214 ; NORMAL-NEXT: pushl $1
216 ; NORMAL-NEXT: addl $16, %esp
217 define void @test8(i32 %a, i32 %b) optsize {
219 call void @good(i32 1, i32 %a, i32 %b, i32 4)
223 ; If one function is using push instructions, and the other isn't
224 ; (because it has frame-index references), then we must resolve
225 ; these references correctly.
226 ; NORMAL-LABEL: test9:
227 ; NORMAL-NOT: leal (%esp),
229 ; NORMAL-NEXT: pushl $3
230 ; NORMAL-NEXT: pushl $2
231 ; NORMAL-NEXT: pushl $1
233 ; NORMAL-NEXT: addl $16, %esp
234 ; NORMAL-NEXT: movl (%esp), [[E1:%e..]]
235 ; NORMAL-NEXT: movl 4(%esp), [[E2:%e..]]
236 ; NORMAL-NEXT: leal 16(%esp), [[E3:%e..]]
237 ; NORMAL-NEXT: leal 12(%esp), [[E4:%e..]]
238 ; NORMAL-NEXT: pushl [[E3]]
239 ; NORMAL-NEXT: pushl [[E4]]
240 ; NORMAL-NEXT: pushl $6
241 ; NORMAL-NEXT: pushl [[E2]]
242 ; NORMAL-NEXT: pushl [[E1]]
244 ; NORMAL-NEXT: addl $20, %esp
245 define void @test9() optsize {
247 %p = alloca i32, align 4
248 %q = alloca i32, align 4
249 %s = alloca %struct.s, align 4
250 call void @good(i32 1, i32 2, i32 3, i32 4)
251 %pv = ptrtoint i32* %p to i32
252 %qv = ptrtoint i32* %q to i32
253 call void @struct(%struct.s* byval %s, i32 6, i32 %qv, i32 %pv)
257 ; We can end up with an indirect call which gets reloaded on the spot.
258 ; Make sure we reference the correct stack slot - we spill into (%esp)
259 ; and reload from 16(%esp) due to the pushes.
260 ; NORMAL-LABEL: test10:
261 ; NORMAL: movl $_good, [[ALLOC:.*]]
262 ; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]
263 ; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill
266 ; NORMAL-NEXT: pushl $3
267 ; NORMAL-NEXT: pushl $2
268 ; NORMAL-NEXT: pushl $1
269 ; NORMAL-NEXT: calll *16(%esp)
270 ; NORMAL-NEXT: addl $24, %esp
271 define void @test10() optsize {
272 %stack_fptr = alloca void (i32, i32, i32, i32)*
273 store void (i32, i32, i32, i32)* @good, void (i32, i32, i32, i32)** %stack_fptr
274 %good_ptr = load volatile void (i32, i32, i32, i32)*, void (i32, i32, i32, i32)** %stack_fptr
275 call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()
276 call void (i32, i32, i32, i32) %good_ptr(i32 1, i32 2, i32 3, i32 4)
280 ; We can't fold the load from the global into the push because of
281 ; interference from the store
282 ; NORMAL-LABEL: test11:
283 ; NORMAL: movl _the_global, [[EAX:%e..]]
284 ; NORMAL-NEXT: movl $42, _the_global
285 ; NORMAL-NEXT: pushl $4
286 ; NORMAL-NEXT: pushl $3
287 ; NORMAL-NEXT: pushl $2
288 ; NORMAL-NEXT: pushl [[EAX]]
290 ; NORMAL-NEXT: addl $16, %esp
291 @the_global = external global i32
292 define void @test11() optsize {
293 %myload = load i32, i32* @the_global
294 store i32 42, i32* @the_global
295 call void @good(i32 %myload, i32 2, i32 3, i32 4)
299 ; Converting one mov into a push isn't worth it when
300 ; doing so forces too much overhead for other calls.
301 ; NORMAL-LABEL: test12:
303 ; NORMAL-NEXT: pushl $7
304 ; NORMAL-NEXT: pushl $6
305 ; NORMAL-NEXT: pushl $5
306 ; NORMAL-NEXT: calll _good
307 define void @test12() optsize {
309 %s = alloca %struct.s, align 4
310 call void @struct(%struct.s* %s, i32 2, i32 3, i32 4)
311 call void @good(i32 5, i32 6, i32 7, i32 8)
312 call void @struct(%struct.s* %s, i32 10, i32 11, i32 12)
316 ; But if the gains outweigh the overhead, we should do it
317 ; NORMAL-LABEL: test12b:
319 ; NORMAL-NEXT: pushl $3
320 ; NORMAL-NEXT: pushl $2
321 ; NORMAL-NEXT: pushl $1
322 ; NORMAL-NEXT: calll _good
323 ; NORMAL-NEXT: addl $16, %esp
324 ; NORMAL=NEXT: movl (%esp), %eax
325 ; NORMAL=NEXT: movl 4(%esp), %ecx
326 ; NORMAL=NEXT: pushl $8
327 ; NORMAL=NEXT: pushl $7
328 ; NORMAL=NEXT: pushl $6
329 ; NORMAL=NEXT: pushl %ecx
330 ; NORMAL=NEXT: pushl %eax
331 ; NORMAL=NEXT: calll _struct
332 ; NORMAL=NEXT: addl $20, %esp
333 ; NORMAL=NEXT: pushl $12
334 ; NORMAL=NEXT: pushl $11
335 ; NORMAL=NEXT: pushl $10
336 ; NORMAL=NEXT: pushl $9
337 ; NORMAL=NEXT: calll _good
338 ; NORMAL=NEXT: addl $16, %esp
339 define void @test12b() optsize {
341 %s = alloca %struct.s, align 4
342 call void @good(i32 1, i32 2, i32 3, i32 4)
343 call void @struct(%struct.s* %s, i32 6, i32 7, i32 8)
344 call void @good(i32 9, i32 10, i32 11, i32 12)
348 ; Make sure the add does not prevent folding loads into pushes.
349 ; val1 and val2 will not be folded into pushes since they have
350 ; an additional use, but val3 should be.
351 ; NORMAL-LABEL: test13:
352 ; NORMAL: movl ([[P1:%e..]]), [[V1:%e..]]
353 ; NORMAL-NEXT: movl ([[P2:%e..]]), [[V2:%e..]]
354 ; NORMAL-NEXT: , [[ADD:%e..]]
355 ; NORMAL-NEXT: pushl [[ADD]]
356 ; NORMAL-NEXT: pushl ([[P3:%e..]])
357 ; NORMAL-NEXT: pushl [[V2]]
358 ; NORMAL-NEXT: pushl [[V1]]
359 ; NORMAL-NEXT: calll _good
360 ; NORMAL: movl [[P3]], %eax
361 define i32* @test13(i32* inreg %ptr1, i32* inreg %ptr2, i32* inreg %ptr3) optsize {
363 %val1 = load i32, i32* %ptr1
364 %val2 = load i32, i32* %ptr2
365 %val3 = load i32, i32* %ptr3
366 %add = add i32 %val1, %val2
367 call void @good(i32 %val1, i32 %val2, i32 %val3, i32 %add)
371 ; Make sure to fold adjacent stack adjustments.
372 ; LINUX-LABEL: pr27140:
373 ; LINUX: subl $12, %esp
374 ; LINUX: .cfi_def_cfa_offset 16
377 ; LINUX: .cfi_adjust_cfa_offset 4
379 ; LINUX: .cfi_adjust_cfa_offset 4
381 ; LINUX: .cfi_adjust_cfa_offset 4
383 ; LINUX: .cfi_adjust_cfa_offset 4
385 ; LINUX: addl $28, %esp
386 ; LINUX: .cfi_adjust_cfa_offset -28
389 define void @pr27140() optsize {
391 tail call void @good(i32 1, i32 2, i32 3, i32 4)
395 ; Check that a stack restore (leal -4(%ebp), %esp) doesn't get merged with a
396 ; stack adjustment (addl $12, %esp). Just because it's a lea doesn't mean it's
397 ; simply decreasing the stack pointer.
398 ; NORMAL-LABEL: test14:
399 ; NORMAL: calll _B_func
400 ; NORMAL: leal -4(%ebp), %esp
403 %struct.A = type { i32, i32 }
404 %struct.B = type { i8 }
405 declare x86_thiscallcc %struct.B* @B_ctor(%struct.B* returned, %struct.A* byval)
406 declare void @B_func(%struct.B* sret, %struct.B*, i32)
407 define void @test14(%struct.A* %a) {
409 %ref.tmp = alloca %struct.B, align 1
410 %agg.tmp = alloca i64, align 4
411 %tmpcast = bitcast i64* %agg.tmp to %struct.A*
412 %tmp = alloca %struct.B, align 1
413 %0 = bitcast %struct.A* %a to i64*
414 %1 = load i64, i64* %0, align 4
415 store i64 %1, i64* %agg.tmp, align 4
416 %call = call x86_thiscallcc %struct.B* @B_ctor(%struct.B* %ref.tmp, %struct.A* byval %tmpcast)
417 %2 = getelementptr inbounds %struct.B, %struct.B* %tmp, i32 0, i32 0
418 call void @B_func(%struct.B* sret %tmp, %struct.B* %ref.tmp, i32 1)
422 ; NORMAL-LABEL: pr34863_16
423 ; NORMAL: movl 4(%esp), %eax
424 ; NORMAL-NEXT: pushl $65535
425 ; NORMAL-NEXT: pushl $0
426 ; NORMAL-NEXT: pushl %eax
427 ; NORMAL-NEXT: pushl %eax
428 ; NORMAL-NEXT: pushl %eax
429 ; NORMAL-NEXT: pushl %eax
430 ; NORMAL-NEXT: pushl %eax
431 ; NORMAL-NEXT: pushl %eax
432 ; NORMAL-NEXT: calll _eightparams16
433 ; NORMAL-NEXT: addl $32, %esp
435 ; NOPUSH-LABEL: pr34863_16
436 ; NOPUSH: subl $32, %esp
437 ; NOPUSH-NEXT: movl 36(%esp), %eax
438 ; NOPUSH-NEXT: movl %eax, 20(%esp)
439 ; NOPUSH-NEXT: movl %eax, 16(%esp)
440 ; NOPUSH-NEXT: movl %eax, 12(%esp)
441 ; NOPUSH-NEXT: movl %eax, 8(%esp)
442 ; NOPUSH-NEXT: movl %eax, 4(%esp)
443 ; NOPUSH-NEXT: movl %eax, (%esp)
444 ; NOPUSH-NEXT: movl $65535, 28(%esp)
445 ; NOPUSH-NEXT: andl $0, 24(%esp)
446 ; NOPUSH-NEXT: calll _eightparams16
447 ; NOPUSH-NEXT: addl $32, %esp
448 define void @pr34863_16(i16 %x) minsize nounwind {
450 tail call void @eightparams16(i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 0, i16 -1)
454 ; NORMAL-LABEL: pr34863_32
455 ; NORMAL: movl 4(%esp), %eax
456 ; NORMAL-NEXT: pushl $-1
457 ; NORMAL-NEXT: pushl $0
458 ; NORMAL-NEXT: pushl %eax
459 ; NORMAL-NEXT: pushl %eax
460 ; NORMAL-NEXT: pushl %eax
461 ; NORMAL-NEXT: pushl %eax
462 ; NORMAL-NEXT: pushl %eax
463 ; NORMAL-NEXT: pushl %eax
464 ; NORMAL-NEXT: calll _eightparams
465 ; NORMAL-NEXT: addl $32, %esp
467 ; NOPUSH-LABEL: pr34863_32
468 ; NOPUSH: subl $32, %esp
469 ; NOPUSH-NEXT: movl 36(%esp), %eax
470 ; NOPUSH-NEXT: movl %eax, 20(%esp)
471 ; NOPUSH-NEXT: movl %eax, 16(%esp)
472 ; NOPUSH-NEXT: movl %eax, 12(%esp)
473 ; NOPUSH-NEXT: movl %eax, 8(%esp)
474 ; NOPUSH-NEXT: movl %eax, 4(%esp)
475 ; NOPUSH-NEXT: movl %eax, (%esp)
476 ; NOPUSH-NEXT: orl $-1, 28(%esp)
477 ; NOPUSH-NEXT: andl $0, 24(%esp)
478 ; NOPUSH-NEXT: calll _eightparams
479 ; NOPUSH-NEXT: addl $32, %esp
480 define void @pr34863_32(i32 %x) minsize nounwind {
482 tail call void @eightparams(i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 0, i32 -1)
486 ; NORMAL-LABEL: pr34863_64
487 ; NORMAL: movl 4(%esp), %eax
488 ; NORMAL-NEXT: movl 8(%esp), %ecx
489 ; NORMAL-NEXT: pushl $-1
490 ; NORMAL-NEXT: pushl $-1
491 ; NORMAL-NEXT: pushl $0
492 ; NORMAL-NEXT: pushl $0
493 ; NORMAL-NEXT: pushl %ecx
494 ; NORMAL-NEXT: pushl %eax
495 ; NORMAL-NEXT: pushl %ecx
496 ; NORMAL-NEXT: pushl %eax
497 ; NORMAL-NEXT: pushl %ecx
498 ; NORMAL-NEXT: pushl %eax
499 ; NORMAL-NEXT: pushl %ecx
500 ; NORMAL-NEXT: pushl %eax
501 ; NORMAL-NEXT: pushl %ecx
502 ; NORMAL-NEXT: pushl %eax
503 ; NORMAL-NEXT: pushl %ecx
504 ; NORMAL-NEXT: pushl %eax
505 ; NORMAL-NEXT: calll _eightparams64
506 ; NORMAL-NEXT: addl $64, %esp
508 ; NOPUSH-LABEL: pr34863_64
509 ; NOPUSH: subl $64, %esp
510 ; NOPUSH-NEXT: movl 68(%esp), %eax
511 ; NOPUSH-NEXT: movl 72(%esp), %ecx
512 ; NOPUSH-NEXT: movl %ecx, 44(%esp)
513 ; NOPUSH-NEXT: movl %eax, 40(%esp)
514 ; NOPUSH-NEXT: movl %ecx, 36(%esp)
515 ; NOPUSH-NEXT: movl %eax, 32(%esp)
516 ; NOPUSH-NEXT: movl %ecx, 28(%esp)
517 ; NOPUSH-NEXT: movl %eax, 24(%esp)
518 ; NOPUSH-NEXT: movl %ecx, 20(%esp)
519 ; NOPUSH-NEXT: movl %eax, 16(%esp)
520 ; NOPUSH-NEXT: movl %ecx, 12(%esp)
521 ; NOPUSH-NEXT: movl %eax, 8(%esp)
522 ; NOPUSH-NEXT: movl %ecx, 4(%esp)
523 ; NOPUSH-NEXT: movl %eax, (%esp)
524 ; NOPUSH-NEXT: orl $-1, 60(%esp)
525 ; NOPUSH-NEXT: orl $-1, 56(%esp)
526 ; NOPUSH-NEXT: andl $0, 52(%esp)
527 ; NOPUSH-NEXT: andl $0, 48(%esp)
528 ; NOPUSH-NEXT: calll _eightparams64
529 ; NOPUSH-NEXT: addl $64, %esp
530 define void @pr34863_64(i64 %x) minsize nounwind {
532 tail call void @eightparams64(i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 0, i64 -1)