|  | ; RUN: llc < %s -tailcallopt -mtriple=x86_64-linux-gnu | FileCheck %s | 
|  |  | 
|  | ; Check the GHC call convention works (x86-64) | 
|  |  | 
|  | @base  = external dso_local global i64 ; assigned to register: R13 | 
|  | @sp    = external dso_local global i64 ; assigned to register: rbp | 
|  | @hp    = external dso_local global i64 ; assigned to register: R12 | 
|  | @r1    = external dso_local global i64 ; assigned to register: rbx | 
|  | @r2    = external dso_local global i64 ; assigned to register: R14 | 
|  | @r3    = external dso_local global i64 ; assigned to register: rsi | 
|  | @r4    = external dso_local global i64 ; assigned to register: rdi | 
|  | @r5    = external dso_local global i64 ; assigned to register: R8 | 
|  | @r6    = external dso_local global i64 ; assigned to register: R9 | 
|  | @splim = external dso_local global i64 ; assigned to register: R15 | 
|  |  | 
|  | @f1 = external dso_local global float  ; assigned to register: xmm1 | 
|  | @f2 = external dso_local global float  ; assigned to register: xmm2 | 
|  | @f3 = external dso_local global float  ; assigned to register: xmm3 | 
|  | @f4 = external dso_local global float  ; assigned to register: xmm4 | 
|  | @d1 = external dso_local global double ; assigned to register: xmm5 | 
|  | @d2 = external dso_local global double ; assigned to register: xmm6 | 
|  |  | 
|  | define void @zap(i64 %a, i64 %b) nounwind { | 
|  | entry: | 
|  | ; CHECK:      movq %rsi, %rbp | 
|  | ; CHECK-NEXT: movq %rdi, %r13 | 
|  | ; CHECK-NEXT: callq addtwo | 
|  | %0 = call ghccc i64 @addtwo(i64 %a, i64 %b) | 
|  | ; CHECK:      callq foo | 
|  | call void @foo() nounwind | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define ghccc i64 @addtwo(i64 %x, i64 %y) nounwind { | 
|  | entry: | 
|  | ; CHECK:      leaq (%r13,%rbp), %rax | 
|  | %0 = add i64 %x, %y | 
|  | ; CHECK-NEXT: ret | 
|  | ret i64 %0 | 
|  | } | 
|  |  | 
|  | define ghccc void @foo() nounwind { | 
|  | entry: | 
|  | ; CHECK:      movsd d2(%rip), %xmm6 | 
|  | ; CHECK-NEXT: movsd d1(%rip), %xmm5 | 
|  | ; CHECK-NEXT: movss f4(%rip), %xmm4 | 
|  | ; CHECK-NEXT: movss f3(%rip), %xmm3 | 
|  | ; CHECK-NEXT: movss f2(%rip), %xmm2 | 
|  | ; CHECK-NEXT: movss f1(%rip), %xmm1 | 
|  | ; CHECK-NEXT: movq splim(%rip), %r15 | 
|  | ; CHECK-NEXT: movq r6(%rip), %r9 | 
|  | ; CHECK-NEXT: movq r5(%rip), %r8 | 
|  | ; CHECK-NEXT: movq r4(%rip), %rdi | 
|  | ; CHECK-NEXT: movq r3(%rip), %rsi | 
|  | ; CHECK-NEXT: movq r2(%rip), %r14 | 
|  | ; CHECK-NEXT: movq r1(%rip), %rbx | 
|  | ; CHECK-NEXT: movq hp(%rip), %r12 | 
|  | ; CHECK-NEXT: movq sp(%rip), %rbp | 
|  | ; CHECK-NEXT: movq base(%rip), %r13 | 
|  | %0 = load double, ptr @d2 | 
|  | %1 = load double, ptr @d1 | 
|  | %2 = load float, ptr @f4 | 
|  | %3 = load float, ptr @f3 | 
|  | %4 = load float, ptr @f2 | 
|  | %5 = load float, ptr @f1 | 
|  | %6 = load i64, ptr @splim | 
|  | %7 = load i64, ptr @r6 | 
|  | %8 = load i64, ptr @r5 | 
|  | %9 = load i64, ptr @r4 | 
|  | %10 = load i64, ptr @r3 | 
|  | %11 = load i64, ptr @r2 | 
|  | %12 = load i64, ptr @r1 | 
|  | %13 = load i64, ptr @hp | 
|  | %14 = load i64, ptr @sp | 
|  | %15 = load i64, ptr @base | 
|  | ; CHECK: jmp bar | 
|  | tail call ghccc void @bar( i64 %15, i64 %14, i64 %13, i64 %12, i64 %11, | 
|  | i64 %10, i64 %9, i64 %8, i64 %7, i64 %6, | 
|  | float %5, float %4, float %3, float %2, double %1, | 
|  | double %0 ) nounwind | 
|  | ret void | 
|  | } | 
|  |  | 
|  | declare ghccc void @bar(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, | 
|  | float, float, float, float, double, double) |