Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s | FileCheck %s
      2 ; This file contains a collection of basic tests to ensure we didn't
      3 ; screw up normal call lowering when a statepoint is a GC transition.
      4 
      5 target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
      6 target triple = "x86_64-pc-linux-gnu"
      7 
      8 declare zeroext i1 @return_i1()
      9 declare zeroext i32 @return_i32()
     10 declare zeroext i32 @return_i32_with_args(i32, i8*)
     11 declare i32* @return_i32ptr()
     12 declare float @return_float()
     13 declare void @varargf(i32, ...)
     14 
     15 define i1 @test_i1_return() gc "statepoint-example" {
     16 ; CHECK-LABEL: test_i1_return
     17 ; This is just checking that a i1 gets lowered normally when there's no extra
     18 ; state arguments to the statepoint
     19 ; CHECK: pushq %rax
     20 ; CHECK: callq return_i1
     21 ; CHECK: popq %rcx
     22 ; CHECK: retq
     23 entry:
     24   %safepoint_token = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0)
     25   %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
     26   ret i1 %call1
     27 }
     28 
     29 define i32 @test_i32_return() gc "statepoint-example" {
     30 ; CHECK-LABEL: test_i32_return
     31 ; CHECK: pushq %rax
     32 ; CHECK: callq return_i32
     33 ; CHECK: popq %rcx
     34 ; CHECK: retq
     35 entry:
     36   %safepoint_token = tail call i32 (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 0, i32 0, i32 ()* @return_i32, i32 0, i32 1, i32 0, i32 0)
     37   %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
     38   ret i32 %call1
     39 }
     40 
     41 define i32* @test_i32ptr_return() gc "statepoint-example" {
     42 ; CHECK-LABEL: test_i32ptr_return
     43 ; CHECK: pushq %rax
     44 ; CHECK: callq return_i32ptr
     45 ; CHECK: popq %rcx
     46 ; CHECK: retq
     47 entry:
     48   %safepoint_token = tail call i32 (i64, i32, i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i64 0, i32 0, i32* ()* @return_i32ptr, i32 0, i32 1, i32 0, i32 0)
     49   %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
     50   ret i32* %call1
     51 }
     52 
     53 define float @test_float_return() gc "statepoint-example" {
     54 ; CHECK-LABEL: test_float_return
     55 ; CHECK: pushq %rax
     56 ; CHECK: callq return_float
     57 ; CHECK: popq %rax
     58 ; CHECK: retq
     59 entry:
     60   %safepoint_token = tail call i32 (i64, i32, float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(i64 0, i32 0, float ()* @return_float, i32 0, i32 1, i32 0, i32 0)
     61   %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
     62   ret float %call1
     63 }
     64 
     65 define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
     66 ; CHECK-LABEL: test_relocate
     67 ; Check that an ununsed relocate has no code-generation impact
     68 ; CHECK: pushq %rax
     69 ; CHECK: callq return_i1
     70 ; CHECK-NEXT: .Ltmp9:
     71 ; CHECK-NEXT: popq %rcx
     72 ; CHECK-NEXT: retq
     73 entry:
     74   %safepoint_token = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0, i32 addrspace(1)* %a)
     75   %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
     76   %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
     77   ret i1 %call2
     78 }
     79 
     80 define void @test_void_vararg() gc "statepoint-example" {
     81 ; CHECK-LABEL: test_void_vararg
     82 ; Check a statepoint wrapping a *void* returning vararg function works
     83 ; CHECK: callq varargf
     84 entry:
     85   %safepoint_token = tail call i32 (i64, i32, void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64 0, i32 0, void (i32, ...)* @varargf, i32 2, i32 1, i32 42, i32 43, i32 0, i32 0)
     86   ;; if we try to use the result from a statepoint wrapping a
     87   ;; non-void-returning varargf, we will experience a crash.
     88   ret void
     89 }
     90 
     91 define i32 @test_transition_args() gc "statepoint-example" {
     92 ; CHECK-LABEL: test_transition_args
     93 ; CHECK: pushq %rax
     94 ; CHECK: callq return_i32
     95 ; CHECK: popq %rcx
     96 ; CHECK: retq
     97 entry:
     98   %val = alloca i32
     99   %safepoint_token = call i32 (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 0, i32 0, i32 ()* @return_i32, i32 0, i32 1, i32 2, i32* %val, i64 42, i32 0)
    100   %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
    101   ret i32 %call1
    102 }
    103 
    104 define i32 @test_transition_args_2() gc "statepoint-example" {
    105 ; CHECK-LABEL: test_transition_args_2
    106 ; CHECK: pushq %rax
    107 ; CHECK: callq return_i32
    108 ; CHECK: popq %rcx
    109 ; CHECK: retq
    110 entry:
    111   %val = alloca i32
    112   %arg = alloca i8
    113   %safepoint_token = call i32 (i64, i32, i32 (i32, i8*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i64 0, i32 0, i32 (i32, i8*)* @return_i32_with_args, i32 2, i32 1, i32 0, i8* %arg, i32 2, i32* %val, i64 42, i32 0)
    114   %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
    115   ret i32 %call1
    116 }
    117 
    118 declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
    119 declare i1 @llvm.experimental.gc.result.i1(i32)
    120 
    121 declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i64, i32, i32 ()*, i32, i32, ...)
    122 declare i32 @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i64, i32, i32 (i32, i8*)*, i32, i32, ...)
    123 declare i32 @llvm.experimental.gc.result.i32(i32)
    124 
    125 declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i64, i32, i32* ()*, i32, i32, ...)
    126 declare i32* @llvm.experimental.gc.result.p0i32(i32)
    127 
    128 declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(i64, i32, float ()*, i32, i32, ...)
    129 declare float @llvm.experimental.gc.result.f32(i32)
    130 
    131 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64, i32, void (i32, ...)*, i32, i32, ...)
    132 
    133 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)