mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 05:00:09 +01:00
nir: Add nir_foreach_phi(_safe) macro
Serious preprocessor voodoo here. There are two tricks here.
1. Iterating only phis. We know that phis come only at the beginning of a block,
so all over the tree, we open-code iteration like:
nir_foreach_instr(instr, block) {
if (instr->type != phi)
break;
/* do stuff */
}
We can express this equivalently as
nir_foreach_instr(instr, block)
if (instr->type != phi)
break;
else {
/* do stuff */
}
So, we can define a macro
#define nir_foreach_phi(instr, block)
if (instr->type != phi)
break;
else
and then
nir_foreach_phi(..)
statement;
and
nir_foreach_phi(..) {
...
}
will expand to the right thing.
2. Automatically getting the phi as a phi. We want the instruction to go to some
hidden variable, and then automatically insert nir_phi_instr *phi =
nir_instr_as_phi(instr_internal); We can't do that directly, since we need to
express the assignment implicitly in the control flow for the above trick to
work. But we can do it indirectly with a loop initializer.
for (nir_phi_instr *phi = nir_instr_as_phi(instr_internal); ...)
That loop needs to break after exactly one iteration. We know that phi
will always be non-null on its first iteration, since the original
instruction is non-null, so we can use phi==NULL as a sentinel and express a
one-iteration loop as for (phi = nonnull; phi != NULL; phi = NULL).
Putting these together gives the macros implemented used.
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22967>
This commit is contained in:
parent
04976beac7
commit
7dc297cc14
1 changed files with 16 additions and 0 deletions
|
|
@ -2896,6 +2896,22 @@ nir_block_ends_in_break(nir_block *block)
|
|||
#define nir_foreach_instr_reverse_safe(instr, block) \
|
||||
foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
|
||||
|
||||
/* Phis come first in the block */
|
||||
#define nir_foreach_phi_internal(instr, phi) \
|
||||
if (instr->type != nir_instr_type_phi) \
|
||||
break; \
|
||||
else \
|
||||
for (nir_phi_instr *phi = nir_instr_as_phi(instr); phi != NULL; \
|
||||
phi = NULL)
|
||||
|
||||
#define nir_foreach_phi(instr, block) \
|
||||
nir_foreach_instr(nir_foreach_phi_##instr, block) \
|
||||
nir_foreach_phi_internal(nir_foreach_phi_##instr, instr)
|
||||
|
||||
#define nir_foreach_phi_safe(instr, block) \
|
||||
nir_foreach_instr_safe(nir_foreach_phi_safe_##instr, block) \
|
||||
nir_foreach_phi_internal(nir_foreach_phi_safe_##instr, instr)
|
||||
|
||||
static inline nir_phi_instr *
|
||||
nir_block_last_phi_instr(nir_block *block)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue