[pocl] Drop dead deferred-codegen bodies before SPIR-V translation - #736
Draft
vchuravy wants to merge 1 commit into
Draft
[pocl] Drop dead deferred-codegen bodies before SPIR-V translation#736vchuravy wants to merge 1 commit into
vchuravy wants to merge 1 commit into
Conversation
Deferred-codegen entrypoints -- notably the wrappers Enzyme generates -- are
held externally live across GPUCompiler's `InternalizePass` so that linking can
resolve them. Once linked and `alwaysinline`d they are dead, but external
linkage keeps `GlobalDCEPass` from dropping them, so the SPIR-V backend still
has to translate a function it cannot express: they take first-class aggregates
containing `addrspace(1)` pointers, and extracting one back out miscompiles.
The backend types the struct member as pointer-to-uchar but the extract result
as pointer-to-double, so `spirv-val` rejects the module:
error: Result type (OpTypePointer) does not match the type that results
from indexing into the composite (OpTypePointer).
%105 = OpCompositeExtract %_ptr_CrossWorkgroup_double %91 0
Reproduces without Enzyme in eight lines of IR, so the real fix belongs
upstream. Until then, empty the bodies of unreferenced non-kernel definitions in
`finish_ir!` so only declarations reach the backend. We empty rather than erase
so the `finish_ir!` loop over the remaining deferred jobs can still look them up
by name.
With this plus EnzymeAD/Enzyme.jl#3309, forward-mode Enzyme over a POCL kernel
compiles, runs and produces correct derivatives.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Benchmark ResultsShow table
Benchmark PlotsA plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #736 +/- ##
==========================================
+ Coverage 64.77% 64.98% +0.20%
==========================================
Files 24 24
Lines 2024 2036 +12
==========================================
+ Hits 1311 1323 +12
Misses 713 713 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Companion to EnzymeAD/Enzyme.jl#3405. Needed to make Enzyme work over the POCL backend (x-ref #583, EnzymeAD/Enzyme.jl#3309). Standalone — does not depend on #583.
Problem
Deferred-codegen entrypoints — notably the wrappers Enzyme generates — are held externally live across GPUCompiler's
InternalizePassso linking can resolve them. Once linked andalwaysinlined they are dead, but external linkage keepsGlobalDCEPassfrom dropping them, so the SPIR-V backend still has to translate a function it cannot express.These wrappers take first-class aggregates containing
addrspace(1)pointers. Extracting one back out miscompiles — the backend types the struct member as pointer-to-uchar but the extract result as pointer-to-double:This reproduces with no Enzyme involved:
so the real fix belongs upstream in the LLVM SPIR-V backend. Setting
spir_funcon the wrapper is not sufficient — I checked.This change
Empty the bodies of unreferenced non-kernel definitions in
finish_ir!, so only declarations reach the backend.finish_ir!is the right hook because it runs afterAlwaysInlinerPass(which is what makes these functions dead) and after thecleanupGlobalDCEPassthat would otherwise have handled them. We empty rather than erase so thefinish_ir!loop over the remaining deferred jobs can still look them up by name.Guarded on
job.config.kernelso it runs once for the entry job, not again for each deferred job.Result
With this plus EnzymeAD/Enzyme.jl#3405, forward-mode Enzyme over a POCL kernel compiles, runs on device and produces correct derivatives:
Reverse mode remains blocked on a separate LLVM SPIR-V backend segfault in
SPIRVInstructionSelector::selectExtractVal; see the Enzyme PR for the minimal reproducer.🤖 Generated with Claude Code