[Mesa-dev] [PATCH] nir/deref: Support casts in comparisons

Jason Ekstrand jason at jlekstrand.net
Mon Nov 19 18:29:31 UTC 2018


The code which constructs deref paths already gives you the path
starting at the nearest deref_cast or deref_var.  All we need to do is
handle the case where the start of the path isn't a deref_var.

Cc: Karol Herbst <kherbst at redhat.com>
Cc: Dave Airlie <airlied at redhat.com>
---
 src/compiler/nir/nir_deref.c | 42 +++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index 4a2e81956d1..59b36a7f255 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -272,13 +272,51 @@ nir_fixup_deref_modes(nir_shader *shader)
    }
 }
 
+static bool
+modes_may_alias(nir_variable_mode a, nir_variable_mode b)
+{
+   /* Two pointers can only alias if they have the same mode.
+    *
+    * NOTE: In future, with things like OpenCL generic pointers, this may not
+    * be true and will have to be re-evaluated.  However, with graphics only,
+    * it should be safe.
+    */
+   return a == b;
+}
+
 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)
+   if (!modes_may_alias(b_path->path[0]->mode, a_path->path[0]->mode))
       return 0;
 
+   if (a_path->path[0]->deref_type != b_path->path[0]->deref_type)
+      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)
+         return 0;
+   } else {
+      assert(a_path->path[0]->deref_type == nir_deref_type_cast);
+      /* If they're not exactly the same cast, we can't compare them so we
+       * have to assume they alias.  Comparing casts is tricky as there are
+       * lots of things such as mode, type, etc. to make sure work out; for
+       * now, we just assume CSE will combine them and compare the deref
+       * instructions.
+       *
+       * TODO: At some point in the future, we could be clever and understand
+       * that a float[] and int[] have the same layout and aliasing structure
+       * but double[] and vec3[] do not and we could potentially be a bit
+       * smarter here.
+       */
+      if (a_path->path[0] != b_path->path[0])
+         return nir_derefs_may_alias_bit;
+   }
+
    /* Start off assuming they fully compare.  We ignore equality for now.  In
     * the end, we'll determine that by containment.
     */
@@ -368,8 +406,6 @@ nir_compare_derefs(nir_deref_instr *a, nir_deref_instr *b)
    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);
 
-- 
2.19.1



More information about the mesa-dev mailing list