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)
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