[Mesa-dev] [PATCH 1/2] nir: Export deref comparison functions

2018-07-27 Thread Caio Marcelo de Oliveira Filho
---
 src/compiler/nir/nir_deref.c  | 111 +
 src/compiler/nir/nir_deref.h  |  10 ++
 src/compiler/nir/nir_opt_copy_prop_vars.c | 145 ++
 3 files changed, 134 insertions(+), 132 deletions(-)

diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index c03acf83597..0c951279672 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -270,3 +270,114 @@ nir_fixup_deref_modes(nir_shader *shader)
   }
}
 }
+
+/** Returns true if the storage referrenced to by deref completely contains
+ * the storage referenced by sub.
+ */
+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)
+  return 0;
+
+   /* Start off assuming they fully compare.  We ignore equality for now.  In
+* the end, we'll determine that by containment.
+*/
+   nir_deref_compare_result result = nir_derefs_may_alias_bit |
+ nir_derefs_a_contains_b_bit |
+ nir_derefs_b_contains_a_bit;
+
+   nir_deref_instr **a_p = &a_path->path[1];
+   nir_deref_instr **b_p = &b_path->path[1];
+   while (*a_p != NULL && *b_p != NULL) {
+  nir_deref_instr *a_tail = *(a_p++);
+  nir_deref_instr *b_tail = *(b_p++);
+
+  switch (a_tail->deref_type) {
+  case nir_deref_type_array:
+  case nir_deref_type_array_wildcard: {
+ assert(b_tail->deref_type == nir_deref_type_array ||
+b_tail->deref_type == nir_deref_type_array_wildcard);
+
+ if (a_tail->deref_type == nir_deref_type_array_wildcard) {
+if (b_tail->deref_type != nir_deref_type_array_wildcard)
+   result &= ~nir_derefs_b_contains_a_bit;
+ } else if (b_tail->deref_type == nir_deref_type_array_wildcard) {
+if (a_tail->deref_type != nir_deref_type_array_wildcard)
+   result &= ~nir_derefs_a_contains_b_bit;
+ } else {
+assert(a_tail->deref_type == nir_deref_type_array &&
+   b_tail->deref_type == nir_deref_type_array);
+assert(a_tail->arr.index.is_ssa && b_tail->arr.index.is_ssa);
+
+nir_const_value *a_index_const =
+   nir_src_as_const_value(a_tail->arr.index);
+nir_const_value *b_index_const =
+   nir_src_as_const_value(b_tail->arr.index);
+if (a_index_const && b_index_const) {
+   /* If they're both direct and have different offsets, they
+* don't even alias much less anything else.
+*/
+   if (a_index_const->u32[0] != b_index_const->u32[0])
+  return 0;
+} else if (a_tail->arr.index.ssa == b_tail->arr.index.ssa) {
+   /* They're the same indirect, continue on */
+} else {
+   /* They're not the same index so we can't prove anything about
+* containment.
+*/
+   result &= ~(nir_derefs_a_contains_b_bit | 
nir_derefs_b_contains_a_bit);
+}
+ }
+ break;
+  }
+
+  case nir_deref_type_struct: {
+ /* If they're different struct members, they don't even alias */
+ if (a_tail->strct.index != b_tail->strct.index)
+return 0;
+ break;
+  }
+
+  default:
+ unreachable("Invalid deref type");
+  }
+   }
+
+   /* If a is longer than b, then it can't contain b */
+   if (*a_p != NULL)
+  result &= ~nir_derefs_a_contains_b_bit;
+   if (*b_p != NULL)
+  result &= ~nir_derefs_b_contains_a_bit;
+
+   /* If a contains b and b contains a they must be equal. */
+   if ((result & nir_derefs_a_contains_b_bit) && (result & 
nir_derefs_b_contains_a_bit))
+  result |= nir_derefs_equal_bit;
+
+   return result;
+}
+
+nir_deref_compare_result
+nir_compare_derefs(nir_deref_instr *a, nir_deref_instr *b)
+{
+   if (a == b) {
+  return nir_derefs_equal_bit | nir_derefs_may_alias_bit |
+ nir_derefs_a_contains_b_bit | nir_derefs_b_contains_a_bit;
+   }
+
+   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);
+
+   nir_deref_path_finish(&a_path);
+   nir_deref_path_finish(&b_path);
+
+   return result;
+}
+
+
diff --git a/src/compiler/nir/nir_deref.h b/src/compiler/nir/nir_deref.h
index 6f4141aaf82..c61c3f9366f 100644
--- a/src/compiler/nir/nir_deref.h
+++ b/src/compiler/nir/nir_deref.h
@@ -54,6 +54,16 @@ unsigned nir_deref_instr_get_const_offset(nir_deref_instr 
*deref,
 nir_ssa_def *nir_build_deref_offset(nir_builder *b, nir_deref_instr *deref,
 gl

Re: [Mesa-dev] [PATCH 1/2] nir: Export deref comparison functions

2018-07-27 Thread Timothy Arceri



On 28/07/18 07:51, Caio Marcelo de Oliveira Filho wrote:

---
  src/compiler/nir/nir_deref.c  | 111 +
  src/compiler/nir/nir_deref.h  |  10 ++
  src/compiler/nir/nir_opt_copy_prop_vars.c | 145 ++
  3 files changed, 134 insertions(+), 132 deletions(-)

diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index c03acf83597..0c951279672 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -270,3 +270,114 @@ nir_fixup_deref_modes(nir_shader *shader)
}
 }
  }
+
+/** Returns true if the storage referrenced to by deref completely contains
+ * the storage referenced by sub.
+ */
+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)
+  return 0;
+
+   /* Start off assuming they fully compare.  We ignore equality for now.  In
+* the end, we'll determine that by containment.
+*/
+   nir_deref_compare_result result = nir_derefs_may_alias_bit |
+ nir_derefs_a_contains_b_bit |
+ nir_derefs_b_contains_a_bit;
+
+   nir_deref_instr **a_p = &a_path->path[1];
+   nir_deref_instr **b_p = &b_path->path[1];
+   while (*a_p != NULL && *b_p != NULL) {
+  nir_deref_instr *a_tail = *(a_p++);
+  nir_deref_instr *b_tail = *(b_p++);
+
+  switch (a_tail->deref_type) {
+  case nir_deref_type_array:
+  case nir_deref_type_array_wildcard: {
+ assert(b_tail->deref_type == nir_deref_type_array ||
+b_tail->deref_type == nir_deref_type_array_wildcard);
+
+ if (a_tail->deref_type == nir_deref_type_array_wildcard) {
+if (b_tail->deref_type != nir_deref_type_array_wildcard)
+   result &= ~nir_derefs_b_contains_a_bit;
+ } else if (b_tail->deref_type == nir_deref_type_array_wildcard) {
+if (a_tail->deref_type != nir_deref_type_array_wildcard)
+   result &= ~nir_derefs_a_contains_b_bit;
+ } else {
+assert(a_tail->deref_type == nir_deref_type_array &&
+   b_tail->deref_type == nir_deref_type_array);
+assert(a_tail->arr.index.is_ssa && b_tail->arr.index.is_ssa);
+
+nir_const_value *a_index_const =
+   nir_src_as_const_value(a_tail->arr.index);
+nir_const_value *b_index_const =
+   nir_src_as_const_value(b_tail->arr.index);
+if (a_index_const && b_index_const) {
+   /* If they're both direct and have different offsets, they
+* don't even alias much less anything else.
+*/
+   if (a_index_const->u32[0] != b_index_const->u32[0])
+  return 0;
+} else if (a_tail->arr.index.ssa == b_tail->arr.index.ssa) {
+   /* They're the same indirect, continue on */
+} else {
+   /* They're not the same index so we can't prove anything about
+* containment.
+*/
+   result &= ~(nir_derefs_a_contains_b_bit | 
nir_derefs_b_contains_a_bit);
+}
+ }
+ break;
+  }
+
+  case nir_deref_type_struct: {
+ /* If they're different struct members, they don't even alias */
+ if (a_tail->strct.index != b_tail->strct.index)
+return 0;
+ break;
+  }
+
+  default:
+ unreachable("Invalid deref type");
+  }
+   }
+
+   /* If a is longer than b, then it can't contain b */
+   if (*a_p != NULL)
+  result &= ~nir_derefs_a_contains_b_bit;
+   if (*b_p != NULL)
+  result &= ~nir_derefs_b_contains_a_bit;
+
+   /* If a contains b and b contains a they must be equal. */
+   if ((result & nir_derefs_a_contains_b_bit) && (result & 
nir_derefs_b_contains_a_bit))
+  result |= nir_derefs_equal_bit;
+
+   return result;
+}
+
+nir_deref_compare_result
+nir_compare_derefs(nir_deref_instr *a, nir_deref_instr *b)
+{
+   if (a == b) {
+  return nir_derefs_equal_bit | nir_derefs_may_alias_bit |
+ nir_derefs_a_contains_b_bit | nir_derefs_b_contains_a_bit;
+   }
+
+   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);
+
+   nir_deref_path_finish(&a_path);
+   nir_deref_path_finish(&b_path);
+
+   return result;
+}
+
+


Please remove the extra lines introduced at the end of the file.

Otherwise this patch is:

Reviewed-by: Timothy Arceri 



diff --git a/src/compiler/nir/nir_deref.h b/src/compiler/nir/nir_deref.h
index 6f4141aaf82..c61c3f9366f 100644
--- a/src/compiler/nir/nir_deref.h
+++ b/src/compiler/nir/nir_deref.h
@@ -54,6