Module: Mesa
Branch: staging/23.0
Commit: 785cf852962aba988215aa15031ab5269a58a6cb
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=785cf852962aba988215aa15031ab5269a58a6cb

Author: Faith Ekstrand <[email protected]>
Date:   Fri Feb 10 16:21:19 2023 -0600

nir/deref: Preserve alignments in opt_remove_cast_cast()

This also removes the loop so opt_remove_cast_cast() will only optimize
cast(cast(x)) and not cast(cast(cast(x))).  However, since nir_opt_deref
walks instructions top-down, there will almost never be a tripple cast
because the parent cast will have opt_remove_cast_cast() run on it.

Reviewed-by: Jesse Natalie <[email protected]>
(cherry picked from commit af9212dd82b8885e0d94921e8500b90561faa5e0)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21467>

---

 src/compiler/nir/nir_deref.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index e03be3ac662..3de401d9853 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -1024,19 +1024,28 @@ opt_remove_restricting_cast_alignments(nir_deref_instr 
*cast)
 static bool
 opt_remove_cast_cast(nir_deref_instr *cast)
 {
-   nir_deref_instr *first_cast = cast;
+   nir_deref_instr *parent = nir_deref_instr_parent(cast);
+   if (parent == NULL || parent->deref_type != nir_deref_type_cast)
+      return false;
 
-   while (true) {
-      nir_deref_instr *parent = nir_deref_instr_parent(first_cast);
-      if (parent == NULL || parent->deref_type != nir_deref_type_cast)
-         break;
-      first_cast = parent;
+   /* Copy align info from the parent cast if needed
+    *
+    * In the case that align_mul = 0, the alignment for this cast is inhereted
+    * from the parent deref (if any). If we aren't careful, removing our
+    * parent cast from the chain may lose alignment information so we need to
+    * copy the parent's alignment information (if any).
+    *
+    * opt_remove_restricting_cast_alignments() above is run before this pass
+    * and will will have cleared our alignment (set align_mul = 0) in the case
+    * where the parent's alignment information is somehow superior.
+    */
+   if (cast->cast.align_mul == 0) {
+      cast->cast.align_mul = parent->cast.align_mul;
+      cast->cast.align_offset = parent->cast.align_offset;
    }
-   if (cast == first_cast)
-      return false;
 
    nir_instr_rewrite_src(&cast->instr, &cast->parent,
-                         nir_src_for_ssa(first_cast->parent.ssa));
+                         nir_src_for_ssa(parent->parent.ssa));
    return true;
 }
 

Reply via email to