blob: b236393e9f49f8675359c5db9cb656ae0d9c467b [file] [log] [blame]
Philip Reames2b1084a2016-08-31 15:12:17 +00001; RUN: llc -O3 < %s | FileCheck %s
2target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3target triple = "x86_64-apple-macosx10.11.0"
4
5declare void @bar() #0
6declare void @baz()
7
8define void @test1(i32 %a) gc "statepoint-example" {
9entry:
10; We expect the argument to be passed in an extra register to bar
11; CHECK-LABEL: test1
12; CHECK: pushq %rax
Matthias Braun39c3c892016-11-30 23:48:26 +000013; CHECK-NEXT: Lcfi0:
Philip Reames2b1084a2016-08-31 15:12:17 +000014; CHECK-NEXT: .cfi_def_cfa_offset 16
15; CHECK-NEXT: callq _bar
16 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
17 ret void
18}
19
20define void @test2(i32 %a, i32 %b) gc "statepoint-example" {
21entry:
22; Because the first call clobbers esi, we have to move the values into
23; new registers. Note that they stay in the registers for both calls.
24; CHECK-LABEL: @test2
25; CHECK: movl %esi, %ebx
26; CHECK-NEXT: movl %edi, %ebp
27; CHECK-NEXT: callq _bar
28 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 2, i32 %a, i32 %b)
29 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 2, i32 %b, i32 %a)
30 ret void
31}
32
33define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i) gc "statepoint-example" {
34entry:
35; TODO: We should have folded the reload into the statepoint.
36; CHECK-LABEL: @test3
Philip Reames1f1bbac2016-12-13 01:38:41 +000037; CHECK: pushq %rax
38; CHECK-NEXT: Lcfi
39; CHECK-NEXT: .cfi_def_cfa_offset 16
Philip Reames2b1084a2016-08-31 15:12:17 +000040; CHECK-NEXT: callq _bar
41 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 9, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i)
42 ret void
43}
44
45; This case just confirms that we don't crash when given more live values
Philip Reames1f1bbac2016-12-13 01:38:41 +000046; than registers. This is a case where we *have* to use a stack slot. This
47; also ends up being a good test of whether we can fold loads from immutable
48; stack slots into the statepoint.
Philip Reames2b1084a2016-08-31 15:12:17 +000049define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" {
50entry:
Philip Reames2b1084a2016-08-31 15:12:17 +000051; CHECK-LABEL: test4
Philip Reames1f1bbac2016-12-13 01:38:41 +000052; CHECK: pushq %rax
53; CHECK-NEXT: Lcfi
54; CHECK-NEXT: .cfi_def_cfa_offset 16
Philip Reames2b1084a2016-08-31 15:12:17 +000055; CHECK-NEXT: callq _bar
56 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 26, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)
57 ret void
58}
59
60; A live-through gc-value must be spilled even if it is also a live-in deopt
61; value. For live-in, we could technically report the register copy, but from
62; a code quality perspective it's better to reuse the required stack slot so
63; as to put less stress on the register allocator for no benefit.
64define i32 addrspace(1)* @test5(i32 %a, i32 addrspace(1)* %p) gc "statepoint-example" {
65entry:
66; CHECK-LABEL: test5
67; CHECK: movq %rsi, (%rsp)
68; CHECK-NEXT: callq _bar
69 %token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a, i32 addrspace(1)* %p, i32 addrspace(1)* %p)
70 %p2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 9, i32 9)
71 ret i32 addrspace(1)* %p2
72}
73
74; Show the interaction of live-through spilling followed by live-in.
75define void @test6(i32 %a) gc "statepoint-example" {
76entry:
77; TODO: We could have reused the previous spill slot at zero additional cost.
78; CHECK-LABEL: test6
79; CHECK: movl %edi, %ebx
80; CHECK: movl %ebx, 12(%rsp)
81; CHECK-NEXT: callq _baz
Philip Reames1f1bbac2016-12-13 01:38:41 +000082; CHECK-NEXT: Ltmp
Philip Reames2b1084a2016-08-31 15:12:17 +000083; CHECK-NEXT: callq _bar
84 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 %a)
85 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
86 ret void
87}
88
89
Matthias Braun39c3c892016-11-30 23:48:26 +000090; CHECK: Ltmp0-_test1
Philip Reames2b1084a2016-08-31 15:12:17 +000091; CHECK: .byte 1
92; CHECK-NEXT: .byte 4
93; CHECK-NEXT: .short 5
94; CHECK-NEXT: .long 0
95
Matthias Braun39c3c892016-11-30 23:48:26 +000096; CHECK: Ltmp1-_test2
Philip Reames2b1084a2016-08-31 15:12:17 +000097; CHECK: .byte 1
98; CHECK-NEXT: .byte 4
99; CHECK-NEXT: .short 6
100; CHECK-NEXT: .long 0
101; CHECK: .byte 1
102; CHECK-NEXT: .byte 4
103; CHECK-NEXT: .short 3
104; CHECK-NEXT: .long 0
Matthias Braun39c3c892016-11-30 23:48:26 +0000105; CHECK: Ltmp2-_test2
Philip Reames2b1084a2016-08-31 15:12:17 +0000106; CHECK: .byte 1
107; CHECK-NEXT: .byte 4
108; CHECK-NEXT: .short 3
109; CHECK-NEXT: .long 0
110; CHECK: .byte 1
111; CHECK-NEXT: .byte 4
112; CHECK-NEXT: .short 6
113; CHECK-NEXT: .long 0
114
115declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
116declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
117
118
119attributes #0 = { "deopt-lowering"="live-in" }
120attributes #1 = { "deopt-lowering"="live-through" }