Make DCE mandatory and run it much earlier (even per-crate, shrinking .rlib
s).
#350
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.
The DCE ("dead code elimination", i.e. removing definitions not reachable from e.g. shader entry-points) pass was, for one reason or another, toggleable, and supposedly shaders should've still compiled without it.
However, the way this was achieved was by ignoring anything that DCE would've removed, in the "zombie" (deferred error) reporting pass, and removing the subset that also had "zombie" decorations.
Additionally, I believe that the concept of "optional DCE" has been outdated for a while, because of:
Type
,Const
) / module-scoped (GlobalVar
,Func
) handlesFooDef
without finding aFoo
handle elsewherespirt::Module
exports (linker ones + shader entry-points)(the DCE pass has a similar definition of "roots", even if
rspirv
makes it more ad-hoc)all unreachable ones are lost (tho returning some kind of
Map<Id, _>
might be nice)IntN
/FloatN
) on SPIR-T. #332RUSTGPU_CODEGEN_ARGS=--no-early-report-zombies
(reporting errors at the very end, on SPIR-T)has been around for a while, and it's only not the default due to the risk of random bugs
So this PR removes the
--no-dce
flag, applies DCE in a few more places, and gets to simplify the early "zombie" reporting pass (as it no longer has any reason to mutate the SPIR-V module, itself).A niche (but welcome) benefit from running DCE really early, is that
--dump-post-merge
is now actually able to dump.spirt
/.spirt.html
, as well (instead of only.spv
), since the pre-DCE SPIR-V module is really malformed (instructions referring to IDs never defined anywhere) and DCE is needed to clean that up.However, the most exciting new use of DCE being added (in the last commit), is in the per-crate "optimize" stage (just before saving SPIR-V modules on disk for e.g.
.rlib
s and the final linking step).We've been neglecting it because we're effectively stuck doing something like LTO, but there's no reason to not optimize CGUs (or, well, crates, because we run with 1 CGU for now - another thing I want to fix), and DCE is a pretty safe way to start (but we could also consider e.g. the mem2reg->inline->mem2reg sequence).
And it turns out we can save over 1 MiB of SPIR-V (that shader linking will never see again after this PR), from the minimal dependency set (
core
,compiler-builtins
,glam
,libm
,num-traits
,spirv-std
):(click for exact numbers and methodology)
Before
After
Debug (via
cargo compiletest
)(
core
)(
spirv-std
)Release (via
example-runner-wgpu
)(
core
)(
spirv-std
)(the overall impact of such a change might look even better, if/once we can find a way to remove e.g. the
OpSource
embedded source code,which amounts to e.g. almost 4 MiB of
core
's 8-9 MiB - but that's more future work, alongside with increasing CGU count etc.)