nir/vars_to_ssa: Add phi sources for unreachable predecessors
authorJason Ekstrand <jason.ekstrand@intel.com>
Mon, 11 Jan 2016 23:33:41 +0000 (15:33 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 11 Jan 2016 23:33:44 +0000 (15:33 -0800)
It is possible to end up with unreachable blocks if, for instance, you have
an "if (...) { break; } else { continue; } unreachable()".  In this case,
the unreachable block does not show up in the dominance tree so it never
gets visited.  Instead, we go and visit all of those in follow-on pass.

src/glsl/nir/nir_lower_vars_to_ssa.c

index 75d31ff60afb1e6d51f3fd152c1410b41dcebe87..a5f5ef2de3ceffdd89c8c171b8637523d4981cb0 100644 (file)
@@ -581,6 +581,33 @@ add_phi_sources(nir_block *block, nir_block *pred,
    }
 }
 
+static void
+add_undef_phi_sources(nir_block *block, nir_block *pred,
+                      struct lower_variables_state *state)
+{
+   nir_foreach_instr(block, instr) {
+      if (instr->type != nir_instr_type_phi)
+         break;
+
+      nir_phi_instr *phi = nir_instr_as_phi(instr);
+
+      nir_ssa_undef_instr *undef =
+         nir_ssa_undef_instr_create(state->shader,
+                                    phi->dest.ssa.num_components);
+      nir_instr_insert(nir_before_cf_list(&state->impl->body), &undef->instr);
+
+      nir_phi_src *src = ralloc(phi, nir_phi_src);
+      src->pred = pred;
+      src->src.parent_instr = &phi->instr;
+      src->src.is_ssa = true;
+      src->src.ssa = &undef->def;
+
+      list_addtail(&src->src.use_link, &undef->def.uses);
+
+      exec_list_push_tail(&phi->srcs, &src->node);
+   }
+}
+
 /* Performs variable renaming by doing a DFS of the dominance tree
  *
  * This algorithm is very similar to the one outlined in "Efficiently
@@ -774,6 +801,23 @@ rename_variables_block(nir_block *block, struct lower_variables_state *state)
    return true;
 }
 
+static bool
+add_unreachable_phi_srcs_block(nir_block *block, void *void_state)
+{
+   struct lower_variables_state *state = void_state;
+
+   /* Only run on unreachable blocks */
+   if (block->imm_dom || block == nir_start_block(state->impl))
+      return true;
+
+   if (block->successors[0])
+      add_undef_phi_sources(block->successors[0], block, state);
+   if (block->successors[1])
+      add_undef_phi_sources(block->successors[1], block, state);
+
+   return true;
+}
+
 /* Inserts phi nodes for all variables marked lower_to_ssa
  *
  * This is the same algorithm as presented in "Efficiently Computing Static
@@ -955,6 +999,8 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
    insert_phi_nodes(&state);
    rename_variables_block(nir_start_block(impl), &state);
 
+   nir_foreach_block(impl, add_unreachable_phi_srcs_block, &state);
+
    nir_metadata_preserve(impl, nir_metadata_block_index |
                                nir_metadata_dominance);