comparison test/CodeGen/X86/sibcall.ll @ 147:c2174574ed3a

LLVM 10
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 14 Aug 2019 16:55:33 +0900
parents afa8332a0e37
children
comparison
equal deleted inserted replaced
134:3a76565eade5 147:c2174574ed3a
1 ; RUN: llc < %s -mtriple=i686-linux -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=32 1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-linux -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=64 2 ; RUN: llc -verify-machineinstrs < %s -mtriple=i686-linux -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X86
3 ; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=X32ABI 3 ; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X64
4 ; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-linux-gnux32 -mcpu=core2 -mattr=+sse2 | FileCheck %s --check-prefix=X32
4 5
5 define void @t1(i32 %x) nounwind ssp { 6 define void @t1(i32 %x) nounwind ssp {
6 entry: 7 ; X86-LABEL: t1:
7 ; 32-LABEL: t1: 8 ; X86: # %bb.0:
8 ; 32: jmp {{_?}}foo 9 ; X86-NEXT: jmp foo # TAILCALL
9 10 ;
10 ; 64-LABEL: t1: 11 ; X64-LABEL: t1:
11 ; 64: jmp {{_?}}foo 12 ; X64: # %bb.0:
12 13 ; X64-NEXT: jmp foo # TAILCALL
13 ; X32ABI-LABEL: t1: 14 ;
14 ; X32ABI: jmp {{_?}}foo 15 ; X32-LABEL: t1:
16 ; X32: # %bb.0:
17 ; X32-NEXT: jmp foo # TAILCALL
15 tail call void @foo() nounwind 18 tail call void @foo() nounwind
16 ret void 19 ret void
17 } 20 }
18 21
19 declare void @foo() 22 declare void @foo()
20 23
21 define void @t2() nounwind ssp { 24 define void @t2() nounwind ssp {
22 entry: 25 ; X86-LABEL: t2:
23 ; 32-LABEL: t2: 26 ; X86: # %bb.0:
24 ; 32: jmp {{_?}}foo2 27 ; X86-NEXT: jmp foo2 # TAILCALL
25 28 ;
26 ; 64-LABEL: t2: 29 ; X64-LABEL: t2:
27 ; 64: jmp {{_?}}foo2 30 ; X64: # %bb.0:
28 31 ; X64-NEXT: jmp foo2 # TAILCALL
29 ; X32ABI-LABEL: t2: 32 ;
30 ; X32ABI: jmp {{_?}}foo2 33 ; X32-LABEL: t2:
31 %0 = tail call i32 @foo2() nounwind 34 ; X32: # %bb.0:
35 ; X32-NEXT: jmp foo2 # TAILCALL
36 %t0 = tail call i32 @foo2() nounwind
32 ret void 37 ret void
33 } 38 }
34 39
35 declare i32 @foo2() 40 declare i32 @foo2()
36 41
37 define void @t3() nounwind ssp { 42 define void @t3() nounwind ssp {
38 entry: 43 ; X86-LABEL: t3:
39 ; 32-LABEL: t3: 44 ; X86: # %bb.0:
40 ; 32: jmp {{_?}}foo3 45 ; X86-NEXT: jmp foo3 # TAILCALL
41 46 ;
42 ; 64-LABEL: t3: 47 ; X64-LABEL: t3:
43 ; 64: jmp {{_?}}foo3 48 ; X64: # %bb.0:
44 49 ; X64-NEXT: jmp foo3 # TAILCALL
45 ; X32ABI-LABEL: t3: 50 ;
46 ; X32ABI: jmp {{_?}}foo3 51 ; X32-LABEL: t3:
47 %0 = tail call i32 @foo3() nounwind 52 ; X32: # %bb.0:
53 ; X32-NEXT: jmp foo3 # TAILCALL
54 %t0 = tail call i32 @foo3() nounwind
48 ret void 55 ret void
49 } 56 }
50 57
51 declare i32 @foo3() 58 declare i32 @foo3()
52 59
53 define void @t4(void (i32)* nocapture %x) nounwind ssp { 60 define void @t4(void (i32)* nocapture %x) nounwind ssp {
54 entry: 61 ; X86-LABEL: t4:
55 ; 32-LABEL: t4: 62 ; X86: # %bb.0:
56 ; 32: calll * 63 ; X86-NEXT: subl $12, %esp
57 ; FIXME: gcc can generate a tailcall for this. But it's tricky. 64 ; X86-NEXT: movl $0, (%esp)
58 65 ; X86-NEXT: calll *{{[0-9]+}}(%esp)
59 ; 64-LABEL: t4: 66 ; X86-NEXT: addl $12, %esp
60 ; 64-NOT: call 67 ; X86-NEXT: retl
61 ; 64: jmpq * 68 ;
62 69 ; X64-LABEL: t4:
63 ; X32ABI-LABEL: t4: 70 ; X64: # %bb.0:
64 ; X32ABI-NOT: call 71 ; X64-NEXT: movq %rdi, %rax
65 ; X32ABI: jmpq * 72 ; X64-NEXT: xorl %edi, %edi
73 ; X64-NEXT: jmpq *%rax # TAILCALL
74 ;
75 ; X32-LABEL: t4:
76 ; X32: # %bb.0:
77 ; X32-NEXT: movl %edi, %eax
78 ; X32-NEXT: xorl %edi, %edi
79 ; X32-NEXT: jmpq *%rax # TAILCALL
66 tail call void %x(i32 0) nounwind 80 tail call void %x(i32 0) nounwind
67 ret void 81 ret void
68 } 82 }
69 83
70 define void @t5(void ()* nocapture %x) nounwind ssp {
71 entry:
72 ; 32-LABEL: t5:
73 ; 32-NOT: call
74 ; 32: jmpl *4(%esp)
75
76 ; 64-LABEL: t5:
77 ; 64-NOT: call
78 ; 64: jmpq *%rdi
79
80 ; X32ABI-LABEL: t5:
81 ; X32ABI-NOT: call
82 ; FIXME: This isn't needed since x32 psABI specifies that callers must 84 ; FIXME: This isn't needed since x32 psABI specifies that callers must
83 ; zero-extend pointers passed in registers. 85 ; zero-extend pointers passed in registers.
84 ; X32ABI: movl %edi, %eax 86
85 ; X32ABI: jmpq *%rax 87 define void @t5(void ()* nocapture %x) nounwind ssp {
88 ; X86-LABEL: t5:
89 ; X86: # %bb.0:
90 ; X86-NEXT: jmpl *{{[0-9]+}}(%esp) # TAILCALL
91 ;
92 ; X64-LABEL: t5:
93 ; X64: # %bb.0:
94 ; X64-NEXT: jmpq *%rdi # TAILCALL
95 ;
96 ; X32-LABEL: t5:
97 ; X32: # %bb.0:
98 ; X32-NEXT: movl %edi, %eax
99 ; X32-NEXT: jmpq *%rax # TAILCALL
86 tail call void %x() nounwind 100 tail call void %x() nounwind
87 ret void 101 ret void
88 } 102 }
89 103
104 ; Basically the same test as t5, except pass the function pointer on the stack
105 ; for x86_64.
106
107 define void @t5_x64(i32, i32, i32, i32, i32, i32, void ()* nocapture %x) nounwind ssp {
108 ; X86-LABEL: t5_x64:
109 ; X86: # %bb.0:
110 ; X86-NEXT: jmpl *{{[0-9]+}}(%esp) # TAILCALL
111 ;
112 ; X64-LABEL: t5_x64:
113 ; X64: # %bb.0:
114 ; X64-NEXT: jmpq *{{[0-9]+}}(%rsp) # TAILCALL
115 ;
116 ; X32-LABEL: t5_x64:
117 ; X32: # %bb.0:
118 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
119 ; X32-NEXT: jmpq *%rax # TAILCALL
120 tail call void %x() nounwind
121 ret void
122 }
123
124
90 define i32 @t6(i32 %x) nounwind ssp { 125 define i32 @t6(i32 %x) nounwind ssp {
91 entry: 126 ; X86-LABEL: t6:
92 ; 32-LABEL: t6: 127 ; X86: # %bb.0:
93 ; 32: calll {{_?}}t6 128 ; X86-NEXT: subl $12, %esp
94 ; 32: jmp {{_?}}bar 129 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
95 130 ; X86-NEXT: cmpl $9, %eax
96 ; 64-LABEL: t6: 131 ; X86-NEXT: jg .LBB6_2
97 ; 64: jmp {{_?}}t6 132 ; X86-NEXT: # %bb.1: # %bb
98 ; 64: jmp {{_?}}bar 133 ; X86-NEXT: decl %eax
99 134 ; X86-NEXT: movl %eax, (%esp)
100 ; X32ABI-LABEL: t6: 135 ; X86-NEXT: calll t6
101 ; X32ABI: jmp {{_?}}t6 136 ; X86-NEXT: addl $12, %esp
102 ; X32ABI: jmp {{_?}}bar 137 ; X86-NEXT: retl
103 %0 = icmp slt i32 %x, 10 138 ; X86-NEXT: .LBB6_2: # %bb1
104 br i1 %0, label %bb, label %bb1 139 ; X86-NEXT: addl $12, %esp
140 ; X86-NEXT: jmp bar # TAILCALL
141 ;
142 ; X64-LABEL: t6:
143 ; X64: # %bb.0:
144 ; X64-NEXT: cmpl $9, %edi
145 ; X64-NEXT: jg .LBB6_2
146 ; X64-NEXT: # %bb.1: # %bb
147 ; X64-NEXT: decl %edi
148 ; X64-NEXT: jmp t6 # TAILCALL
149 ; X64-NEXT: .LBB6_2: # %bb1
150 ; X64-NEXT: jmp bar # TAILCALL
151 ;
152 ; X32-LABEL: t6:
153 ; X32: # %bb.0:
154 ; X32-NEXT: cmpl $9, %edi
155 ; X32-NEXT: jg .LBB6_2
156 ; X32-NEXT: # %bb.1: # %bb
157 ; X32-NEXT: decl %edi
158 ; X32-NEXT: jmp t6 # TAILCALL
159 ; X32-NEXT: .LBB6_2: # %bb1
160 ; X32-NEXT: jmp bar # TAILCALL
161 %t0 = icmp slt i32 %x, 10
162 br i1 %t0, label %bb, label %bb1
105 163
106 bb: 164 bb:
107 %1 = add nsw i32 %x, -1 165 %t1 = add nsw i32 %x, -1
108 %2 = tail call i32 @t6(i32 %1) nounwind ssp 166 %t2 = tail call i32 @t6(i32 %t1) nounwind ssp
109 ret i32 %2 167 ret i32 %t2
110 168
111 bb1: 169 bb1:
112 %3 = tail call i32 @bar(i32 %x) nounwind 170 %t3 = tail call i32 @bar(i32 %x) nounwind
113 ret i32 %3 171 ret i32 %t3
114 } 172 }
115 173
116 declare i32 @bar(i32) 174 declare i32 @bar(i32)
117 175
118 define i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp { 176 define i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
119 entry: 177 ; X86-LABEL: t7:
120 ; 32-LABEL: t7: 178 ; X86: # %bb.0:
121 ; 32: jmp {{_?}}bar2 179 ; X86-NEXT: jmp bar2 # TAILCALL
122 180 ;
123 ; 64-LABEL: t7: 181 ; X64-LABEL: t7:
124 ; 64: jmp {{_?}}bar2 182 ; X64: # %bb.0:
125 183 ; X64-NEXT: jmp bar2 # TAILCALL
126 ; X32ABI-LABEL: t7: 184 ;
127 ; X32ABI: jmp {{_?}}bar2 185 ; X32-LABEL: t7:
128 %0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind 186 ; X32: # %bb.0:
129 ret i32 %0 187 ; X32-NEXT: jmp bar2 # TAILCALL
188 %t0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind
189 ret i32 %t0
130 } 190 }
131 191
132 declare i32 @bar2(i32, i32, i32) 192 declare i32 @bar2(i32, i32, i32)
133 193
134 define signext i16 @t8() nounwind ssp { 194 define signext i16 @t8() nounwind ssp {
135 entry: 195 ; X86-LABEL: t8:
136 ; 32-LABEL: t8: 196 ; X86: # %bb.0: # %entry
137 ; 32: jmp {{_?}}bar3 197 ; X86-NEXT: jmp bar3 # TAILCALL
138 198 ;
139 ; 64-LABEL: t8: 199 ; X64-LABEL: t8:
140 ; 64: jmp {{_?}}bar3 200 ; X64: # %bb.0: # %entry
141 201 ; X64-NEXT: jmp bar3 # TAILCALL
142 ; X32ABI-LABEL: t8: 202 ;
143 ; X32ABI: jmp {{_?}}bar3 203 ; X32-LABEL: t8:
204 ; X32: # %bb.0: # %entry
205 ; X32-NEXT: jmp bar3 # TAILCALL
206 entry:
144 %0 = tail call signext i16 @bar3() nounwind ; <i16> [#uses=1] 207 %0 = tail call signext i16 @bar3() nounwind ; <i16> [#uses=1]
145 ret i16 %0 208 ret i16 %0
146 } 209 }
147 210
148 declare signext i16 @bar3() 211 declare signext i16 @bar3()
149 212
150 define signext i16 @t9(i32 (i32)* nocapture %x) nounwind ssp { 213 define signext i16 @t9(i32 (i32)* nocapture %x) nounwind ssp {
151 entry: 214 ; X86-LABEL: t9:
152 ; 32-LABEL: t9: 215 ; X86: # %bb.0: # %entry
153 ; 32: calll * 216 ; X86-NEXT: subl $12, %esp
154 217 ; X86-NEXT: movl $0, (%esp)
155 ; 64-LABEL: t9: 218 ; X86-NEXT: calll *{{[0-9]+}}(%esp)
156 ; 64: jmpq * 219 ; X86-NEXT: addl $12, %esp
157 220 ; X86-NEXT: retl
158 ; X32ABI-LABEL: t9: 221 ;
159 ; X32ABI: jmpq * 222 ; X64-LABEL: t9:
223 ; X64: # %bb.0: # %entry
224 ; X64-NEXT: movq %rdi, %rax
225 ; X64-NEXT: xorl %edi, %edi
226 ; X64-NEXT: jmpq *%rax # TAILCALL
227 ;
228 ; X32-LABEL: t9:
229 ; X32: # %bb.0: # %entry
230 ; X32-NEXT: movl %edi, %eax
231 ; X32-NEXT: xorl %edi, %edi
232 ; X32-NEXT: jmpq *%rax # TAILCALL
233 entry:
160 %0 = bitcast i32 (i32)* %x to i16 (i32)* 234 %0 = bitcast i32 (i32)* %x to i16 (i32)*
161 %1 = tail call signext i16 %0(i32 0) nounwind 235 %1 = tail call signext i16 %0(i32 0) nounwind
162 ret i16 %1 236 ret i16 %1
163 } 237 }
164 238
165 define void @t10() nounwind ssp { 239 define void @t10() nounwind ssp {
166 entry: 240 ; X86-LABEL: t10:
167 ; 32-LABEL: t10: 241 ; X86: # %bb.0: # %entry
168 ; 32: calll 242 ; X86-NEXT: subl $12, %esp
169 243 ; X86-NEXT: calll foo4
170 ; 64-LABEL: t10: 244 ;
171 ; 64: callq 245 ; X64-LABEL: t10:
172 246 ; X64: # %bb.0: # %entry
173 ; X32ABI-LABEL: t10: 247 ; X64-NEXT: pushq %rax
174 ; X32ABI: callq 248 ; X64-NEXT: callq foo4
249 ;
250 ; X32-LABEL: t10:
251 ; X32: # %bb.0: # %entry
252 ; X32-NEXT: pushq %rax
253 ; X32-NEXT: callq foo4
254 entry:
175 %0 = tail call i32 @foo4() noreturn nounwind 255 %0 = tail call i32 @foo4() noreturn nounwind
176 unreachable 256 unreachable
177 } 257 }
178 258
179 declare i32 @foo4() 259 declare i32 @foo4()
180 260
181 define i32 @t11(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind ssp {
182 ; In 32-bit mode, it's emitting a bunch of dead loads that are not being 261 ; In 32-bit mode, it's emitting a bunch of dead loads that are not being
183 ; eliminated currently. 262 ; eliminated currently.
184 263
185 ; 32-LABEL: t11: 264 define i32 @t11(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind ssp {
186 ; 32-NOT: subl ${{[0-9]+}}, %esp 265 ; X86-LABEL: t11:
187 ; 32: je 266 ; X86: # %bb.0: # %entry
188 ; 32-NOT: movl 267 ; X86-NEXT: cmpl $0, {{[0-9]+}}(%esp)
189 ; 32-NOT: addl ${{[0-9]+}}, %esp 268 ; X86-NEXT: je .LBB11_1
190 ; 32: jmp {{_?}}foo5 269 ; X86-NEXT: # %bb.2: # %bb
191 270 ; X86-NEXT: jmp foo5 # TAILCALL
192 ; 64-LABEL: t11: 271 ; X86-NEXT: .LBB11_1: # %bb6
193 ; 64-NOT: subq ${{[0-9]+}}, %rsp 272 ; X86-NEXT: xorl %eax, %eax
194 ; 64-NOT: addq ${{[0-9]+}}, %rsp 273 ; X86-NEXT: retl
195 ; 64: jmp {{_?}}foo5 274 ;
196 275 ; X64-LABEL: t11:
197 ; X32ABI-LABEL: t11: 276 ; X64: # %bb.0: # %entry
198 ; X32ABI-NOT: subl ${{[0-9]+}}, %esp 277 ; X64-NEXT: testl %edi, %edi
199 ; X32ABI-NOT: addl ${{[0-9]+}}, %esp 278 ; X64-NEXT: je .LBB11_1
200 ; X32ABI: jmp {{_?}}foo5 279 ; X64-NEXT: # %bb.2: # %bb
280 ; X64-NEXT: jmp foo5 # TAILCALL
281 ; X64-NEXT: .LBB11_1: # %bb6
282 ; X64-NEXT: xorl %eax, %eax
283 ; X64-NEXT: retq
284 ;
285 ; X32-LABEL: t11:
286 ; X32: # %bb.0: # %entry
287 ; X32-NEXT: testl %edi, %edi
288 ; X32-NEXT: je .LBB11_1
289 ; X32-NEXT: # %bb.2: # %bb
290 ; X32-NEXT: jmp foo5 # TAILCALL
291 ; X32-NEXT: .LBB11_1: # %bb6
292 ; X32-NEXT: xorl %eax, %eax
293 ; X32-NEXT: retq
201 entry: 294 entry:
202 %0 = icmp eq i32 %x, 0 295 %0 = icmp eq i32 %x, 0
203 br i1 %0, label %bb6, label %bb 296 br i1 %0, label %bb6, label %bb
204 297
205 bb: 298 bb:
213 declare i32 @foo5(i32, i32, i32, i32, i32) 306 declare i32 @foo5(i32, i32, i32, i32, i32)
214 307
215 %struct.t = type { i32, i32, i32, i32, i32 } 308 %struct.t = type { i32, i32, i32, i32, i32 }
216 309
217 define i32 @t12(i32 %x, i32 %y, %struct.t* byval align 4 %z) nounwind ssp { 310 define i32 @t12(i32 %x, i32 %y, %struct.t* byval align 4 %z) nounwind ssp {
218 ; 32-LABEL: t12: 311 ; X86-LABEL: t12:
219 ; 32-NOT: subl ${{[0-9]+}}, %esp 312 ; X86: # %bb.0: # %entry
220 ; 32-NOT: addl ${{[0-9]+}}, %esp 313 ; X86-NEXT: cmpl $0, {{[0-9]+}}(%esp)
221 ; 32: jmp {{_?}}foo6 314 ; X86-NEXT: je .LBB12_1
222 315 ; X86-NEXT: # %bb.2: # %bb
223 ; 64-LABEL: t12: 316 ; X86-NEXT: jmp foo6 # TAILCALL
224 ; 64-NOT: subq ${{[0-9]+}}, %rsp 317 ; X86-NEXT: .LBB12_1: # %bb2
225 ; 64-NOT: addq ${{[0-9]+}}, %rsp 318 ; X86-NEXT: xorl %eax, %eax
226 ; 64: jmp {{_?}}foo6 319 ; X86-NEXT: retl
227 320 ;
228 ; X32ABI-LABEL: t12: 321 ; X64-LABEL: t12:
229 ; X32ABI-NOT: subl ${{[0-9]+}}, %esp 322 ; X64: # %bb.0: # %entry
230 ; X32ABI-NOT: addl ${{[0-9]+}}, %esp 323 ; X64-NEXT: testl %edi, %edi
231 ; X32ABI: jmp {{_?}}foo6 324 ; X64-NEXT: je .LBB12_1
325 ; X64-NEXT: # %bb.2: # %bb
326 ; X64-NEXT: jmp foo6 # TAILCALL
327 ; X64-NEXT: .LBB12_1: # %bb2
328 ; X64-NEXT: xorl %eax, %eax
329 ; X64-NEXT: retq
330 ;
331 ; X32-LABEL: t12:
332 ; X32: # %bb.0: # %entry
333 ; X32-NEXT: testl %edi, %edi
334 ; X32-NEXT: je .LBB12_1
335 ; X32-NEXT: # %bb.2: # %bb
336 ; X32-NEXT: jmp foo6 # TAILCALL
337 ; X32-NEXT: .LBB12_1: # %bb2
338 ; X32-NEXT: xorl %eax, %eax
339 ; X32-NEXT: retq
232 entry: 340 entry:
233 %0 = icmp eq i32 %x, 0 341 %0 = icmp eq i32 %x, 0
234 br i1 %0, label %bb2, label %bb 342 br i1 %0, label %bb2, label %bb
235 343
236 bb: 344 bb:
246 ; rdar://r7717598 354 ; rdar://r7717598
247 %struct.ns = type { i32, i32 } 355 %struct.ns = type { i32, i32 }
248 %struct.cp = type { float, float, float, float, float } 356 %struct.cp = type { float, float, float, float, float }
249 357
250 define %struct.ns* @t13(%struct.cp* %yy) nounwind ssp { 358 define %struct.ns* @t13(%struct.cp* %yy) nounwind ssp {
251 ; 32-LABEL: t13: 359 ; X86-LABEL: t13:
252 ; 32-NOT: jmp 360 ; X86: # %bb.0: # %entry
253 ; 32: calll 361 ; X86-NEXT: subl $28, %esp
254 ; 32: ret 362 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
255 363 ; X86-NEXT: movl 16(%eax), %ecx
256 ; 64-LABEL: t13: 364 ; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp)
257 ; 64-NOT: jmp 365 ; X86-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
258 ; 64: callq 366 ; X86-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
259 ; 64: ret 367 ; X86-NEXT: movsd %xmm1, {{[0-9]+}}(%esp)
260 368 ; X86-NEXT: movsd %xmm0, (%esp)
261 ; X32ABI-LABEL: t13: 369 ; X86-NEXT: xorl %ecx, %ecx
262 ; X32ABI-NOT: jmp 370 ; X86-NEXT: calll foo7
263 ; X32ABI: callq 371 ; X86-NEXT: addl $28, %esp
264 ; X32ABI: ret 372 ; X86-NEXT: retl
373 ;
374 ; X64-LABEL: t13:
375 ; X64: # %bb.0: # %entry
376 ; X64-NEXT: pushq %rax
377 ; X64-NEXT: subq $8, %rsp
378 ; X64-NEXT: movl 16(%rdi), %eax
379 ; X64-NEXT: movq (%rdi), %rcx
380 ; X64-NEXT: movq 8(%rdi), %rdx
381 ; X64-NEXT: xorl %edi, %edi
382 ; X64-NEXT: pushq %rax
383 ; X64-NEXT: pushq %rdx
384 ; X64-NEXT: pushq %rcx
385 ; X64-NEXT: callq foo7
386 ; X64-NEXT: addq $32, %rsp
387 ; X64-NEXT: popq %rcx
388 ; X64-NEXT: retq
389 ;
390 ; X32-LABEL: t13:
391 ; X32: # %bb.0: # %entry
392 ; X32-NEXT: pushq %rax
393 ; X32-NEXT: subl $8, %esp
394 ; X32-NEXT: movl 16(%edi), %eax
395 ; X32-NEXT: movq (%edi), %rcx
396 ; X32-NEXT: movq 8(%edi), %rdx
397 ; X32-NEXT: xorl %edi, %edi
398 ; X32-NEXT: pushq %rax
399 ; X32-NEXT: pushq %rdx
400 ; X32-NEXT: pushq %rcx
401 ; X32-NEXT: callq foo7
402 ; X32-NEXT: addl $32, %esp
403 ; X32-NEXT: popq %rcx
404 ; X32-NEXT: retq
265 entry: 405 entry:
266 %0 = tail call fastcc %struct.ns* @foo7(%struct.cp* byval align 4 %yy, i8 signext 0) nounwind 406 %0 = tail call fastcc %struct.ns* @foo7(%struct.cp* byval align 4 %yy, i8 signext 0) nounwind
267 ret %struct.ns* %0 407 ret %struct.ns* %0
268 } 408 }
269 409
275 %struct.__block_descriptor_withcopydispose = type { i64, i64, i8*, i8* } 415 %struct.__block_descriptor_withcopydispose = type { i64, i64, i8*, i8* }
276 %struct.__block_literal_1 = type { i8*, i32, i32, i8*, %struct.__block_descriptor* } 416 %struct.__block_literal_1 = type { i8*, i32, i32, i8*, %struct.__block_descriptor* }
277 %struct.__block_literal_2 = type { i8*, i32, i32, i8*, %struct.__block_descriptor_withcopydispose*, void ()* } 417 %struct.__block_literal_2 = type { i8*, i32, i32, i8*, %struct.__block_descriptor_withcopydispose*, void ()* }
278 418
279 define void @t14(%struct.__block_literal_2* nocapture %.block_descriptor) nounwind ssp { 419 define void @t14(%struct.__block_literal_2* nocapture %.block_descriptor) nounwind ssp {
280 entry: 420 ; X86-LABEL: t14:
281 ; 64-LABEL: t14: 421 ; X86: # %bb.0: # %entry
282 ; 64: movq 32(%rdi) 422 ; X86-NEXT: subl $12, %esp
283 ; 64-NOT: movq 16(%rdi) 423 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
284 ; 64: jmpq *16({{%rdi|%rax}}) 424 ; X86-NEXT: movl 20(%eax), %eax
285 425 ; X86-NEXT: movl %eax, (%esp)
286 ; X32ABI-LABEL: t14: 426 ; X86-NEXT: calll *12(%eax)
287 ; X32ABI: movl 20(%edi), %edi 427 ; X86-NEXT: addl $12, %esp
288 ; X32ABI-NEXT: movl 12(%edi), %eax 428 ; X86-NEXT: retl
289 ; X32ABI-NEXT: jmpq *%rax 429 ;
430 ; X64-LABEL: t14:
431 ; X64: # %bb.0: # %entry
432 ; X64-NEXT: movq 32(%rdi), %rdi
433 ; X64-NEXT: jmpq *16(%rdi) # TAILCALL
434 ;
435 ; X32-LABEL: t14:
436 ; X32: # %bb.0: # %entry
437 ; X32-NEXT: movl 20(%edi), %edi
438 ; X32-NEXT: movl 12(%edi), %eax
439 ; X32-NEXT: jmpq *%rax # TAILCALL
440 entry:
290 %0 = getelementptr inbounds %struct.__block_literal_2, %struct.__block_literal_2* %.block_descriptor, i64 0, i32 5 ; <void ()**> [#uses=1] 441 %0 = getelementptr inbounds %struct.__block_literal_2, %struct.__block_literal_2* %.block_descriptor, i64 0, i32 5 ; <void ()**> [#uses=1]
291 %1 = load void ()*, void ()** %0, align 8 ; <void ()*> [#uses=2] 442 %1 = load void ()*, void ()** %0, align 8 ; <void ()*> [#uses=2]
292 %2 = bitcast void ()* %1 to %struct.__block_literal_1* ; <%struct.__block_literal_1*> [#uses=1] 443 %2 = bitcast void ()* %1 to %struct.__block_literal_1* ; <%struct.__block_literal_1*> [#uses=1]
293 %3 = getelementptr inbounds %struct.__block_literal_1, %struct.__block_literal_1* %2, i64 0, i32 3 ; <i8**> [#uses=1] 444 %3 = getelementptr inbounds %struct.__block_literal_1, %struct.__block_literal_1* %2, i64 0, i32 3 ; <i8**> [#uses=1]
294 %4 = load i8*, i8** %3, align 8 ; <i8*> [#uses=1] 445 %4 = load i8*, i8** %3, align 8 ; <i8*> [#uses=1]
300 451
301 ; rdar://7726868 452 ; rdar://7726868
302 %struct.foo = type { [4 x i32] } 453 %struct.foo = type { [4 x i32] }
303 454
304 define void @t15(%struct.foo* noalias sret %agg.result) nounwind { 455 define void @t15(%struct.foo* noalias sret %agg.result) nounwind {
305 ; 32-LABEL: t15: 456 ; X86-LABEL: t15:
306 ; 32: calll {{_?}}f 457 ; X86: # %bb.0:
307 ; 32: retl $4 458 ; X86-NEXT: pushl %esi
308 459 ; X86-NEXT: subl $8, %esp
309 ; 64-LABEL: t15: 460 ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
310 ; 64: callq {{_?}}f 461 ; X86-NEXT: movl %esi, %ecx
311 ; 64: retq 462 ; X86-NEXT: calll f
312 463 ; X86-NEXT: movl %esi, %eax
313 ; X32ABI-LABEL: t15: 464 ; X86-NEXT: addl $8, %esp
314 ; X32ABI: callq {{_?}}f 465 ; X86-NEXT: popl %esi
315 ; X32ABI: retq 466 ; X86-NEXT: retl $4
467 ;
468 ; X64-LABEL: t15:
469 ; X64: # %bb.0:
470 ; X64-NEXT: pushq %rbx
471 ; X64-NEXT: movq %rdi, %rbx
472 ; X64-NEXT: callq f
473 ; X64-NEXT: movq %rbx, %rax
474 ; X64-NEXT: popq %rbx
475 ; X64-NEXT: retq
476 ;
477 ; X32-LABEL: t15:
478 ; X32: # %bb.0:
479 ; X32-NEXT: pushq %rbx
480 ; X32-NEXT: movl %edi, %ebx
481 ; X32-NEXT: callq f
482 ; X32-NEXT: movl %ebx, %eax
483 ; X32-NEXT: popq %rbx
484 ; X32-NEXT: retq
316 tail call fastcc void @f(%struct.foo* noalias sret %agg.result) nounwind 485 tail call fastcc void @f(%struct.foo* noalias sret %agg.result) nounwind
317 ret void 486 ret void
318 } 487 }
319 488
320 declare void @f(%struct.foo* noalias sret) nounwind 489 declare void @f(%struct.foo* noalias sret) nounwind
321 490
322 define void @t16() nounwind ssp { 491 define void @t16() nounwind ssp {
323 entry: 492 ; X86-LABEL: t16:
324 ; 32-LABEL: t16: 493 ; X86: # %bb.0: # %entry
325 ; 32: calll {{_?}}bar4 494 ; X86-NEXT: subl $12, %esp
326 ; 32: fstp 495 ; X86-NEXT: calll bar4
327 496 ; X86-NEXT: fstp %st(0)
328 ; 64-LABEL: t16: 497 ; X86-NEXT: addl $12, %esp
329 ; 64: jmp {{_?}}bar4 498 ; X86-NEXT: retl
330 499 ;
331 ; X32ABI-LABEL: t16: 500 ; X64-LABEL: t16:
332 ; X32ABI: jmp {{_?}}bar4 501 ; X64: # %bb.0: # %entry
502 ; X64-NEXT: jmp bar4 # TAILCALL
503 ;
504 ; X32-LABEL: t16:
505 ; X32: # %bb.0: # %entry
506 ; X32-NEXT: jmp bar4 # TAILCALL
507 entry:
333 %0 = tail call double @bar4() nounwind 508 %0 = tail call double @bar4() nounwind
334 ret void 509 ret void
335 } 510 }
336 511
337 declare double @bar4() 512 declare double @bar4()
338 513
339 ; rdar://6283267 514 ; rdar://6283267
340 define void @t17() nounwind ssp { 515 define void @t17() nounwind ssp {
341 entry: 516 ; X86-LABEL: t17:
342 ; 32-LABEL: t17: 517 ; X86: # %bb.0: # %entry
343 ; 32: jmp {{_?}}bar5 518 ; X86-NEXT: jmp bar5 # TAILCALL
344 519 ;
345 ; 64-LABEL: t17: 520 ; X64-LABEL: t17:
346 ; 64: xorl %eax, %eax 521 ; X64: # %bb.0: # %entry
347 ; 64: jmp {{_?}}bar5 522 ; X64-NEXT: xorl %eax, %eax
348 523 ; X64-NEXT: jmp bar5 # TAILCALL
349 ; X32ABI-LABEL: t17: 524 ;
350 ; X32ABI: xorl %eax, %eax 525 ; X32-LABEL: t17:
351 ; X32ABI: jmp {{_?}}bar5 526 ; X32: # %bb.0: # %entry
527 ; X32-NEXT: xorl %eax, %eax
528 ; X32-NEXT: jmp bar5 # TAILCALL
529 entry:
352 tail call void (...) @bar5() nounwind 530 tail call void (...) @bar5() nounwind
353 ret void 531 ret void
354 } 532 }
355 533
356 declare void @bar5(...) 534 declare void @bar5(...)
357 535
358 ; rdar://7774847 536 ; rdar://7774847
359 define void @t18() nounwind ssp { 537 define void @t18() nounwind ssp {
360 entry: 538 ; X86-LABEL: t18:
361 ; 32-LABEL: t18: 539 ; X86: # %bb.0: # %entry
362 ; 32: calll {{_?}}bar6 540 ; X86-NEXT: subl $12, %esp
363 ; 32: fstp %st(0) 541 ; X86-NEXT: calll bar6
364 542 ; X86-NEXT: fstp %st(0)
365 ; 64-LABEL: t18: 543 ; X86-NEXT: addl $12, %esp
366 ; 64: xorl %eax, %eax 544 ; X86-NEXT: retl
367 ; 64: jmp {{_?}}bar6 545 ;
368 546 ; X64-LABEL: t18:
369 ; X32ABI-LABEL: t18: 547 ; X64: # %bb.0: # %entry
370 ; X32ABI: xorl %eax, %eax 548 ; X64-NEXT: xorl %eax, %eax
371 ; X32ABI: jmp {{_?}}bar6 549 ; X64-NEXT: jmp bar6 # TAILCALL
550 ;
551 ; X32-LABEL: t18:
552 ; X32: # %bb.0: # %entry
553 ; X32-NEXT: xorl %eax, %eax
554 ; X32-NEXT: jmp bar6 # TAILCALL
555 entry:
372 %0 = tail call double (...) @bar6() nounwind 556 %0 = tail call double (...) @bar6() nounwind
373 ret void 557 ret void
374 } 558 }
375 559
376 declare double @bar6(...) 560 declare double @bar6(...)
377 561
378 define void @t19() alignstack(32) nounwind { 562 define void @t19() alignstack(32) nounwind {
379 entry: 563 ; X86-LABEL: t19:
380 ; CHECK-LABEL: t19: 564 ; X86: # %bb.0: # %entry
381 ; CHECK: andl $-32 565 ; X86-NEXT: pushl %ebp
382 ; CHECK: calll {{_?}}foo 566 ; X86-NEXT: movl %esp, %ebp
383 567 ; X86-NEXT: andl $-32, %esp
384 ; X32ABI-LABEL: t19: 568 ; X86-NEXT: subl $32, %esp
385 ; X32ABI: andl $-32 569 ; X86-NEXT: calll foo
386 ; X32ABI: callq {{_?}}foo 570 ; X86-NEXT: movl %ebp, %esp
571 ; X86-NEXT: popl %ebp
572 ; X86-NEXT: retl
573 ;
574 ; X64-LABEL: t19:
575 ; X64: # %bb.0: # %entry
576 ; X64-NEXT: pushq %rbp
577 ; X64-NEXT: movq %rsp, %rbp
578 ; X64-NEXT: andq $-32, %rsp
579 ; X64-NEXT: subq $32, %rsp
580 ; X64-NEXT: callq foo
581 ; X64-NEXT: movq %rbp, %rsp
582 ; X64-NEXT: popq %rbp
583 ; X64-NEXT: retq
584 ;
585 ; X32-LABEL: t19:
586 ; X32: # %bb.0: # %entry
587 ; X32-NEXT: pushq %rbp
588 ; X32-NEXT: movl %esp, %ebp
589 ; X32-NEXT: andl $-32, %esp
590 ; X32-NEXT: subl $32, %esp
591 ; X32-NEXT: callq foo
592 ; X32-NEXT: movl %ebp, %esp
593 ; X32-NEXT: popq %rbp
594 ; X32-NEXT: retq
595 entry:
387 tail call void @foo() nounwind 596 tail call void @foo() nounwind
388 ret void 597 ret void
389 } 598 }
390 599
391 ; If caller / callee calling convention mismatch then check if the return 600 ; If caller / callee calling convention mismatch then check if the return
392 ; values are returned in the same registers. 601 ; values are returned in the same registers.
393 ; rdar://7874780 602 ; rdar://7874780
394 603
395 define double @t20(double %x) nounwind { 604 define double @t20(double %x) nounwind {
396 entry: 605 ; X86-LABEL: t20:
397 ; 32-LABEL: t20: 606 ; X86: # %bb.0: # %entry
398 ; 32: calll {{_?}}foo20 607 ; X86-NEXT: subl $12, %esp
399 ; 32: fldl (%esp) 608 ; X86-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
400 609 ; X86-NEXT: calll foo20
401 ; 64-LABEL: t20: 610 ; X86-NEXT: movsd %xmm0, (%esp)
402 ; 64: jmp {{_?}}foo20 611 ; X86-NEXT: fldl (%esp)
403 612 ; X86-NEXT: addl $12, %esp
404 ; X32ABI-LABEL: t20: 613 ; X86-NEXT: retl
405 ; X32ABI: jmp {{_?}}foo20 614 ;
615 ; X64-LABEL: t20:
616 ; X64: # %bb.0: # %entry
617 ; X64-NEXT: jmp foo20 # TAILCALL
618 ;
619 ; X32-LABEL: t20:
620 ; X32: # %bb.0: # %entry
621 ; X32-NEXT: jmp foo20 # TAILCALL
622 entry:
406 %0 = tail call fastcc double @foo20(double %x) nounwind 623 %0 = tail call fastcc double @foo20(double %x) nounwind
407 ret double %0 624 ret double %0
408 } 625 }
409 626
410 declare fastcc double @foo20(double) nounwind 627 declare fastcc double @foo20(double) nounwind
628
629 ; bug 28417
630 define fastcc void @t21_sret_to_sret(%struct.foo* noalias sret %agg.result) nounwind {
631 ; X86-LABEL: t21_sret_to_sret:
632 ; X86: # %bb.0:
633 ; X86-NEXT: pushl %esi
634 ; X86-NEXT: subl $8, %esp
635 ; X86-NEXT: movl %ecx, %esi
636 ; X86-NEXT: calll t21_f_sret
637 ; X86-NEXT: movl %esi, %eax
638 ; X86-NEXT: addl $8, %esp
639 ; X86-NEXT: popl %esi
640 ; X86-NEXT: retl
641 ;
642 ; X64-LABEL: t21_sret_to_sret:
643 ; X64: # %bb.0:
644 ; X64-NEXT: pushq %rbx
645 ; X64-NEXT: movq %rdi, %rbx
646 ; X64-NEXT: callq t21_f_sret
647 ; X64-NEXT: movq %rbx, %rax
648 ; X64-NEXT: popq %rbx
649 ; X64-NEXT: retq
650 ;
651 ; X32-LABEL: t21_sret_to_sret:
652 ; X32: # %bb.0:
653 ; X32-NEXT: pushq %rbx
654 ; X32-NEXT: movl %edi, %ebx
655 ; X32-NEXT: callq t21_f_sret
656 ; X32-NEXT: movl %ebx, %eax
657 ; X32-NEXT: popq %rbx
658 ; X32-NEXT: retq
659 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %agg.result) nounwind
660 ret void
661 }
662
663 define fastcc void @t21_sret_to_sret_alloca(%struct.foo* noalias sret %agg.result) nounwind {
664 ; X86-LABEL: t21_sret_to_sret_alloca:
665 ; X86: # %bb.0:
666 ; X86-NEXT: pushl %esi
667 ; X86-NEXT: subl $24, %esp
668 ; X86-NEXT: movl %ecx, %esi
669 ; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx
670 ; X86-NEXT: calll t21_f_sret
671 ; X86-NEXT: movl %esi, %eax
672 ; X86-NEXT: addl $24, %esp
673 ; X86-NEXT: popl %esi
674 ; X86-NEXT: retl
675 ;
676 ; X64-LABEL: t21_sret_to_sret_alloca:
677 ; X64: # %bb.0:
678 ; X64-NEXT: pushq %rbx
679 ; X64-NEXT: subq $16, %rsp
680 ; X64-NEXT: movq %rdi, %rbx
681 ; X64-NEXT: movq %rsp, %rdi
682 ; X64-NEXT: callq t21_f_sret
683 ; X64-NEXT: movq %rbx, %rax
684 ; X64-NEXT: addq $16, %rsp
685 ; X64-NEXT: popq %rbx
686 ; X64-NEXT: retq
687 ;
688 ; X32-LABEL: t21_sret_to_sret_alloca:
689 ; X32: # %bb.0:
690 ; X32-NEXT: pushq %rbx
691 ; X32-NEXT: subl $16, %esp
692 ; X32-NEXT: movl %edi, %ebx
693 ; X32-NEXT: movl %esp, %edi
694 ; X32-NEXT: callq t21_f_sret
695 ; X32-NEXT: movl %ebx, %eax
696 ; X32-NEXT: addl $16, %esp
697 ; X32-NEXT: popq %rbx
698 ; X32-NEXT: retq
699 %a = alloca %struct.foo, align 8
700 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %a) nounwind
701 ret void
702 }
703
704 define fastcc void @t21_sret_to_sret_more_args(%struct.foo* noalias sret %agg.result, i32 %a, i32 %b) nounwind {
705 ; X86-LABEL: t21_sret_to_sret_more_args:
706 ; X86: # %bb.0:
707 ; X86-NEXT: pushl %esi
708 ; X86-NEXT: subl $8, %esp
709 ; X86-NEXT: movl %ecx, %esi
710 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
711 ; X86-NEXT: movl %eax, (%esp)
712 ; X86-NEXT: calll f_sret
713 ; X86-NEXT: movl %esi, %eax
714 ; X86-NEXT: addl $8, %esp
715 ; X86-NEXT: popl %esi
716 ; X86-NEXT: retl
717 ;
718 ; X64-LABEL: t21_sret_to_sret_more_args:
719 ; X64: # %bb.0:
720 ; X64-NEXT: pushq %rbx
721 ; X64-NEXT: movq %rdi, %rbx
722 ; X64-NEXT: callq f_sret
723 ; X64-NEXT: movq %rbx, %rax
724 ; X64-NEXT: popq %rbx
725 ; X64-NEXT: retq
726 ;
727 ; X32-LABEL: t21_sret_to_sret_more_args:
728 ; X32: # %bb.0:
729 ; X32-NEXT: pushq %rbx
730 ; X32-NEXT: movl %edi, %ebx
731 ; X32-NEXT: callq f_sret
732 ; X32-NEXT: movl %ebx, %eax
733 ; X32-NEXT: popq %rbx
734 ; X32-NEXT: retq
735 tail call fastcc void @f_sret(%struct.foo* noalias sret %agg.result, i32 %a, i32 %b) nounwind
736 ret void
737 }
738
739 define fastcc void @t21_sret_to_sret_second_arg_sret(%struct.foo* noalias %agg.result, %struct.foo* noalias sret %ret) nounwind {
740 ; X86-LABEL: t21_sret_to_sret_second_arg_sret:
741 ; X86: # %bb.0:
742 ; X86-NEXT: pushl %esi
743 ; X86-NEXT: subl $8, %esp
744 ; X86-NEXT: movl %edx, %esi
745 ; X86-NEXT: movl %edx, %ecx
746 ; X86-NEXT: calll t21_f_sret
747 ; X86-NEXT: movl %esi, %eax
748 ; X86-NEXT: addl $8, %esp
749 ; X86-NEXT: popl %esi
750 ; X86-NEXT: retl
751 ;
752 ; X64-LABEL: t21_sret_to_sret_second_arg_sret:
753 ; X64: # %bb.0:
754 ; X64-NEXT: pushq %rbx
755 ; X64-NEXT: movq %rsi, %rbx
756 ; X64-NEXT: movq %rsi, %rdi
757 ; X64-NEXT: callq t21_f_sret
758 ; X64-NEXT: movq %rbx, %rax
759 ; X64-NEXT: popq %rbx
760 ; X64-NEXT: retq
761 ;
762 ; X32-LABEL: t21_sret_to_sret_second_arg_sret:
763 ; X32: # %bb.0:
764 ; X32-NEXT: pushq %rbx
765 ; X32-NEXT: movl %esi, %ebx
766 ; X32-NEXT: movl %esi, %edi
767 ; X32-NEXT: callq t21_f_sret
768 ; X32-NEXT: movl %ebx, %eax
769 ; X32-NEXT: popq %rbx
770 ; X32-NEXT: retq
771 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %ret) nounwind
772 ret void
773 }
774
775 define fastcc void @t21_sret_to_sret_more_args2(%struct.foo* noalias sret %agg.result, i32 %a, i32 %b) nounwind {
776 ; X86-LABEL: t21_sret_to_sret_more_args2:
777 ; X86: # %bb.0:
778 ; X86-NEXT: pushl %esi
779 ; X86-NEXT: subl $8, %esp
780 ; X86-NEXT: movl %ecx, %esi
781 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
782 ; X86-NEXT: movl %edx, (%esp)
783 ; X86-NEXT: movl %eax, %edx
784 ; X86-NEXT: calll f_sret
785 ; X86-NEXT: movl %esi, %eax
786 ; X86-NEXT: addl $8, %esp
787 ; X86-NEXT: popl %esi
788 ; X86-NEXT: retl
789 ;
790 ; X64-LABEL: t21_sret_to_sret_more_args2:
791 ; X64: # %bb.0:
792 ; X64-NEXT: pushq %rbx
793 ; X64-NEXT: movl %esi, %eax
794 ; X64-NEXT: movq %rdi, %rbx
795 ; X64-NEXT: movl %edx, %esi
796 ; X64-NEXT: movl %eax, %edx
797 ; X64-NEXT: callq f_sret
798 ; X64-NEXT: movq %rbx, %rax
799 ; X64-NEXT: popq %rbx
800 ; X64-NEXT: retq
801 ;
802 ; X32-LABEL: t21_sret_to_sret_more_args2:
803 ; X32: # %bb.0:
804 ; X32-NEXT: pushq %rbx
805 ; X32-NEXT: movl %esi, %eax
806 ; X32-NEXT: movl %edi, %ebx
807 ; X32-NEXT: movl %edx, %esi
808 ; X32-NEXT: movl %eax, %edx
809 ; X32-NEXT: callq f_sret
810 ; X32-NEXT: movl %ebx, %eax
811 ; X32-NEXT: popq %rbx
812 ; X32-NEXT: retq
813 tail call fastcc void @f_sret(%struct.foo* noalias sret %agg.result, i32 %b, i32 %a) nounwind
814 ret void
815 }
816
817
818 define fastcc void @t21_sret_to_sret_args_mismatch(%struct.foo* noalias sret %agg.result, %struct.foo* noalias %ret) nounwind {
819 ; X86-LABEL: t21_sret_to_sret_args_mismatch:
820 ; X86: # %bb.0:
821 ; X86-NEXT: pushl %esi
822 ; X86-NEXT: subl $8, %esp
823 ; X86-NEXT: movl %ecx, %esi
824 ; X86-NEXT: movl %edx, %ecx
825 ; X86-NEXT: calll t21_f_sret
826 ; X86-NEXT: movl %esi, %eax
827 ; X86-NEXT: addl $8, %esp
828 ; X86-NEXT: popl %esi
829 ; X86-NEXT: retl
830 ;
831 ; X64-LABEL: t21_sret_to_sret_args_mismatch:
832 ; X64: # %bb.0:
833 ; X64-NEXT: pushq %rbx
834 ; X64-NEXT: movq %rdi, %rbx
835 ; X64-NEXT: movq %rsi, %rdi
836 ; X64-NEXT: callq t21_f_sret
837 ; X64-NEXT: movq %rbx, %rax
838 ; X64-NEXT: popq %rbx
839 ; X64-NEXT: retq
840 ;
841 ; X32-LABEL: t21_sret_to_sret_args_mismatch:
842 ; X32: # %bb.0:
843 ; X32-NEXT: pushq %rbx
844 ; X32-NEXT: movl %edi, %ebx
845 ; X32-NEXT: movl %esi, %edi
846 ; X32-NEXT: callq t21_f_sret
847 ; X32-NEXT: movl %ebx, %eax
848 ; X32-NEXT: popq %rbx
849 ; X32-NEXT: retq
850 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %ret) nounwind
851 ret void
852 }
853
854 define fastcc void @t21_sret_to_sret_args_mismatch2(%struct.foo* noalias sret %agg.result, %struct.foo* noalias %ret) nounwind {
855 ; X86-LABEL: t21_sret_to_sret_args_mismatch2:
856 ; X86: # %bb.0:
857 ; X86-NEXT: pushl %esi
858 ; X86-NEXT: subl $8, %esp
859 ; X86-NEXT: movl %ecx, %esi
860 ; X86-NEXT: movl %edx, %ecx
861 ; X86-NEXT: calll t21_f_sret
862 ; X86-NEXT: movl %esi, %eax
863 ; X86-NEXT: addl $8, %esp
864 ; X86-NEXT: popl %esi
865 ; X86-NEXT: retl
866 ;
867 ; X64-LABEL: t21_sret_to_sret_args_mismatch2:
868 ; X64: # %bb.0:
869 ; X64-NEXT: pushq %rbx
870 ; X64-NEXT: movq %rdi, %rbx
871 ; X64-NEXT: movq %rsi, %rdi
872 ; X64-NEXT: callq t21_f_sret
873 ; X64-NEXT: movq %rbx, %rax
874 ; X64-NEXT: popq %rbx
875 ; X64-NEXT: retq
876 ;
877 ; X32-LABEL: t21_sret_to_sret_args_mismatch2:
878 ; X32: # %bb.0:
879 ; X32-NEXT: pushq %rbx
880 ; X32-NEXT: movl %edi, %ebx
881 ; X32-NEXT: movl %esi, %edi
882 ; X32-NEXT: callq t21_f_sret
883 ; X32-NEXT: movl %ebx, %eax
884 ; X32-NEXT: popq %rbx
885 ; X32-NEXT: retq
886 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %ret) nounwind
887 ret void
888 }
889
890 define fastcc void @t21_sret_to_sret_arg_mismatch(%struct.foo* noalias sret %agg.result) nounwind {
891 ; X86-LABEL: t21_sret_to_sret_arg_mismatch:
892 ; X86: # %bb.0:
893 ; X86-NEXT: pushl %esi
894 ; X86-NEXT: subl $8, %esp
895 ; X86-NEXT: movl %ecx, %esi
896 ; X86-NEXT: calll ret_struct
897 ; X86-NEXT: movl %eax, %ecx
898 ; X86-NEXT: calll t21_f_sret
899 ; X86-NEXT: movl %esi, %eax
900 ; X86-NEXT: addl $8, %esp
901 ; X86-NEXT: popl %esi
902 ; X86-NEXT: retl
903 ;
904 ; X64-LABEL: t21_sret_to_sret_arg_mismatch:
905 ; X64: # %bb.0:
906 ; X64-NEXT: pushq %rbx
907 ; X64-NEXT: movq %rdi, %rbx
908 ; X64-NEXT: callq ret_struct
909 ; X64-NEXT: movq %rax, %rdi
910 ; X64-NEXT: callq t21_f_sret
911 ; X64-NEXT: movq %rbx, %rax
912 ; X64-NEXT: popq %rbx
913 ; X64-NEXT: retq
914 ;
915 ; X32-LABEL: t21_sret_to_sret_arg_mismatch:
916 ; X32: # %bb.0:
917 ; X32-NEXT: pushq %rbx
918 ; X32-NEXT: movl %edi, %ebx
919 ; X32-NEXT: callq ret_struct
920 ; X32-NEXT: movl %eax, %edi
921 ; X32-NEXT: callq t21_f_sret
922 ; X32-NEXT: movl %ebx, %eax
923 ; X32-NEXT: popq %rbx
924 ; X32-NEXT: retq
925 %a = call fastcc %struct.foo* @ret_struct()
926 tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %a) nounwind
927 ret void
928 }
929
930 define fastcc void @t21_sret_to_sret_structs_mismatch(%struct.foo* noalias sret %agg.result, %struct.foo* noalias %a) nounwind {
931 ; X86-LABEL: t21_sret_to_sret_structs_mismatch:
932 ; X86: # %bb.0:
933 ; X86-NEXT: pushl %edi
934 ; X86-NEXT: pushl %esi
935 ; X86-NEXT: pushl %eax
936 ; X86-NEXT: movl %edx, %esi
937 ; X86-NEXT: movl %ecx, %edi
938 ; X86-NEXT: calll ret_struct
939 ; X86-NEXT: movl %esi, %ecx
940 ; X86-NEXT: movl %eax, %edx
941 ; X86-NEXT: calll t21_f_sret2
942 ; X86-NEXT: movl %edi, %eax
943 ; X86-NEXT: addl $4, %esp
944 ; X86-NEXT: popl %esi
945 ; X86-NEXT: popl %edi
946 ; X86-NEXT: retl
947 ;
948 ; X64-LABEL: t21_sret_to_sret_structs_mismatch:
949 ; X64: # %bb.0:
950 ; X64-NEXT: pushq %r14
951 ; X64-NEXT: pushq %rbx
952 ; X64-NEXT: pushq %rax
953 ; X64-NEXT: movq %rsi, %rbx
954 ; X64-NEXT: movq %rdi, %r14
955 ; X64-NEXT: callq ret_struct
956 ; X64-NEXT: movq %rbx, %rdi
957 ; X64-NEXT: movq %rax, %rsi
958 ; X64-NEXT: callq t21_f_sret2
959 ; X64-NEXT: movq %r14, %rax
960 ; X64-NEXT: addq $8, %rsp
961 ; X64-NEXT: popq %rbx
962 ; X64-NEXT: popq %r14
963 ; X64-NEXT: retq
964 ;
965 ; X32-LABEL: t21_sret_to_sret_structs_mismatch:
966 ; X32: # %bb.0:
967 ; X32-NEXT: pushq %rbp
968 ; X32-NEXT: pushq %rbx
969 ; X32-NEXT: pushq %rax
970 ; X32-NEXT: movl %esi, %ebx
971 ; X32-NEXT: movl %edi, %ebp
972 ; X32-NEXT: callq ret_struct
973 ; X32-NEXT: movl %ebx, %edi
974 ; X32-NEXT: movl %eax, %esi
975 ; X32-NEXT: callq t21_f_sret2
976 ; X32-NEXT: movl %ebp, %eax
977 ; X32-NEXT: addl $8, %esp
978 ; X32-NEXT: popq %rbx
979 ; X32-NEXT: popq %rbp
980 ; X32-NEXT: retq
981 %b = call fastcc %struct.foo* @ret_struct()
982 tail call fastcc void @t21_f_sret2(%struct.foo* noalias sret %a, %struct.foo* noalias %b) nounwind
983 ret void
984 }
985
986 declare ccc %struct.foo* @ret_struct() nounwind
987
988
989 define fastcc void @t21_sret_to_non_sret(%struct.foo* noalias sret %agg.result) nounwind {
990 ; X86-LABEL: t21_sret_to_non_sret:
991 ; X86: # %bb.0:
992 ; X86-NEXT: pushl %esi
993 ; X86-NEXT: subl $8, %esp
994 ; X86-NEXT: movl %ecx, %esi
995 ; X86-NEXT: calll t21_f_non_sret
996 ; X86-NEXT: movl %esi, %eax
997 ; X86-NEXT: addl $8, %esp
998 ; X86-NEXT: popl %esi
999 ; X86-NEXT: retl
1000 ;
1001 ; X64-LABEL: t21_sret_to_non_sret:
1002 ; X64: # %bb.0:
1003 ; X64-NEXT: pushq %rbx
1004 ; X64-NEXT: movq %rdi, %rbx
1005 ; X64-NEXT: callq t21_f_non_sret
1006 ; X64-NEXT: movq %rbx, %rax
1007 ; X64-NEXT: popq %rbx
1008 ; X64-NEXT: retq
1009 ;
1010 ; X32-LABEL: t21_sret_to_non_sret:
1011 ; X32: # %bb.0:
1012 ; X32-NEXT: pushq %rbx
1013 ; X32-NEXT: movl %edi, %ebx
1014 ; X32-NEXT: callq t21_f_non_sret
1015 ; X32-NEXT: movl %ebx, %eax
1016 ; X32-NEXT: popq %rbx
1017 ; X32-NEXT: retq
1018 tail call fastcc void @t21_f_non_sret(%struct.foo* %agg.result) nounwind
1019 ret void
1020 }
1021
1022
1023 define ccc void @t22_non_sret_to_sret(%struct.foo* %agg.result) nounwind {
1024 ; X86-LABEL: t22_non_sret_to_sret:
1025 ; X86: # %bb.0:
1026 ; X86-NEXT: subl $12, %esp
1027 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
1028 ; X86-NEXT: movl %eax, (%esp)
1029 ; X86-NEXT: calll t22_f_sret
1030 ; X86-NEXT: addl $8, %esp
1031 ; X86-NEXT: retl
1032 ;
1033 ; X64-LABEL: t22_non_sret_to_sret:
1034 ; X64: # %bb.0:
1035 ; X64-NEXT: pushq %rax
1036 ; X64-NEXT: callq t22_f_sret
1037 ; X64-NEXT: popq %rax
1038 ; X64-NEXT: retq
1039 ;
1040 ; X32-LABEL: t22_non_sret_to_sret:
1041 ; X32: # %bb.0:
1042 ; X32-NEXT: pushq %rax
1043 ; X32-NEXT: callq t22_f_sret
1044 ; X32-NEXT: popq %rax
1045 ; X32-NEXT: retq
1046 tail call ccc void @t22_f_sret(%struct.foo* noalias sret %agg.result) nounwind
1047 ret void
1048 }
1049
1050 declare fastcc void @t21_f_sret(%struct.foo* noalias sret) nounwind
1051 declare fastcc void @t21_f_sret2(%struct.foo* noalias sret, %struct.foo* noalias) nounwind
1052 declare fastcc void @t21_f_non_sret(%struct.foo*) nounwind
1053
1054 declare ccc void @t22_f_sret(%struct.foo* noalias sret) nounwind
1055
1056 declare ccc void @f_sret(%struct.foo* noalias sret, i32, i32) nounwind