Commit 8bdf5a00 authored by Caio Oliveira's avatar Caio Oliveira
Browse files

nir: Allow derefs to be used as phi sources

It is possible and valid for a pointer to be selected based on a
conditional before used, and depending on the mode, those cases will
result in a phi with derefs as sources.

To achieve this, we don't rematerialize derefs that are used by phis.
As a consequence, when converting from SSA to regs, we may have phis
that come from different blocks and are used by phis.  We now convert
those to regs too.

Validation was added to ensure only derefs of certain modes can be
used as phi sources.  No extra validation is needed for the presence
of cast, any instruction that uses derefs will validate the
deref-chain is complete (ending in a cast or a var).
Reviewed-by: Jason Ekstrand's avatarJason Ekstrand <>
parent ee2a92bc
Pipeline #39354 passed with stages
in 9 minutes and 24 seconds
...@@ -601,6 +601,8 @@ rematerialize_deref_src(nir_src *src, void *_state) ...@@ -601,6 +601,8 @@ rematerialize_deref_src(nir_src *src, void *_state)
* used. After this pass has been run, every use of a deref will be of a * used. After this pass has been run, every use of a deref will be of a
* deref in the same block as the use. Also, all unused derefs will be * deref in the same block as the use. Also, all unused derefs will be
* deleted as a side-effect. * deleted as a side-effect.
* Derefs used as sources of phi instructions are not rematerialized.
*/ */
bool bool
nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl) nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl)
...@@ -620,6 +622,12 @@ nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl) ...@@ -620,6 +622,12 @@ nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl)
nir_deref_instr_remove_if_unused(nir_instr_as_deref(instr))) nir_deref_instr_remove_if_unused(nir_instr_as_deref(instr)))
continue; continue;
/* If a deref is used in a phi, we can't rematerialize it, as the new
* derefs would appear before the phi, which is not valid.
if (instr->type == nir_instr_type_phi)
state.builder.cursor = nir_before_instr(instr); state.builder.cursor = nir_before_instr(instr);
nir_foreach_src(instr, rematerialize_deref_src, &state); nir_foreach_src(instr, rematerialize_deref_src, &state);
} }
...@@ -902,8 +902,6 @@ nir_lower_phis_to_regs_block(nir_block *block) ...@@ -902,8 +902,6 @@ nir_lower_phis_to_regs_block(nir_block *block)
nir_foreach_phi_src(src, phi) { nir_foreach_phi_src(src, phi) {
assert(src->src.is_ssa); assert(src->src.is_ssa);
/* We don't want derefs ending up in phi sources */
place_phi_read(shader, reg, src->src.ssa, src->pred); place_phi_read(shader, reg, src->src.ssa, src->pred);
} }
...@@ -499,6 +499,15 @@ validate_deref_instr(nir_deref_instr *instr, validate_state *state) ...@@ -499,6 +499,15 @@ validate_deref_instr(nir_deref_instr *instr, validate_state *state)
* NULL, an explicit comparison operation should be used. * NULL, an explicit comparison operation should be used.
*/ */
validate_assert(state, list_empty(&instr->dest.ssa.if_uses)); validate_assert(state, list_empty(&instr->dest.ssa.if_uses));
/* Only certain modes can be used as sources for phi instructions. */
nir_foreach_use(use, &instr->dest.ssa) {
if (use->parent_instr->type == nir_instr_type_phi) {
validate_assert(state, instr->mode == nir_var_mem_ubo ||
instr->mode == nir_var_mem_ssbo ||
instr->mode == nir_var_mem_shared);
} }
static void static void
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment