Skip to content

Commit a95fd25

Browse files
authored
Metal: Remove ability to generate machine code. (#548)
1 parent fd8f36d commit a95fd25

File tree

5 files changed

+110
-171
lines changed

5 files changed

+110
-171
lines changed

.github/workflows/ci.yml

+61-61
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,36 @@ jobs:
1818
strategy:
1919
fail-fast: false
2020
matrix:
21-
version: ['1.8', '1.9', '1.10.0-beta3', 'nightly']
21+
version: ['1.8', '1.9', '1.10'] # 'nightly'
2222
os: [ubuntu-latest, macOS-latest, windows-latest]
2323
arch: [x64]
2424
llvm_args: ['']
2525
include:
2626
# starting with Julia 1.10, we can enable opaque pointers
27-
- version: '1.10.0-beta3'
27+
- version: '1.10'
2828
os: 'ubuntu-latest'
2929
arch: 'x64'
3030
llvm_args: '--opaque-pointers'
31-
- version: '1.10.0-beta3'
31+
- version: '1.10'
3232
os: 'macOS-latest'
3333
arch: 'x64'
3434
llvm_args: '--opaque-pointers'
35-
- version: '1.10.0-beta3'
36-
os: 'windows-latest'
37-
arch: 'x64'
38-
llvm_args: '--opaque-pointers'
39-
- version: 'nightly'
40-
os: 'ubuntu-latest'
41-
arch: 'x64'
42-
llvm_args: '--opaque-pointers'
43-
- version: 'nightly'
44-
os: 'macOS-latest'
45-
arch: 'x64'
46-
llvm_args: '--opaque-pointers'
47-
- version: 'nightly'
35+
- version: '1.10'
4836
os: 'windows-latest'
4937
arch: 'x64'
5038
llvm_args: '--opaque-pointers'
39+
#- version: 'nightly'
40+
# os: 'ubuntu-latest'
41+
# arch: 'x64'
42+
# llvm_args: '--opaque-pointers'
43+
#- version: 'nightly'
44+
# os: 'macOS-latest'
45+
# arch: 'x64'
46+
# llvm_args: '--opaque-pointers'
47+
#- version: 'nightly'
48+
# os: 'windows-latest'
49+
# arch: 'x64'
50+
# llvm_args: '--opaque-pointers'
5151
steps:
5252
- uses: actions/checkout@v4
5353

@@ -82,48 +82,48 @@ jobs:
8282
file: lcov.info
8383

8484
# fetching builds from Buildkite with assertions enabled
85-
assert_test:
86-
name: Julia-master ${{ matrix.build }} ${{ matrix.llvm_args }}
87-
runs-on: ${{ matrix.os }}
88-
strategy:
89-
fail-fast: false
90-
matrix:
91-
build: ['x86_64-linux-gnuassert']
92-
os: ['ubuntu-latest']
93-
arch: ['x64']
94-
llvm_args: ['', '--opaque-pointers']
95-
steps:
96-
- uses: actions/checkout@v4
97-
98-
- name: Download Julia
99-
env:
100-
BUILDKITE_TOKEN: ${{ secrets.BUILDKITE_TOKEN }}
101-
run: |
102-
./.github/download_build.sh build_${{ matrix.build }} julia.tar.gz
103-
tar -xf julia.tar.gz -C ../
104-
rm julia.tar.gz
105-
echo $PWD/../julia-*/bin >> $GITHUB_PATH
106-
107-
# set-up packages
108-
- uses: actions/cache@v4
109-
env:
110-
cache-name: cache-artifacts
111-
with:
112-
path: ~/.julia/artifacts
113-
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
114-
restore-keys: |
115-
${{ runner.os }}-test-${{ env.cache-name }}-
116-
${{ runner.os }}-test-
117-
${{ runner.os }}-
118-
- uses: julia-actions/julia-buildpkg@v1
119-
120-
- name: Run tests
121-
uses: julia-actions/julia-runtest@v1
122-
env:
123-
JULIA_LLVM_ARGS: ${{ matrix.llvm_args }}
124-
125-
# post-process
126-
- uses: julia-actions/julia-processcoverage@v1
127-
- uses: codecov/codecov-action@v4
128-
with:
129-
file: lcov.info
85+
#assert_test:
86+
# name: Julia-master ${{ matrix.build }} ${{ matrix.llvm_args }}
87+
# runs-on: ${{ matrix.os }}
88+
# strategy:
89+
# fail-fast: false
90+
# matrix:
91+
# build: ['x86_64-linux-gnuassert']
92+
# os: ['ubuntu-latest']
93+
# arch: ['x64']
94+
# llvm_args: ['', '--opaque-pointers']
95+
# steps:
96+
# - uses: actions/checkout@v4
97+
#
98+
# - name: Download Julia
99+
# env:
100+
# BUILDKITE_TOKEN: ${{ secrets.BUILDKITE_TOKEN }}
101+
# run: |
102+
# ./.github/download_build.sh build_${{ matrix.build }} julia.tar.gz
103+
# tar -xf julia.tar.gz -C ../
104+
# rm julia.tar.gz
105+
# echo $PWD/../julia-*/bin >> $GITHUB_PATH
106+
#
107+
# # set-up packages
108+
# - uses: actions/cache@v4
109+
# env:
110+
# cache-name: cache-artifacts
111+
# with:
112+
# path: ~/.julia/artifacts
113+
# key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
114+
# restore-keys: |
115+
# ${{ runner.os }}-test-${{ env.cache-name }}-
116+
# ${{ runner.os }}-test-
117+
# ${{ runner.os }}-
118+
# - uses: julia-actions/julia-buildpkg@v1
119+
#
120+
# - name: Run tests
121+
# uses: julia-actions/julia-runtest@v1
122+
# env:
123+
# JULIA_LLVM_ARGS: ${{ matrix.llvm_args }}
124+
#
125+
# # post-process
126+
# - uses: julia-actions/julia-processcoverage@v1
127+
# - uses: codecov/codecov-action@v4
128+
# with:
129+
# file: lcov.info

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "GPUCompiler"
22
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
33
authors = ["Tim Besard <[email protected]>"]
4-
version = "0.25.0"
4+
version = "0.26.0"
55

66
[deps]
77
ExprTools = "e2ba6199-217a-4e67-a87a-7c52f15ade04"

src/metal.jl

+47-79
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# implementation of the GPUCompiler interfaces for generating Metal code
22

3-
const Metal_LLVM_Tools_jll = LazyModule("Metal_LLVM_Tools_jll", UUID("0418c028-ff8c-56b8-a53e-0f9676ed36fc"))
4-
53
## target
64

75
export MetalCompilerTarget
@@ -47,21 +45,11 @@ runtime_slug(job::CompilerJob{MetalCompilerTarget}) = "metal-macos$(job.config.t
4745
isintrinsic(@nospecialize(job::CompilerJob{MetalCompilerTarget}), fn::String) =
4846
return startswith(fn, "air.")
4947

50-
const LLVMMETALFUNCCallConv = LLVM.API.LLVMCallConv(102)
51-
const LLVMMETALKERNELCallConv = LLVM.API.LLVMCallConv(103)
52-
5348
function finish_module!(@nospecialize(job::CompilerJob{MetalCompilerTarget}), mod::LLVM.Module, entry::LLVM.Function)
5449
entry_fn = LLVM.name(entry)
5550

5651
# update calling conventions
57-
for f in functions(mod)
58-
#callconv!(f, LLVMMETALFUNCCallConv)
59-
# XXX: this makes InstCombine erase kernel->func calls.
60-
# do we even need this? if we do, do so in metallib-instead.
61-
end
6252
if job.config.kernel
63-
callconv!(entry, LLVMMETALKERNELCallConv)
64-
6553
entry = pass_by_reference!(job, mod, entry)
6654

6755
add_input_arguments!(job, mod, entry)
@@ -110,6 +98,49 @@ function validate_ir(job::CompilerJob{MetalCompilerTarget}, mod::LLVM.Module)
11098
check_ir_values(mod, LLVM.DoubleType())
11199
end
112100

101+
# hide `noreturn` function attributes, which cause issues with the back-end compiler,
102+
# probably because of thread-divergent control flow as we've encountered with CUDA.
103+
# note that it isn't enough to remove the function attribute, because the Metal LLVM
104+
# compiler re-optimizes and will rediscover the property. to avoid this, we inline
105+
# all functions that are marked noreturn, i.e., until LLVM cannot rediscover it.
106+
function hide_noreturn!(mod::LLVM.Module)
107+
noreturn_attr = EnumAttribute("noreturn", 0)
108+
noinline_attr = EnumAttribute("noinline", 0)
109+
alwaysinline_attr = EnumAttribute("alwaysinline", 0)
110+
111+
any_noreturn = false
112+
for f in functions(mod)
113+
attrs = function_attributes(f)
114+
if noreturn_attr in collect(attrs)
115+
delete!(attrs, noreturn_attr)
116+
delete!(attrs, noinline_attr)
117+
push!(attrs, alwaysinline_attr)
118+
any_noreturn = true
119+
end
120+
end
121+
any_noreturn || return false
122+
123+
if use_newpm
124+
@dispose pb=PassBuilder() mpm=NewPMModulePassManager(pb) begin
125+
add!(mpm, AlwaysInlinerPass())
126+
add!(mpm, NewPMFunctionPassManager) do fpm
127+
add!(fpm, SimplifyCFGPass())
128+
add!(fpm, InstCombinePass())
129+
end
130+
run!(mpm, mod)
131+
end
132+
else
133+
@dispose pm=ModulePassManager() begin
134+
always_inliner!(pm)
135+
cfgsimplification!(pm)
136+
instruction_combining!(pm)
137+
run!(pm, mod)
138+
end
139+
end
140+
141+
return true
142+
end
143+
113144
function finish_ir!(@nospecialize(job::CompilerJob{MetalCompilerTarget}), mod::LLVM.Module,
114145
entry::LLVM.Function)
115146
entry_fn = LLVM.name(entry)
@@ -121,6 +152,8 @@ function finish_ir!(@nospecialize(job::CompilerJob{MetalCompilerTarget}), mod::L
121152
add_argument_metadata!(job, mod, entry)
122153

123154
add_module_metadata!(job, mod)
155+
156+
hide_noreturn!(mod)
124157
end
125158

126159
# lower LLVM intrinsics that AIR doesn't support
@@ -154,73 +187,8 @@ end
154187

155188
@unlocked function mcgen(job::CompilerJob{MetalCompilerTarget}, mod::LLVM.Module,
156189
format=LLVM.API.LLVMObjectFile)
157-
strip_debuginfo!(mod) # XXX: is this needed?
158-
159-
# hide `noreturn` function attributes, which cause issues with the back-end compiler,
160-
# probably because of thread-divergent control flow as we've encountered with CUDA.
161-
# note that it isn't enough to remove the function attribute, because the Metal LLVM
162-
# compiler re-optimizes and will rediscover the property. to avoid this, we inline
163-
# all functions that are marked noreturn, i.e., until LLVM cannot rediscover it.
164-
let
165-
noreturn_attr = EnumAttribute("noreturn", 0)
166-
noinline_attr = EnumAttribute("noinline", 0)
167-
alwaysinline_attr = EnumAttribute("alwaysinline", 0)
168-
169-
any_noreturn = false
170-
for f in functions(mod)
171-
attrs = function_attributes(f)
172-
if noreturn_attr in collect(attrs)
173-
delete!(attrs, noreturn_attr)
174-
delete!(attrs, noinline_attr)
175-
push!(attrs, alwaysinline_attr)
176-
any_noreturn = true
177-
end
178-
end
179-
180-
if any_noreturn
181-
if use_newpm
182-
@dispose pb=PassBuilder() mpm=NewPMModulePassManager(pb) begin
183-
add!(mpm, AlwaysInlinerPass())
184-
add!(mpm, NewPMFunctionPassManager) do fpm
185-
add!(fpm, SimplifyCFGPass())
186-
add!(fpm, InstCombinePass())
187-
end
188-
run!(mpm, mod)
189-
end
190-
else
191-
@dispose pm=ModulePassManager() begin
192-
always_inliner!(pm)
193-
cfgsimplification!(pm)
194-
instruction_combining!(pm)
195-
run!(pm, mod)
196-
end
197-
end
198-
end
199-
end
200-
201-
# translate to metallib
202-
input = tempname(cleanup=false) * ".bc"
203-
translated = tempname(cleanup=false) * ".metallib"
204-
write(input, mod)
205-
let cmd = `$(Metal_LLVM_Tools_jll.metallib_as()) -o $translated $input`
206-
proc = run(ignorestatus(cmd))
207-
if !success(proc)
208-
error("""Failed to translate LLVM code to MetalLib.
209-
If you think this is a bug, please file an issue and attach $(input).""")
210-
end
211-
end
212-
213-
output = if format == LLVM.API.LLVMObjectFile
214-
read(translated)
215-
else
216-
# disassemble
217-
read(`$(Metal_LLVM_Tools_jll.metallib_dis()) -o - $translated`, String)
218-
end
219-
220-
rm(input)
221-
rm(translated)
222-
223-
return output
190+
# our LLVM version does not support emitting Metal libraries
191+
return nothing
224192
end
225193

226194

test/Project.toml

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
33
Cthulhu = "f68482b8-f384-11e8-15f7-abe071a5a75f"
44
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
55
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
6-
Metal_LLVM_Tools_jll = "0418c028-ff8c-56b8-a53e-0f9676ed36fc"
76
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
87
ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823"
98
SPIRV_LLVM_Translator_unified_jll = "85f0d8ed-5b39-5caa-b1ae-7472de402361"

test/metal_tests.jl

+1-29
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
@testitem "Metal" setup=[Metal, Helpers] begin
22

3-
using Metal_LLVM_Tools_jll, LLVM
3+
using LLVM
44

55
############################################################################################
66

77
@testset "IR" begin
88

99
@testset "kernel functions" begin
10-
@testset "calling convention" begin
11-
kernel() = return
12-
13-
ir = sprint(io->Metal.code_llvm(io, kernel, Tuple{}; dump_module=true))
14-
@test !occursin("cc103", ir)
15-
16-
ir = sprint(io->Metal.code_llvm(io, kernel, Tuple{};
17-
dump_module=true, kernel=true))
18-
@test occursin("cc103", ir)
19-
end
20-
2110
@testset "byref aggregates" begin
2211
kernel(x) = return
2312

@@ -94,21 +83,4 @@ end
9483

9584
end
9685

97-
############################################################################################
98-
99-
Sys.isapple() && @testset "asm" begin
100-
101-
@testset "smoke test" begin
102-
kernel() = return
103-
104-
asm = sprint(io->Metal.code_native(io, kernel, Tuple{};
105-
dump_module=true, kernel=true))
106-
@test occursin("[header]", asm)
107-
@test occursin("[program]", asm)
108-
@test occursin(r"name: \w*kernel\w*", asm)
109-
@test occursin(r"define void @\w*kernel\w*", asm)
110-
end
111-
112-
end
113-
11486
end

0 commit comments

Comments
 (0)