Repository navigation
Conversation
This was referenced Oct 20, 2026
maleadt
marked this pull request as draft
October 20, 2026 19:29
Member
Author
|
FWIW, the motivation here is to allow LLVM to const-prop things like |
Expose the pin in the root environment for Julia versions without workspaces and read URL sources explicitly in the Julia 1.10 CI setup. Keep SIMD test dependencies sorted and bounded.
Track the resolver fix for linkonce exports and the public bitcode metadata snapshot accessor added while migrating AMDGPU.
Use the infrastructure revision tested with typed-pointer ROCm imports, keeping both backend migrations on the same dependency revision.
GPUCompiler's lower_intrinsics! hook now only takes the job and module, and device libraries are imported before optimization as well as afterwards. The runtime is warmed through load_runtime again, as selected_device_libraries and load_device_library are no longer public.
`fill` resolved to CUDACore's array constructor in the generated function, so every `@fastmath` math call failed to compile. The wrapper's llvmcall entry also needs to be `alwaysinline`: Julia does not mark full-module llvmcall functions as such, so the call stayed out of line.
They contain inline PTX, so compiling them for the host (e.g. during ahead-of-time compilation) fails. Like other intrinsics, define them with `@device_functions`; the device library still finds them through the method table.
LLVM costs math intrinsics that are lowered to calls as a single instruction, so loops calling them are unrolled before the libdevice implementation is substituted, and that implementation is not optimized along with the kernel anymore. For `sin`, `cos`, `tan` and `sincos` this leaves the slow-path reduction's array in local memory, and `atan` (two arguments), `pow` and the Float64 trigonometric functions run slower in loops. Keep calling libdevice directly for those, compute the affected half-precision functions in Float32 as before, and keep using Julia's faster `exp_fast` and `exp10_fast` for Float64. The late lowering still supports all of these intrinsics; test that every scalar intrinsic lowers to what the corresponding function computes.
The added PTX ISA check made the method too large for Julia's inliner, leaving an out-of-line call that halves the throughput of `@fastmath tanh` on Float16.
maleadt
force-pushed
the
tb/llvm-math-intrinsics
branch
from
October 21, 2026 11:34
58281cb to
8ba4839
Compare
Pin GPUCompiler to the tb/device-libraries branch rather than a commit, so the source follows JuliaGPU/GPUCompiler.jl#1044 as it is rebased.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3433 +/- ##
===========================================
- Coverage 87.46% 39.40% -48.07%
===========================================
Files 191 193 +2
Lines 19646 19157 -489
===========================================
- Hits 17184 7548 -9636
- Misses 2462 11609 +9147 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Math functions on vectors fail to compile today (JuliaGPU/GPUCompiler.jl#679), because NVPTX can't select LLVM's math intrinsics, and our overlays only cover scalar Julia calls. This PR lets those intrinsics survive optimization, and lowers them afterwards with GPUCompiler's new
lower_intrinsics!hook (JuliaGPU/GPUCompiler.jl#1044). The hook scalarizes vector calls and turns each intrinsic into a call to libdevice, or, for Float16 and BFloat16, to a Julia library that ports NVIDIA's half-precision routines. The resulting references are resolved like any other device-library function. Rawllvmcalls and SIMD.jl code get the same treatment.Libraries are now declared through
device_libraries(job): the CUDA runtime, the half-precision math library, and libdevice. Libdevice is linked before optimization, as before. The half-precision library is linked late, because the references to it only appear during lowering.Overlays kept as a workaround
LLVM's cost model treats intrinsics as cheap, even when the target will lower them to library calls. Loops over math intrinsics therefore get unrolled before they are lowered. For some functions the lowered code is also worse: the slow path of
sin/coskeeps its array in local memory. To avoid regressions, the following functions keep calling libdevice directly, each marked# COST MODELin the code:sinandcosfor Float32 and Float64, including the fast variants;tan,sincos,atan2andpowfor Float32;maincomputes in Float32.Without them, for example, a Float32 loop summing
singrows from 123 to 566 SASS instructions and spills to local memory, andsinof large arguments is 65% slower. The late lowering still supports all of these operations, and a new test compiles every operation through the raw intrinsic and compares the result bit for bit with the device function. The overlays can be removed once LLVM's cost model accounts for these calls.All other math functions go through intrinsics. They are neutral or faster: Float32
logloops are about 10% faster; Float16expandlogare about 30% faster, and Float16powis 3.5× faster.Other fixes
@fastmathintrinsic wrapper used the full-module form ofllvmcall. Julia doesn't mark thatalwaysinline, so every@fastmathcall stayed out of line. The IR now sets the attribute. It also calledCUDACore.fillinstead ofBase.fill.FastMath.tanh_fast(::Float16)is inlined again: the added PTX ISA check made it too large for Julia's inliner, which made@fastmath tanh1.86× slower in loops.@fastmath exp/exp10on Float64 use Julia's implementation again, which is faster than__nv_exp.Validation
On an RTX 5080, Julia 1.12 and 1.13, compared to
main:coregroup passes, as do thellvm_mathtests (226 on 1.13).expon Float16 is shorter (33 → 22 instructions, no call);powon Float64 grows from 235 to 239 instructions;mainfails.cufunctiontakes about 200 ns,@cudaabout 1.7 µs, with the same allocations.@cudais 4% slower on 1.12 (1.60 vs 1.53 s) and 8% slower on 1.13 (1.09 vs 1.01 s).Depends on JuliaGPU/GPUCompiler.jl#1044. The
[sources]pins inProject.toml,CUDACore/Project.tomlandtest/Project.tomlstill point at an old revision of that PR and need to be updated, then replaced by a compat bound once it is released.