Mesa (staging/21.3): ir3/spill: Fix simplify_phi_nodes with multiple loop nesting

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Feb 20 17:40:40 UTC 2022


Module: Mesa
Branch: staging/21.3
Commit: 1db2d1726c454eeeaa673a944f01218cc4084c60
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1db2d1726c454eeeaa673a944f01218cc4084c60

Author: Connor Abbott <cwabbott0 at gmail.com>
Date:   Wed Nov 24 17:51:19 2021 +0100

ir3/spill: Fix simplify_phi_nodes with multiple loop nesting

Once we simplified a phi node, we never updated the definition it points
to, which meant that it could become out of date if that definition were
also simplified, and we didn't check that when rewriting sources. That
could happen when there are multiple nested loops with phi nodes at the
header.

Fix it by updating the phi's pointer. Since we always update sources
after visiting the definition it points to, when we go to rewrite a
source, if that source points to a simplified phi, the phi's pointer
can't be pointing to a simplified phi because we already visited the phi
earlier in the pass and updated it, or else it's been simplified in the
meantime and this isn't the last pass. This way we don't need to
keep recursing when rewriting sources.

Fixes: 613eaac7b53 ("ir3: Initial support for spilling non-shared registers")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15035>
(cherry picked from commit 3ef858a6f6789207e3f24550e9dfb595e3018029)

---

 .pick_status.json             |  2 +-
 src/freedreno/ir3/ir3_spill.c | 42 ++++++++++++++++++++++++++++++++----------
 2 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index 057d4a2d73f..5fc3648c261 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -1129,7 +1129,7 @@
         "description": "ir3/spill: Fix simplify_phi_nodes with multiple loop nesting",
         "nominated": true,
         "nomination_type": 1,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": "613eaac7b53bfbfcd6ef536412be6c9c63cdea4f"
     },
diff --git a/src/freedreno/ir3/ir3_spill.c b/src/freedreno/ir3/ir3_spill.c
index 43cad0a4366..4816be93f3f 100644
--- a/src/freedreno/ir3/ir3_spill.c
+++ b/src/freedreno/ir3/ir3_spill.c
@@ -1783,15 +1783,31 @@ simplify_phi_node(struct ir3_instruction *phi)
    return true;
 }
 
+static struct ir3_register *
+simplify_phi_def(struct ir3_register *def)
+{
+   if (def->instr->opc == OPC_META_PHI) {
+      struct ir3_instruction *phi = def->instr;
+
+      /* Note: this function is always called at least once after visiting the
+       * phi, so either there has been a simplified phi in the meantime, in
+       * which case we will set progress=true and visit the definition again, or
+       * phi->data already has the most up-to-date value. Therefore we don't
+       * have to recursively check phi->data.
+       */
+      if (phi->data)
+         return phi->data;
+   }
+
+   return def;
+}
+
 static void
 simplify_phi_srcs(struct ir3_instruction *instr)
 {
    foreach_src (src, instr) {
-      if (src->def && src->def->instr->opc == OPC_META_PHI) {
-         struct ir3_instruction *phi = src->def->instr;
-         if (phi->data)
-            src->def = phi->data;
-      }
+      if (src->def)
+         src->def = simplify_phi_def(src->def);
    }
 }
 
@@ -1821,6 +1837,10 @@ simplify_phi_nodes(struct ir3 *ir)
             simplify_phi_srcs(instr);
          }
 
+         /* Visit phi nodes in the sucessors to make sure that phi sources are
+          * always visited at least once after visiting the definition they
+          * point to. See note in simplify_phi_def() for why this is necessary.
+          */
          for (unsigned i = 0; i < 2; i++) {
             struct ir3_block *succ = block->successors[i];
             if (!succ)
@@ -1828,11 +1848,13 @@ simplify_phi_nodes(struct ir3 *ir)
             foreach_instr (instr, &succ->instr_list) {
                if (instr->opc != OPC_META_PHI)
                   break;
-               if (instr->flags & IR3_INSTR_UNUSED)
-                  continue;
-
-               simplify_phi_srcs(instr);
-               progress |= simplify_phi_node(instr);
+               if (instr->flags & IR3_INSTR_UNUSED) {
+                  if (instr->data)
+                     instr->data = simplify_phi_def(instr->data);
+               } else {
+                  simplify_phi_srcs(instr);
+                  progress |= simplify_phi_node(instr);
+               }
             }
          }
       }



More information about the mesa-commit mailing list