Module: Mesa
Branch: main
Commit: 0ce53b002f5c8eed00f862387a5424a20fc216d9
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0ce53b002f5c8eed00f862387a5424a20fc216d9

Author: Simon Perretta <[email protected]>
Date:   Mon Feb 13 14:17:01 2023 +0000

pvr: Amend subarray ownership code

Signed-off-by: Simon Perretta <[email protected]>
Acked-by: Frank Binns <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21474>

---

 src/imagination/rogue/passes/rogue_regalloc.c | 45 +++++++++++++++++----------
 src/imagination/rogue/rogue.c                 | 15 ++++++++-
 src/imagination/rogue/rogue.h                 | 33 ++++++++++++++++++--
 3 files changed, 73 insertions(+), 20 deletions(-)

diff --git a/src/imagination/rogue/passes/rogue_regalloc.c 
b/src/imagination/rogue/passes/rogue_regalloc.c
index b643b266c7a..d46ef62044f 100644
--- a/src/imagination/rogue/passes/rogue_regalloc.c
+++ b/src/imagination/rogue/passes/rogue_regalloc.c
@@ -23,10 +23,12 @@
 
 #include "rogue.h"
 #include "util/macros.h"
+#include "util/u_qsort.h"
 #include "util/ralloc.h"
 #include "util/register_allocate.h"
 
 #include <stdbool.h>
+#include <stdlib.h>
 
 /**
  * \file rogue_regalloc.c
@@ -41,6 +43,20 @@ typedef struct rogue_live_range {
    unsigned end;
 } rogue_live_range;
 
+static int regarray_cmp(const void *lhs, const void *rhs, UNUSED void *arg)
+{
+   const rogue_regarray *l = lhs;
+   const rogue_regarray *r = rhs;
+
+   /* Signs swapped for sorting largest->smallest. */
+   if (l->size > r->size)
+      return -1;
+   else if (l->size < r->size)
+      return 1;
+
+   return 0;
+}
+
 PUBLIC
 bool rogue_regalloc(rogue_shader *shader)
 {
@@ -201,6 +217,7 @@ bool rogue_regalloc(rogue_shader *shader)
    rogue_regarray **parent_regarrays =
       rzalloc_array_size(shader, sizeof(*parent_regarrays), regarray_count);
 
+   /* Construct list of sorted parent regarrays. */
    unsigned num_parent_regarrays = 0;
    rogue_foreach_regarray (regarray, shader) {
       if (regarray->parent || regarray->regs[0]->class != ROGUE_REG_CLASS_SSA)
@@ -209,6 +226,12 @@ bool rogue_regalloc(rogue_shader *shader)
       parent_regarrays[num_parent_regarrays++] = regarray;
    }
 
+   util_qsort_r(parent_regarrays,
+                num_parent_regarrays,
+                sizeof(*parent_regarrays),
+                regarray_cmp,
+                NULL);
+
    for (unsigned u = 0; u < num_parent_regarrays; ++u) {
       rogue_regarray *regarray = parent_regarrays[u];
 
@@ -219,9 +242,13 @@ bool rogue_regalloc(rogue_shader *shader)
       enum rogue_reg_class new_class = regalloc_info[ra_class].class;
 
       bool used = false;
-      for (unsigned r = 0; r < regarray->size; ++r)
+      for (unsigned r = 0; r < regarray->size; ++r) {
          used |= rogue_reg_is_used(shader, new_class, new_base_index + r);
 
+         if (used)
+            break;
+      }
+
       /* First time using new regarray, modify in place. */
       if (!used) {
          progress |=
@@ -234,21 +261,7 @@ bool rogue_regalloc(rogue_shader *shader)
                                                               regarray->size,
                                                               new_class,
                                                               new_base_index);
-         progress |= rogue_regarray_replace(regarray, new_regarray);
-
-         /* Replace subarrays. */
-         rogue_foreach_subarray_safe (subarray, regarray) {
-            unsigned idx_offset =
-               subarray->regs[0]->index - regarray->regs[0]->index;
-            new_regarray = rogue_regarray_cached(shader,
-                                                 subarray->size,
-                                                 new_class,
-                                                 new_base_index + idx_offset);
-            progress |= rogue_regarray_replace(subarray, new_regarray);
-            rogue_regarray_delete(subarray);
-         }
-
-         rogue_regarray_delete(regarray);
+         progress |= rogue_regarray_replace(shader, regarray, new_regarray);
       }
    }
 
diff --git a/src/imagination/rogue/rogue.c b/src/imagination/rogue/rogue.c
index d8f23bc5f49..c3563f39ce4 100644
--- a/src/imagination/rogue/rogue.c
+++ b/src/imagination/rogue/rogue.c
@@ -475,10 +475,23 @@ static rogue_regarray *rogue_regarray_create(rogue_shader 
*shader,
          for (unsigned u = 0; u < common_regarray->size; ++u)
             common_regarray->regs[u]->regarray = regarray;
 
+         /* Steal its children. */
+         rogue_foreach_subarray_safe (subarray, common_regarray) {
+            unsigned parent_index = common_regarray->regs[0]->index;
+            unsigned child_index = subarray->regs[0]->index;
+            assert(child_index >= parent_index);
+
+            subarray->parent = regarray;
+            subarray->regs = &parent_regptr[child_index - parent_index];
+
+            list_del(&subarray->child_link);
+            list_addtail(&subarray->child_link, &regarray->children);
+         }
+
          common_regarray->parent = regarray;
          ralloc_free(common_regarray->regs);
          common_regarray->regs = parent_regptr;
-         list_addtail(&regarray->children, &common_regarray->child_link);
+         list_addtail(&common_regarray->child_link, &regarray->children);
       } else {
          /* We share registers with another regarray, and we are a subset of 
it.
           */
diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h
index 4afc6e91927..e0262ab80f7 100644
--- a/src/imagination/rogue/rogue.h
+++ b/src/imagination/rogue/rogue.h
@@ -2379,11 +2379,15 @@ static inline bool 
rogue_src_regarray_replace(rogue_regarray_use *use,
    return true;
 }
 
-static inline bool rogue_regarray_replace(rogue_regarray *old_regarray,
+static inline bool rogue_regarray_replace(rogue_shader *shader,
+                                          rogue_regarray *old_regarray,
                                           rogue_regarray *new_regarray)
 {
    bool replaced = true;
 
+   assert(!old_regarray->parent);
+   assert(!new_regarray->parent);
+
    rogue_foreach_regarray_write_safe (write, old_regarray) {
       replaced &= rogue_dst_regarray_replace(write, new_regarray);
    }
@@ -2392,8 +2396,31 @@ static inline bool rogue_regarray_replace(rogue_regarray 
*old_regarray,
       replaced &= rogue_src_regarray_replace(use, new_regarray);
    }
 
-   /* N.B. The old regarray isn't automatically deleted here, this needs to be
-    * done manually. */
+   enum rogue_reg_class new_class = new_regarray->regs[0]->class;
+   unsigned new_base_index = new_regarray->regs[0]->index;
+
+   /* Replace subarrays. */
+   rogue_foreach_subarray_safe (old_subarray, old_regarray) {
+      unsigned idx_offset =
+         old_subarray->regs[0]->index - old_regarray->regs[0]->index;
+      rogue_regarray *new_subarray =
+         rogue_regarray_cached(shader,
+                               old_subarray->size,
+                               new_class,
+                               new_base_index + idx_offset);
+
+      rogue_foreach_regarray_write_safe (write, old_subarray) {
+         replaced &= rogue_dst_regarray_replace(write, new_subarray);
+      }
+
+      rogue_foreach_regarray_use_safe (use, old_subarray) {
+         replaced &= rogue_src_regarray_replace(use, new_subarray);
+      }
+
+      rogue_regarray_delete(old_subarray);
+   }
+
+   rogue_regarray_delete(old_regarray);
 
    return replaced;
 }

Reply via email to