1 ; RUN: llc < %s | FileCheck %s
3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
6 declare hhvmcc i64 @bar(i64, i64, i64) nounwind
8 ; Simply check we can modify %rbx and %rbp before returning via call to bar.
9 define hhvmcc i64 @foo(i64 %a, i64 %b, i64 %c) nounwind {
12 ; CHECK-DAG: movl $1, %ebx
13 ; CHECK-DAG: movl $3, %ebp
15 %ret = musttail call hhvmcc i64 @bar(i64 1, i64 %b, i64 3)
19 ; Check that we can read and modify %rbx returned from PHP function.
20 define hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind {
22 ; CHECK-LABEL: mod_return:
23 ; CHECK-NEXT: {{^#.*}}
24 ; CHECK-NEXT: callq bar
25 ; CHECK-NEXT: incq %rbx
26 %tmp = call hhvmcc i64 @bar(i64 %a, i64 %b, i64 %c)
27 %retval = add i64 %tmp, 1
31 %rettype = type { i64, i64, i64, i64, i64, i64, i64,
32 i64, i64, i64, i64, i64, i64, i64
35 ; Check that we can return up to 14 64-bit args in registers.
36 define hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind {
38 ; CHECK-LABEL: return_all:
39 ; CHECK-DAG: movl $1, %ebx
40 ; CHECK-DAG: movl $2, %ebp
41 ; CHECK-DAG: movl $3, %edi
42 ; CHECK-DAG: movl $4, %esi
43 ; CHECK-DAG: movl $5, %edx
44 ; CHECK-DAG: movl $6, %ecx
45 ; CHECK-DAG: movl $7, %r8
46 ; CHECK-DAG: movl $8, %r9
47 ; CHECK-DAG: movl $9, %eax
48 ; CHECK-DAG: movl $10, %r10
49 ; CHECK-DAG: movl $11, %r11
50 ; CHECK-DAG: movl $12, %r13
51 ; CHECK-DAG: movl $13, %r14
52 ; CHECK-DAG: movl $14, %r15
54 %r1 = insertvalue %rettype zeroinitializer, i64 1, 0
55 %r2 = insertvalue %rettype %r1, i64 2, 1
56 %r3 = insertvalue %rettype %r2, i64 3, 2
57 %r4 = insertvalue %rettype %r3, i64 4, 3
58 %r5 = insertvalue %rettype %r4, i64 5, 4
59 %r6 = insertvalue %rettype %r5, i64 6, 5
60 %r7 = insertvalue %rettype %r6, i64 7, 6
61 %r8 = insertvalue %rettype %r7, i64 8, 7
62 %r9 = insertvalue %rettype %r8, i64 9, 8
63 %r10 = insertvalue %rettype %r9, i64 10, 9
64 %r11 = insertvalue %rettype %r10, i64 11, 10
65 %r12 = insertvalue %rettype %r11, i64 12, 11
66 %r13 = insertvalue %rettype %r12, i64 13, 12
67 %r14 = insertvalue %rettype %r13, i64 14, 13
71 declare hhvmcc void @return_all_tc(i64, i64, i64, i64, i64, i64, i64, i64,
72 i64, i64, i64, i64, i64, i64, i64)
74 ; Check that we can return up to 14 64-bit args in registers via tail call.
75 define hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind {
77 ; CHECK-LABEL: test_return_all_tc:
78 ; CHECK-NEXT: {{^#.*}}
79 ; CHECK-DAG: movl $1, %ebx
80 ; CHECK-DAG: movl $3, %ebp
81 ; CHECK-DAG: movl $4, %r15
82 ; CHECK-DAG: movl $5, %edi
83 ; CHECK-DAG: movl $6, %esi
84 ; CHECK-DAG: movl $7, %edx
85 ; CHECK-DAG: movl $8, %ecx
86 ; CHECK-DAG: movl $9, %r8
87 ; CHECK-DAG: movl $10, %r9
88 ; CHECK-DAG: movl $11, %eax
89 ; CHECK-DAG: movl $12, %r10
90 ; CHECK-DAG: movl $13, %r11
91 ; CHECK-DAG: movl $14, %r13
92 ; CHECK-DAG: movl $15, %r14
93 ; CHECK: jmp return_all_tc
94 tail call hhvmcc void @return_all_tc(
95 i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
96 i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
100 declare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64)
102 define hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind {
104 ; CHECK-LABEL: test_php_short:
105 ; CHECK-NEXT: {{^#.*}}
106 ; CHECK-NEXT: movl $42, %r15
107 ; CHECK-NEXT: callq php_short
108 ; CHECK-NEXT: leaq (%rbp,%r12), %rbx
110 %pair = call hhvmcc {i64, i64} @php_short(i64 %a, i64 %b, i64 %c, i64 42)
111 %fp = extractvalue {i64, i64} %pair, 1
112 %rv = add i64 %fp, %b
116 declare hhvmcc %rettype @php_all(i64, i64, i64, i64, i64, i64, i64,
117 i64, i64, i64, i64, i64, i64, i64, i64)
119 ; Check that we can pass 15 arguments in registers.
120 ; Also check that %r12 (2nd arg) is not spilled.
121 define hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind {
123 ; CHECK-LABEL: test_php_all:
124 ; CHECK-NEXT: {{^#.*}}
127 ; CHECK-DAG: movl $1, %ebx
128 ; CHECK-DAG: movl $3, %ebp
129 ; CHECK-DAG: movl $4, %r15
130 ; CHECK-DAG: movl $5, %edi
131 ; CHECK-DAG: movl $6, %esi
132 ; CHECK-DAG: movl $7, %edx
133 ; CHECK-DAG: movl $8, %ecx
134 ; CHECK-DAG: movl $9, %r8
135 ; CHECK-DAG: movl $10, %r9
136 ; CHECK-DAG: movl $11, %eax
137 ; CHECK-DAG: movl $12, %r10
138 ; CHECK-DAG: movl $13, %r11
139 ; CHECK-DAG: movl $14, %r13
140 ; CHECK-DAG: movl $15, %r14
141 ; CHECK: callq php_all
142 %pair = call hhvmcc %rettype @php_all(
143 i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
144 i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
145 %fp = extractvalue %rettype %pair, 1
146 %rv = add i64 %fp, %b
150 declare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
153 define hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind {
155 ; CHECK-LABEL: test_svcreq:
156 ; CHECK-DAG: movl $42, %r10
157 ; CHECK-DAG: movl $1, %edi
158 ; CHECK-DAG: movl $2, %esi
159 ; CHECK-DAG: movl $3, %edx
160 ; CHECK-DAG: movl $4, %ecx
161 ; CHECK-DAG: movl $5, %r8
162 ; CHECK-DAG: movl $6, %r9
164 tail call hhvmcc void @svcreq(i64 %a, i64 %b, i64 %c, i64 undef, i64 1,
165 i64 2, i64 3, i64 4, i64 5, i64 6, i64 undef,
170 declare hhvm_ccc void @helper_short(i64, i64, i64, i64, i64, i64, i64)
172 ; Pass all arguments in registers and check that we don't adjust stack
174 define hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind {
176 ; CHECK-LABEL: test_helper_short:
179 ; CHECK-DAG: movl $1, %edi
180 ; CHECK-DAG: movl $2, %esi
181 ; CHECK-DAG: movl $3, %edx
182 ; CHECK-DAG: movl $4, %ecx
183 ; CHECK-DAG: movl $5, %r8
184 ; CHECK-DAG: movl $6, %r9
185 ; CHECK: callq helper_short
186 call hhvm_ccc void @helper_short(i64 %c, i64 1, i64 2, i64 3, i64 4,
191 declare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
193 define hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind {
195 ; CHECK-LABEL: test_helper:
196 ; CHECK-DAG: movl $1, %edi
197 ; CHECK-DAG: movl $2, %esi
198 ; CHECK-DAG: movl $3, %edx
199 ; CHECK-DAG: movl $4, %ecx
200 ; CHECK-DAG: movl $5, %r8
201 ; CHECK-DAG: movl $6, %r9
202 ; CHECK: callq helper
203 call hhvm_ccc void @helper(i64 %c, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6,
208 ; When we enter function with HHVM calling convention, the stack is aligned
209 ; at 16 bytes. This means we align objects on the stack differently and
210 ; adjust the stack differently for calls.
211 declare hhvm_ccc void @stack_helper(i64, i64, i64)
212 declare hhvm_ccc void @stack_helper2(<2 x double>, i64)
214 define hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind {
216 ; CHECK-LABEL: test_stack_helper:
218 ; CHECK: subq $32, %rsp
219 ; CHECK: movaps 16(%rsp), %xmm0
220 ; CHECK: callq stack_helper2
221 %t1 = alloca <2 x double>, align 16
222 %t2 = alloca i64, align 8
223 %t3 = alloca i64, align 8
224 %load3 = load i64, i64 *%t3
225 call hhvm_ccc void @stack_helper(i64 %c, i64 %load3, i64 42)
226 %load = load <2 x double>, <2 x double> *%t1
227 %load2 = load i64, i64 *%t2
228 call hhvm_ccc void @stack_helper2(<2 x double> %load, i64 %load2)
232 ; Check that we are not adjusting the stack before calling the helper.
233 define hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind {
235 ; CHECK-LABEL: test_stack_helper2:
238 call hhvm_ccc void @stack_helper(i64 %c, i64 7, i64 42)