xref: /aosp_15_r20/external/llvm/test/CodeGen/X86/movtopush.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-windows | FileCheck %s -check-prefix=NORMAL
2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-windows -no-x86-call-frame-opt | FileCheck %s -check-prefix=NOPUSH
3*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64
4*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-windows -stackrealign -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED
5*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX
6*9880d681SAndroid Build Coastguard Worker
7*9880d681SAndroid Build Coastguard Worker%class.Class = type { i32 }
8*9880d681SAndroid Build Coastguard Worker%struct.s = type { i64 }
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Workerdeclare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
11*9880d681SAndroid Build Coastguard Workerdeclare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)
12*9880d681SAndroid Build Coastguard Workerdeclare x86_thiscallcc void @thiscall(%class.Class* %class, i32 %a, i32 %b, i32 %c, i32 %d)
13*9880d681SAndroid Build Coastguard Workerdeclare void @oneparam(i32 %a)
14*9880d681SAndroid Build Coastguard Workerdeclare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
15*9880d681SAndroid Build Coastguard Workerdeclare void @struct(%struct.s* byval %a, i32 %b, i32 %c, i32 %d)
16*9880d681SAndroid Build Coastguard Workerdeclare void @inalloca(<{ %struct.s }>* inalloca)
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Workerdeclare i8* @llvm.stacksave()
19*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.stackrestore(i8*)
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker; We should get pushes for x86, even though there is a reserved call frame.
22*9880d681SAndroid Build Coastguard Worker; Make sure we don't touch x86-64, and that turning it off works.
23*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test1:
24*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: subl {{.*}} %esp
25*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl   $4
26*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3
27*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2
28*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
29*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
30*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
31*9880d681SAndroid Build Coastguard Worker; X64-LABEL: test1:
32*9880d681SAndroid Build Coastguard Worker; X64: movl    $1, %ecx
33*9880d681SAndroid Build Coastguard Worker; X64-NEXT: movl    $2, %edx
34*9880d681SAndroid Build Coastguard Worker; X64-NEXT: movl    $3, %r8d
35*9880d681SAndroid Build Coastguard Worker; X64-NEXT: movl    $4, %r9d
36*9880d681SAndroid Build Coastguard Worker; X64-NEXT: callq   good
37*9880d681SAndroid Build Coastguard Worker; NOPUSH-LABEL: test1:
38*9880d681SAndroid Build Coastguard Worker; NOPUSH: subl    $16, %esp
39*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: movl    $4, 12(%esp)
40*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: movl    $3, 8(%esp)
41*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: movl    $2, 4(%esp)
42*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: movl    $1, (%esp)
43*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: call
44*9880d681SAndroid Build Coastguard Worker; NOPUSH-NEXT: addl $16, %esp
45*9880d681SAndroid Build Coastguard Workerdefine void @test1() {
46*9880d681SAndroid Build Coastguard Workerentry:
47*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 3, i32 4)
48*9880d681SAndroid Build Coastguard Worker  ret void
49*9880d681SAndroid Build Coastguard Worker}
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker; If we have a reserved frame, we should have pushes
52*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test2:
53*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: subl {{.*}} %esp
54*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl   $4
55*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3
56*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2
57*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
58*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
59*9880d681SAndroid Build Coastguard Workerdefine void @test2(i32 %k) {
60*9880d681SAndroid Build Coastguard Workerentry:
61*9880d681SAndroid Build Coastguard Worker  %a = alloca i32, i32 %k
62*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 3, i32 4)
63*9880d681SAndroid Build Coastguard Worker  ret void
64*9880d681SAndroid Build Coastguard Worker}
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker; Again, we expect a sequence of 4 immediate pushes
67*9880d681SAndroid Build Coastguard Worker; Checks that we generate the right pushes for >8bit immediates
68*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test2b:
69*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: subl {{.*}} %esp
70*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl   $4096
71*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3072
72*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2048
73*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1024
74*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
75*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
76*9880d681SAndroid Build Coastguard Workerdefine void @test2b() optsize {
77*9880d681SAndroid Build Coastguard Workerentry:
78*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1024, i32 2048, i32 3072, i32 4096)
79*9880d681SAndroid Build Coastguard Worker  ret void
80*9880d681SAndroid Build Coastguard Worker}
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker; The first push should push a register
83*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test3:
84*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: subl {{.*}} %esp
85*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl   $4
86*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3
87*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2
88*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   %e{{..}}
89*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
90*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
91*9880d681SAndroid Build Coastguard Workerdefine void @test3(i32 %k) optsize {
92*9880d681SAndroid Build Coastguard Workerentry:
93*9880d681SAndroid Build Coastguard Worker  %f = add i32 %k, 1
94*9880d681SAndroid Build Coastguard Worker  call void @good(i32 %f, i32 2, i32 3, i32 4)
95*9880d681SAndroid Build Coastguard Worker  ret void
96*9880d681SAndroid Build Coastguard Worker}
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker; We support weird calling conventions
99*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test4:
100*9880d681SAndroid Build Coastguard Worker; NORMAL: movl    $2, %eax
101*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $4
102*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3
103*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
104*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
105*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $12, %esp
106*9880d681SAndroid Build Coastguard Workerdefine void @test4() optsize {
107*9880d681SAndroid Build Coastguard Workerentry:
108*9880d681SAndroid Build Coastguard Worker  call void @inreg(i32 1, i32 2, i32 3, i32 4)
109*9880d681SAndroid Build Coastguard Worker  ret void
110*9880d681SAndroid Build Coastguard Worker}
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test4b:
113*9880d681SAndroid Build Coastguard Worker; NORMAL: movl 4(%esp), %ecx
114*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $4
115*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $3
116*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2
117*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
118*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
119*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: ret
120*9880d681SAndroid Build Coastguard Workerdefine void @test4b(%class.Class* %f) optsize {
121*9880d681SAndroid Build Coastguard Workerentry:
122*9880d681SAndroid Build Coastguard Worker  call x86_thiscallcc void @thiscall(%class.Class* %f, i32 1, i32 2, i32 3, i32 4)
123*9880d681SAndroid Build Coastguard Worker  ret void
124*9880d681SAndroid Build Coastguard Worker}
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker; When there is no reserved call frame, check that additional alignment
127*9880d681SAndroid Build Coastguard Worker; is added when the pushes don't add up to the required alignment.
128*9880d681SAndroid Build Coastguard Worker; ALIGNED-LABEL: test5:
129*9880d681SAndroid Build Coastguard Worker; ALIGNED: subl    $16, %esp
130*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $4
131*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $3
132*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $2
133*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $1
134*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: call
135*9880d681SAndroid Build Coastguard Workerdefine void @test5(i32 %k) {
136*9880d681SAndroid Build Coastguard Workerentry:
137*9880d681SAndroid Build Coastguard Worker  %a = alloca i32, i32 %k
138*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 3, i32 4)
139*9880d681SAndroid Build Coastguard Worker  ret void
140*9880d681SAndroid Build Coastguard Worker}
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker; When the alignment adds up, do the transformation
143*9880d681SAndroid Build Coastguard Worker; ALIGNED-LABEL: test5b:
144*9880d681SAndroid Build Coastguard Worker; ALIGNED: pushl   $8
145*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $7
146*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $6
147*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $5
148*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $4
149*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $3
150*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $2
151*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: pushl   $1
152*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: call
153*9880d681SAndroid Build Coastguard Workerdefine void @test5b() optsize {
154*9880d681SAndroid Build Coastguard Workerentry:
155*9880d681SAndroid Build Coastguard Worker  call void @eightparams(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8)
156*9880d681SAndroid Build Coastguard Worker  ret void
157*9880d681SAndroid Build Coastguard Worker}
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker; When having to compensate for the alignment isn't worth it,
160*9880d681SAndroid Build Coastguard Worker; don't use pushes.
161*9880d681SAndroid Build Coastguard Worker; ALIGNED-LABEL: test5c:
162*9880d681SAndroid Build Coastguard Worker; ALIGNED: movl $1, (%esp)
163*9880d681SAndroid Build Coastguard Worker; ALIGNED-NEXT: call
164*9880d681SAndroid Build Coastguard Workerdefine void @test5c() optsize {
165*9880d681SAndroid Build Coastguard Workerentry:
166*9880d681SAndroid Build Coastguard Worker  call void @oneparam(i32 1)
167*9880d681SAndroid Build Coastguard Worker  ret void
168*9880d681SAndroid Build Coastguard Worker}
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker; Check that pushing the addresses of globals (Or generally, things that
171*9880d681SAndroid Build Coastguard Worker; aren't exactly immediates) isn't broken.
172*9880d681SAndroid Build Coastguard Worker; Fixes PR21878.
173*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test6:
174*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl    $_ext
175*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
176*9880d681SAndroid Build Coastguard Workerdeclare void @f(i8*)
177*9880d681SAndroid Build Coastguard Worker@ext = external constant i8
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Workerdefine void @test6() {
180*9880d681SAndroid Build Coastguard Worker  call void @f(i8* @ext)
181*9880d681SAndroid Build Coastguard Worker  br label %bb
182*9880d681SAndroid Build Coastguard Workerbb:
183*9880d681SAndroid Build Coastguard Worker  alloca i32
184*9880d681SAndroid Build Coastguard Worker  ret void
185*9880d681SAndroid Build Coastguard Worker}
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker; Check that we fold simple cases into the push
188*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test7:
189*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: subl {{.*}} %esp
190*9880d681SAndroid Build Coastguard Worker; NORMAL: movl 4(%esp), [[EAX:%e..]]
191*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $4
192*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   ([[EAX]])
193*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $2
194*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
195*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
196*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
197*9880d681SAndroid Build Coastguard Workerdefine void @test7(i32* %ptr) optsize {
198*9880d681SAndroid Build Coastguard Workerentry:
199*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %ptr
200*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 %val, i32 4)
201*9880d681SAndroid Build Coastguard Worker  ret void
202*9880d681SAndroid Build Coastguard Worker}
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker; Fold stack-relative loads into the push, with correct offset
205*9880d681SAndroid Build Coastguard Worker; In particular, at the second push, %b was at 12(%esp) and
206*9880d681SAndroid Build Coastguard Worker; %a wast at 8(%esp), but the second push bumped %esp, so %a
207*9880d681SAndroid Build Coastguard Worker; is now it at 12(%esp)
208*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test8:
209*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl   $4
210*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   12(%esp)
211*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   12(%esp)
212*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl   $1
213*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
214*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
215*9880d681SAndroid Build Coastguard Workerdefine void @test8(i32 %a, i32 %b) optsize {
216*9880d681SAndroid Build Coastguard Workerentry:
217*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 %a, i32 %b, i32 4)
218*9880d681SAndroid Build Coastguard Worker  ret void
219*9880d681SAndroid Build Coastguard Worker}
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker; If one function is using push instructions, and the other isn't
222*9880d681SAndroid Build Coastguard Worker; (because it has frame-index references), then we must resolve
223*9880d681SAndroid Build Coastguard Worker; these references correctly.
224*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test9:
225*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: leal (%esp),
226*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl $4
227*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $3
228*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $2
229*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $1
230*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
231*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: subl $4, %esp
232*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl 20(%esp), [[E1:%e..]]
233*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl 24(%esp), [[E2:%e..]]
234*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    [[E2]], 4(%esp)
235*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    [[E1]], (%esp)
236*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: leal 32(%esp), [[E3:%e..]]
237*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    [[E3]], 16(%esp)
238*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: leal 28(%esp), [[E4:%e..]]
239*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    [[E4]], 12(%esp)
240*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $6, 8(%esp)
241*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
242*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $20, %esp
243*9880d681SAndroid Build Coastguard Workerdefine void @test9() optsize {
244*9880d681SAndroid Build Coastguard Workerentry:
245*9880d681SAndroid Build Coastguard Worker  %p = alloca i32, align 4
246*9880d681SAndroid Build Coastguard Worker  %q = alloca i32, align 4
247*9880d681SAndroid Build Coastguard Worker  %s = alloca %struct.s, align 4
248*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 3, i32 4)
249*9880d681SAndroid Build Coastguard Worker  %pv = ptrtoint i32* %p to i32
250*9880d681SAndroid Build Coastguard Worker  %qv = ptrtoint i32* %q to i32
251*9880d681SAndroid Build Coastguard Worker  call void @struct(%struct.s* byval %s, i32 6, i32 %qv, i32 %pv)
252*9880d681SAndroid Build Coastguard Worker  ret void
253*9880d681SAndroid Build Coastguard Worker}
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker; We can end up with an indirect call which gets reloaded on the spot.
256*9880d681SAndroid Build Coastguard Worker; Make sure we reference the correct stack slot - we spill into (%esp)
257*9880d681SAndroid Build Coastguard Worker; and reload from 16(%esp) due to the pushes.
258*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test10:
259*9880d681SAndroid Build Coastguard Worker; NORMAL: movl $_good, [[ALLOC:.*]]
260*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]
261*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill
262*9880d681SAndroid Build Coastguard Worker; NORMAL: nop
263*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl $4
264*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $3
265*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $2
266*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $1
267*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll *16(%esp)
268*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $24, %esp
269*9880d681SAndroid Build Coastguard Workerdefine void @test10() optsize {
270*9880d681SAndroid Build Coastguard Worker  %stack_fptr = alloca void (i32, i32, i32, i32)*
271*9880d681SAndroid Build Coastguard Worker  store void (i32, i32, i32, i32)* @good, void (i32, i32, i32, i32)** %stack_fptr
272*9880d681SAndroid Build Coastguard Worker  %good_ptr = load volatile void (i32, i32, i32, i32)*, void (i32, i32, i32, i32)** %stack_fptr
273*9880d681SAndroid Build Coastguard Worker  call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()
274*9880d681SAndroid Build Coastguard Worker  call void (i32, i32, i32, i32) %good_ptr(i32 1, i32 2, i32 3, i32 4)
275*9880d681SAndroid Build Coastguard Worker  ret void
276*9880d681SAndroid Build Coastguard Worker}
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker; We can't fold the load from the global into the push because of
279*9880d681SAndroid Build Coastguard Worker; interference from the store
280*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test11:
281*9880d681SAndroid Build Coastguard Worker; NORMAL: movl    _the_global, [[EAX:%e..]]
282*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $42, _the_global
283*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $4
284*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $3
285*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl $2
286*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl [[EAX]]
287*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: call
288*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
289*9880d681SAndroid Build Coastguard Worker@the_global = external global i32
290*9880d681SAndroid Build Coastguard Workerdefine void @test11() optsize {
291*9880d681SAndroid Build Coastguard Worker  %myload = load i32, i32* @the_global
292*9880d681SAndroid Build Coastguard Worker  store i32 42, i32* @the_global
293*9880d681SAndroid Build Coastguard Worker  call void @good(i32 %myload, i32 2, i32 3, i32 4)
294*9880d681SAndroid Build Coastguard Worker  ret void
295*9880d681SAndroid Build Coastguard Worker}
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker; Converting one mov into a push isn't worth it when
298*9880d681SAndroid Build Coastguard Worker; doing so forces too much overhead for other calls.
299*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test12:
300*9880d681SAndroid Build Coastguard Worker; NORMAL: movl    $8, 12(%esp)
301*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $7, 8(%esp)
302*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $6, 4(%esp)
303*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $5, (%esp)
304*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll _good
305*9880d681SAndroid Build Coastguard Workerdefine void @test12() optsize {
306*9880d681SAndroid Build Coastguard Workerentry:
307*9880d681SAndroid Build Coastguard Worker  %s = alloca %struct.s, align 4
308*9880d681SAndroid Build Coastguard Worker  call void @struct(%struct.s* %s, i32 2, i32 3, i32 4)
309*9880d681SAndroid Build Coastguard Worker  call void @good(i32 5, i32 6, i32 7, i32 8)
310*9880d681SAndroid Build Coastguard Worker  call void @struct(%struct.s* %s, i32 10, i32 11, i32 12)
311*9880d681SAndroid Build Coastguard Worker  ret void
312*9880d681SAndroid Build Coastguard Worker}
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker; But if the gains outweigh the overhead, we should do it
315*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test12b:
316*9880d681SAndroid Build Coastguard Worker; NORMAL: pushl    $4
317*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $3
318*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $2
319*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $1
320*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll _good
321*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: subl    $4, %esp
322*9880d681SAndroid Build Coastguard Worker; NORMAL: movl    $8, 16(%esp)
323*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $7, 12(%esp)
324*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl    $6, 8(%esp)
325*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll _struct
326*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl    $20, %esp
327*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $12
328*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $11
329*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $10
330*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl    $9
331*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll _good
332*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: addl $16, %esp
333*9880d681SAndroid Build Coastguard Workerdefine void @test12b() optsize {
334*9880d681SAndroid Build Coastguard Workerentry:
335*9880d681SAndroid Build Coastguard Worker  %s = alloca %struct.s, align 4
336*9880d681SAndroid Build Coastguard Worker  call void @good(i32 1, i32 2, i32 3, i32 4)
337*9880d681SAndroid Build Coastguard Worker  call void @struct(%struct.s* %s, i32 6, i32 7, i32 8)
338*9880d681SAndroid Build Coastguard Worker  call void @good(i32 9, i32 10, i32 11, i32 12)
339*9880d681SAndroid Build Coastguard Worker  ret void
340*9880d681SAndroid Build Coastguard Worker}
341*9880d681SAndroid Build Coastguard Worker
342*9880d681SAndroid Build Coastguard Worker; Make sure the add does not prevent folding loads into pushes.
343*9880d681SAndroid Build Coastguard Worker; val1 and val2 will not be folded into pushes since they have
344*9880d681SAndroid Build Coastguard Worker; an additional use, but val3 should be.
345*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test13:
346*9880d681SAndroid Build Coastguard Worker; NORMAL: movl ([[P1:%e..]]), [[V1:%e..]]
347*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: movl ([[P2:%e..]]), [[V2:%e..]]
348*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: , [[ADD:%e..]]
349*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl [[ADD]]
350*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl ([[P3:%e..]])
351*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl [[V2]]
352*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: pushl [[V1]]
353*9880d681SAndroid Build Coastguard Worker; NORMAL-NEXT: calll _good
354*9880d681SAndroid Build Coastguard Worker; NORMAL: movl [[P3]], %eax
355*9880d681SAndroid Build Coastguard Workerdefine i32* @test13(i32* inreg %ptr1, i32* inreg %ptr2, i32* inreg %ptr3) optsize {
356*9880d681SAndroid Build Coastguard Workerentry:
357*9880d681SAndroid Build Coastguard Worker  %val1 = load i32, i32* %ptr1
358*9880d681SAndroid Build Coastguard Worker  %val2 = load i32, i32* %ptr2
359*9880d681SAndroid Build Coastguard Worker  %val3 = load i32, i32* %ptr3
360*9880d681SAndroid Build Coastguard Worker  %add = add i32 %val1, %val2
361*9880d681SAndroid Build Coastguard Worker  call void @good(i32 %val1, i32 %val2, i32 %val3, i32 %add)
362*9880d681SAndroid Build Coastguard Worker  ret i32* %ptr3
363*9880d681SAndroid Build Coastguard Worker}
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker; Make sure to fold adjacent stack adjustments.
366*9880d681SAndroid Build Coastguard Worker; LINUX-LABEL: pr27140:
367*9880d681SAndroid Build Coastguard Worker; LINUX: subl    $12, %esp
368*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_def_cfa_offset 16
369*9880d681SAndroid Build Coastguard Worker; LINUX-NOT: sub
370*9880d681SAndroid Build Coastguard Worker; LINUX: pushl   $4
371*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_adjust_cfa_offset 4
372*9880d681SAndroid Build Coastguard Worker; LINUX: pushl   $3
373*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_adjust_cfa_offset 4
374*9880d681SAndroid Build Coastguard Worker; LINUX: pushl   $2
375*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_adjust_cfa_offset 4
376*9880d681SAndroid Build Coastguard Worker; LINUX: pushl   $1
377*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_adjust_cfa_offset 4
378*9880d681SAndroid Build Coastguard Worker; LINUX: calll   good
379*9880d681SAndroid Build Coastguard Worker; LINUX: addl    $28, %esp
380*9880d681SAndroid Build Coastguard Worker; LINUX: .cfi_adjust_cfa_offset -16
381*9880d681SAndroid Build Coastguard Worker; LINUX-NOT: add
382*9880d681SAndroid Build Coastguard Worker; LINUX: retl
383*9880d681SAndroid Build Coastguard Workerdefine void @pr27140() optsize {
384*9880d681SAndroid Build Coastguard Workerentry:
385*9880d681SAndroid Build Coastguard Worker  tail call void @good(i32 1, i32 2, i32 3, i32 4)
386*9880d681SAndroid Build Coastguard Worker  ret void
387*9880d681SAndroid Build Coastguard Worker}
388*9880d681SAndroid Build Coastguard Worker
389*9880d681SAndroid Build Coastguard Worker; Check that a stack restore (leal -4(%ebp), %esp) doesn't get merged with a
390*9880d681SAndroid Build Coastguard Worker; stack adjustment (addl $12, %esp). Just because it's a lea doesn't mean it's
391*9880d681SAndroid Build Coastguard Worker; simply decreasing the stack pointer.
392*9880d681SAndroid Build Coastguard Worker; NORMAL-LABEL: test14:
393*9880d681SAndroid Build Coastguard Worker; NORMAL: calll _B_func
394*9880d681SAndroid Build Coastguard Worker; NORMAL: leal -4(%ebp), %esp
395*9880d681SAndroid Build Coastguard Worker; NORMAL-NOT: %esp
396*9880d681SAndroid Build Coastguard Worker; NORMAL: retl
397*9880d681SAndroid Build Coastguard Worker%struct.A = type { i32, i32 }
398*9880d681SAndroid Build Coastguard Worker%struct.B = type { i8 }
399*9880d681SAndroid Build Coastguard Workerdeclare x86_thiscallcc %struct.B* @B_ctor(%struct.B* returned, %struct.A* byval)
400*9880d681SAndroid Build Coastguard Workerdeclare void @B_func(%struct.B* sret, %struct.B*, i32)
401*9880d681SAndroid Build Coastguard Workerdefine void @test14(%struct.A* %a) {
402*9880d681SAndroid Build Coastguard Workerentry:
403*9880d681SAndroid Build Coastguard Worker  %ref.tmp = alloca %struct.B, align 1
404*9880d681SAndroid Build Coastguard Worker  %agg.tmp = alloca i64, align 4
405*9880d681SAndroid Build Coastguard Worker  %tmpcast = bitcast i64* %agg.tmp to %struct.A*
406*9880d681SAndroid Build Coastguard Worker  %tmp = alloca %struct.B, align 1
407*9880d681SAndroid Build Coastguard Worker  %0 = bitcast %struct.A* %a to i64*
408*9880d681SAndroid Build Coastguard Worker  %1 = load i64, i64* %0, align 4
409*9880d681SAndroid Build Coastguard Worker  store i64 %1, i64* %agg.tmp, align 4
410*9880d681SAndroid Build Coastguard Worker  %call = call x86_thiscallcc %struct.B* @B_ctor(%struct.B* %ref.tmp, %struct.A* byval %tmpcast)
411*9880d681SAndroid Build Coastguard Worker  %2 = getelementptr inbounds %struct.B, %struct.B* %tmp, i32 0, i32 0
412*9880d681SAndroid Build Coastguard Worker  call void @B_func(%struct.B* sret %tmp, %struct.B* %ref.tmp, i32 1)
413*9880d681SAndroid Build Coastguard Worker  ret void
414*9880d681SAndroid Build Coastguard Worker}
415