xref: /llvm-project/llvm/test/CodeGen/X86/statepoint-stackmap-format.ll (revision 2f448bf509432c1a19ec46ab8cbc7353c03c6280)
1; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-linux-gnu" | FileCheck %s
2; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-unknown-elf" | FileCheck %s
3
4; This test is a basic correctness check to ensure statepoints are generating
5; StackMap sections correctly.  This is not intended to be a rigorous test of
6; the StackMap format (see the stackmap tests for that).
7
8target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
9
10declare zeroext i1 @return_i1()
11
12define i1 @test(ptr addrspace(1) %ptr_base, i32 %arg)
13  gc "statepoint-example" {
14; CHECK-LABEL: test:
15; Do we see two spills for the local values and the store to the
16; alloca?
17; CHECK: subq	$40, %rsp
18; CHECK: movq	$0,   24(%rsp)
19; CHECK: movq	%rdi, 16(%rsp)
20; CHECK: movq	%rax, 8(%rsp)
21; CHECK: callq return_i1
22; CHECK: addq	$40, %rsp
23; CHECK: retq
24entry:
25  %metadata1 = alloca ptr addrspace(1), i32 2, align 8
26  store ptr addrspace(1) null, ptr %metadata1
27  %ptr_derived = getelementptr i32, ptr addrspace(1) %ptr_base, i32 %arg
28  %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %ptr_base, ptr addrspace(1) %ptr_derived, ptr addrspace(1) null), "deopt" (ptr addrspace(1) %ptr_base, ptr addrspace(1) null)]
29  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
30  %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
31  %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
32  %c = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)
33;
34  ret i1 %call1
35}
36
37; This is similar to the previous test except that we have derived pointer as
38; argument to the function. Despite that this can not happen after the
39; RewriteSafepointForGC pass, lowering should be able to handle it anyway.
40define i1 @test_derived_arg(ptr addrspace(1) %ptr_base,
41                            ptr addrspace(1) %ptr_derived)
42  gc "statepoint-example" {
43; CHECK-LABEL: test_derived_arg
44; Do we see two spills for the local values and the store to the
45; alloca?
46; CHECK: subq	$40, %rsp
47; CHECK: movq	$0,   24(%rsp)
48; CHECK: movq	%rdi, 16(%rsp)
49; CHECK: movq	%rsi, 8(%rsp)
50; CHECK: callq return_i1
51; CHECK: addq	$40, %rsp
52; CHECK: retq
53entry:
54  %metadata1 = alloca ptr addrspace(1), i32 2, align 8
55  store ptr addrspace(1) null, ptr %metadata1
56  %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %ptr_base, ptr addrspace(1) %ptr_derived, ptr addrspace(1) null), "deopt" (ptr addrspace(1) %ptr_base, ptr addrspace(1) null)]
57  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
58  %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
59  %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
60  %c = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)
61;
62  ret i1 %call1
63}
64
65; Simple test case to check that we emit the ID field correctly
66define i1 @test_id() gc "statepoint-example" {
67; CHECK-LABEL: test_id
68entry:
69  %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 237, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0)
70  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
71  ret i1 %call1
72}
73
74; This test checks that when SP is changed in the function
75; (e.g. passing arguments on stack), the stack map entry
76; takes this adjustment into account.
77declare void @many_arg(i64, i64, i64, i64, i64, i64, i64, i64)
78
79define i32 @test_spadj(ptr addrspace(1) %p) gc "statepoint-example" {
80  ; CHECK-LABEL: test_spadj
81  ; CHECK: movq %rdi, (%rsp)
82  ; CHECK: xorl %edi, %edi
83  ; CHECK: xorl %esi, %esi
84  ; CHECK: xorl %edx, %edx
85  ; CHECK: xorl %ecx, %ecx
86  ; CHECK: xorl %r8d, %r8d
87  ; CHECK: xorl %r9d, %r9d
88  ; CHECK: pushq $0
89  ; CHECK: pushq $0
90  ; CHECK: callq many_arg
91  ; CHECK: addq $16, %rsp
92  ; CHECK: movq (%rsp)
93  %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i64, i64, i64, i64, i64, i64, i64, i64)) @many_arg, i32 8, i32 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %p)]
94  %p.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint_token, i32 0, i32 0) ; (%p, %p)
95  %ld = load i32, ptr addrspace(1) %p.relocated
96  ret i32 %ld
97}
98
99; Test that function arguments at fixed stack offset
100; can be directly encoded in the stack map, without
101; spilling.
102%struct = type { i64, i64, i64 }
103
104declare void @use(ptr)
105
106define void @test_fixed_arg(ptr byval(%struct) %x) gc "statepoint-example" {
107; CHECK-LABEL: test_fixed_arg
108; CHECK: pushq %rax
109; CHECK: leaq 16(%rsp), %rdi
110; Should not spill fixed stack address.
111; CHECK-NOT: movq %rdi, (%rsp)
112; CHECK: callq use
113; CHECK: popq %rax
114; CHECK: retq
115entry:
116  br label %bb
117
118bb:                                               ; preds = %entry
119  %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr)) @use, i32 1, i32 0, ptr %x, i32 0, i32 0) ["deopt" (ptr %x)]
120  ret void
121}
122
123declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
124declare i1 @llvm.experimental.gc.result.i1(token)
125declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) #3
126
127; CHECK-LABEL: .section .llvm_stackmaps
128; CHECK-NEXT:  __LLVM_StackMaps:
129; Header
130; CHECK-NEXT:   .byte 3
131; CHECK-NEXT:   .byte 0
132; CHECK-NEXT:   .short 0
133; Num Functions
134; CHECK-NEXT:   .long 5
135; Num LargeConstants
136; CHECK-NEXT:   .long 0
137; Num Callsites
138; CHECK-NEXT:   .long 5
139
140; Functions and stack size
141; CHECK-NEXT:   .quad test
142; CHECK-NEXT:   .quad 40
143; CHECK-NEXT:   .quad 1
144; CHECK-NEXT:   .quad test_derived_arg
145; CHECK-NEXT:   .quad 40
146; CHECK-NEXT:   .quad 1
147; CHECK-NEXT:   .quad test_id
148; CHECK-NEXT:   .quad 8
149; CHECK-NEXT:   .quad 1
150; CHECK-NEXT:   .quad test_spadj
151; CHECK-NEXT:   .quad 8
152; CHECK-NEXT:   .quad 1
153; CHECK-NEXT:   .quad test_fixed_arg
154; CHECK-NEXT:   .quad 8
155; CHECK-NEXT:   .quad 1
156
157;
158; test
159;
160
161; Statepoint ID
162; CHECK-NEXT: .quad	0
163
164; Callsites
165; Constant arguments
166; CHECK-NEXT: .long	.Ltmp0-test
167; CHECK: .short	0
168; CHECK: .short	11
169; SmallConstant (0)
170; CHECK: .byte	4
171; CHECK-NEXT:   .byte   0
172; CHECK: .short 8
173; CHECK: .short	0
174; CHECK-NEXT:   .short  0
175; CHECK: .long	0
176; SmallConstant (0)
177; CHECK: .byte	4
178; CHECK-NEXT:   .byte   0
179; CHECK: .short 8
180; CHECK: .short	0
181; CHECK-NEXT:   .short  0
182; CHECK: .long	0
183; SmallConstant (2)
184; CHECK: .byte	4
185; CHECK-NEXT:   .byte   0
186; CHECK: .short 8
187; CHECK: .short	0
188; CHECK-NEXT:   .short  0
189; CHECK: .long	2
190; Indirect Spill Slot [RSP+0]
191; CHECK: .byte	3
192; CHECK-NEXT:   .byte   0
193; CHECK: .short 8
194; CHECK: .short	7
195; CHECK-NEXT:   .short  0
196; CHECK: .long	16
197; SmallConstant  (0)
198; CHECK: .byte	4
199; CHECK-NEXT:   .byte   0
200; CHECK: .short 8
201; CHECK: .short	0
202; CHECK-NEXT:   .short  0
203; CHECK: .long	0
204; SmallConstant  (0)
205; CHECK: .byte	4
206; CHECK-NEXT:   .byte   0
207; CHECK: .short 8
208; CHECK: .short	0
209; CHECK-NEXT:   .short  0
210; CHECK: .long	0
211; SmallConstant  (0)
212; CHECK: .byte	4
213; CHECK-NEXT:   .byte   0
214; CHECK: .short 8
215; CHECK: .short	0
216; CHECK-NEXT:   .short  0
217; CHECK: .long	0
218; Indirect Spill Slot [RSP+16]
219; CHECK: .byte	3
220; CHECK-NEXT:   .byte   0
221; CHECK: .short 8
222; CHECK: .short	7
223; CHECK-NEXT:   .short  0
224; CHECK: .long	16
225; Indirect Spill Slot [RSP+8]
226; CHECK: .byte	3
227; CHECK-NEXT:   .byte   0
228; CHECK: .short 8
229; CHECK: .short	7
230; CHECK-NEXT:   .short  0
231; CHECK: .long	8
232; Indirect Spill Slot [RSP+16]
233; CHECK: .byte	3
234; CHECK-NEXT:   .byte   0
235; CHECK: .short 8
236; CHECK: .short	7
237; CHECK-NEXT:   .short  0
238; CHECK: .long	16
239; Indirect Spill Slot [RSP+16]
240; CHECK: .byte	3
241; CHECK-NEXT:   .byte   0
242; CHECK: .short 8
243; CHECK: .short	7
244; CHECK-NEXT:   .short  0
245; CHECK: .long	16
246
247; No Padding or LiveOuts
248; CHECK: .short	0
249; CHECK: .short	0
250; CHECK: .p2align	3
251
252;
253; test_derived_arg
254
255; Statepoint ID
256; CHECK-NEXT: .quad	0
257
258; Callsites
259; Constant arguments
260; CHECK-NEXT: .long	.Ltmp1-test_derived_arg
261; CHECK: .short	0
262; CHECK: .short	11
263; SmallConstant (0)
264; CHECK: .byte	4
265; CHECK-NEXT:   .byte   0
266; CHECK: .short 8
267; CHECK: .short	0
268; CHECK-NEXT:   .short  0
269; CHECK: .long	0
270; SmallConstant (2)
271; CHECK: .byte	4
272; CHECK-NEXT:   .byte   0
273; CHECK: .short 8
274; CHECK: .short	0
275; CHECK-NEXT:   .short  0
276; CHECK: .long	2
277; Indirect Spill Slot [RSP+0]
278; CHECK: .byte	3
279; CHECK-NEXT:   .byte   0
280; CHECK: .short 8
281; CHECK: .short	7
282; CHECK-NEXT:   .short  0
283; CHECK: .long	16
284; SmallConstant  (0)
285; CHECK: .byte	4
286; CHECK-NEXT:   .byte   0
287; CHECK: .short 8
288; CHECK: .short	0
289; CHECK-NEXT:   .short  0
290; CHECK: .long	0
291; SmallConstant  (0)
292; CHECK: .byte	4
293; CHECK-NEXT:   .byte   0
294; CHECK: .short 8
295; CHECK: .short	0
296; CHECK-NEXT:   .short  0
297; CHECK: .long	0
298; SmallConstant  (0)
299; CHECK: .byte	4
300; CHECK-NEXT:   .byte   0
301; CHECK: .short 8
302; CHECK: .short	0
303; CHECK-NEXT:   .short  0
304; CHECK: .long	0
305; Indirect Spill Slot [RSP+16]
306; CHECK: .byte	3
307; CHECK-NEXT:   .byte   0
308; CHECK: .short 8
309; CHECK: .short	7
310; CHECK-NEXT:   .short  0
311; CHECK: .long	16
312; Indirect Spill Slot [RSP+8]
313; CHECK: .byte	3
314; CHECK-NEXT:   .byte   0
315; CHECK: .short 8
316; CHECK: .short	7
317; CHECK-NEXT:   .short  0
318; CHECK: .long	8
319; Indirect Spill Slot [RSP+16]
320; CHECK: .byte	3
321; CHECK-NEXT:   .byte   0
322; CHECK: .short 8
323; CHECK: .short	7
324; CHECK-NEXT:   .short  0
325; CHECK: .long	16
326; Indirect Spill Slot [RSP+16]
327; CHECK: .byte	3
328; CHECK-NEXT:   .byte   0
329; CHECK: .short 8
330; CHECK: .short	7
331; CHECK-NEXT:   .short  0
332; CHECK: .long	16
333
334; No Padding or LiveOuts
335; CHECK: .short	0
336; CHECK: .short	0
337; CHECK: .p2align	3
338
339; Records for the test_id function:
340
341; The Statepoint ID:
342; CHECK-NEXT: .quad	237
343
344; Instruction Offset
345; CHECK-NEXT: .long	.Ltmp2-test_id
346
347; Reserved:
348; CHECK: .short	0
349
350; NumLocations:
351; CHECK: .short	3
352
353; StkMapRecord[0]:
354; SmallConstant(0):
355; CHECK: .byte	4
356; CHECK-NEXT:   .byte   0
357; CHECK: .short 8
358; CHECK: .short	0
359; CHECK-NEXT:   .short  0
360; CHECK: .long	0
361
362; StkMapRecord[1]:
363; SmallConstant(0):
364; CHECK: .byte	4
365; CHECK-NEXT:   .byte   0
366; CHECK: .short 8
367; CHECK: .short	0
368; CHECK-NEXT:   .short  0
369; CHECK: .long	0
370
371; StkMapRecord[2]:
372; SmallConstant(0):
373; CHECK: .byte	4
374; CHECK-NEXT:   .byte   0
375; CHECK: .short 8
376; CHECK: .short	0
377; CHECK-NEXT:   .short  0
378; CHECK: .long	0
379
380; No padding or LiveOuts
381; CHECK: .short	0
382; CHECK: .short	0
383; CHECK: .p2align	3
384
385;
386; test_spadj
387
388; Statepoint ID
389; CHECK-NEXT: .quad	0
390
391; Instruction Offset
392; CHECK-NEXT: .long	.Ltmp3-test_spadj
393
394; Reserved:
395; CHECK: .short	0
396
397; NumLocations:
398; CHECK: .short	5
399
400; StkMapRecord[0]:
401; SmallConstant(0):
402; CHECK: .byte	4
403; CHECK-NEXT:   .byte   0
404; CHECK: .short 8
405; CHECK: .short	0
406; CHECK-NEXT:   .short  0
407; CHECK: .long	0
408
409; StkMapRecord[1]:
410; SmallConstant(0):
411; CHECK: .byte	4
412; CHECK-NEXT:   .byte   0
413; CHECK: .short 8
414; CHECK: .short	0
415; CHECK-NEXT:   .short  0
416; CHECK: .long	0
417
418; StkMapRecord[2]:
419; SmallConstant(0):
420; CHECK: .byte	4
421; CHECK-NEXT:   .byte   0
422; CHECK: .short 8
423; CHECK: .short	0
424; CHECK-NEXT:   .short  0
425; CHECK: .long	0
426
427; StkMapRecord[3]:
428; Indirect Spill Slot [RSP+16]
429; CHECK: .byte	3
430; CHECK-NEXT:   .byte   0
431; CHECK: .short 8
432; CHECK: .short	7
433; CHECK-NEXT:   .short  0
434; CHECK: .long	16
435
436; StkMapRecord[4]:
437; Indirect Spill Slot [RSP+16]
438; CHECK: .byte	3
439; CHECK-NEXT:   .byte   0
440; CHECK: .short 8
441; CHECK: .short	7
442; CHECK-NEXT:   .short  0
443; CHECK: .long	16
444
445; No padding or LiveOuts
446; CHECK: .short	0
447; CHECK: .short	0
448; CHECK: .p2align	3
449
450;
451; test_fixed_arg
452
453; Statepoint ID
454; CHECK-NEXT: .quad	0
455
456; Instruction Offset
457; CHECK-NEXT: .long	.Ltmp4-test_fixed_arg
458
459; Reserved:
460; CHECK: .short	0
461
462; NumLocations:
463; CHECK: .short	4
464
465; StkMapRecord[0]:
466; SmallConstant(0):
467; CHECK: .byte	4
468; CHECK-NEXT:   .byte   0
469; CHECK: .short 8
470; CHECK: .short	0
471; CHECK-NEXT:   .short  0
472; CHECK: .long	0
473
474; StkMapRecord[1]:
475; SmallConstant(0):
476; CHECK: .byte	4
477; CHECK-NEXT:   .byte   0
478; CHECK: .short 8
479; CHECK: .short	0
480; CHECK-NEXT:   .short  0
481; CHECK: .long	0
482
483; StkMapRecord[2]:
484; SmallConstant(1):
485; CHECK: .byte	4
486; CHECK-NEXT:   .byte   0
487; CHECK: .short 8
488; CHECK: .short	0
489; CHECK-NEXT:   .short  0
490; CHECK: .long	1
491
492; StkMapRecord[3]:
493; Direct RSP+16
494; CHECK: .byte	2
495; CHECK-NEXT:   .byte   0
496; CHECK: .short 8
497; CHECK: .short	7
498; CHECK-NEXT:   .short  0
499; CHECK: .long	16
500
501; No padding or LiveOuts
502; CHECK: .short	0
503; CHECK: .short	0
504; CHECK: .p2align	3
505