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
3
4target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
5target triple = "x86_64-pc-linux-gnu"
6
7declare i1 @return_i1()
8declare void @func()
9declare void @consume(i32 addrspace(1)*)
10declare i32 @consume1(i32) gc "statepoint-example"
11declare void @consume2(i32 addrspace(1)*, i32 addrspace(1)*)
12declare void @consume3(float) gc "statepoint-example"
13declare float @consume4(i64) gc "statepoint-example"
14declare void @consume5(i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*)
15
16declare void @use1(i32 addrspace(1)*, i8 addrspace(1)*)
17
18; test most simple relocate
19define 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
44entry:
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
50}
51
52; test pointer variables intermixed with pointer constants
53define 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
83entry:
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
92}
93
94; same as above, but for alloca
95define 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
121entry:
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
129}
130
131; test base != derived
132define 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
160}
161
162; deopt GC pointer not present in GC args goes on reg.
163define 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
191}
192
193;; Two gc.relocates of the same input, should require only a single spill/fill
194define 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
214}
215
216; Two gc.relocates of a bitcasted pointer should only require a single spill/fill
217define 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
239}
240
241;
242; Cross-basicblock relocates are handled with spilling for now.
243define 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
277entry:
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
280
281left:
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
286
287right:
288  ret i1 true
289}
290
291; No need to check post-regalloc output as it is the same
292define 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
305entry:
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
316}
317
318; Vectors cannot go in VRegs
319; No need to check post-regalloc output as it is lowered using old scheme
320define <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
332entry:
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
336}
337
338
339; test limit on amount of vregs
340define 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
381entry:
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
390}
391
392; test ISEL for constant base pointer - must properly tie operands
393define 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
407entry:
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
412}
413
414; test multiple statepoints/relocates within single block.
415; relocates must be properly scheduled w.r.t. statepoints
416define 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
473entry:
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"() ]
488ret void
489}
490
491declare token @llvm.experimental.gc.statepoint.p0f_f32i64f(i64 immarg, i32 immarg, float (i64)*, i32 immarg, i32 immarg, ...)
492declare token @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 immarg, i32 immarg, i32 (i32)*, i32 immarg, i32 immarg, ...)
493declare token @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 immarg, i32 immarg, void (float)*, i32 immarg, i32 immarg, ...)
494declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
495declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
496declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
497declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32)
498declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
499declare <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token, i32, i32)
500declare i1 @llvm.experimental.gc.result.i1(token)
501