aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2019-03-10 17:41:02 -0500
committerJason Ekstrand <[email protected]>2019-03-15 01:02:19 +0000
commit60af3a93e9c25e9d5661bfda215a0b07463fe146 (patch)
tree02c948ba672e77083938a51aeee075a55ff6a2ff /src/compiler
parent8b073832ffab2f36338b85e6e67fbefb1b4f4ba9 (diff)
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 <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/nir/nir_deref.c51
1 files 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