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:

committed by
Marge Bot

parent
04976beac7
commit
7dc297cc14
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user