Skip to content

Commit 998feec

Browse files
authored
Use Enzyme's optimization and late lowering mechanisms (#63)
* Use Enzyme's optimization and late lowering mechanisms * BLAS calls work again * update README * add another test case * re-enable the `@test_skip` on remotely calling BLAS
1 parent f85891a commit 998feec

4 files changed

Lines changed: 359 additions & 37 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
# StaticCompiler
22

3-
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://tshort.github.io/StaticCompiler.jl/dev)
4-
[![Build Status](https://travis-ci.com/tshort/StaticCompiler.jl.svg?branch=master)](https://travis-ci.com/tshort/StaticCompiler.jl)
5-
[![Build Status](https://ci.appveyor.com/api/projects/status/github/tshort/StaticCompiler.jl?svg=true)](https://ci.appveyor.com/project/tshort/StaticCompiler-jl)
3+
[![CI](https://github.com/tshort/StaticCompiler.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/tshort/StaticCompiler.jl/actions/workflows/ci.yml)
64
[![Codecov](https://codecov.io/gh/tshort/StaticCompiler.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/tshort/StaticCompiler.jl)
7-
[![Coveralls](https://coveralls.io/repos/github/tshort/StaticCompiler.jl/badge.svg?branch=master)](https://coveralls.io/github/tshort/StaticCompiler.jl?branch=master)
85

9-
This is an experimental package to compile Julia code to standalone libraries. A system image is not needed. It is also meant for cross compilation, so Julia code can be compiled for other targets, including WebAssembly and embedded targets.
6+
This is an experimental package to compile Julia code to standalone libraries. A system image is not needed.
107

118
## Installation and Usage
129

@@ -41,6 +38,9 @@ julia> fib_compiled(10)
4138
55
4239
```
4340

41+
See the file `tests/runtests.jl` for some examples of functions that work with static compilation (and some that don't,
42+
marked with `@test_skip`)
43+
4444
## Approach
4545

4646
This package uses the [GPUCompiler package](https://github.com/JuliaGPU/GPUCompiler.jl) to generate code.

src/StaticCompiler.jl

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export native_code_llvm, native_code_typed, native_llvm_module, native_code_nati
1515
include("target.jl")
1616
include("pointer_patching.jl")
1717
include("code_loading.jl")
18+
include("optimize.jl")
19+
1820

1921
"""
2022
compile(f, types, path::String = tempname()) --> (compiled_f, path)
@@ -148,20 +150,27 @@ function generate_shlib(f, tt, path::String = tempname(), name = GPUCompiler.saf
148150
mkpath(path)
149151
obj_path = joinpath(path, "$filenamebase.o")
150152
lib_path = joinpath(path, "$filenamebase.$(Libdl.dlext)")
151-
153+
tm = GPUCompiler.llvm_machine(NativeCompilerTarget())
152154
job, kwargs = native_job(f, tt; name, kwargs...)
153155
#Get LLVM to generated a module of code for us. We don't want GPUCompiler's optimization passes.
154156
mod, meta = GPUCompiler.codegen(:llvm, job; strip=strip_llvm, only_entry=false, validate=false, optimize=false)
155-
#use Julia's optimization pass on the LLVM code, but leave intrinsics alone
156-
julia_opt_passes(mod, job; opt_level, lower_intrinsics=0)
157+
158+
# Use Enzyme's annotation and optimization pipeline
159+
annotate!(mod)
160+
optimize!(mod, tm)
161+
157162
# Scoop up all the pointers in the optimized module, and replace them with unitialized global variables.
158-
# table is a dictionary where the keys are julia objects that are needed by the function, and the values
163+
# `table` is a dictionary where the keys are julia objects that are needed by the function, and the values
159164
# of the dictionary are the names of their associated LLVM GlobalVariable names.
160165
table = relocation_table!(mod)
166+
161167
# Now that we've removed all the pointers from the code, we can (hopefully) safely lower all the instrinsics
162-
julia_opt_passes(mod, job; opt_level, lower_intrinsics=1)
168+
# (again, using Enzyme's pipeline)
169+
post_optimize!(mod, tm)
170+
163171
# Make sure we didn't make any glaring errors
164172
LLVM.verify(mod)
173+
165174
# Compile the LLVM module to native code and save it to disk
166175
obj, _ = GPUCompiler.emit_asm(job, mod; strip=strip_asm, validate=false, format=LLVM.API.LLVMObjectFile)
167176
open(obj_path, "w") do io
@@ -170,25 +179,6 @@ function generate_shlib(f, tt, path::String = tempname(), name = GPUCompiler.saf
170179
path, name, table
171180
end
172181

173-
function julia_opt_passes(mod, job; opt_level, lower_intrinsics)
174-
triple = GPUCompiler.llvm_triple(job.target)
175-
tm = GPUCompiler.llvm_machine(job.target)
176-
177-
lib_path = VERSION > v"1.8.0-DEV" ? "libjulia-codegen" : "libjulia"
178-
179-
dlopen(lib_path) do lib
180-
opt_func = dlsym(lib, "jl_add_optimization_passes")
181-
ModulePassManager() do pm
182-
add_library_info!(pm, triple)
183-
add_transform_info!(pm, tm)
184-
ccall(opt_func, Cvoid,
185-
(LLVM.API.LLVMPassManagerRef, Cint, Cint),
186-
pm, opt_level, lower_intrinsics)
187-
run!(pm, mod)
188-
end
189-
end
190-
end
191-
192182
"""
193183
```julia
194184
compile_executable(f, types::Tuple, path::String, name::String=repr(f); filename::String=name, kwargs...)

0 commit comments

Comments
 (0)