aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <[email protected]>2019-05-07 02:03:59 -0700
committerCaio Marcelo de Oliveira Filho <[email protected]>2019-05-29 08:19:15 -0700
commit8bdf5a008b3e22f0cd2e836184decfac3265f0df (patch)
treec1598e7c929b02e919c39deded40d07d0dcb76a1
parentee2a92bcde0d34f5f92375598167422206efda21 (diff)
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 <[email protected]>
-rw-r--r--src/compiler/nir/nir_deref.c8
-rw-r--r--src/compiler/nir/nir_from_ssa.c2
-rw-r--r--src/compiler/nir/nir_validate.c9
3 files changed, 17 insertions, 2 deletions
diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index f1e6eee7745..90bb9a0dc3c 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -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
* deref in the same block as the use. Also, all unused derefs will be
* deleted as a side-effect.
+ *
+ * Derefs used as sources of phi instructions are not rematerialized.
*/
bool
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)))
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)
+ continue;
+
state.builder.cursor = nir_before_instr(instr);
nir_foreach_src(instr, rematerialize_deref_src, &state);
}
diff --git a/src/compiler/nir/nir_from_ssa.c b/src/compiler/nir/nir_from_ssa.c
index b406e7401d6..2ac67b2b997 100644
--- a/src/compiler/nir/nir_from_ssa.c
+++ b/src/compiler/nir/nir_from_ssa.c
@@ -902,8 +902,6 @@ nir_lower_phis_to_regs_block(nir_block *block)
nir_foreach_phi_src(src, phi) {
assert(src->src.is_ssa);
- /* We don't want derefs ending up in phi sources */
- assert(!nir_src_as_deref(src->src));
place_phi_read(shader, reg, src->src.ssa, src->pred);
}
diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index bf3f23f2547..682ed762f57 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -499,6 +499,15 @@ validate_deref_instr(nir_deref_instr *instr, validate_state *state)
* NULL, an explicit comparison operation should be used.
*/
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