Skip to content

POCL: fuse muladd into fma on devices with a fused multiply-add - #892

Draft
vchuravy wants to merge 1 commit into
mainfrom
vc/pocl-fma
Draft

vchuravy wants to merge 1 commit into
mainfrom
vc/pocl-fma

Conversation

@vchuravy

Copy link
Copy Markdown
Member

Fixes the PoCL half of #865 with today's pocl_standalone_jll. Draft until JuliaGPU/GPUCompiler.jl#1010 is released; this PR should then raise the GPUCompiler compat to that release.

SPIR-V can't carry the contract flag without SPV_KHR_float_controls2, so muladd reaches PoCL as a separate multiply and add, which it never fuses. JuliaGPU/GPUCompiler.jl#1010 can instead fuse what may be contracted into OpenCL's fma before emitting SPIR-V (SPIRVCompilerTarget(; fma = true)). Since OpenCL's fma must be correctly rounded, that is only worth it on a device with a fused multiply-add. This PR:

  • adds a single_fp_config device property to nanoOpenCL (CL_DEVICE_SINGLE_FP_CONFIG);
  • defaults fma in compiler_config to whether that config has CL_FP_FMA. PoCL sets the bit on x86 only when the CPU has an FMA. The double-precision config isn't used, because OpenCL mandates CL_FP_FMA there, and PoCL's generic fallback always sets it;
  • accepts fma as a keyword of compiler_config and @opencl, to override it.

Results

On an AMD Ryzen 9 5950X (AVX2 + FMA), y[i] = muladd(a[i], x[i], y[i]) in a @kernel compiles to a vectorized vfmadd231ps, and the result matches fma.(a, x, y) bit for bit. Without this PR it compiles to vmulps + vaddps. Plain a * x + y stays unfused, and @simd reductions still vectorize (see the GPUCompiler PR for details).

Testing

  • New testset "POCL fused multiply-add" checks:
    • that the default follows CL_FP_FMA;
    • that a muladd kernel is fused exactly when it does;
    • that fma = false turns fusion off.
  • The full test suite passes locally on PoCL with GPUCompiler#1010 dev'ed.

Relation to #876: this route works with today's PoCL (LLVM 22). #876 (SPV_KHR_float_controls2) needs PoCL with LLVM 23. Once both are in, a device that accepts the extension could leave the contraction to the driver instead.

🤖 Generated with Claude Code

SPIR-V can't carry the `contract` flag without SPV_KHR_float_controls2,
so `muladd` reaches PoCL as a separate multiply and add, which it never
fuses (#865). GPUCompiler can fuse what may be contracted into OpenCL's
`fma` before emitting SPIR-V; enable that (`SPIRVCompilerTarget(; fma)`)
when the device reports `CL_FP_FMA` in its single-precision capabilities,
which PoCL does on x86 only for CPUs with an FMA (OpenCL mandates it for
double precision, so that one doesn't tell). The `fma` keyword of
`compiler_config` and `@opencl` overrides it.

With it, `y[i] = muladd(a[i], x[i], y[i])` compiles to a vectorized
`vfmadd231ps` and matches `fma.(a, x, y)` bit for bit; `@simd`
reductions still vectorize. Needs the GPUCompiler release with the
`fma` field.

Assisted-by: Claude Code (Opus 5.5)
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 13.27%. Comparing base (b8b5e1a) to head (6149f32).

Files with missing lines Patch % Lines
src/pocl/nanoOpenCL.jl 0.00% 4 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (b8b5e1a) and HEAD (6149f32). Click for more details.

HEAD has 60 uploads less than BASE
Flag BASE (b8b5e1a) HEAD (6149f32)
65 5
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #892       +/-   ##
===========================================
- Coverage   82.59%   13.27%   -69.33%     
===========================================
  Files          28       26        -2     
  Lines        2454     2342      -112     
===========================================
- Hits         2027      311     -1716     
- Misses        427     2031     +1604     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant