Home | History | Annotate | Download | only in X86
      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 
    242