Home | History | Annotate | Download | only in X86
      1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
      2 ; RUN: llc -verify-machineinstrs -O3 < %s | FileCheck %s
      3 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
      4 target triple = "x86_64-apple-macosx10.11.0"
      5 
      6 declare void @bar() #0
      7 declare void @baz()
      8 
      9 define void @test1(i32 %a) gc "statepoint-example" {
     10 ; CHECK-LABEL: test1:
     11 ; CHECK:       ## %bb.0: ## %entry
     12 ; CHECK-NEXT:    pushq %rax
     13 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
     14 ; CHECK-NEXT:    callq _bar
     15 ; CHECK-NEXT:  Ltmp0:
     16 ; CHECK-NEXT:    popq %rax
     17 ; CHECK-NEXT:    retq
     18 entry:
     19 ; We expect the argument to be passed in an extra register to bar
     20   %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
     21   ret void
     22 }
     23 
     24 define void @test2(i32 %a, i32 %b) gc "statepoint-example" {
     25 ; CHECK-LABEL: test2:
     26 ; CHECK:       ## %bb.0: ## %entry
     27 ; CHECK-NEXT:    pushq %rbp
     28 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
     29 ; CHECK-NEXT:    pushq %rbx
     30 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
     31 ; CHECK-NEXT:    pushq %rax
     32 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
     33 ; CHECK-NEXT:    .cfi_offset %rbx, -24
     34 ; CHECK-NEXT:    .cfi_offset %rbp, -16
     35 ; CHECK-NEXT:    movl %esi, %ebx
     36 ; CHECK-NEXT:    movl %edi, %ebp
     37 ; CHECK-NEXT:    callq _bar
     38 ; CHECK-NEXT:  Ltmp1:
     39 ; CHECK-NEXT:    callq _bar
     40 ; CHECK-NEXT:  Ltmp2:
     41 ; CHECK-NEXT:    addq $8, %rsp
     42 ; CHECK-NEXT:    popq %rbx
     43 ; CHECK-NEXT:    popq %rbp
     44 ; CHECK-NEXT:    retq
     45 entry:
     46 ; Because the first call clobbers esi, we have to move the values into
     47 ; new registers.  Note that they stay in the registers for both calls.
     48   call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 2, i32 %a, i32 %b)
     49   call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 2, i32 %b, i32 %a)
     50   ret void
     51 }
     52 
     53 define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i) gc "statepoint-example" {
     54 ; CHECK-LABEL: test3:
     55 ; CHECK:       ## %bb.0: ## %entry
     56 ; CHECK-NEXT:    pushq %rax
     57 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
     58 ; CHECK-NEXT:    callq _bar
     59 ; CHECK-NEXT:  Ltmp3:
     60 ; CHECK-NEXT:    popq %rax
     61 ; CHECK-NEXT:    retq
     62 entry:
     63 ; We directly reference the argument slot
     64   %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 9, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i)
     65   ret void
     66 }
     67 
     68 ; This case just confirms that we don't crash when given more live values
     69 ; than registers.  This is a case where we *have* to use a stack slot.  This
     70 ; also ends up being a good test of whether we can fold loads from immutable
     71 ; stack slots into the statepoint.
     72 define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" {
     73 ; CHECK-LABEL: test4:
     74 ; CHECK:       ## %bb.0: ## %entry
     75 ; CHECK-NEXT:    pushq %rax
     76 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
     77 ; CHECK-NEXT:    callq _bar
     78 ; CHECK-NEXT:  Ltmp4:
     79 ; CHECK-NEXT:    popq %rax
     80 ; CHECK-NEXT:    retq
     81 entry:
     82   %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 26, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)
     83   ret void
     84 }
     85 
     86 ; A live-through gc-value must be spilled even if it is also a live-in deopt
     87 ; value.  For live-in, we could technically report the register copy, but from
     88 ; a code quality perspective it's better to reuse the required stack slot so
     89 ; as to put less stress on the register allocator for no benefit.
     90 define  i32 addrspace(1)* @test5(i32 %a, i32 addrspace(1)* %p) gc "statepoint-example" {
     91 ; CHECK-LABEL: test5:
     92 ; CHECK:       ## %bb.0: ## %entry
     93 ; CHECK-NEXT:    pushq %rax
     94 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
     95 ; CHECK-NEXT:    movq %rsi, (%rsp)
     96 ; CHECK-NEXT:    callq _bar
     97 ; CHECK-NEXT:  Ltmp5:
     98 ; CHECK-NEXT:    movq (%rsp), %rax
     99 ; CHECK-NEXT:    popq %rcx
    100 ; CHECK-NEXT:    retq
    101 entry:
    102   %token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a, i32 addrspace(1)* %p, i32 addrspace(1)* %p)
    103   %p2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token,  i32 9, i32 9)
    104   ret i32 addrspace(1)* %p2
    105 }
    106 
    107 ; Show the interaction of live-through spilling followed by live-in.
    108 define void @test6(i32 %a) gc "statepoint-example" {
    109 ; CHECK-LABEL: test6:
    110 ; CHECK:       ## %bb.0: ## %entry
    111 ; CHECK-NEXT:    pushq %rbx
    112 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
    113 ; CHECK-NEXT:    subq $16, %rsp
    114 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
    115 ; CHECK-NEXT:    .cfi_offset %rbx, -16
    116 ; CHECK-NEXT:    movl %edi, %ebx
    117 ; CHECK-NEXT:    movl %edi, {{[0-9]+}}(%rsp)
    118 ; CHECK-NEXT:    callq _baz
    119 ; CHECK-NEXT:  Ltmp6:
    120 ; CHECK-NEXT:    callq _bar
    121 ; CHECK-NEXT:  Ltmp7:
    122 ; CHECK-NEXT:    addq $16, %rsp
    123 ; CHECK-NEXT:    popq %rbx
    124 ; CHECK-NEXT:    retq
    125 entry:
    126   call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 %a)
    127   call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
    128   ret void
    129 }
    130 
    131 
    132 ; CHECK: Ltmp0-_test1
    133 ; CHECK:      .byte	1
    134 ; CHECK-NEXT:   .byte   0
    135 ; CHECK-NEXT: .short 4
    136 ; CHECK-NEXT: .short	5
    137 ; CHECK-NEXT:   .short  0
    138 ; CHECK-NEXT: .long	0
    139 
    140 ; CHECK: Ltmp1-_test2
    141 ; CHECK:      .byte	1
    142 ; CHECK-NEXT:   .byte   0
    143 ; CHECK-NEXT: .short 4
    144 ; CHECK-NEXT: .short	6
    145 ; CHECK-NEXT:   .short  0
    146 ; CHECK-NEXT: .long	0
    147 ; CHECK:      .byte	1
    148 ; CHECK-NEXT:   .byte   0
    149 ; CHECK-NEXT: .short 4
    150 ; CHECK-NEXT: .short	3
    151 ; CHECK-NEXT:   .short  0
    152 ; CHECK-NEXT: .long	0
    153 ; CHECK: Ltmp2-_test2
    154 ; CHECK:      .byte	1
    155 ; CHECK-NEXT:   .byte   0
    156 ; CHECK-NEXT: .short 4
    157 ; CHECK-NEXT: .short	3
    158 ; CHECK-NEXT:   .short  0
    159 ; CHECK-NEXT: .long	0
    160 ; CHECK:      .byte	1
    161 ; CHECK-NEXT:   .byte   0
    162 ; CHECK-NEXT: .short 4
    163 ; CHECK-NEXT: .short	6
    164 ; CHECK-NEXT:   .short  0
    165 ; CHECK-NEXT: .long	0
    166 
    167 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
    168 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
    169 
    170 
    171 attributes #0 = { "deopt-lowering"="live-in" }
    172 attributes #1 = { "deopt-lowering"="live-through" }
    173