numba_vulkan.structurize#
Restructure control flow before SPIR-V code generation.
SPIR-V requires structured control flow: each conditional branch declares a merge block, selections must nest properly, and a block inside a selection may only leave it through that selection’s merge block. Ordinary Python breaks this shape in two ways.
Early exits. In
if a: return x
if b: return y
return z
all three returns jump to the same continuation from different nesting depths, so several selections share one merge block.
Short-circuit conditions. In
if a or b: X
else: Y
the block X is entered from the test of a and from the test of b,
which is a join that is not the merge block of any selection.
LLVM’s SPIR-V structurizer is meant to repair such graphs, but in LLVM 22 it emits invalid modules for many of them. structurize therefore brings the graph into properly nested form itself, in three steps:
_unify_loop_exits makes every loop leave through its latch only;
_resolve_joins deals with every block that is entered from several places without being a merge block: a small one is copied once per entry, a large one is guarded by a flag, so that only proper merge blocks have more than one predecessor;
_split_merges gives each selection that shares its merge block with an enclosing one a fresh merge block that forwards to the shared one.
Loops. A return or break inside a loop leaves it from a nested
position. _unify_loop_exits records the wanted target in a flag, jumps to
the loop’s latch instead and dispatches on the flag after the loop, which
turns the loop body into an acyclic region with early exits.
The transformation works on textual LLVM IR, because it has to run after all LLVM passes and llvmlite offers no API for editing a module.
Functions#
|
Bring the control flow of every function into properly nested form. |
Module Contents#
- numba_vulkan.structurize.structurize(text)#
Bring the control flow of every function into properly nested form.