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:
Alyssa Rosenzweig
2023-05-11 13:11:57 -04:00
committed by Marge Bot
parent 04976beac7
commit 7dc297cc14

View File

@@ -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)
{