11; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2- ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -x86-asm-syntax=intel | FileCheck %s
2+ ; RUN: llc < %s -mtriple=i686-unknown-unknown -x86-asm-syntax=intel | FileCheck %s --check-prefix=X32
3+ ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -x86-asm-syntax=intel | FileCheck %s --check-prefix=X64
34
45; Test correct handling of a musttail call with a byval struct argument.
56
@@ -13,54 +14,80 @@ declare dso_local i32 @Func5(ptr byval(%struct.5xi32) %0)
1314declare dso_local i32 @FuncManyArgs (i32 %0 , i32 %1 , i32 %2 , i32 %3 , i32 %4 , i32 %5 , i8 %6 , ptr byval (%struct.5xi32 ) %7 )
1415
1516define dso_local i32 @test1 (ptr byval (%struct.1xi32 ) %0 ) {
16- ; CHECK-LABEL: test1:
17- ; CHECK: # %bb.0:
18- ; CHECK-NEXT: jmp Func1 # TAILCALL
17+ ; X32-LABEL: test1:
18+ ; X32: # %bb.0:
19+ ; X32-NEXT: jmp Func1 # TAILCALL
20+ ;
21+ ; X64-LABEL: test1:
22+ ; X64: # %bb.0:
23+ ; X64-NEXT: jmp Func1 # TAILCALL
1924 %r = musttail call i32 @Func1 (ptr byval (%struct.1xi32 ) %0 )
2025 ret i32 %r
2126}
2227
2328define dso_local i32 @test3 (ptr byval (%struct.3xi32 ) %0 ) {
24- ; CHECK-LABEL: test3:
25- ; CHECK: # %bb.0:
26- ; CHECK-NEXT: jmp Func3 # TAILCALL
29+ ; X32-LABEL: test3:
30+ ; X32: # %bb.0:
31+ ; X32-NEXT: jmp Func3 # TAILCALL
32+ ;
33+ ; X64-LABEL: test3:
34+ ; X64: # %bb.0:
35+ ; X64-NEXT: jmp Func3 # TAILCALL
2736 %r = musttail call i32 @Func3 (ptr byval (%struct.3xi32 ) %0 )
2837 ret i32 %r
2938}
3039
3140; sizeof(%struct.5xi32) > 16, in x64 this is passed on stack.
3241define dso_local i32 @test5 (ptr byval (%struct.5xi32 ) %0 ) {
33- ; CHECK-LABEL: test5:
34- ; CHECK: # %bb.0:
35- ; CHECK-NEXT: jmp Func5 # TAILCALL
42+ ; X32-LABEL: test5:
43+ ; X32: # %bb.0:
44+ ; X32-NEXT: jmp Func5 # TAILCALL
45+ ;
46+ ; X64-LABEL: test5:
47+ ; X64: # %bb.0:
48+ ; X64-NEXT: jmp Func5 # TAILCALL
3649 %r = musttail call i32 @Func5 (ptr byval (%struct.5xi32 ) %0 )
3750 ret i32 %r
3851}
3952
4053; Test passing multiple arguments with different sizes on stack. In x64 Linux
4154; the first 6 are passed by register.
4255define dso_local i32 @testManyArgs (i32 %0 , i32 %1 , i32 %2 , i32 %3 , i32 %4 , i32 %5 , i8 %6 , ptr byval (%struct.5xi32 ) %7 ) {
43- ; CHECK-LABEL: testManyArgs:
44- ; CHECK: # %bb.0:
45- ; CHECK-NEXT: jmp FuncManyArgs # TAILCALL
56+ ; X32-LABEL: testManyArgs:
57+ ; X32: # %bb.0:
58+ ; X32-NEXT: jmp FuncManyArgs # TAILCALL
59+ ;
60+ ; X64-LABEL: testManyArgs:
61+ ; X64: # %bb.0:
62+ ; X64-NEXT: jmp FuncManyArgs # TAILCALL
4663 %r = musttail call i32 @FuncManyArgs (i32 %0 , i32 %1 , i32 %2 , i32 %3 , i32 %4 , i32 %5 , i8 %6 , ptr byval (%struct.5xi32 ) %7 )
4764 ret i32 %r
4865}
4966
5067define dso_local i32 @testRecursion (i32 %0 , i32 %1 , i32 %2 , i32 %3 , i32 %4 , i32 %5 , i8 %6 , ptr byval (%struct.5xi32 ) %7 ) {
51- ; CHECK-LABEL: testRecursion:
52- ; CHECK: # %bb.0:
53- ; CHECK-NEXT: jmp testRecursion # TAILCALL
68+ ; X32-LABEL: testRecursion:
69+ ; X32: # %bb.0:
70+ ; X32-NEXT: jmp testRecursion # TAILCALL
71+ ;
72+ ; X64-LABEL: testRecursion:
73+ ; X64: # %bb.0:
74+ ; X64-NEXT: jmp testRecursion # TAILCALL
5475 %r = musttail call i32 @testRecursion (i32 %0 , i32 %1 , i32 %2 , i32 %3 , i32 %4 , i32 %5 , i8 %6 , ptr byval (%struct.5xi32 ) %7 )
5576 ret i32 %r
5677}
5778
5879define dso_local i32 @swap (ptr byval (%struct.1xi32 ) %0 , ptr byval (%struct.1xi32 ) %1 ) noinline {
59- ; CHECK-LABEL: swap:
60- ; CHECK: # %bb.0: # %entry
61- ; CHECK-NEXT: mov eax, dword ptr [rsp + 8]
62- ; CHECK-NEXT: add eax, dword ptr [rsp + 16]
63- ; CHECK-NEXT: ret
80+ ; X32-LABEL: swap:
81+ ; X32: # %bb.0: # %entry
82+ ; X32-NEXT: mov eax, dword ptr [esp + 4]
83+ ; X32-NEXT: add eax, dword ptr [esp + 8]
84+ ; X32-NEXT: ret
85+ ;
86+ ; X64-LABEL: swap:
87+ ; X64: # %bb.0: # %entry
88+ ; X64-NEXT: mov eax, dword ptr [rsp + 8]
89+ ; X64-NEXT: add eax, dword ptr [rsp + 16]
90+ ; X64-NEXT: ret
6491entry:
6592 %a.ptr = getelementptr inbounds %struct.1xi32 , ptr %0 , i32 0 , i32 0 , i32 0
6693 %a = load i32 , ptr %a.ptr , align 4
@@ -71,15 +98,25 @@ entry:
7198}
7299
73100define dso_local i32 @swapByValArguments (ptr byval (%struct.1xi32 ) %0 , ptr byval (%struct.1xi32 ) %1 ) {
74- ; CHECK-LABEL: swapByValArguments:
75- ; CHECK: # %bb.0:
76- ; CHECK-NEXT: mov eax, dword ptr [rsp + 8]
77- ; CHECK-NEXT: mov dword ptr [rsp - 16], eax
78- ; CHECK-NEXT: mov eax, dword ptr [rsp + 16]
79- ; CHECK-NEXT: mov dword ptr [rsp - 8], eax
80- ; CHECK-NEXT: jmp swap # TAILCALL
81-
82-
101+ ; X32-LABEL: swapByValArguments:
102+ ; X32: # %bb.0:
103+ ; X32-NEXT: sub esp, 8
104+ ; X32-NEXT: .cfi_def_cfa_offset 12
105+ ; X32-NEXT: mov eax, dword ptr [esp + 12]
106+ ; X32-NEXT: mov dword ptr [esp], eax
107+ ; X32-NEXT: mov eax, dword ptr [esp + 16]
108+ ; X32-NEXT: mov dword ptr [esp + 4], eax
109+ ; X32-NEXT: add esp, 8
110+ ; X32-NEXT: .cfi_def_cfa_offset 4
111+ ; X32-NEXT: jmp swap # TAILCALL
112+ ;
113+ ; X64-LABEL: swapByValArguments:
114+ ; X64: # %bb.0:
115+ ; X64-NEXT: mov eax, dword ptr [rsp + 8]
116+ ; X64-NEXT: mov dword ptr [rsp - 16], eax
117+ ; X64-NEXT: mov eax, dword ptr [rsp + 16]
118+ ; X64-NEXT: mov dword ptr [rsp - 8], eax
119+ ; X64-NEXT: jmp swap # TAILCALL
83120 %r = musttail call i32 @swap (ptr byval (%struct.1xi32 ) %1 , ptr byval (%struct.1xi32 ) %0 )
84121 ret i32 %r
85122}
@@ -94,9 +131,13 @@ declare void @large_callee(%twenty_bytes* byval(%twenty_bytes) align 4)
94131; actually passed in registers and the stack in the same way for the caller and
95132; callee. On x86 byval arguments are never (partially) passed via registers.
96133define void @large_caller (%twenty_bytes* byval (%twenty_bytes ) align 4 %a ) {
97- ; CHECK-LABEL: large_caller:
98- ; CHECK: # %bb.0: # %entry
99- ; CHECK-NEXT: jmp large_callee@PLT # TAILCALL
134+ ; X32-LABEL: large_caller:
135+ ; X32: # %bb.0: # %entry
136+ ; X32-NEXT: jmp large_callee@PLT # TAILCALL
137+ ;
138+ ; X64-LABEL: large_caller:
139+ ; X64: # %bb.0: # %entry
140+ ; X64-NEXT: jmp large_callee@PLT # TAILCALL
100141entry:
101142 musttail call void @large_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 %a )
102143 ret void
@@ -107,17 +148,35 @@ entry:
107148; into the stack space allocated by @large_caller_new_value's caller, so is
108149; valid.
109150define void @large_caller_new_value (%twenty_bytes* byval (%twenty_bytes ) align 4 %a ) {
110- ; CHECK-LABEL: large_caller_new_value:
111- ; CHECK: # %bb.0: # %entry
112- ; CHECK-NEXT: movabs rax, 4294967296
113- ; CHECK-NEXT: mov qword ptr [rsp - 20], rax
114- ; CHECK-NEXT: movabs rcx, 12884901890
115- ; CHECK-NEXT: mov qword ptr [rsp - 12], rcx
116- ; CHECK-NEXT: mov dword ptr [rsp - 4], 4
117- ; CHECK-NEXT: mov qword ptr [rsp + 8], rax
118- ; CHECK-NEXT: mov qword ptr [rsp + 16], rcx
119- ; CHECK-NEXT: mov dword ptr [rsp + 24], 4
120- ; CHECK-NEXT: jmp large_callee@PLT # TAILCALL
151+ ; X32-LABEL: large_caller_new_value:
152+ ; X32: # %bb.0: # %entry
153+ ; X32-NEXT: sub esp, 20
154+ ; X32-NEXT: .cfi_def_cfa_offset 24
155+ ; X32-NEXT: mov dword ptr [esp], 0
156+ ; X32-NEXT: mov dword ptr [esp + 4], 1
157+ ; X32-NEXT: mov dword ptr [esp + 8], 2
158+ ; X32-NEXT: mov dword ptr [esp + 12], 3
159+ ; X32-NEXT: mov dword ptr [esp + 16], 4
160+ ; X32-NEXT: mov dword ptr [esp + 24], 0
161+ ; X32-NEXT: mov dword ptr [esp + 28], 1
162+ ; X32-NEXT: mov dword ptr [esp + 32], 2
163+ ; X32-NEXT: mov dword ptr [esp + 36], 3
164+ ; X32-NEXT: mov dword ptr [esp + 40], 4
165+ ; X32-NEXT: add esp, 20
166+ ; X32-NEXT: .cfi_def_cfa_offset 4
167+ ; X32-NEXT: jmp large_callee@PLT # TAILCALL
168+ ;
169+ ; X64-LABEL: large_caller_new_value:
170+ ; X64: # %bb.0: # %entry
171+ ; X64-NEXT: movabs rax, 4294967296
172+ ; X64-NEXT: mov qword ptr [rsp - 20], rax
173+ ; X64-NEXT: movabs rcx, 12884901890
174+ ; X64-NEXT: mov qword ptr [rsp - 12], rcx
175+ ; X64-NEXT: mov dword ptr [rsp - 4], 4
176+ ; X64-NEXT: mov qword ptr [rsp + 8], rax
177+ ; X64-NEXT: mov qword ptr [rsp + 16], rcx
178+ ; X64-NEXT: mov dword ptr [rsp + 24], 4
179+ ; X64-NEXT: jmp large_callee@PLT # TAILCALL
121180entry:
122181 %y = alloca %twenty_bytes , align 4
123182 store i32 0 , ptr %y , align 4
@@ -135,19 +194,47 @@ entry:
135194
136195declare void @two_byvals_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 , %twenty_bytes* byval (%twenty_bytes ) align 4 )
137196define void @swap_byvals (%twenty_bytes* byval (%twenty_bytes ) align 4 %a , %twenty_bytes* byval (%twenty_bytes ) align 4 %b ) {
138- ; CHECK-LABEL: swap_byvals:
139- ; CHECK: # %bb.0: # %entry
140- ; CHECK-NEXT: mov eax, dword ptr [rsp + 24]
141- ; CHECK-NEXT: mov dword ptr [rsp - 8], eax
142- ; CHECK-NEXT: movaps xmm0, xmmword ptr [rsp + 8]
143- ; CHECK-NEXT: movaps xmmword ptr [rsp - 24], xmm0
144- ; CHECK-NEXT: mov eax, dword ptr [rsp + 48]
145- ; CHECK-NEXT: mov dword ptr [rsp - 32], eax
146- ; CHECK-NEXT: mov rax, qword ptr [rsp + 32]
147- ; CHECK-NEXT: mov rcx, qword ptr [rsp + 40]
148- ; CHECK-NEXT: mov qword ptr [rsp - 40], rcx
149- ; CHECK-NEXT: mov qword ptr [rsp - 48], rax
150- ; CHECK-NEXT: jmp two_byvals_callee@PLT # TAILCALL
197+ ; X32-LABEL: swap_byvals:
198+ ; X32: # %bb.0: # %entry
199+ ; X32-NEXT: sub esp, 40
200+ ; X32-NEXT: .cfi_def_cfa_offset 44
201+ ; X32-NEXT: mov eax, dword ptr [esp + 60]
202+ ; X32-NEXT: mov dword ptr [esp + 16], eax
203+ ; X32-NEXT: mov eax, dword ptr [esp + 56]
204+ ; X32-NEXT: mov dword ptr [esp + 12], eax
205+ ; X32-NEXT: mov eax, dword ptr [esp + 52]
206+ ; X32-NEXT: mov dword ptr [esp + 8], eax
207+ ; X32-NEXT: mov eax, dword ptr [esp + 44]
208+ ; X32-NEXT: mov ecx, dword ptr [esp + 48]
209+ ; X32-NEXT: mov dword ptr [esp + 4], ecx
210+ ; X32-NEXT: mov dword ptr [esp], eax
211+ ; X32-NEXT: mov eax, dword ptr [esp + 80]
212+ ; X32-NEXT: mov dword ptr [esp + 36], eax
213+ ; X32-NEXT: mov eax, dword ptr [esp + 76]
214+ ; X32-NEXT: mov dword ptr [esp + 32], eax
215+ ; X32-NEXT: mov eax, dword ptr [esp + 72]
216+ ; X32-NEXT: mov dword ptr [esp + 28], eax
217+ ; X32-NEXT: mov eax, dword ptr [esp + 64]
218+ ; X32-NEXT: mov ecx, dword ptr [esp + 68]
219+ ; X32-NEXT: mov dword ptr [esp + 24], ecx
220+ ; X32-NEXT: mov dword ptr [esp + 20], eax
221+ ; X32-NEXT: add esp, 40
222+ ; X32-NEXT: .cfi_def_cfa_offset 4
223+ ; X32-NEXT: jmp two_byvals_callee@PLT # TAILCALL
224+ ;
225+ ; X64-LABEL: swap_byvals:
226+ ; X64: # %bb.0: # %entry
227+ ; X64-NEXT: mov eax, dword ptr [rsp + 24]
228+ ; X64-NEXT: mov dword ptr [rsp - 8], eax
229+ ; X64-NEXT: movaps xmm0, xmmword ptr [rsp + 8]
230+ ; X64-NEXT: movaps xmmword ptr [rsp - 24], xmm0
231+ ; X64-NEXT: mov eax, dword ptr [rsp + 48]
232+ ; X64-NEXT: mov dword ptr [rsp - 32], eax
233+ ; X64-NEXT: mov rax, qword ptr [rsp + 32]
234+ ; X64-NEXT: mov rcx, qword ptr [rsp + 40]
235+ ; X64-NEXT: mov qword ptr [rsp - 40], rcx
236+ ; X64-NEXT: mov qword ptr [rsp - 48], rax
237+ ; X64-NEXT: jmp two_byvals_callee@PLT # TAILCALL
151238entry:
152239 musttail call void @two_byvals_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 %b , %twenty_bytes* byval (%twenty_bytes ) align 4 %a )
153240 ret void
@@ -159,9 +246,41 @@ entry:
159246; can be tail-call optimized.
160247declare void @shift_byval_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 )
161248define void @shift_byval (i32 %a , %twenty_bytes* byval (%twenty_bytes ) align 4 %b ) {
162- ; CHECK-LABEL: shift_byval:
163- ; CHECK: # %bb.0: # %entry
164- ; CHECK-NEXT: jmp shift_byval_callee@PLT # TAILCALL
249+ ; X32-LABEL: shift_byval:
250+ ; X32: # %bb.0: # %entry
251+ ; X32-NEXT: push edi
252+ ; X32-NEXT: .cfi_def_cfa_offset 8
253+ ; X32-NEXT: push esi
254+ ; X32-NEXT: .cfi_def_cfa_offset 12
255+ ; X32-NEXT: .cfi_offset esi, -12
256+ ; X32-NEXT: .cfi_offset edi, -8
257+ ; X32-NEXT: mov eax, dword ptr [esp + 32]
258+ ; X32-NEXT: mov ecx, dword ptr [esp + 28]
259+ ; X32-NEXT: mov edx, dword ptr [esp + 24]
260+ ; X32-NEXT: mov esi, dword ptr [esp + 16]
261+ ; X32-NEXT: mov edi, dword ptr [esp + 20]
262+ ; X32-NEXT: push eax
263+ ; X32-NEXT: .cfi_adjust_cfa_offset 4
264+ ; X32-NEXT: push ecx
265+ ; X32-NEXT: .cfi_adjust_cfa_offset 4
266+ ; X32-NEXT: push edx
267+ ; X32-NEXT: .cfi_adjust_cfa_offset 4
268+ ; X32-NEXT: push edi
269+ ; X32-NEXT: .cfi_adjust_cfa_offset 4
270+ ; X32-NEXT: push esi
271+ ; X32-NEXT: .cfi_adjust_cfa_offset 4
272+ ; X32-NEXT: call shift_byval_callee@PLT
273+ ; X32-NEXT: add esp, 20
274+ ; X32-NEXT: .cfi_adjust_cfa_offset -20
275+ ; X32-NEXT: pop esi
276+ ; X32-NEXT: .cfi_def_cfa_offset 8
277+ ; X32-NEXT: pop edi
278+ ; X32-NEXT: .cfi_def_cfa_offset 4
279+ ; X32-NEXT: ret
280+ ;
281+ ; X64-LABEL: shift_byval:
282+ ; X64: # %bb.0: # %entry
283+ ; X64-NEXT: jmp shift_byval_callee@PLT # TAILCALL
165284entry:
166285 tail call void @shift_byval_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 %b )
167286 ret void
@@ -171,16 +290,30 @@ entry:
171290; need a stack temporary.
172291@large_global = external global %twenty_bytes
173292define void @large_caller_from_global (%twenty_bytes* byval (%twenty_bytes ) align 4 %a ) {
174- ; CHECK-LABEL: large_caller_from_global:
175- ; CHECK: # %bb.0: # %entry
176- ; CHECK-NEXT: mov rax, qword ptr [rip + large_global@GOTPCREL]
177- ; CHECK-NEXT: mov ecx, dword ptr [rax + 16]
178- ; CHECK-NEXT: mov dword ptr [rsp + 24], ecx
179- ; CHECK-NEXT: mov rcx, qword ptr [rax]
180- ; CHECK-NEXT: mov rax, qword ptr [rax + 8]
181- ; CHECK-NEXT: mov qword ptr [rsp + 16], rax
182- ; CHECK-NEXT: mov qword ptr [rsp + 8], rcx
183- ; CHECK-NEXT: jmp large_callee@PLT # TAILCALL
293+ ; X32-LABEL: large_caller_from_global:
294+ ; X32: # %bb.0: # %entry
295+ ; X32-NEXT: mov eax, dword ptr [large_global+16]
296+ ; X32-NEXT: mov dword ptr [esp + 20], eax
297+ ; X32-NEXT: mov eax, dword ptr [large_global+12]
298+ ; X32-NEXT: mov dword ptr [esp + 16], eax
299+ ; X32-NEXT: mov eax, dword ptr [large_global+8]
300+ ; X32-NEXT: mov dword ptr [esp + 12], eax
301+ ; X32-NEXT: mov eax, dword ptr [large_global+4]
302+ ; X32-NEXT: mov dword ptr [esp + 8], eax
303+ ; X32-NEXT: mov eax, dword ptr [large_global]
304+ ; X32-NEXT: mov dword ptr [esp + 4], eax
305+ ; X32-NEXT: jmp large_callee@PLT # TAILCALL
306+ ;
307+ ; X64-LABEL: large_caller_from_global:
308+ ; X64: # %bb.0: # %entry
309+ ; X64-NEXT: mov rax, qword ptr [rip + large_global@GOTPCREL]
310+ ; X64-NEXT: mov ecx, dword ptr [rax + 16]
311+ ; X64-NEXT: mov dword ptr [rsp + 24], ecx
312+ ; X64-NEXT: mov rcx, qword ptr [rax]
313+ ; X64-NEXT: mov rax, qword ptr [rax + 8]
314+ ; X64-NEXT: mov qword ptr [rsp + 16], rax
315+ ; X64-NEXT: mov qword ptr [rsp + 8], rcx
316+ ; X64-NEXT: jmp large_callee@PLT # TAILCALL
184317entry:
185318 musttail call void @large_callee (%twenty_bytes* byval (%twenty_bytes ) align 4 @large_global )
186319 ret void
0 commit comments