nir/deref: Consider COHERENT decorated var derefs as aliasing
authorJason Ekstrand <jason.ekstrand@intel.com>
Sun, 10 Mar 2019 22:41:02 +0000 (17:41 -0500)
committerJason Ekstrand <jason@jlekstrand.net>
Fri, 15 Mar 2019 01:02:19 +0000 (01:02 +0000)
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 <caio.oliveira@intel.com>
src/compiler/nir/nir_deref.c

index c07a8c50691a5bb03d53e520770602c896011b02..14d8804c389e2178420a5587f2a2b3ecc65fd615 100644 (file)
@@ -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