|
1 | 1 | if :AMDGPU in LLVM.backends() |
| 2 | + |
| 3 | +# XXX: generic `sink` generates an instruction selection error |
| 4 | +sink_gcn(i) = sink(i, Val(5)) |
| 5 | + |
2 | 6 | @testset "IR" begin |
3 | 7 |
|
4 | 8 | @testset "kernel calling convention" begin |
5 | | - kernel() = return |
| 9 | + mod = @eval module $(gensym()) |
| 10 | + kernel() = return |
| 11 | + end |
6 | 12 |
|
7 | 13 | @test @filecheck begin |
8 | 14 | check"CHECK-NOT: amdgpu_kernel" |
9 | | - GCN.code_llvm(kernel, Tuple{}; dump_module=true) |
| 15 | + GCN.code_llvm(mod.kernel, Tuple{}; dump_module=true) |
10 | 16 | end |
11 | 17 |
|
12 | 18 | @test @filecheck begin |
13 | 19 | check"CHECK: amdgpu_kernel" |
14 | | - GCN.code_llvm(kernel, Tuple{}; dump_module=true, kernel=true) |
| 20 | + GCN.code_llvm(mod.kernel, Tuple{}; dump_module=true, kernel=true) |
15 | 21 | end |
16 | 22 | end |
17 | 23 |
|
|
21 | 27 | @testset "assembly" begin |
22 | 28 |
|
23 | 29 | @testset "skip scalar trap" begin |
24 | | - workitem_idx_x() = ccall("llvm.amdgcn.workitem.id.x", llvmcall, Int32, ()) |
25 | | - trap() = ccall("llvm.trap", llvmcall, Nothing, ()) |
26 | | - function kernel() |
27 | | - if workitem_idx_x() > 1 |
28 | | - trap() |
| 30 | + mod = @eval module $(gensym()) |
| 31 | + workitem_idx_x() = ccall("llvm.amdgcn.workitem.id.x", llvmcall, Int32, ()) |
| 32 | + trap() = ccall("llvm.trap", llvmcall, Nothing, ()) |
| 33 | + |
| 34 | + function kernel() |
| 35 | + if workitem_idx_x() > 1 |
| 36 | + trap() |
| 37 | + end |
| 38 | + return |
29 | 39 | end |
30 | | - return |
31 | 40 | end |
32 | 41 |
|
33 | 42 | @test @filecheck begin |
| 43 | + check"CHECK-LABEL: {{.*kernel.*}}:" |
34 | 44 | check"CHECK: s_trap 2" |
35 | | - GCN.code_native(kernel, Tuple{}) |
| 45 | + GCN.code_native(mod.kernel, Tuple{}) |
36 | 46 | end |
| 47 | + # XXX |
37 | 48 | @test_skip occursin("s_cbranch_execz", asm) |
38 | 49 | if Base.libllvm_version < v"9" |
39 | 50 | @test_broken occursin("v_readfirstlane", asm) |
|
43 | 54 | @testset "child functions" begin |
44 | 55 | # we often test using @noinline child functions, so test whether these survive |
45 | 56 | # (despite not having side-effects) |
46 | | - @noinline child(i) = sink_gcn(i) |
47 | | - function parent(i) |
48 | | - child(i) |
49 | | - return |
| 57 | + mod = @eval module $(gensym()) |
| 58 | + import ..sink_gcn |
| 59 | + @noinline child(i) = sink_gcn(i) |
| 60 | + function parent(i) |
| 61 | + child(i) |
| 62 | + return |
| 63 | + end |
50 | 64 | end |
51 | 65 |
|
52 | 66 | @test @filecheck begin |
| 67 | + check"CHECK-LABEL: {{.*parent.*}}:" |
53 | 68 | check"CHECK: s_add_u32{{.*(julia|j)_child_.*}}@rel32@" |
54 | 69 | check"CHECK: s_addc_u32{{.*(julia|j)_child_.*}}@rel32@" |
55 | | - GCN.code_native(parent, Tuple{Int64}; dump_module=true) |
| 70 | + GCN.code_native(mod.parent, Tuple{Int64}; dump_module=true) |
56 | 71 | end |
57 | 72 | end |
58 | 73 |
|
59 | 74 | @testset "kernel functions" begin |
60 | | - @noinline nonentry(i) = sink_gcn(i) |
61 | | - function entry(i) |
62 | | - nonentry(i) |
63 | | - return |
| 75 | + mod = @eval module $(gensym()) |
| 76 | + import ..sink_gcn |
| 77 | + @noinline nonentry(i) = sink_gcn(i) |
| 78 | + function entry(i) |
| 79 | + nonentry(i) |
| 80 | + return |
| 81 | + end |
64 | 82 | end |
65 | 83 |
|
66 | 84 | @test @filecheck begin |
67 | 85 | check"CHECK-NOT: .amdhsa_kernel {{.*}}nonentry" |
68 | 86 | check"CHECK: .type {{.*nonentry.*}},@function" |
69 | 87 | check"CHECK: .amdhsa_kernel {{.*entry.*}}" |
70 | | - GCN.code_native(entry, Tuple{Int64}; dump_module=true, kernel=true) |
| 88 | + GCN.code_native(mod.entry, Tuple{Int64}; dump_module=true, kernel=true) |
71 | 89 | end |
72 | 90 | end |
73 | 91 |
|
|
76 | 94 | # the child only being present once |
77 | 95 |
|
78 | 96 | mod = @eval module $(gensym()) |
79 | | - export child, parent1, parent2 |
80 | | - |
| 97 | + import ..sink_gcn |
81 | 98 | @noinline child(i) = sink_gcn(i) |
82 | 99 | function parent1(i) |
83 | 100 | child(i) |
|
105 | 122 | # in the case of two child functions |
106 | 123 |
|
107 | 124 | mod = @eval module $(gensym()) |
108 | | - export parent1, parent2, child1, child2 |
109 | | - |
| 125 | + import ..sink_gcn |
110 | 126 | @noinline child1(i) = sink_gcn(i) |
111 | 127 | @noinline child2(i) = sink_gcn(i+1) |
112 | 128 | function parent1(i) |
@@ -138,49 +154,57 @@ end |
138 | 154 |
|
139 | 155 | # NOTE: Int32 to test for #49 |
140 | 156 |
|
141 | | - function kernel(out) |
142 | | - wid, lane = fldmod1(unsafe_load(out), Int32(32)) |
143 | | - unsafe_store!(out, wid) |
144 | | - return |
| 157 | + mod = @eval module $(gensym()) |
| 158 | + function kernel(out) |
| 159 | + wid, lane = fldmod1(unsafe_load(out), Int32(32)) |
| 160 | + unsafe_store!(out, wid) |
| 161 | + return |
| 162 | + end |
145 | 163 | end |
146 | 164 |
|
147 | 165 | @test @filecheck begin |
| 166 | + check"CHECK-LABEL: {{.*kernel.*}}:" |
148 | 167 | check"CHECK-NOT: jl_throw" |
149 | 168 | check"CHECK-NOT: jl_invoke" |
150 | | - GCN.code_native(kernel, Tuple{Ptr{Int32}}) |
| 169 | + GCN.code_native(mod.kernel, Tuple{Ptr{Int32}}) |
151 | 170 | end |
152 | 171 | end |
153 | 172 |
|
154 | 173 | @testset "LLVM intrinsics" begin |
155 | 174 | # issue #13 (a): cannot select trunc |
156 | | - function kernel(x) |
157 | | - unsafe_trunc(Int, x) |
158 | | - return |
| 175 | + mod = @eval module $(gensym()) |
| 176 | + function kernel(x) |
| 177 | + unsafe_trunc(Int, x) |
| 178 | + return |
| 179 | + end |
159 | 180 | end |
160 | | - GCN.code_native(devnull, kernel, Tuple{Float64}) |
| 181 | + GCN.code_native(devnull, mod.kernel, Tuple{Float64}) |
161 | 182 | @test "We did not crash!" != "" |
162 | 183 | end |
163 | 184 |
|
164 | 185 | # FIXME: _ZNK4llvm14TargetLowering20scalarizeVectorStoreEPNS_11StoreSDNodeERNS_12SelectionDAGE |
165 | 186 | false && @testset "exception arguments" begin |
166 | | - function kernel(a) |
167 | | - unsafe_store!(a, trunc(Int, unsafe_load(a))) |
168 | | - return |
| 187 | + mod = @eval module $(gensym()) |
| 188 | + function kernel(a) |
| 189 | + unsafe_store!(a, trunc(Int, unsafe_load(a))) |
| 190 | + return |
| 191 | + end |
169 | 192 | end |
170 | 193 |
|
171 | | - GCN.code_native(devnull, kernel, Tuple{Ptr{Float64}}) |
| 194 | + GCN.code_native(devnull, mod.kernel, Tuple{Ptr{Float64}}) |
172 | 195 | end |
173 | 196 |
|
174 | 197 | # FIXME: in function julia_inner_18528 void (%jl_value_t addrspace(10)*): invalid addrspacecast |
175 | 198 | false && @testset "GC and TLS lowering" begin |
176 | 199 | mod = @eval module $(gensym()) |
| 200 | + import ..sink_gcn |
177 | 201 | mutable struct PleaseAllocate |
178 | 202 | y::Csize_t |
179 | 203 | end |
180 | 204 |
|
181 | 205 | # common pattern in Julia 0.7: outlined throw to avoid a GC frame in the calling code |
182 | 206 | @noinline function inner(x) |
183 | | - sink(x.y) |
| 207 | + sink_gcn(x.y) |
184 | 208 | nothing |
185 | 209 | end |
186 | 210 |
|
@@ -219,21 +243,24 @@ false && @testset "GC and TLS lowering" begin |
219 | 243 | end |
220 | 244 |
|
221 | 245 | @testset "float boxes" begin |
222 | | - function kernel(a,b) |
223 | | - c = Int32(a) |
224 | | - # the conversion to Int32 may fail, in which case the input Float32 is boxed in order to |
225 | | - # pass it to the @nospecialize exception constructor. we should really avoid that (eg. |
226 | | - # by avoiding @nospecialize, or optimize the unused arguments away), but for now the box |
227 | | - # should just work. |
228 | | - unsafe_store!(b, c) |
229 | | - return |
| 246 | + mod = @eval module $(gensym()) |
| 247 | + function kernel(a,b) |
| 248 | + c = Int32(a) |
| 249 | + # the conversion to Int32 may fail, in which case the input Float32 is boxed in order to |
| 250 | + # pass it to the @nospecialize exception constructor. we should really avoid that (eg. |
| 251 | + # by avoiding @nospecialize, or optimize the unused arguments away), but for now the box |
| 252 | + # should just work. |
| 253 | + unsafe_store!(b, c) |
| 254 | + return |
| 255 | + end |
230 | 256 | end |
231 | 257 |
|
232 | 258 | @test @filecheck begin |
| 259 | + check"CHECK-LABEL: define void @{{.*kernel.*}}" |
233 | 260 | check"CHECK: jl_box_float32" |
234 | | - GCN.code_llvm(kernel, Tuple{Float32,Ptr{Float32}}) |
| 261 | + GCN.code_llvm(mod.kernel, Tuple{Float32,Ptr{Float32}}) |
235 | 262 | end |
236 | | - GCN.code_native(devnull, kernel, Tuple{Float32,Ptr{Float32}}) |
| 263 | + GCN.code_native(devnull, mod.kernel, Tuple{Float32,Ptr{Float32}}) |
237 | 264 | end |
238 | 265 |
|
239 | 266 | end |
|
0 commit comments