nir/deref: Add a has_complex_use helper

This lets passes easily detect derefs which have uses that fall outside
the standard load/store/copy pattern so they can bail appropriately.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
This commit is contained in:
Jason Ekstrand
2019-05-22 15:00:20 -05:00
parent 8948048c6f
commit e84194686d
2 changed files with 79 additions and 0 deletions

View File

@@ -1085,6 +1085,7 @@ nir_deref_instr_get_variable(const nir_deref_instr *instr)
}
bool nir_deref_instr_has_indirect(nir_deref_instr *instr);
bool nir_deref_instr_has_complex_use(nir_deref_instr *instr);
bool nir_deref_instr_remove_if_unused(nir_deref_instr *instr);

View File

@@ -121,6 +121,84 @@ nir_deref_instr_has_indirect(nir_deref_instr *instr)
return false;
}
bool
nir_deref_instr_has_complex_use(nir_deref_instr *deref)
{
nir_foreach_use(use_src, &deref->dest.ssa) {
nir_instr *use_instr = use_src->parent_instr;
switch (use_instr->type) {
case nir_instr_type_deref: {
nir_deref_instr *use_deref = nir_instr_as_deref(use_instr);
/* A var deref has no sources */
assert(use_deref->deref_type != nir_deref_type_var);
/* If a deref shows up in an array index or something like that, it's
* a complex use.
*/
if (use_src != &use_deref->parent)
return true;
/* Anything that isn't a basic struct or array deref is considered to
* be a "complex" use. In particular, we don't allow ptr_as_array
* because we assume that opt_deref will turn any non-complex
* ptr_as_array derefs into regular array derefs eventually so passes
* which only want to handle simple derefs will pick them up in a
* later pass.
*/
if (use_deref->deref_type != nir_deref_type_struct &&
use_deref->deref_type != nir_deref_type_array_wildcard &&
use_deref->deref_type != nir_deref_type_array)
return true;
if (nir_deref_instr_has_complex_use(use_deref))
return true;
continue;
}
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *use_intrin = nir_instr_as_intrinsic(use_instr);
switch (use_intrin->intrinsic) {
case nir_intrinsic_load_deref:
assert(use_src == &use_intrin->src[0]);
continue;
case nir_intrinsic_copy_deref:
assert(use_src == &use_intrin->src[0] ||
use_src == &use_intrin->src[1]);
continue;
case nir_intrinsic_store_deref:
/* A use in src[1] of a store means we're taking that pointer and
* writing it to a variable. Because we have no idea who will
* read that variable and what they will do with the pointer, it's
* considered a "complex" use. A use in src[0], on the other
* hand, is a simple use because we're just going to dereference
* it and write a value there.
*/
if (use_src == &use_intrin->src[0])
continue;
return true;
default:
return true;
}
unreachable("Switch default failed");
}
default:
return true;
}
}
nir_foreach_if_use(use, &deref->dest.ssa)
return true;
return false;
}
unsigned
nir_deref_instr_ptr_as_array_stride(nir_deref_instr *deref)
{