The code which constructs deref paths already gives you the path starting at the nearest deref_cast or deref_var. All we need to do is handle the case where the start of the path isn't a deref_var.
Cc: Caio Marcelo de Oliveira Filho <caio.olive...@intel.com> --- src/compiler/nir/nir_deref.c | 40 +++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c index 16502c23d04..ed7e1369ca6 100644 --- a/src/compiler/nir/nir_deref.c +++ b/src/compiler/nir/nir_deref.c @@ -278,13 +278,49 @@ nir_fixup_deref_modes(nir_shader *shader) } } +static bool +modes_may_alias(nir_variable_mode a, nir_variable_mode b) +{ + /* Function parameters can alias anything except local variables in the + * current function. + */ + if ((a == nir_var_param && b != nir_var_local) || + (b == nir_var_param && a != nir_var_local)) + return true; + + /* For everything else, they can only alias if they have the same mode. + * This may not hold for external things such UBOs and SSBOs but those + * don't use derefs today. + */ + return a == b; +} + nir_deref_compare_result nir_compare_deref_paths(nir_deref_path *a_path, nir_deref_path *b_path) { - if (a_path->path[0]->var != b_path->path[0]->var) + if (!modes_may_alias(b_path->path[0]->mode, a_path->path[0]->mode)) return 0; + if (a_path->path[0]->deref_type != b_path->path[0]->deref_type) + return nir_derefs_may_alias_bit; + + if (a_path->path[0]->deref_type == nir_deref_type_var) { + /* If we can chase the deref all the way back to the variable and + * they're not the same variable, we know they can't possibly alias. + */ + if (a_path->path[0]->var != b_path->path[0]->var) + return 0; + } else { + /* If they're not exactly the same cast, we can't compare them so we + * have to assume they alias. We could potentially be a bit smarter + * here and compare the two casts for equality but let's just hope CSE + * combines identical casts instead. + */ + if (a_path->path[0] != b_path->path[0]) + return nir_derefs_may_alias_bit; + } + /* Start off assuming they fully compare. We ignore equality for now. In * the end, we'll determine that by containment. */ @@ -376,8 +412,6 @@ nir_compare_derefs(nir_deref_instr *a, nir_deref_instr *b) nir_deref_path a_path, b_path; nir_deref_path_init(&a_path, a, NULL); nir_deref_path_init(&b_path, b, NULL); - assert(a_path.path[0]->deref_type == nir_deref_type_var); - assert(b_path.path[0]->deref_type == nir_deref_type_var); nir_deref_compare_result result = nir_compare_deref_paths(&a_path, &b_path); -- 2.19.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev