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-pc-linux | FileCheck %s -check-prefix=LINUX
6 %class.Class = type { i32 }
7 %struct.s = type { i64 }
9 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
10 declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)
11 declare x86_thiscallcc void @thiscall(ptr %class, i32 %a, i32 %b, i32 %c, i32 %d)
12 declare void @oneparam(i32 %a)
13 declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
14 declare void @eightparams16(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h)
15 declare void @eightparams64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)
16 declare void @struct(ptr byval(%struct.s) %a, i32 %b, i32 %c, i32 %d)
17 declare void @inalloca(ptr inalloca(<{ %struct.s }>))
19 declare ptr @llvm.stacksave()
20 declare void @llvm.stackrestore(ptr)
22 ; We should get pushes for x86, even though there is a reserved call frame.
23 ; Make sure we don't touch x86-64, and that turning it off works.
24 ; NORMAL-LABEL: test1:
25 ; NORMAL-NOT: subl {{.*}} %esp
27 ; NORMAL-NEXT: pushl $3
28 ; NORMAL-NEXT: pushl $2
29 ; NORMAL-NEXT: pushl $1
31 ; NORMAL-NEXT: addl $16, %esp
34 ; X64-NEXT: movl $2, %edx
35 ; X64-NEXT: movl $3, %r8d
36 ; X64-NEXT: movl $4, %r9d
37 ; X64-NEXT: callq good
38 ; NOPUSH-LABEL: test1:
39 ; NOPUSH: subl $16, %esp
40 ; NOPUSH-NEXT: movl $4, 12(%esp)
41 ; NOPUSH-NEXT: movl $3, 8(%esp)
42 ; NOPUSH-NEXT: movl $2, 4(%esp)
43 ; NOPUSH-NEXT: movl $1, (%esp)
45 ; NOPUSH-NEXT: addl $16, %esp
46 define void @test1() {
48 call void @good(i32 1, i32 2, i32 3, i32 4)
52 ; If we have a reserved frame, we should have pushes
53 ; NORMAL-LABEL: test2:
54 ; NORMAL-NOT: subl {{.*}} %esp
56 ; NORMAL-NEXT: pushl $3
57 ; NORMAL-NEXT: pushl $2
58 ; NORMAL-NEXT: pushl $1
60 define void @test2(i32 %k) {
62 %a = alloca i32, i32 %k
63 call void @good(i32 1, i32 2, i32 3, i32 4)
67 ; Again, we expect a sequence of 4 immediate pushes
68 ; Checks that we generate the right pushes for >8bit immediates
69 ; NORMAL-LABEL: test2b:
70 ; NORMAL-NOT: subl {{.*}} %esp
72 ; NORMAL-NEXT: pushl $3072
73 ; NORMAL-NEXT: pushl $2048
74 ; NORMAL-NEXT: pushl $1024
76 ; NORMAL-NEXT: addl $16, %esp
77 define void @test2b() optsize {
79 call void @good(i32 1024, i32 2048, i32 3072, i32 4096)
83 ; The first push should push a register
84 ; NORMAL-LABEL: test3:
85 ; NORMAL-NOT: subl {{.*}} %esp
87 ; NORMAL-NEXT: pushl $3
88 ; NORMAL-NEXT: pushl $2
89 ; NORMAL-NEXT: pushl %e{{..}}
91 ; NORMAL-NEXT: addl $16, %esp
92 define void @test3(i32 %k) optsize {
95 call void @good(i32 %f, i32 2, i32 3, i32 4)
99 ; We support weird calling conventions
100 ; NORMAL-LABEL: test4:
101 ; NORMAL: movl $2, %eax
102 ; NORMAL-NEXT: pushl $4
103 ; NORMAL-NEXT: pushl $3
104 ; NORMAL-NEXT: pushl $1
106 ; NORMAL-NEXT: addl $12, %esp
107 define void @test4() optsize {
109 call void @inreg(i32 1, i32 inreg 2, i32 3, i32 4)
113 ; NORMAL-LABEL: test4b:
114 ; NORMAL: movl 4(%esp), %ecx
115 ; NORMAL-NEXT: pushl $4
116 ; NORMAL-NEXT: pushl $3
117 ; NORMAL-NEXT: pushl $2
118 ; NORMAL-NEXT: pushl $1
121 define void @test4b(ptr %f) optsize {
123 call x86_thiscallcc void @thiscall(ptr %f, i32 1, i32 2, i32 3, i32 4)
127 ; Check that pushing the addresses of globals (Or generally, things that
128 ; aren't exactly immediates) isn't broken.
130 ; NORMAL-LABEL: test6:
131 ; NORMAL: pushl $_ext
134 @ext = external dso_local constant i8
136 define void @test6() {
137 call void @f(ptr @ext)
144 ; Check that we fold simple cases into the push
145 ; NORMAL-LABEL: test7:
146 ; NORMAL-NOT: subl {{.*}} %esp
147 ; NORMAL: movl 4(%esp), [[EAX:%e..]]
148 ; NORMAL-NEXT: pushl $4
149 ; NORMAL-NEXT: pushl ([[EAX]])
150 ; NORMAL-NEXT: pushl $2
151 ; NORMAL-NEXT: pushl $1
153 ; NORMAL-NEXT: addl $16, %esp
154 define void @test7(ptr %ptr) optsize {
156 %val = load i32, ptr %ptr
157 call void @good(i32 1, i32 2, i32 %val, i32 4)
161 ; Fold stack-relative loads into the push, with correct offset
162 ; In particular, at the second push, %b was at 12(%esp) and
163 ; %a wast at 8(%esp), but the second push bumped %esp, so %a
164 ; is now it at 12(%esp)
165 ; NORMAL-LABEL: test8:
167 ; NORMAL-NEXT: pushl 12(%esp)
168 ; NORMAL-NEXT: pushl 12(%esp)
169 ; NORMAL-NEXT: pushl $1
171 ; NORMAL-NEXT: addl $16, %esp
172 define void @test8(i32 %a, i32 %b) optsize {
174 call void @good(i32 1, i32 %a, i32 %b, i32 4)
178 ; If one function is using push instructions, and the other isn't
179 ; (because it has frame-index references), then we must resolve
180 ; these references correctly.
181 ; NORMAL-LABEL: test9:
182 ; NORMAL-NOT: leal (%esp),
184 ; NORMAL-NEXT: pushl $3
185 ; NORMAL-NEXT: pushl $2
186 ; NORMAL-NEXT: pushl $1
188 ; NORMAL-NEXT: addl $16, %esp
189 ; NORMAL-NEXT: movl (%esp), [[E1:%e..]]
190 ; NORMAL-NEXT: movl 4(%esp), [[E2:%e..]]
191 ; NORMAL-NEXT: leal 16(%esp), [[E3:%e..]]
192 ; NORMAL-NEXT: leal 12(%esp), [[E4:%e..]]
193 ; NORMAL-NEXT: pushl [[E3]]
194 ; NORMAL-NEXT: pushl [[E4]]
195 ; NORMAL-NEXT: pushl $6
196 ; NORMAL-NEXT: pushl [[E2]]
197 ; NORMAL-NEXT: pushl [[E1]]
199 ; NORMAL-NEXT: addl $20, %esp
200 define void @test9() optsize {
202 %p = alloca i32, align 4
203 %q = alloca i32, align 4
204 %s = alloca %struct.s, align 8
205 call void @good(i32 1, i32 2, i32 3, i32 4)
206 %pv = ptrtoint ptr %p to i32
207 %qv = ptrtoint ptr %q to i32
208 call void @struct(ptr byval(%struct.s) %s, i32 6, i32 %qv, i32 %pv)
212 ; We can end up with an indirect call which gets reloaded on the spot.
213 ; Make sure we reference the correct stack slot - we spill into (%esp)
214 ; and reload from 16(%esp) due to the pushes.
215 ; NORMAL-LABEL: test10:
216 ; NORMAL: movl $_good, [[ALLOC:.*]]
217 ; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]
218 ; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill
221 ; NORMAL-NEXT: pushl $3
222 ; NORMAL-NEXT: pushl $2
223 ; NORMAL-NEXT: pushl $1
224 ; NORMAL-NEXT: calll *16(%esp)
225 ; NORMAL-NEXT: addl $24, %esp
226 define void @test10() optsize {
227 %stack_fptr = alloca ptr
228 store ptr @good, ptr %stack_fptr
229 %good_ptr = load volatile ptr, ptr %stack_fptr
230 call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()
231 call void (i32, i32, i32, i32) %good_ptr(i32 1, i32 2, i32 3, i32 4)
235 ; We can't fold the load from the global into the push because of
236 ; interference from the store
237 ; NORMAL-LABEL: test11:
238 ; NORMAL: movl _the_global, [[EAX:%e..]]
239 ; NORMAL-NEXT: movl $42, _the_global
240 ; NORMAL-NEXT: pushl $4
241 ; NORMAL-NEXT: pushl $3
242 ; NORMAL-NEXT: pushl $2
243 ; NORMAL-NEXT: pushl [[EAX]]
245 ; NORMAL-NEXT: addl $16, %esp
246 @the_global = external dso_local global i32
247 define void @test11() optsize {
248 %myload = load i32, ptr @the_global
249 store i32 42, ptr @the_global
250 call void @good(i32 %myload, i32 2, i32 3, i32 4)
254 ; Converting one mov into a push isn't worth it when
255 ; doing so forces too much overhead for other calls.
256 ; NORMAL-LABEL: test12:
258 ; NORMAL-NEXT: pushl $7
259 ; NORMAL-NEXT: pushl $6
260 ; NORMAL-NEXT: pushl $5
261 ; NORMAL-NEXT: calll _good
262 define void @test12() optsize {
264 %s = alloca %struct.s, align 4
265 call void @struct(ptr byval(%struct.s) %s, i32 2, i32 3, i32 4)
266 call void @good(i32 5, i32 6, i32 7, i32 8)
267 call void @struct(ptr byval(%struct.s) %s, i32 10, i32 11, i32 12)
271 ; But if the gains outweigh the overhead, we should do it
272 ; NORMAL-LABEL: test12b:
274 ; NORMAL-NEXT: pushl $3
275 ; NORMAL-NEXT: pushl $2
276 ; NORMAL-NEXT: pushl $1
277 ; NORMAL-NEXT: calll _good
278 ; NORMAL-NEXT: addl $16, %esp
279 ; NORMAL=NEXT: movl (%esp), %eax
280 ; NORMAL=NEXT: movl 4(%esp), %ecx
281 ; NORMAL=NEXT: pushl $8
282 ; NORMAL=NEXT: pushl $7
283 ; NORMAL=NEXT: pushl $6
284 ; NORMAL=NEXT: pushl %ecx
285 ; NORMAL=NEXT: pushl %eax
286 ; NORMAL=NEXT: calll _struct
287 ; NORMAL=NEXT: addl $20, %esp
288 ; NORMAL=NEXT: pushl $12
289 ; NORMAL=NEXT: pushl $11
290 ; NORMAL=NEXT: pushl $10
291 ; NORMAL=NEXT: pushl $9
292 ; NORMAL=NEXT: calll _good
293 ; NORMAL=NEXT: addl $16, %esp
294 define void @test12b() optsize {
296 %s = alloca %struct.s, align 4
297 call void @good(i32 1, i32 2, i32 3, i32 4)
298 call void @struct(ptr byval(%struct.s) %s, i32 6, i32 7, i32 8)
299 call void @good(i32 9, i32 10, i32 11, i32 12)
303 ; Make sure the add does not prevent folding loads into pushes.
304 ; val1 and val2 will not be folded into pushes since they have
305 ; an additional use, but val3 should be.
306 ; NORMAL-LABEL: test13:
307 ; NORMAL: movl ([[P1:%e..]]), [[V1:%e..]]
308 ; NORMAL-NEXT: movl ([[P2:%e..]]), [[V2:%e..]]
309 ; NORMAL-NEXT: , [[ADD:%e..]]
310 ; NORMAL-NEXT: pushl [[ADD]]
311 ; NORMAL-NEXT: pushl ([[P3:%e..]])
312 ; NORMAL-NEXT: pushl [[V2]]
313 ; NORMAL-NEXT: pushl [[V1]]
314 ; NORMAL-NEXT: calll _good
315 ; NORMAL: movl [[P3]], %eax
316 define ptr @test13(ptr inreg %ptr1, ptr inreg %ptr2, ptr inreg %ptr3) optsize {
318 %val1 = load i32, ptr %ptr1
319 %val2 = load i32, ptr %ptr2
320 %val3 = load i32, ptr %ptr3
321 %add = add i32 %val1, %val2
322 call void @good(i32 %val1, i32 %val2, i32 %val3, i32 %add)
326 ; Make sure to fold adjacent stack adjustments.
327 ; LINUX-LABEL: pr27140:
328 ; LINUX: subl $12, %esp
329 ; LINUX: .cfi_def_cfa_offset 16
332 ; LINUX: .cfi_adjust_cfa_offset 4
334 ; LINUX: .cfi_adjust_cfa_offset 4
336 ; LINUX: .cfi_adjust_cfa_offset 4
338 ; LINUX: .cfi_adjust_cfa_offset 4
340 ; LINUX: addl $28, %esp
341 ; LINUX: .cfi_adjust_cfa_offset -28
344 define void @pr27140() optsize {
346 tail call void @good(i32 1, i32 2, i32 3, i32 4)
350 ; Check that a stack restore (leal -4(%ebp), %esp) doesn't get merged with a
351 ; stack adjustment (addl $12, %esp). Just because it's a lea doesn't mean it's
352 ; simply decreasing the stack pointer.
353 ; NORMAL-LABEL: test14:
354 ; NORMAL: calll _B_func
355 ; NORMAL: leal -4(%ebp), %esp
358 %struct.A = type { i32, i32 }
359 %struct.B = type { i8 }
360 declare x86_thiscallcc ptr @B_ctor(ptr returned, ptr byval(%struct.A))
361 declare void @B_func(ptr sret(%struct.B), ptr, i32)
362 define void @test14(ptr %a) {
364 %ref.tmp = alloca %struct.B, align 1
365 %agg.tmp = alloca i64, align 8
366 %tmp = alloca %struct.B, align 1
367 %0 = load i64, ptr %a, align 4
368 store i64 %0, ptr %agg.tmp, align 4
369 %call = call x86_thiscallcc ptr @B_ctor(ptr returned %ref.tmp, ptr byval(%struct.A) %agg.tmp)
370 call void @B_func(ptr sret(%struct.B) %tmp, ptr %ref.tmp, i32 1)
374 ; NORMAL-LABEL: pr34863_16
375 ; NORMAL: movl 4(%esp), %eax
376 ; NORMAL-NEXT: pushl $65535
377 ; NORMAL-NEXT: pushl $0
378 ; NORMAL-NEXT: pushl %eax
379 ; NORMAL-NEXT: pushl %eax
380 ; NORMAL-NEXT: pushl %eax
381 ; NORMAL-NEXT: pushl %eax
382 ; NORMAL-NEXT: pushl %eax
383 ; NORMAL-NEXT: pushl %eax
384 ; NORMAL-NEXT: calll _eightparams16
385 ; NORMAL-NEXT: addl $32, %esp
387 ; NOPUSH-LABEL: pr34863_16
388 ; NOPUSH: subl $32, %esp
389 ; NOPUSH-NEXT: movl 36(%esp), %eax
390 ; NOPUSH-NEXT: movl %eax, 20(%esp)
391 ; NOPUSH-NEXT: movl %eax, 16(%esp)
392 ; NOPUSH-NEXT: movl %eax, 12(%esp)
393 ; NOPUSH-NEXT: movl %eax, 8(%esp)
394 ; NOPUSH-NEXT: movl %eax, 4(%esp)
395 ; NOPUSH-NEXT: movl %eax, (%esp)
396 ; NOPUSH-NEXT: movl $65535, 28(%esp)
397 ; NOPUSH-NEXT: andl $0, 24(%esp)
398 ; NOPUSH-NEXT: calll _eightparams16
399 ; NOPUSH-NEXT: addl $32, %esp
400 define void @pr34863_16(i16 %x) minsize nounwind {
402 tail call void @eightparams16(i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 0, i16 -1)
406 ; NORMAL-LABEL: pr34863_32
407 ; NORMAL: movl 4(%esp), %eax
408 ; NORMAL-NEXT: pushl $-1
409 ; NORMAL-NEXT: pushl $0
410 ; NORMAL-NEXT: pushl %eax
411 ; NORMAL-NEXT: pushl %eax
412 ; NORMAL-NEXT: pushl %eax
413 ; NORMAL-NEXT: pushl %eax
414 ; NORMAL-NEXT: pushl %eax
415 ; NORMAL-NEXT: pushl %eax
416 ; NORMAL-NEXT: calll _eightparams
417 ; NORMAL-NEXT: addl $32, %esp
419 ; NOPUSH-LABEL: pr34863_32
420 ; NOPUSH: subl $32, %esp
421 ; NOPUSH-NEXT: movl 36(%esp), %eax
422 ; NOPUSH-NEXT: movl %eax, 20(%esp)
423 ; NOPUSH-NEXT: movl %eax, 16(%esp)
424 ; NOPUSH-NEXT: movl %eax, 12(%esp)
425 ; NOPUSH-NEXT: movl %eax, 8(%esp)
426 ; NOPUSH-NEXT: movl %eax, 4(%esp)
427 ; NOPUSH-NEXT: movl %eax, (%esp)
428 ; NOPUSH-NEXT: orl $-1, 28(%esp)
429 ; NOPUSH-NEXT: andl $0, 24(%esp)
430 ; NOPUSH-NEXT: calll _eightparams
431 ; NOPUSH-NEXT: addl $32, %esp
432 define void @pr34863_32(i32 %x) minsize nounwind {
434 tail call void @eightparams(i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 0, i32 -1)
438 ; NORMAL-LABEL: pr34863_64
439 ; NORMAL: movl 4(%esp), %eax
440 ; NORMAL-NEXT: movl 8(%esp), %ecx
441 ; NORMAL-NEXT: pushl $-1
442 ; NORMAL-NEXT: pushl $-1
443 ; NORMAL-NEXT: pushl $0
444 ; NORMAL-NEXT: pushl $0
445 ; NORMAL-NEXT: pushl %ecx
446 ; NORMAL-NEXT: pushl %eax
447 ; NORMAL-NEXT: pushl %ecx
448 ; NORMAL-NEXT: pushl %eax
449 ; NORMAL-NEXT: pushl %ecx
450 ; NORMAL-NEXT: pushl %eax
451 ; NORMAL-NEXT: pushl %ecx
452 ; NORMAL-NEXT: pushl %eax
453 ; NORMAL-NEXT: pushl %ecx
454 ; NORMAL-NEXT: pushl %eax
455 ; NORMAL-NEXT: pushl %ecx
456 ; NORMAL-NEXT: pushl %eax
457 ; NORMAL-NEXT: calll _eightparams64
458 ; NORMAL-NEXT: addl $64, %esp
460 ; NOPUSH-LABEL: pr34863_64
461 ; NOPUSH: subl $64, %esp
462 ; NOPUSH-NEXT: movl 68(%esp), %eax
463 ; NOPUSH-NEXT: movl 72(%esp), %ecx
464 ; NOPUSH-NEXT: movl %ecx, 44(%esp)
465 ; NOPUSH-NEXT: movl %eax, 40(%esp)
466 ; NOPUSH-NEXT: movl %ecx, 36(%esp)
467 ; NOPUSH-NEXT: movl %eax, 32(%esp)
468 ; NOPUSH-NEXT: movl %ecx, 28(%esp)
469 ; NOPUSH-NEXT: movl %eax, 24(%esp)
470 ; NOPUSH-NEXT: movl %ecx, 20(%esp)
471 ; NOPUSH-NEXT: movl %eax, 16(%esp)
472 ; NOPUSH-NEXT: movl %ecx, 12(%esp)
473 ; NOPUSH-NEXT: movl %eax, 8(%esp)
474 ; NOPUSH-NEXT: movl %ecx, 4(%esp)
475 ; NOPUSH-NEXT: movl %eax, (%esp)
476 ; NOPUSH-NEXT: orl $-1, 60(%esp)
477 ; NOPUSH-NEXT: orl $-1, 56(%esp)
478 ; NOPUSH-NEXT: andl $0, 52(%esp)
479 ; NOPUSH-NEXT: andl $0, 48(%esp)
480 ; NOPUSH-NEXT: calll _eightparams64
481 ; NOPUSH-NEXT: addl $64, %esp
482 define void @pr34863_64(i64 %x) minsize nounwind {
484 tail call void @eightparams64(i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 0, i64 -1)