[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / X86 / statepoint-vreg.ll
blob7581c5fb98c17e45e2b77ecd35f5e62018f8e083
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -max-registers-for-gc-values=4 -fixup-allow-gcptr-in-csr=true < %s | FileCheck %s
4 target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-pc-linux-gnu"
7 declare i1 @return_i1()
8 declare void @func()
9 declare void @consume(i32 addrspace(1)*)
10 declare i32 @consume1(i32) gc "statepoint-example"
11 declare void @consume2(i32 addrspace(1)*, i32 addrspace(1)*)
12 declare void @consume3(float) gc "statepoint-example"
13 declare float @consume4(i64) gc "statepoint-example"
14 declare void @consume5(i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*)
16 declare void @use1(i32 addrspace(1)*, i8 addrspace(1)*)
18 ; test most simple relocate
19 define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
20 ; CHECK-LABEL: test_relocate:
21 ; CHECK:       # %bb.0: # %entry
22 ; CHECK-NEXT:    pushq %rbp
23 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
24 ; CHECK-NEXT:    pushq %rbx
25 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
26 ; CHECK-NEXT:    pushq %rax
27 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
28 ; CHECK-NEXT:    .cfi_offset %rbx, -24
29 ; CHECK-NEXT:    .cfi_offset %rbp, -16
30 ; CHECK-NEXT:    movq %rdi, %rbx
31 ; CHECK-NEXT:    callq return_i1@PLT
32 ; CHECK-NEXT:  .Ltmp0:
33 ; CHECK-NEXT:    movl %eax, %ebp
34 ; CHECK-NEXT:    movq %rbx, %rdi
35 ; CHECK-NEXT:    callq consume@PLT
36 ; CHECK-NEXT:    movl %ebp, %eax
37 ; CHECK-NEXT:    addq $8, %rsp
38 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
39 ; CHECK-NEXT:    popq %rbx
40 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
41 ; CHECK-NEXT:    popq %rbp
42 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
43 ; CHECK-NEXT:    retq
44 entry:
45   %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) ["gc-live" (i32 addrspace(1)* %a)]
46   %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
47   %res1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
48   call void @consume(i32 addrspace(1)* %rel1)
49   ret i1 %res1
52 ; test pointer variables intermixed with pointer constants
53 define void @test_mixed(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) gc "statepoint-example" {
54 ; CHECK-LABEL: test_mixed:
55 ; CHECK:       # %bb.0: # %entry
56 ; CHECK-NEXT:    pushq %r15
57 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
58 ; CHECK-NEXT:    pushq %r14
59 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
60 ; CHECK-NEXT:    pushq %rbx
61 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
62 ; CHECK-NEXT:    .cfi_offset %rbx, -32
63 ; CHECK-NEXT:    .cfi_offset %r14, -24
64 ; CHECK-NEXT:    .cfi_offset %r15, -16
65 ; CHECK-NEXT:    movq %rdx, %r14
66 ; CHECK-NEXT:    movq %rsi, %r15
67 ; CHECK-NEXT:    movq %rdi, %rbx
68 ; CHECK-NEXT:    callq func@PLT
69 ; CHECK-NEXT:  .Ltmp1:
70 ; CHECK-NEXT:    movq %rbx, %rdi
71 ; CHECK-NEXT:    xorl %esi, %esi
72 ; CHECK-NEXT:    movq %r15, %rdx
73 ; CHECK-NEXT:    xorl %ecx, %ecx
74 ; CHECK-NEXT:    movq %r14, %r8
75 ; CHECK-NEXT:    callq consume5@PLT
76 ; CHECK-NEXT:    popq %rbx
77 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
78 ; CHECK-NEXT:    popq %r14
79 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
80 ; CHECK-NEXT:    popq %r15
81 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
82 ; CHECK-NEXT:    retq
83 entry:
84   %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a, i32 addrspace(1)* null, i32 addrspace(1)* %b, i32 addrspace(1)* null, i32 addrspace(1)* %c)]
85   %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
86   %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 1, i32 1)
87   %rel3 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 2, i32 2)
88   %rel4 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 3, i32 3)
89   %rel5 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 4, i32 4)
90   call void @consume5(i32 addrspace(1)* %rel1, i32 addrspace(1)* %rel2, i32 addrspace(1)* %rel3, i32 addrspace(1)* %rel4, i32 addrspace(1)* %rel5)
91   ret void
94 ; same as above, but for alloca
95 define i32 addrspace(1)* @test_alloca(i32 addrspace(1)* %ptr) gc "statepoint-example" {
96 ; CHECK-LABEL: test_alloca:
97 ; CHECK:       # %bb.0: # %entry
98 ; CHECK-NEXT:    pushq %r14
99 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
100 ; CHECK-NEXT:    pushq %rbx
101 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
102 ; CHECK-NEXT:    pushq %rax
103 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
104 ; CHECK-NEXT:    .cfi_offset %rbx, -24
105 ; CHECK-NEXT:    .cfi_offset %r14, -16
106 ; CHECK-NEXT:    movq %rdi, %rbx
107 ; CHECK-NEXT:    movq %rdi, (%rsp)
108 ; CHECK-NEXT:    callq return_i1@PLT
109 ; CHECK-NEXT:  .Ltmp2:
110 ; CHECK-NEXT:    movq (%rsp), %r14
111 ; CHECK-NEXT:    movq %rbx, %rdi
112 ; CHECK-NEXT:    callq consume@PLT
113 ; CHECK-NEXT:    movq %r14, %rax
114 ; CHECK-NEXT:    addq $8, %rsp
115 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
116 ; CHECK-NEXT:    popq %rbx
117 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
118 ; CHECK-NEXT:    popq %r14
119 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
120 ; CHECK-NEXT:    retq
121 entry:
122   %alloca = alloca i32 addrspace(1)*, align 8
123   store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
124   %safepoint_token = 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) ["gc-live" (i32 addrspace(1)** %alloca, i32 addrspace(1)* %ptr)]
125   %rel1 = load i32 addrspace(1)*, i32 addrspace(1)** %alloca
126   %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 1, i32 1)
127   call void @consume(i32 addrspace(1)* %rel2)
128   ret i32 addrspace(1)* %rel1
131 ; test base != derived
132 define void @test_base_derived(i32 addrspace(1)* %base, i32 addrspace(1)* %derived) gc "statepoint-example" {
133 ; CHECK-LABEL: test_base_derived:
134 ; CHECK:       # %bb.0:
135 ; CHECK-NEXT:    pushq %r14
136 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
137 ; CHECK-NEXT:    pushq %rbx
138 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
139 ; CHECK-NEXT:    pushq %rax
140 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
141 ; CHECK-NEXT:    .cfi_offset %rbx, -24
142 ; CHECK-NEXT:    .cfi_offset %r14, -16
143 ; CHECK-NEXT:    movq %rsi, %rbx
144 ; CHECK-NEXT:    movq %rdi, %r14
145 ; CHECK-NEXT:    callq func@PLT
146 ; CHECK-NEXT:  .Ltmp3:
147 ; CHECK-NEXT:    movq %rbx, %rdi
148 ; CHECK-NEXT:    callq consume@PLT
149 ; CHECK-NEXT:    addq $8, %rsp
150 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
151 ; CHECK-NEXT:    popq %rbx
152 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
153 ; CHECK-NEXT:    popq %r14
154 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
155 ; CHECK-NEXT:    retq
156   %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %base, i32 addrspace(1)* %derived)]
157   %reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 1)
158   call void @consume(i32 addrspace(1)* %reloc)
159   ret void
162 ; deopt GC pointer not present in GC args goes on reg.
163 define void @test_deopt_gcpointer(i32 addrspace(1)* %a, i32 addrspace(1)* %b) gc "statepoint-example" {
164 ; CHECK-LABEL: test_deopt_gcpointer:
165 ; CHECK:       # %bb.0:
166 ; CHECK-NEXT:    pushq %r14
167 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
168 ; CHECK-NEXT:    pushq %rbx
169 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
170 ; CHECK-NEXT:    pushq %rax
171 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
172 ; CHECK-NEXT:    .cfi_offset %rbx, -24
173 ; CHECK-NEXT:    .cfi_offset %r14, -16
174 ; CHECK-NEXT:    movq %rsi, %rbx
175 ; CHECK-NEXT:    movq %rdi, %r14
176 ; CHECK-NEXT:    callq func@PLT
177 ; CHECK-NEXT:  .Ltmp4:
178 ; CHECK-NEXT:    movq %rbx, %rdi
179 ; CHECK-NEXT:    callq consume@PLT
180 ; CHECK-NEXT:    addq $8, %rsp
181 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
182 ; CHECK-NEXT:    popq %rbx
183 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
184 ; CHECK-NEXT:    popq %r14
185 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
186 ; CHECK-NEXT:    retq
187   %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %a), "gc-live" (i32 addrspace(1)* %b)]
188   %rel = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
189   call void @consume(i32 addrspace(1)* %rel)
190   ret void
193 ;; Two gc.relocates of the same input, should require only a single spill/fill
194 define void @test_gcrelocate_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" {
195 ; CHECK-LABEL: test_gcrelocate_uniqueing:
196 ; CHECK:       # %bb.0:
197 ; CHECK-NEXT:    pushq %rbx
198 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
199 ; CHECK-NEXT:    .cfi_offset %rbx, -16
200 ; CHECK-NEXT:    movq %rdi, %rbx
201 ; CHECK-NEXT:    callq func@PLT
202 ; CHECK-NEXT:  .Ltmp5:
203 ; CHECK-NEXT:    movq %rbx, %rdi
204 ; CHECK-NEXT:    movq %rbx, %rsi
205 ; CHECK-NEXT:    callq consume2@PLT
206 ; CHECK-NEXT:    popq %rbx
207 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
208 ; CHECK-NEXT:    retq
209   %tok = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %ptr, i32 undef), "gc-live" (i32 addrspace(1)* %ptr, i32 addrspace(1)* %ptr)]
210   %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
211   %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 1, i32 1)
212   call void @consume2(i32 addrspace(1)* %a, i32 addrspace(1)* %b)
213   ret void
216 ; Two gc.relocates of a bitcasted pointer should only require a single spill/fill
217 define void @test_gcptr_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" {
218 ; CHECK-LABEL: test_gcptr_uniqueing:
219 ; CHECK:       # %bb.0:
220 ; CHECK-NEXT:    pushq %rbx
221 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
222 ; CHECK-NEXT:    .cfi_offset %rbx, -16
223 ; CHECK-NEXT:    movq %rdi, %rbx
224 ; CHECK-NEXT:    callq func@PLT
225 ; CHECK-NEXT:  .Ltmp6:
226 ; CHECK-NEXT:    movq %rbx, %rdi
227 ; CHECK-NEXT:    movq %rbx, %rsi
228 ; CHECK-NEXT:    callq use1@PLT
229 ; CHECK-NEXT:    popq %rbx
230 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
231 ; CHECK-NEXT:    retq
232   %ptr2 = bitcast i32 addrspace(1)* %ptr to i8 addrspace(1)*
233   %tok = tail call token (i64, i32, void ()*, i32, i32, ...)
234       @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %ptr, i32 undef), "gc-live" (i32 addrspace(1)* %ptr, i8 addrspace(1)* %ptr2)]
235   %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
236   %b = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %tok, i32 1, i32 1)
237   call void @use1(i32 addrspace(1)* %a, i8 addrspace(1)* %b)
238   ret void
242 ; Cross-basicblock relocates are handled with spilling for now.
243 define i1 @test_cross_bb(i32 addrspace(1)* %a, i1 %external_cond) gc "statepoint-example" {
244 ; CHECK-LABEL: test_cross_bb:
245 ; CHECK:       # %bb.0: # %entry
246 ; CHECK-NEXT:    pushq %rbp
247 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
248 ; CHECK-NEXT:    pushq %r14
249 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
250 ; CHECK-NEXT:    pushq %rbx
251 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
252 ; CHECK-NEXT:    .cfi_offset %rbx, -32
253 ; CHECK-NEXT:    .cfi_offset %r14, -24
254 ; CHECK-NEXT:    .cfi_offset %rbp, -16
255 ; CHECK-NEXT:    movl %esi, %ebp
256 ; CHECK-NEXT:    movq %rdi, %rbx
257 ; CHECK-NEXT:    callq return_i1@PLT
258 ; CHECK-NEXT:  .Ltmp7:
259 ; CHECK-NEXT:    testb $1, %bpl
260 ; CHECK-NEXT:    je .LBB7_2
261 ; CHECK-NEXT:  # %bb.1: # %left
262 ; CHECK-NEXT:    movl %eax, %r14d
263 ; CHECK-NEXT:    movq %rbx, %rdi
264 ; CHECK-NEXT:    callq consume@PLT
265 ; CHECK-NEXT:    movl %r14d, %eax
266 ; CHECK-NEXT:    jmp .LBB7_3
267 ; CHECK-NEXT:  .LBB7_2: # %right
268 ; CHECK-NEXT:    movb $1, %al
269 ; CHECK-NEXT:  .LBB7_3: # %right
270 ; CHECK-NEXT:    popq %rbx
271 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
272 ; CHECK-NEXT:    popq %r14
273 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
274 ; CHECK-NEXT:    popq %rbp
275 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
276 ; CHECK-NEXT:    retq
277 entry:
278   %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) ["gc-live" (i32 addrspace(1)* %a)]
279   br i1 %external_cond, label %left, label %right
281 left:
282   %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
283   %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
284   call void @consume(i32 addrspace(1)* %call1)
285   ret i1 %call2
287 right:
288   ret i1 true
291 ; No need to check post-regalloc output as it is the same
292 define i1 @duplicate_reloc() gc "statepoint-example" {
293 ; CHECK-LABEL: duplicate_reloc:
294 ; CHECK:       # %bb.0: # %entry
295 ; CHECK-NEXT:    pushq %rax
296 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
297 ; CHECK-NEXT:    callq func@PLT
298 ; CHECK-NEXT:  .Ltmp8:
299 ; CHECK-NEXT:    callq func@PLT
300 ; CHECK-NEXT:  .Ltmp9:
301 ; CHECK-NEXT:    movb $1, %al
302 ; CHECK-NEXT:    popq %rcx
303 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
304 ; CHECK-NEXT:    retq
305 entry:
306   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* null, i32 addrspace(1)* null)]
307   %base = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
308   %derived = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 1)
309   %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %base, i32 addrspace(1)* %derived)]
310   %base_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2,  i32 0, i32 0)
311   %derived_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2,  i32 0, i32 1)
312   %cmp1 = icmp eq i32 addrspace(1)* %base_reloc, null
313   %cmp2 = icmp eq i32 addrspace(1)* %derived_reloc, null
314   %cmp = and i1 %cmp1, %cmp2
315   ret i1 %cmp
318 ; Vectors cannot go in VRegs
319 ; No need to check post-regalloc output as it is lowered using old scheme
320 define <2 x i8 addrspace(1)*> @test_vector(<2 x i8 addrspace(1)*> %obj) gc "statepoint-example" {
321 ; CHECK-LABEL: test_vector:
322 ; CHECK:       # %bb.0: # %entry
323 ; CHECK-NEXT:    subq $24, %rsp
324 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
325 ; CHECK-NEXT:    movaps %xmm0, (%rsp)
326 ; CHECK-NEXT:    callq func@PLT
327 ; CHECK-NEXT:  .Ltmp10:
328 ; CHECK-NEXT:    movaps (%rsp), %xmm0
329 ; CHECK-NEXT:    addq $24, %rsp
330 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
331 ; CHECK-NEXT:    retq
332 entry:
333   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x i8 addrspace(1)*> %obj)]
334   %obj.relocated = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj)
335   ret <2 x i8 addrspace(1)*> %obj.relocated
339 ; test limit on amount of vregs
340 define void @test_limit(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c, i32 addrspace(1)* %d, i32 addrspace(1)*  %e) gc "statepoint-example" {
341 ; CHECK-LABEL: test_limit:
342 ; CHECK:       # %bb.0: # %entry
343 ; CHECK-NEXT:    pushq %r15
344 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
345 ; CHECK-NEXT:    pushq %r14
346 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
347 ; CHECK-NEXT:    pushq %r12
348 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
349 ; CHECK-NEXT:    pushq %rbx
350 ; CHECK-NEXT:    .cfi_def_cfa_offset 40
351 ; CHECK-NEXT:    pushq %rax
352 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
353 ; CHECK-NEXT:    .cfi_offset %rbx, -40
354 ; CHECK-NEXT:    .cfi_offset %r12, -32
355 ; CHECK-NEXT:    .cfi_offset %r14, -24
356 ; CHECK-NEXT:    .cfi_offset %r15, -16
357 ; CHECK-NEXT:    movq %r8, %r14
358 ; CHECK-NEXT:    movq %rcx, %r15
359 ; CHECK-NEXT:    movq %rdx, %r12
360 ; CHECK-NEXT:    movq %rsi, %rbx
361 ; CHECK-NEXT:    movq %rdi, (%rsp)
362 ; CHECK-NEXT:    callq func@PLT
363 ; CHECK-NEXT:  .Ltmp11:
364 ; CHECK-NEXT:    movq (%rsp), %rdi
365 ; CHECK-NEXT:    movq %rbx, %rsi
366 ; CHECK-NEXT:    movq %r12, %rdx
367 ; CHECK-NEXT:    movq %r15, %rcx
368 ; CHECK-NEXT:    movq %r14, %r8
369 ; CHECK-NEXT:    callq consume5@PLT
370 ; CHECK-NEXT:    addq $8, %rsp
371 ; CHECK-NEXT:    .cfi_def_cfa_offset 40
372 ; CHECK-NEXT:    popq %rbx
373 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
374 ; CHECK-NEXT:    popq %r12
375 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
376 ; CHECK-NEXT:    popq %r14
377 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
378 ; CHECK-NEXT:    popq %r15
379 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
380 ; CHECK-NEXT:    retq
381 entry:
382   %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c, i32 addrspace(1)* %d, i32 addrspace(1)* %e)]
383   %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
384   %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 1, i32 1)
385   %rel3 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 2, i32 2)
386   %rel4 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 3, i32 3)
387   %rel5 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 4, i32 4)
388   call void @consume5(i32 addrspace(1)* %rel1, i32 addrspace(1)* %rel2, i32 addrspace(1)* %rel3, i32 addrspace(1)* %rel4, i32 addrspace(1)* %rel5)
389   ret void
392 ; test ISEL for constant base pointer - must properly tie operands
393 define void @test_const_base(i32 addrspace(1)* %a) gc "statepoint-example" {
394 ; CHECK-LABEL: test_const_base:
395 ; CHECK:       # %bb.0: # %entry
396 ; CHECK-NEXT:    pushq %rbx
397 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
398 ; CHECK-NEXT:    .cfi_offset %rbx, -16
399 ; CHECK-NEXT:    movq %rdi, %rbx
400 ; CHECK-NEXT:    callq func@PLT
401 ; CHECK-NEXT:  .Ltmp12:
402 ; CHECK-NEXT:    movq %rbx, %rdi
403 ; CHECK-NEXT:    callq consume@PLT
404 ; CHECK-NEXT:    popq %rbx
405 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
406 ; CHECK-NEXT:    retq
407 entry:
408   %token1 = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 0, i32 1, i32 7, i32 addrspace(1)* null, i32 9), "gc-live" (i32 addrspace(1)* null, i32 addrspace(1)* %a)]
409   %rel = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token1,  i32 0, i32 1)
410   call void @consume(i32 addrspace(1)* %rel)
411   ret void
414 ; test multiple statepoints/relocates within single block.
415 ; relocates must be properly scheduled w.r.t. statepoints
416 define void @test_sched(float %0, i32 %1, i8 addrspace(1)* %2) gc "statepoint-example" {
417 ; CHECK-LABEL: test_sched:
418 ; CHECK:       # %bb.0: # %entry
419 ; CHECK-NEXT:    pushq %rbp
420 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
421 ; CHECK-NEXT:    pushq %rbx
422 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
423 ; CHECK-NEXT:    subq $24, %rsp
424 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
425 ; CHECK-NEXT:    .cfi_offset %rbx, -24
426 ; CHECK-NEXT:    .cfi_offset %rbp, -16
427 ; CHECK-NEXT:    movq %rsi, %rbx
428 ; CHECK-NEXT:    movl %edi, %ebp
429 ; CHECK-NEXT:    movss %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
430 ; CHECK-NEXT:    callq consume3@PLT
431 ; CHECK-NEXT:  .Ltmp13:
432 ; CHECK-NEXT:    xorps %xmm0, %xmm0
433 ; CHECK-NEXT:    cvtsi2sd %ebp, %xmm0
434 ; CHECK-NEXT:    movsd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
435 ; CHECK-NEXT:    nopl 8(%rax,%rax)
436 ; CHECK-NEXT:  .Ltmp14:
437 ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload
438 ; CHECK-NEXT:    # xmm0 = mem[0],zero
439 ; CHECK-NEXT:    movsd %xmm0, {{[0-9]+}}(%rsp)
440 ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
441 ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
442 ; CHECK-NEXT:    movss %xmm0, (%rsp)
443 ; CHECK-NEXT:    nopl 8(%rax,%rax)
444 ; CHECK-NEXT:  .Ltmp15:
445 ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload
446 ; CHECK-NEXT:    # xmm0 = mem[0],zero
447 ; CHECK-NEXT:    movsd %xmm0, {{[0-9]+}}(%rsp)
448 ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
449 ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
450 ; CHECK-NEXT:    movss %xmm0, (%rsp)
451 ; CHECK-NEXT:    nopl 8(%rax,%rax)
452 ; CHECK-NEXT:  .Ltmp16:
453 ; CHECK-NEXT:    xorl %eax, %eax
454 ; CHECK-NEXT:    xorpd %xmm0, %xmm0
455 ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload
456 ; CHECK-NEXT:    # xmm1 = mem[0],zero
457 ; CHECK-NEXT:    ucomisd %xmm0, %xmm1
458 ; CHECK-NEXT:    movabsq $9223372036854775807, %rdi # imm = 0x7FFFFFFFFFFFFFFF
459 ; CHECK-NEXT:    cmovbeq %rax, %rdi
460 ; CHECK-NEXT:    movsd %xmm1, {{[0-9]+}}(%rsp)
461 ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
462 ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
463 ; CHECK-NEXT:    movss %xmm0, (%rsp)
464 ; CHECK-NEXT:    nopl 8(%rax,%rax)
465 ; CHECK-NEXT:  .Ltmp17:
466 ; CHECK-NEXT:    addq $24, %rsp
467 ; CHECK-NEXT:    .cfi_def_cfa_offset 24
468 ; CHECK-NEXT:    popq %rbx
469 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
470 ; CHECK-NEXT:    popq %rbp
471 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
472 ; CHECK-NEXT:    retq
473 entry:
474   %token0 = call token (i64, i32, void (float)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 2, i32 0, void (float)* nonnull @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %2) ]
475   %reloc1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token0, i32 0, i32 0) ; (%2, %2)
476   %tmp1 = sitofp i32 %1 to double
477   %to_max.i29 = fcmp ogt double %tmp1, 0.000000e+00
478   %token1 = call token (i64, i32, i32 (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 2, i32 5, i32 (i32)* nonnull @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %reloc1) ]
479   %reloc2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1)
480   %reloc3 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1)
481   %token2 = call token (i64, i32, i32 (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 2, i32 5, i32 (i32)* nonnull @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(i8 addrspace(1)* %reloc2, i8 addrspace(1)* %reloc3) ]
482   %reloc4 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token2, i32 0, i32 0) ; (%reloc3, %reloc2)
483   %reloc5 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token2, i32 1, i32 1) ; (%reloc3, %reloc3)
484   %token3 = call token (i64, i32, void (float)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 2, i32 5, void (float)* nonnull @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(i8 addrspace(1)* %reloc4, i8 addrspace(1)* %reloc5) ]
485   %reloc6 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token3, i32 1, i32 0) ; (%reloc5, %reloc4)
486   %tmp5 = select i1 %to_max.i29, i64 9223372036854775807, i64 0
487   %token4 = call token (i64, i32, float (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32i64f(i64 2, i32 5, float (i64)* nonnull @consume4, i32 1, i32 0, i64 %tmp5, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"() ]
488 ret void
491 declare token @llvm.experimental.gc.statepoint.p0f_f32i64f(i64 immarg, i32 immarg, float (i64)*, i32 immarg, i32 immarg, ...)
492 declare token @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 immarg, i32 immarg, i32 (i32)*, i32 immarg, i32 immarg, ...)
493 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 immarg, i32 immarg, void (float)*, i32 immarg, i32 immarg, ...)
494 declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
495 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
496 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
497 declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32)
498 declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
499 declare <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token, i32, i32)
500 declare i1 @llvm.experimental.gc.result.i1(token)