nir: Only convert SSA values to regs when needed
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Tue, 7 May 2019 08:49:42 +0000 (01:49 -0700)
committerCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Thu, 16 May 2019 19:23:47 +0000 (12:23 -0700)
If the SSA def produced by this instruction is only in the block in
which it is defined and is not used by ifs or phis, then we don't have
a reason to convert it to a register in
nir_lower_ssa_defs_to_regs_block().

The special case for derefs is covered by the general case, so can be
removed: at this point all derefs in the block are
materialized (i.e. the whole deref chain is in the block) and derefs
are not used in phis.

v2: Fix wrong check for if_uses.  If there's such an use, the def is
    not "local_to_block".  (Jason)

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compiler/nir/nir_from_ssa.c

index 99cfe75747763c119fd8443f7ab4a8e43e3fc732..92effe5610134d17c9bebeaa090bb9fe8b232e5a 100644 (file)
@@ -942,6 +942,23 @@ dest_replace_ssa_with_reg(nir_dest *dest, void *void_state)
    return true;
 }
 
+static bool
+ssa_def_is_local_to_block(nir_ssa_def *def, UNUSED void *state)
+{
+   nir_block *block = def->parent_instr->block;
+   nir_foreach_use(use_src, def) {
+      if (use_src->parent_instr->block != block ||
+          use_src->parent_instr->type == nir_instr_type_phi) {
+         return false;
+      }
+   }
+
+   if (!list_empty(&def->if_uses))
+      return false;
+
+   return true;
+}
+
 /** Lower all of the SSA defs in a block to registers
  *
  * This performs the very simple operation of blindly replacing all of the SSA
@@ -977,12 +994,11 @@ nir_lower_ssa_defs_to_regs_block(nir_block *block)
          mov->dest.dest = nir_dest_for_reg(reg);
          mov->dest.write_mask = (1 << reg->num_components) - 1;
          nir_instr_insert(nir_after_instr(&load->instr), &mov->instr);
-      } else if (instr->type == nir_instr_type_deref) {
-         /* Derefs should always be SSA values, don't rewrite them. */
-         nir_deref_instr *deref = nir_instr_as_deref(instr);
-         nir_foreach_use_safe(use, &deref->dest.ssa)
-            assert(use->parent_instr->block == block);
-         assert(list_empty(&deref->dest.ssa.if_uses));
+      } else if (nir_foreach_ssa_def(instr, ssa_def_is_local_to_block, NULL)) {
+         /* If the SSA def produced by this instruction is only in the block
+          * in which it is defined and is not used by ifs or phis, then we
+          * don't have a reason to convert it to a register.
+          */
       } else {
          nir_foreach_dest(instr, dest_replace_ssa_with_reg, &state);
       }