From 60af3a93e9c25e9d5661bfda215a0b07463fe146 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sun, 10 Mar 2019 17:41:02 -0500 Subject: [PATCH] nir/deref: Consider COHERENT decorated var derefs as aliasing If we get to two deref_var paths with different variables, we usually know they don't alias. However, if both of the paths are marked coherent, we don't have to worry about it. Reviewed-by: Caio Marcelo de Oliveira Filho --- src/compiler/nir/nir_deref.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c index c07a8c50691..14d8804c389 100644 --- a/src/compiler/nir/nir_deref.c +++ b/src/compiler/nir/nir_deref.c @@ -307,6 +307,28 @@ modes_may_alias(nir_variable_mode a, nir_variable_mode b) return a == b; } +static bool +deref_path_contains_coherent_decoration(nir_deref_path *path) +{ + assert(path->path[0]->deref_type == nir_deref_type_var); + + if (path->path[0]->var->data.image.access & ACCESS_COHERENT) + return true; + + for (nir_deref_instr **p = &path->path[1]; *p; p++) { + if ((*p)->deref_type != nir_deref_type_struct) + continue; + + const struct glsl_type *struct_type = (*(p - 1))->type; + const struct glsl_struct_field *field = + glsl_get_struct_field_data(struct_type, (*p)->strct.index); + if (field->memory_coherent) + return true; + } + + return false; +} + nir_deref_compare_result nir_compare_deref_paths(nir_deref_path *a_path, nir_deref_path *b_path) @@ -318,11 +340,32 @@ nir_compare_deref_paths(nir_deref_path *a_path, 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) + if (a_path->path[0]->var != b_path->path[0]->var) { + /* Shader and function temporaries aren't backed by memory so two + * distinct variables never alias. + */ + static const nir_variable_mode temp_var_modes = + nir_var_shader_temp | nir_var_function_temp; + if ((a_path->path[0]->mode & temp_var_modes) || + (b_path->path[0]->mode & temp_var_modes)) + return nir_derefs_do_not_alias; + + /* If they are both declared coherent or have coherent somewhere in + * their path (due to a member of an interface being declared + * coherent), we have to assume we that we could have any kind of + * aliasing. Otherwise, they could still alias but the client didn't + * tell us and that's their fault. + */ + if (deref_path_contains_coherent_decoration(a_path) && + deref_path_contains_coherent_decoration(b_path)) + return nir_derefs_may_alias_bit; + + /* If we can chase the deref all the way back to the variable and + * they're not the same variable and at least one is not declared + * coherent, we know they can't possibly alias. + */ return nir_derefs_do_not_alias; + } } else { assert(a_path->path[0]->deref_type == nir_deref_type_cast); /* If they're not exactly the same cast, it's hard to compare them so we -- 2.30.2