• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 there are no deopt or gc arguments.
4
5target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
6target triple = "x86_64-pc-linux-gnu"
7
8%struct = type { i64, i64 }
9
10declare zeroext i1 @return_i1()
11declare zeroext i32 @return_i32()
12declare i32* @return_i32ptr()
13declare float @return_float()
14declare %struct @return_struct()
15declare void @varargf(i32, ...)
16
17define i1 @test_i1_return() gc "statepoint-example" {
18; CHECK-LABEL: test_i1_return
19; This is just checking that a i1 gets lowered normally when there's no extra
20; state arguments to the statepoint
21; CHECK: pushq %rax
22; CHECK: callq return_i1
23; CHECK: popq %rcx
24; CHECK: retq
25entry:
26  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0)
27  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
28  ret i1 %call1
29}
30
31define i32 @test_i32_return() gc "statepoint-example" {
32; CHECK-LABEL: test_i32_return
33; CHECK: pushq %rax
34; CHECK: callq return_i32
35; CHECK: popq %rcx
36; CHECK: retq
37entry:
38  %safepoint_token = tail call token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 0, i32 0, i32 ()* @return_i32, i32 0, i32 0, i32 0, i32 0)
39  %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(token %safepoint_token)
40  ret i32 %call1
41}
42
43define i32* @test_i32ptr_return() gc "statepoint-example" {
44; CHECK-LABEL: test_i32ptr_return
45; CHECK: pushq %rax
46; CHECK: callq return_i32ptr
47; CHECK: popq %rcx
48; CHECK: retq
49entry:
50  %safepoint_token = tail call token (i64, i32, i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i64 0, i32 0, i32* ()* @return_i32ptr, i32 0, i32 0, i32 0, i32 0)
51  %call1 = call i32* @llvm.experimental.gc.result.p0i32(token %safepoint_token)
52  ret i32* %call1
53}
54
55define float @test_float_return() gc "statepoint-example" {
56; CHECK-LABEL: test_float_return
57; CHECK: pushq %rax
58; CHECK: callq return_float
59; CHECK: popq %rax
60; CHECK: retq
61entry:
62  %safepoint_token = tail call token (i64, i32, float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(i64 0, i32 0, float ()* @return_float, i32 0, i32 0, i32 0, i32 0)
63  %call1 = call float @llvm.experimental.gc.result.f32(token %safepoint_token)
64  ret float %call1
65}
66
67define %struct @test_struct_return() gc "statepoint-example" {
68; CHECK-LABEL: test_struct_return
69; CHECK: pushq %rax
70; CHECK: callq return_struct
71; CHECK: popq %rcx
72; CHECK: retq
73entry:
74  %safepoint_token = tail call token (i64, i32, %struct ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_structf(i64 0, i32 0, %struct ()* @return_struct, i32 0, i32 0, i32 0, i32 0)
75  %call1 = call %struct @llvm.experimental.gc.result.struct(token %safepoint_token)
76  ret %struct %call1
77}
78
79define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
80; CHECK-LABEL: test_relocate
81; Check that an ununsed relocate has no code-generation impact
82; CHECK: pushq %rax
83; CHECK: callq return_i1
84; CHECK-NEXT: .Ltmp11:
85; CHECK-NEXT: popq %rcx
86; CHECK-NEXT: retq
87entry:
88  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
89  %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 7, i32 7)
90  %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
91  ret i1 %call2
92}
93
94define void @test_void_vararg() gc "statepoint-example" {
95; CHECK-LABEL: test_void_vararg
96; Check a statepoint wrapping a *void* returning vararg function works
97; CHECK: callq varargf
98entry:
99  %safepoint_token = tail call token (i64, i32, void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64 0, i32 0, void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0)
100  ;; if we try to use the result from a statepoint wrapping a
101  ;; non-void-returning varargf, we will experience a crash.
102  ret void
103}
104
105define i1 @test_i1_return_patchable() gc "statepoint-example" {
106; CHECK-LABEL: test_i1_return_patchable
107; A patchable variant of test_i1_return
108; CHECK: pushq %rax
109; CHECK: nopl
110; CHECK: popq %rcx
111; CHECK: retq
112entry:
113  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 3, i1 ()*null, i32 0, i32 0, i32 0, i32 0)
114  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
115  ret i1 %call1
116}
117
118declare void @consume(i32 addrspace(1)* %obj)
119
120define i1 @test_cross_bb(i32 addrspace(1)* %a, i1 %external_cond) gc "statepoint-example" {
121; CHECK-LABEL: test_cross_bb
122; CHECK: movq
123; CHECK: callq return_i1
124; CHECK: %left
125; CHECK: movq
126; CHECK-NEXT: callq consume
127; CHECK: retq
128entry:
129  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
130  br i1 %external_cond, label %left, label %right
131
132left:
133  %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 7, i32 7)
134  %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
135  call void @consume(i32 addrspace(1)* %call1)
136  ret i1 %call2
137
138right:
139  ret i1 true
140}
141
142
143declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
144declare i1 @llvm.experimental.gc.result.i1(token)
145
146declare token @llvm.experimental.gc.statepoint.p0f_i32f(i64, i32, i32 ()*, i32, i32, ...)
147declare i32 @llvm.experimental.gc.result.i32(token)
148
149declare token @llvm.experimental.gc.statepoint.p0f_p0i32f(i64, i32, i32* ()*, i32, i32, ...)
150declare i32* @llvm.experimental.gc.result.p0i32(token)
151
152declare token @llvm.experimental.gc.statepoint.p0f_f32f(i64, i32, float ()*, i32, i32, ...)
153declare float @llvm.experimental.gc.result.f32(token)
154
155declare token @llvm.experimental.gc.statepoint.p0f_structf(i64, i32, %struct ()*, i32, i32, ...)
156declare %struct @llvm.experimental.gc.result.struct(token)
157
158declare token @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64, i32, void (i32, ...)*, i32, i32, ...)
159
160declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
161