blob: 939c2f03e2baa69ba36b183d2cc9d0cae59099bd [file] [log] [blame]
Reid Klecknerf7c09802017-03-01 21:42:00 +00001; RUN: llc -mtriple=i686-windows < %s | FileCheck %s
2
Matthias Braun21f340f2017-03-04 01:40:40 +00003declare void @addrof_i1(i1*)
Reid Klecknerf7c09802017-03-01 21:42:00 +00004declare void @addrof_i32(i32*)
5declare void @addrof_i64(i64*)
6declare void @addrof_i128(i128*)
7declare void @addrof_i32_x3(i32*, i32*, i32*)
8
9define void @simple(i32 %x) {
10entry:
11 %x.addr = alloca i32
12 store i32 %x, i32* %x.addr
13 call void @addrof_i32(i32* %x.addr)
14 ret void
15}
16
17; CHECK-LABEL: _simple:
18; CHECK: leal 4(%esp), %[[reg:[^ ]*]]
19; CHECK: pushl %[[reg]]
20; CHECK: calll _addrof_i32
21; CHECK: retl
22
23
24; We need to load %x before calling addrof_i32 now because it could mutate %x in
25; place.
26
27define i32 @use_arg(i32 %x) {
28entry:
29 %x.addr = alloca i32
30 store i32 %x, i32* %x.addr
31 call void @addrof_i32(i32* %x.addr)
32 ret i32 %x
33}
34
35; CHECK-LABEL: _use_arg:
36; CHECK: pushl %[[csr:[^ ]*]]
37; CHECK-DAG: movl 8(%esp), %[[csr]]
38; CHECK-DAG: leal 8(%esp), %[[reg:[^ ]*]]
39; CHECK: pushl %[[reg]]
40; CHECK: calll _addrof_i32
41; CHECK: movl %[[csr]], %eax
42; CHECK: popl %[[csr]]
43; CHECK: retl
44
Matthias Braun21f340f2017-03-04 01:40:40 +000045; We won't copy elide for types needing legalization such as i64 or i1.
Reid Klecknerf7c09802017-03-01 21:42:00 +000046
47define i64 @split_i64(i64 %x) {
48entry:
49 %x.addr = alloca i64, align 4
50 store i64 %x, i64* %x.addr, align 4
51 call void @addrof_i64(i64* %x.addr)
52 ret i64 %x
53}
54
55; CHECK-LABEL: _split_i64:
56; CHECK: pushl %ebp
57; CHECK: movl %esp, %ebp
58; CHECK: pushl %[[csr2:[^ ]*]]
59; CHECK: pushl %[[csr1:[^ ]*]]
60; CHECK: andl $-8, %esp
61; CHECK-DAG: movl 8(%ebp), %[[csr1]]
62; CHECK-DAG: movl 12(%ebp), %[[csr2]]
Matthias Braun21f340f2017-03-04 01:40:40 +000063; CHECK: movl %edi, 4(%esp)
64; CHECK: movl %esi, (%esp)
65; CEHCK: movl %esp, %eax
66; CHECK: pushl %eax
Reid Klecknerf7c09802017-03-01 21:42:00 +000067; CHECK: calll _addrof_i64
68; CHECK-DAG: movl %[[csr1]], %eax
69; CHECK-DAG: movl %[[csr2]], %edx
70; CHECK: leal -8(%ebp), %esp
71; CHECK: popl %[[csr1]]
72; CHECK: popl %[[csr2]]
73; CHECK: popl %ebp
74; CHECK: retl
75
Matthias Braun21f340f2017-03-04 01:40:40 +000076define i1 @i1_arg(i1 %x) {
77 %x.addr = alloca i1
78 store i1 %x, i1* %x.addr
79 call void @addrof_i1(i1* %x.addr)
80 ret i1 %x
81}
82
83; CHECK-LABEL: _i1_arg:
84; CHECK: pushl %ebx
85; CHECK: movb 8(%esp), %bl
86; CHECK: leal 8(%esp), %eax
87; CHECK: pushl %eax
88; CHECK: calll _addrof_i1
89; CHECK: addl $4, %esp
90; CHECK: movl %ebx, %eax
91; CHECK: popl %ebx
92; CHECK: retl
Reid Klecknerf7c09802017-03-01 21:42:00 +000093
94; We can't copy elide when an i64 is split between registers and memory in a
95; fastcc function.
96
97define fastcc i64 @fastcc_split_i64(i64* %p, i64 %x) {
98entry:
99 %x.addr = alloca i64, align 4
100 store i64 %x, i64* %x.addr, align 4
101 call void @addrof_i64(i64* %x.addr)
102 ret i64 %x
103}
104
105; CHECK-LABEL: _fastcc_split_i64:
106; CHECK: pushl %ebp
107; CHECK: movl %esp, %ebp
108; CHECK-DAG: movl %edx, %[[r1:[^ ]*]]
109; CHECK-DAG: movl 8(%ebp), %[[r2:[^ ]*]]
110; CHECK-DAG: movl %[[r2]], 4(%esp)
111; CHECK-DAG: movl %[[r1]], (%esp)
112; CHECK: movl %esp, %[[reg:[^ ]*]]
113; CHECK: pushl %[[reg]]
114; CHECK: calll _addrof_i64
115; CHECK: popl %ebp
116; CHECK: retl
117
118
119; We can't copy elide when it would reduce the user requested alignment.
120
121define void @high_alignment(i32 %x) {
122entry:
123 %x.p = alloca i32, align 128
124 store i32 %x, i32* %x.p
125 call void @addrof_i32(i32* %x.p)
126 ret void
127}
128
129; CHECK-LABEL: _high_alignment:
130; CHECK: andl $-128, %esp
131; CHECK: movl 8(%ebp), %[[reg:[^ ]*]]
132; CHECK: movl %[[reg]], (%esp)
133; CHECK: movl %esp, %[[reg:[^ ]*]]
134; CHECK: pushl %[[reg]]
135; CHECK: calll _addrof_i32
136; CHECK: retl
137
138
139; We can't copy elide when it would reduce the ABI required alignment.
140; FIXME: We should lower the ABI alignment of i64 on Windows, since MSVC
141; doesn't guarantee it.
142
143define void @abi_alignment(i64 %x) {
144entry:
145 %x.p = alloca i64
146 store i64 %x, i64* %x.p
147 call void @addrof_i64(i64* %x.p)
148 ret void
149}
150
151; CHECK-LABEL: _abi_alignment:
152; CHECK: andl $-8, %esp
153; CHECK: movl 8(%ebp), %[[reg:[^ ]*]]
154; CHECK: movl %[[reg]], (%esp)
155; CHECK: movl %esp, %[[reg:[^ ]*]]
156; CHECK: pushl %[[reg]]
157; CHECK: calll _addrof_i64
158; CHECK: retl
159
160
161; The code we generate for this is unimportant. This is mostly a crash test.
162
163define void @split_i128(i128* %sret, i128 %x) {
164entry:
165 %x.addr = alloca i128
166 store i128 %x, i128* %x.addr
167 call void @addrof_i128(i128* %x.addr)
168 store i128 %x, i128* %sret
169 ret void
170}
171
172; CHECK-LABEL: _split_i128:
173; CHECK: pushl %ebp
174; CHECK: calll _addrof_i128
175; CHECK: retl
176
177
178; Check that we load all of x, y, and z before the call.
179
180define i32 @three_args(i32 %x, i32 %y, i32 %z) {
181entry:
182 %z.addr = alloca i32, align 4
183 %y.addr = alloca i32, align 4
184 %x.addr = alloca i32, align 4
185 store i32 %z, i32* %z.addr, align 4
186 store i32 %y, i32* %y.addr, align 4
187 store i32 %x, i32* %x.addr, align 4
188 call void @addrof_i32_x3(i32* %x.addr, i32* %y.addr, i32* %z.addr)
189 %s1 = add i32 %x, %y
190 %sum = add i32 %s1, %z
191 ret i32 %sum
192}
193
194; CHECK-LABEL: _three_args:
195; CHECK: pushl %[[csr:[^ ]*]]
196; CHECK-DAG: movl {{[0-9]+}}(%esp), %[[csr]]
197; CHECK-DAG: addl {{[0-9]+}}(%esp), %[[csr]]
198; CHECK-DAG: addl {{[0-9]+}}(%esp), %[[csr]]
199; CHECK-DAG: leal 8(%esp), %[[x:[^ ]*]]
200; CHECK-DAG: leal 12(%esp), %[[y:[^ ]*]]
201; CHECK-DAG: leal 16(%esp), %[[z:[^ ]*]]
202; CHECK: pushl %[[z]]
203; CHECK: pushl %[[y]]
204; CHECK: pushl %[[x]]
205; CHECK: calll _addrof_i32_x3
206; CHECK: movl %[[csr]], %eax
207; CHECK: popl %[[csr]]
208; CHECK: retl
209
210
211define void @two_args_same_alloca(i32 %x, i32 %y) {
212entry:
213 %x.addr = alloca i32
214 store i32 %x, i32* %x.addr
215 store i32 %y, i32* %x.addr
216 call void @addrof_i32(i32* %x.addr)
217 ret void
218}
219
220; CHECK-LABEL: _two_args_same_alloca:
221; CHECK: movl 8(%esp), {{.*}}
222; CHECK: movl {{.*}}, 4(%esp)
223; CHECK: leal 4(%esp), %[[reg:[^ ]*]]
224; CHECK: pushl %[[reg]]
225; CHECK: calll _addrof_i32
226; CHECK: retl
227
228
229define void @avoid_byval(i32* byval %x) {
230entry:
231 %x.p.p = alloca i32*
232 store i32* %x, i32** %x.p.p
233 call void @addrof_i32(i32* %x)
234 ret void
235}
236
237; CHECK-LABEL: _avoid_byval:
238; CHECK: leal {{[0-9]+}}(%esp), %[[reg:[^ ]*]]
239; CHECK: pushl %[[reg]]
240; CHECK: calll _addrof_i32
241; CHECK: retl
242
243
244define void @avoid_inalloca(i32* inalloca %x) {
245entry:
246 %x.p.p = alloca i32*
247 store i32* %x, i32** %x.p.p
248 call void @addrof_i32(i32* %x)
249 ret void
250}
251
252; CHECK-LABEL: _avoid_inalloca:
253; CHECK: leal {{[0-9]+}}(%esp), %[[reg:[^ ]*]]
254; CHECK: pushl %[[reg]]
255; CHECK: calll _addrof_i32
256; CHECK: retl
257
258
259; Don't elide the copy when the alloca is escaped with a store.
260
261define void @escape_with_store(i32 %x) {
262 %x1 = alloca i32
263 %x2 = alloca i32*
264 store i32* %x1, i32** %x2
265 %x3 = load i32*, i32** %x2
266 store i32 0, i32* %x3
267 store i32 %x, i32* %x1
268 call void @addrof_i32(i32* %x1)
269 ret void
270}
271
272; CHECK-LABEL: _escape_with_store:
273; CHECK-DAG: movl {{.*}}(%esp), %[[reg:[^ ]*]]
274; CHECK-DAG: movl $0, [[offs:[0-9]*]](%esp)
275; CHECK: movl %[[reg]], [[offs]](%esp)
276; CHECK: calll _addrof_i32
277
278
279; This test case exposed issues with the use of TokenFactor.
280
281define void @sret_and_elide(i32* sret %sret, i32 %v) {
282 %v.p = alloca i32
283 store i32 %v, i32* %v.p
284 call void @addrof_i32(i32* %v.p)
285 store i32 %v, i32* %sret
286 ret void
287}
288
289; CHECK-LABEL: _sret_and_elide:
290; CHECK: pushl
291; CHECK: pushl
292; CHECK: movl 12(%esp), %[[sret:[^ ]*]]
293; CHECK: movl 16(%esp), %[[v:[^ ]*]]
294; CHECK: leal 16(%esp), %[[reg:[^ ]*]]
295; CHECK: pushl %[[reg]]
296; CHECK: calll _addrof_i32
297; CHECK: movl %[[v]], (%[[sret]])
298; CHECK: movl %[[sret]], %eax
299; CHECK: popl
300; CHECK: popl
301; CHECK: retl