[TwoAddressInstructionPass] When looking for a 3 addr conversion after commuting...
[oota-llvm.git] / test / CodeGen / X86 / hhvm-cc.ll
1 ; RUN: llc < %s | FileCheck %s
2
3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
5
6 declare hhvmcc i64 @bar(i64, i64, i64) nounwind
7
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 {
10 entry:
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.
20 define hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind {
21 entry:
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.
36 define hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind {
37 entry:
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
71 declare 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.
75 define hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind {
76 entry:
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
100 declare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64)
101
102 define hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind {
103 entry:
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
116 declare 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.
121 define hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind {
122 entry:
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
150 declare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
151                              i64, i64)
152
153 define hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind {
154 entry:
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
170 declare 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.
174 define hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind {
175 entry:
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
191 declare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
192
193 define hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind {
194 entry:
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.
211 declare hhvm_ccc void @stack_helper(i64, i64, i64)
212 declare hhvm_ccc void @stack_helper2(<2 x double>, i64)
213
214 define hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind {
215 entry:
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.
233 define hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind {
234 entry:
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