1 ; This file contains some of the same basic tests as statepoint-vreg.ll, but
2 ; focuses on examining the intermediate representation. It's separate so that
3 ; the main file is easy to update with update_llc_test_checks.py
5 ; This run is to demonstrate what MIR SSA looks like.
6 ; RUN: llc -max-registers-for-gc-values=4 -stop-after finalize-isel < %s | FileCheck --check-prefix=CHECK-VREG %s
7 ; This run is to demonstrate register allocator work.
8 ; RUN: llc -max-registers-for-gc-values=4 -stop-after virtregrewriter < %s | FileCheck --check-prefix=CHECK-PREG %s
10 target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
11 target triple = "x86_64-pc-linux-gnu"
13 declare dso_local i1 @return_i1()
14 declare dso_local void @func()
15 declare dso_local void @consume(ptr addrspace(1))
16 declare dso_local void @consume2(ptr addrspace(1), ptr addrspace(1))
17 declare dso_local void @consume5(ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1))
18 declare dso_local void @use1(ptr addrspace(1), ptr addrspace(1))
19 declare dso_local void @bar(ptr addrspace(1), ptr addrspace(1))
20 declare ptr addrspace(1) @dummy(i32)
22 ; test most simple relocate
23 define i1 @test_relocate(ptr addrspace(1) %a) gc "statepoint-example" {
24 ; CHECK-VREG-LABEL: name: test_relocate
25 ; CHECK-VREG: %0:gr64 = COPY $rdi
26 ; CHECK-VREG: %1:gr64 = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, %0(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $al
27 ; CHECK-VREG: %2:gr8 = COPY $al
28 ; CHECK-VREG: $rdi = COPY %1
29 ; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
31 ; CHECK-PREG-LABEL: name: test_relocate
32 ; CHECK-PREG: renamable $rbx = COPY $rdi
33 ; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, killed renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $al
34 ; CHECK-PREG: renamable $bpl = COPY $al
35 ; CHECK-PREG: $rdi = COPY killed renamable $rbx
36 ; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
39 %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) %a)]
40 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
41 %res1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
42 call void @consume(ptr addrspace(1) %rel1)
45 ; test pointer variables intermixed with pointer constants
46 define void @test_mixed(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c) gc "statepoint-example" {
47 ; CHECK-VREG-LABEL: name: test_mixed
48 ; CHECK-VREG: %2:gr64 = COPY $rdx
49 ; CHECK-VREG: %1:gr64 = COPY $rsi
50 ; CHECK-VREG: %0:gr64 = COPY $rdi
51 ; CHECK-VREG: %3:gr64, %4:gr64, %5:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 4, %2(tied-def 0), 2, 0, %1(tied-def 1), %0(tied-def 2), 2, 0, 2, 4, 0, 0, 1, 1, 2, 2, 3, 3, csr_64, implicit-def $rsp, implicit-def $ssp
52 ; CHECK-VREG: %6:gr32 = MOV32r0 implicit-def dead $eflags
53 ; CHECK-VREG: %7:gr64 = SUBREG_TO_REG 0, killed %6, %subreg.sub_32bit
54 ; CHECK-VREG: $rdi = COPY %5
55 ; CHECK-VREG: $rsi = COPY %7
56 ; CHECK-VREG: $rdx = COPY %4
57 ; CHECK-VREG: $rcx = COPY %7
58 ; CHECK-VREG: $r8 = COPY %3
59 ; CHECK-VREG: CALL64pcrel32 @consume5, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit $rcx, implicit $r8, implicit-def $rsp, implicit-def $ssp
61 ; CHECK-PREG-LABEL: name: test_mixed
62 ; CHECK-PREG: renamable $rbx = COPY $rdx
63 ; CHECK-PREG: renamable $r14 = COPY $rsi
64 ; CHECK-PREG: renamable $r15 = COPY $rdi
65 ; CHECK-PREG: renamable $rbx, renamable $r14, renamable $r15 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 4, killed renamable $rbx(tied-def 0), 2, 0, killed renamable $r14(tied-def 1), killed renamable $r15(tied-def 2), 2, 0, 2, 4, 0, 0, 1, 1, 2, 2, 3, 3, csr_64, implicit-def $rsp, implicit-def $ssp
66 ; CHECK-PREG: $rdi = COPY killed renamable $r15
67 ; CHECK-PREG: dead $esi = MOV32r0 implicit-def dead $eflags, implicit-def $rsi
68 ; CHECK-PREG: $rdx = COPY killed renamable $r14
69 ; CHECK-PREG: dead $ecx = MOV32r0 implicit-def dead $eflags, implicit-def $rcx
70 ; CHECK-PREG: $r8 = COPY killed renamable $rbx
71 ; CHECK-PREG: CALL64pcrel32 @consume5, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit killed $rcx, implicit killed $r8, implicit-def $rsp, implicit-def $ssp
74 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a, ptr addrspace(1) null, ptr addrspace(1) %b, ptr addrspace(1) null, ptr addrspace(1) %c)]
75 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
76 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1)
77 %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)
78 %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 3, i32 3)
79 %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 4, i32 4)
80 call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5)
84 ; same as above, but for alloca
85 define ptr addrspace(1) @test_alloca(ptr addrspace(1) %ptr) gc "statepoint-example" {
86 ; CHECK-VREG-LABEL: name: test_alloca
87 ; CHECK-VREG: %0:gr64 = COPY $rdi
88 ; CHECK-VREG: MOV64mr %stack.0.alloca, 1, $noreg, 0, $noreg, %0 :: (store (s64) into %ir.alloca)
89 ; CHECK-VREG: %1:gr64 = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, %0(tied-def 0), 2, 1, 0, %stack.0.alloca, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $al :: (volatile load store (s64) on %stack.0.alloca)
90 ; CHECK-VREG: %2:gr8 = COPY $al
91 ; CHECK-VREG: %3:gr64 = MOV64rm %stack.0.alloca, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.alloca)
92 ; CHECK-VREG: $rdi = COPY %1
93 ; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
95 ; CHECK-PREG-LABEL: name: test_alloca
96 ; CHECK-PREG: renamable $rbx = COPY $rdi
97 ; CHECK-PREG: MOV64mr %stack.0.alloca, 1, $noreg, 0, $noreg, renamable $rbx :: (store (s64) into %ir.alloca)
98 ; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, killed renamable $rbx(tied-def 0), 2, 1, 0, %stack.0.alloca, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def dead $al :: (volatile load store (s64) on %stack.0.alloca)
99 ; CHECK-PREG: renamable $r14 = MOV64rm %stack.0.alloca, 1, $noreg, 0, $noreg :: (dereferenceable load (s64) from %ir.alloca)
100 ; CHECK-PREG: $rdi = COPY killed renamable $rbx
101 ; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
104 %alloca = alloca ptr addrspace(1), align 8
105 store ptr addrspace(1) %ptr, ptr %alloca
106 %safepoint_token = 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 %alloca, ptr addrspace(1) %ptr)]
107 %rel1 = load ptr addrspace(1), ptr %alloca
108 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1)
109 call void @consume(ptr addrspace(1) %rel2)
110 ret ptr addrspace(1) %rel1
113 ; test base != derived
114 define void @test_base_derived(ptr addrspace(1) %base, ptr addrspace(1) %derived) gc "statepoint-example" {
115 ; CHECK-VREG-LABEL: name: test_base_derived
116 ; CHECK-VREG: %1:gr64 = COPY $rsi
117 ; CHECK-VREG: %0:gr64 = COPY $rdi
118 ; CHECK-VREG: %2:gr64, %3:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 2, %1(tied-def 0), %0(tied-def 1), 2, 0, 2, 1, 1, 0, csr_64, implicit-def $rsp, implicit-def $ssp
119 ; CHECK-VREG: $rdi = COPY %2
120 ; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
122 ; CHECK-PREG-LABEL: name: test_base_derived
123 ; CHECK-PREG: renamable $rbx = COPY $rsi
124 ; CHECK-PREG: renamable $rbx, dead renamable $r14 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 2, killed renamable $rbx(tied-def 0), killed renamable $r14(tied-def 1), 2, 0, 2, 1, 1, 0, csr_64, implicit-def $rsp, implicit-def $ssp
125 ; CHECK-PREG: $rdi = COPY killed renamable $rbx
126 ; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
128 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %base, ptr addrspace(1) %derived)]
129 %reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
130 call void @consume(ptr addrspace(1) %reloc)
134 ; deopt GC pointer not present in GC args must be spilled
135 define void @test_deopt_gcpointer(ptr addrspace(1) %a, ptr addrspace(1) %b) gc "statepoint-example" {
136 ; CHECK-VREG-LABEL: name: test_deopt_gcpointer
137 ; CHECK-VREG: %1:gr64 = COPY $rsi
138 ; CHECK-VREG: %0:gr64 = COPY $rdi
139 ; CHECK-VREG: %2:gr64, %3:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, %0, 2, 2, %1(tied-def 0), %0(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp
140 ; CHECK-VREG: $rdi = COPY %2
141 ; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
144 ; CHECK-PREG-LABEL: name: test_deopt_gcpointer
145 ; CHECK-PREG: renamable $rbx = COPY $rsi
146 ; CHECK-PREG: renamable $r14 = COPY $rdi
147 ; CHECK-PREG: renamable $rbx, dead renamable $r14 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, killed renamable $r14, 2, 2, killed renamable $rbx(tied-def 0), renamable $r14(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp
148 ; CHECK-PREG: $rdi = COPY killed renamable $rbx
149 ; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
151 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %a), "gc-live" (ptr addrspace(1) %b)]
152 %rel = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
153 call void @consume(ptr addrspace(1) %rel)
157 ;; Two gc.relocates of the same input, should require only a single spill/fill
158 define void @test_gcrelocate_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" {
159 ; CHECK-VREG-LABEL: name: test_gcrelocate_uniqueing
160 ; CHECK-VREG: %0:gr64 = COPY $rdi
161 ; CHECK-VREG: %1:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 2, %0, 2, 4278124286, 2, 1, %0(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
162 ; CHECK-VREG: $rdi = COPY %1
163 ; CHECK-VREG: $rsi = COPY %1
164 ; CHECK-VREG: CALL64pcrel32 @consume2, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit-def $rsp, implicit-def $ssp
166 ; CHECK-PREG-LABEL: name: test_gcrelocate_uniqueing
167 ; CHECK-PREG: renamable $rbx = COPY $rdi
168 ; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 2, killed renamable $rbx, 2, 4278124286, 2, 1, renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
169 ; CHECK-PREG: $rdi = COPY renamable $rbx
170 ; CHECK-PREG: $rsi = COPY killed renamable $rbx
171 ; CHECK-PREG: CALL64pcrel32 @consume2, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit killed $rsi, implicit-def $rsp, implicit-def $ssp
173 %tok = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %ptr, i32 undef), "gc-live" (ptr addrspace(1) %ptr, ptr addrspace(1) %ptr)]
174 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
175 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1)
176 call void @consume2(ptr addrspace(1) %a, ptr addrspace(1) %b)
180 ; Two gc.relocates of a bitcasted pointer should only require a single spill/fill
181 define void @test_gcptr_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" {
182 ; CHECK-VREG-LABEL: name: test_gcptr_uniqueing
183 ; CHECK-VREG: %0:gr64 = COPY $rdi
184 ; CHECK-VREG: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
185 ; CHECK-VREG: %1:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 2, %0, 2, 4278124286, 2, 1, %0(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
186 ; CHECK-VREG: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
187 ; CHECK-VREG: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
188 ; CHECK-VREG: $rdi = COPY %1
189 ; CHECK-VREG: $rsi = COPY %1
190 ; CHECK-VREG: CALL64pcrel32 @use1, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit-def $rsp, implicit-def $ssp
192 ; CHECK-PREG-LABEL: name: test_gcptr_uniqueing
193 ; CHECK-PREG: renamable $rbx = COPY $rdi
194 ; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 2, killed renamable $rbx, 2, 4278124286, 2, 1, renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
195 ; CHECK-PREG: $rdi = COPY renamable $rbx
196 ; CHECK-PREG: $rsi = COPY killed renamable $rbx
197 ; CHECK-PREG: CALL64pcrel32 @use1, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit killed $rsi, implicit-def $rsp, implicit-def $ssp
199 %tok = tail call token (i64, i32, ptr, i32, i32, ...)
200 @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %ptr, i32 undef), "gc-live" (ptr addrspace(1) %ptr, ptr addrspace(1) %ptr)]
201 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
202 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1)
203 call void @use1(ptr addrspace(1) %a, ptr addrspace(1) %b)
207 define i1 @test_cross_bb(ptr addrspace(1) %a, i1 %external_cond) gc "statepoint-example" {
208 ; CHECK-VREG-LABEL: name: test_cross_bb
209 ; CHECK-VREG: bb.0.entry:
210 ; CHECK-VREG: %1:gr32 = COPY $esi
211 ; CHECK-VREG-NEXT: %0:gr64 = COPY $rdi
212 ; CHECK-VREG-NEXT: %4:gr8 = COPY %1.sub_8bit
213 ; CHECK-VREG-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
214 ; CHECK-VREG-NEXT: %2:gr64 = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, %0(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $al
215 ; CHECK-VREG-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
216 ; CHECK-VREG-NEXT: %5:gr8 = COPY $al
217 ; CHECK-VREG-NEXT: %3:gr8 = COPY %5
218 ; CHECK-VREG-NEXT: TEST8ri killed %4, 1, implicit-def $eflags
219 ; CHECK-VREG-NEXT: JCC_1 %bb.2, 4, implicit $eflags
220 ; CHECK-VREG-NEXT: JMP_1 %bb.1
221 ; CHECK-VREG: bb.1.left:
222 ; CHECK-VREG-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
223 ; CHECK-VREG-NEXT: $rdi = COPY %2
224 ; CHECK-VREG-NEXT: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
225 ; CHECK-VREG-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
226 ; CHECK-VREG-NEXT: $al = COPY %3
227 ; CHECK-VREG-NEXT: RET 0, $al
228 ; CHECK-VREG: bb.2.right:
229 ; CHECK-VREG-NEXT: %6:gr8 = MOV8ri 1
230 ; CHECK-VREG-NEXT: $al = COPY %6
231 ; CHECK-VREG-NEXT: RET 0, $al
234 %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) %a)]
235 br i1 %external_cond, label %left, label %right
238 %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
239 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
240 call void @consume(ptr addrspace(1) %call1)
247 ; Local and non-local relocates of the same value
248 ; CHECK-VREG-LABEL: name: test_local_non_local_reloc
249 ; CHECK-VREG: bb.0.entry:
250 ; CHECK-VREG: %2:gr64 = COPY $rsi
251 ; CHECK-VREG: %1:gr32 = COPY $edi
252 ; CHECK-VREG: %4:gr8 = COPY %1.sub_8bit
253 ; CHECK-VREG: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
254 ; CHECK-VREG: %5:gr32 = MOV32r0 implicit-def dead $eflags
255 ; CHECK-VREG: $edi = COPY %5
256 ; CHECK-VREG: %6:gr64 = IMPLICIT_DEF
257 ; CHECK-VREG: %0:gr64 = STATEPOINT 2, 5, 1, killed %6, $edi, 2, 0, 2, 0, 2, 0, 2, 1, %2(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
258 ; CHECK-VREG: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
259 ; CHECK-VREG: %7:gr64 = COPY $rax
260 ; CHECK-VREG: %3:gr64 = COPY %0
261 ; CHECK-VREG: TEST8ri killed %4, 1, implicit-def $eflags
262 ; CHECK-VREG: JCC_1 %bb.2, 5, implicit $eflags
263 ; CHECK-VREG: JMP_1 %bb.1
264 ; CHECK-VREG: bb.1.left:
265 ; CHECK-VREG: $rax = COPY %3
266 ; CHECK-VREG: RET 0, $rax
267 ; CHECK-VREG: bb.2.right:
268 ; CHECK-VREG: $rax = COPY %0
269 ; CHECK-VREG: RET 0, $rax
270 define ptr addrspace(1) @test_local_non_local_reloc(i1 %c, ptr addrspace(1) %p) gc "statepoint-example" {
272 %statepoint = call token (i64, i32, ptr addrspace(1) (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 5, ptr addrspace(1) (i32)* nonnull elementtype(ptr addrspace(1) (i32)) @dummy, i32 1, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) %p) ]
273 %p.relocated = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint, i32 0, i32 0) ; (%p, %p)
274 br i1 %c, label %right, label %left
277 %p.relocated.2 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint, i32 0, i32 0) ; (%p, %p)
278 ret ptr addrspace(1) %p.relocated.2
281 ret ptr addrspace(1) %p.relocated
284 ; No need to check post-regalloc output as it is the same
285 define i1 @duplicate_reloc() gc "statepoint-example" {
286 ; CHECK-VREG-LABEL: name: duplicate_reloc
287 ; CHECK-VREG: bb.0.entry:
288 ; CHECK-VREG: STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
289 ; CHECK-VREG: STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
290 ; CHECK-VREG: %0:gr8 = MOV8ri 1
291 ; CHECK-VREG: $al = COPY %0
292 ; CHECK-VREG: RET 0, $al
295 %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) null, ptr addrspace(1) null)]
296 %base = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
297 %derived = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
298 %safepoint_token2 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %base, ptr addrspace(1) %derived)]
299 %base_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2, i32 0, i32 0)
300 %derived_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2, i32 0, i32 1)
301 %cmp1 = icmp eq ptr addrspace(1) %base_reloc, null
302 %cmp2 = icmp eq ptr addrspace(1) %derived_reloc, null
303 %cmp = and i1 %cmp1, %cmp2
307 ; Vectors cannot go in VRegs
308 ; No need to check post-regalloc output as it is lowered using old scheme
309 define <2 x ptr addrspace(1)> @test_vector(<2 x ptr addrspace(1)> %obj) gc "statepoint-example" {
310 ; CHECK-VREG-LABEL: name: test_vector
311 ; CHECK-VREG: %0:vr128 = COPY $xmm0
312 ; CHECK-VREG: MOVAPSmr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store (s128) into %stack.0)
313 ; CHECK-VREG: STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 1, 1, 16, %stack.0, 0, 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store (s128) on %stack.0)
314 ; CHECK-VREG: %1:vr128 = MOVAPSrm %stack.0, 1, $noreg, 0, $noreg :: (load (s128) from %stack.0)
315 ; CHECK-VREG: $xmm0 = COPY %1
316 ; CHECK-VREG: RET 0, $xmm0
319 %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> %obj)]
320 %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj)
321 ret <2 x ptr addrspace(1)> %obj.relocated
325 ; test limit on amount of vregs
326 define void @test_limit(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c, ptr addrspace(1) %d, ptr addrspace(1) %e) gc "statepoint-example" {
327 ; CHECK-VREG-LABEL: name: test_limit
328 ; CHECK-VREG: %4:gr64 = COPY $r8
329 ; CHECK-VREG: %3:gr64 = COPY $rcx
330 ; CHECK-VREG: %2:gr64 = COPY $rdx
331 ; CHECK-VREG: %1:gr64 = COPY $rsi
332 ; CHECK-VREG: %0:gr64 = COPY $rdi
333 ; CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store (s64) into %stack.0)
334 ; CHECK-VREG: %5:gr64, %6:gr64, %7:gr64, %8:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 0, 2, 5, %4(tied-def 0), %3(tied-def 1), %2(tied-def 2), %1(tied-def 3), 1, 8, %stack.0, 0, 2, 0, 2, 5, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store (s64) on %stack.0)
335 ; CHECK-VREG: %9:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
336 ; CHECK-VREG: $rdi = COPY %9
337 ; CHECK-VREG: $rsi = COPY %8
338 ; CHECK-VREG: $rdx = COPY %7
339 ; CHECK-VREG: $rcx = COPY %6
340 ; CHECK-VREG: $r8 = COPY %5
341 ; CHECK-VREG: CALL64pcrel32 @consume5, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit $rcx, implicit $r8, implicit-def $rsp, implicit-def $ssp
344 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c, ptr addrspace(1) %d, ptr addrspace(1) %e)]
345 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
346 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1)
347 %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)
348 %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 3, i32 3)
349 %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 4, i32 4)
350 call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5)
354 ; Test that CopyFromReg emitted during ISEL processing of gc.relocate are properly ordered w.r.t. statepoint.
355 define ptr addrspace(1) @test_isel_sched(ptr addrspace(1) %0, ptr addrspace(1) %1, i32 %2) gc "statepoint-example" {
356 ;CHECK-VREG-LABEL: name: test_isel_sched
357 ;CHECK-VREG: bb.0.entry:
358 ;CHECK-VREG: %2:gr32 = COPY $edx
359 ;CHECK-VREG: %1:gr64 = COPY $rsi
360 ;CHECK-VREG: %0:gr64 = COPY $rdi
361 ;CHECK-VREG: TEST32rr %2, %2, implicit-def $eflags
362 ;CHECK-VREG: %3:gr64 = CMOV64rr %1, %0, 4, implicit $eflags
363 ;CHECK-VREG: %4:gr32 = MOV32r0 implicit-def dead $eflags
364 ;CHECK-VREG: %5:gr64 = SUBREG_TO_REG 0, killed %4, %subreg.sub_32bit
365 ;CHECK-VREG: $rdi = COPY %5
366 ;CHECK-VREG: $rsi = COPY %3
367 ;CHECK-VREG: %6:gr64, %7:gr64 = STATEPOINT 10, 0, 2, @bar, $rdi, $rsi, 2, 0, 2, 0, 2, 0, 2, 2, %1(tied-def 0), %0(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp
368 ;CHECK-VREG: TEST32rr %2, %2, implicit-def $eflags
369 ;CHECK-VREG: %8:gr64 = CMOV64rr %6, killed %7, 4, implicit $eflags
370 ;CHECK-VREG: $rax = COPY %8
371 ;CHECK-VREG: RET 0, $rax
373 %cmp = icmp eq i32 %2, 0
374 %ptr = select i1 %cmp, ptr addrspace(1) %0, ptr addrspace(1) %1
375 %token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 10, i32 0, ptr elementtype(void (ptr addrspace(1), ptr addrspace(1))) @bar, i32 2, i32 0, ptr addrspace(1) null, ptr addrspace(1) %ptr, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) %0, ptr addrspace(1) %1) ]
376 %rel0 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token, i32 0, i32 0)
377 %rel1 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token, i32 1, i32 1)
378 %res = select i1 %cmp, ptr addrspace(1) %rel0, ptr addrspace(1) %rel1
379 ret ptr addrspace(1) %res
382 ; Check that ISEL of gc.relocate used in other BB does not generate extra COPY instruction.
383 define i1 @test_cross_bb_reloc(ptr addrspace(1) %a, i1 %external_cond) gc "statepoint-example" {
384 ; CHECK-VREG-LABEL: test_cross_bb_reloc
385 ; CHECK-VREG: bb.0.entry:
386 ; CHECK-VREG: [[VREG:%[^ ]+]]:gr64 = STATEPOINT 0, 0, 0, @return_i1, 2, 0, 2, 0, 2, 0, 2, 1, %2(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $al
387 ; CHECK-VREG-NOT: COPY [[VREG]]
388 ; CHECK-VREG: bb.1.left:
389 ; CHECK-VREG: $rdi = COPY [[VREG]]
390 ; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
391 ; CHECK-VREG: $al = COPY %1
392 ; CHECK-VREG: RET 0, $al
395 %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) %a)]
396 %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
397 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)
398 br i1 %external_cond, label %left, label %right
401 call void @consume(ptr addrspace(1) %call1)
408 declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
409 declare dso_local ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
410 declare <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token, i32, i32)
411 declare dso_local i1 @llvm.experimental.gc.result.i1(token)