• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s | FileCheck %s
2
3target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6declare hhvmcc i64 @bar(i64, i64, i64) nounwind
7
8; Simply check we can modify %rbx and %rbp before returning via call to bar.
9define hhvmcc i64 @foo(i64 %a, i64 %b, i64 %c) nounwind {
10entry:
11; CHECK-LABEL:  foo:
12; CHECK-DAG:    movl $1, %ebx
13; CHECK-DAG:    movl $3, %ebp
14; CHECK:        jmp bar
15  %ret = musttail call hhvmcc i64 @bar(i64 1, i64 %b, i64 3)
16  ret i64 %ret
17}
18
19; Check that we can read and modify %rbx returned from PHP function.
20define hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind {
21entry:
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
28  ret i64 %retval
29}
30
31%rettype = type { i64, i64, i64, i64, i64, i64, i64,
32                  i64, i64, i64, i64, i64, i64, i64
33}
34
35; Check that we can return up to 14 64-bit args in registers.
36define hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind {
37entry:
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
53; CHECK:        retq
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
68  ret %rettype %r14
69}
70
71declare hhvmcc void @return_all_tc(i64, i64, i64, i64, i64, i64, i64, i64,
72                                 i64, i64, i64, i64, i64, i64, i64)
73
74; Check that we can return up to 14 64-bit args in registers via tail call.
75define hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind {
76entry:
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)
97  ret void
98}
99
100declare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64)
101
102define hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind {
103entry:
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
109; CHECK-NEXT:   retq
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
113  ret i64 %rv
114}
115
116declare hhvmcc %rettype @php_all(i64, i64, i64, i64, i64, i64, i64,
117                                 i64, i64, i64, i64, i64, i64, i64, i64)
118
119; Check that we can pass 15 arguments in registers.
120; Also check that %r12 (2nd arg) is not spilled.
121define hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind {
122entry:
123; CHECK-LABEL:  test_php_all:
124; CHECK-NEXT:   {{^#.*}}
125; CHECK-NOT:    sub
126; CHECK-NOT:    sub
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
147  ret i64 %rv
148}
149
150declare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
151                             i64, i64)
152
153define hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind {
154entry:
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
163; CHECK:        jmp svcreq
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,
166                                i64 42)
167  ret void
168}
169
170declare hhvm_ccc void @helper_short(i64, i64, i64, i64, i64, i64, i64)
171
172; Pass all arguments in registers and check that we don't adjust stack
173; for the call.
174define hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind {
175entry:
176; CHECK-LABEL:  test_helper_short:
177; CHECK-NOT:    push
178; CHECK-NOT:    sub
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,
187                                   i64 5, i64 6)
188  ret void
189}
190
191declare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
192
193define hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind {
194entry:
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,
204                             i64 7, i64 8, i64 9)
205  ret void
206}
207
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.
211declare hhvm_ccc void @stack_helper(i64, i64, i64)
212declare hhvm_ccc void @stack_helper2(<2 x double>, i64)
213
214define hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind {
215entry:
216; CHECK-LABEL:  test_stack_helper:
217; CHECK-NOT:    push
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)
229  ret void
230}
231
232; Check that we are not adjusting the stack before calling the helper.
233define hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind {
234entry:
235; CHECK-LABEL:  test_stack_helper2:
236; CHECK-NOT:    push
237; CHECK-NOT:    subq
238  call hhvm_ccc void @stack_helper(i64 %c, i64 7, i64 42)
239  ret void
240}
241
242