lima/ppir: remove orphan load node after cloning
authorErico Nunes <nunes.erico@gmail.com>
Sun, 12 Jan 2020 13:30:26 +0000 (14:30 +0100)
committerMarge Bot <eric+marge@anholt.net>
Wed, 15 Jan 2020 22:55:31 +0000 (22:55 +0000)
There are some cases in shades using control flow where the varying load
is cloned to every block, and then the original node is left orphan.
This is not harmful for program execution, but it complicates analysis
for register allocation as there is now a case of writing to a register
that is never read.
While ppir doesn't have a dead code elimination pass for its own
optimizations and it is not hard to detect when we cloned the last load,
let's remove it early.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3358>

src/gallium/drivers/lima/ir/pp/nir.c
src/gallium/drivers/lima/ir/pp/node.c
src/gallium/drivers/lima/ir/pp/ppir.h

index 78220aefb03a573b612c871f002820dbc017e46a..a1d10a0be37d0ada2a2aafbffb0fc33d71002021 100644 (file)
@@ -117,7 +117,11 @@ static void ppir_node_add_src(ppir_compiler *comp, ppir_node *node,
          if (!is_load_coords) {
             /* Clone varying loads for each block */
             if (child->block != node->block) {
-               child = ppir_node_clone(node->block, child);
+               ppir_node *new = ppir_node_clone(node->block, child);
+               /* If we clone it for every block and there is no user of
+                * the original load left, delete the original one. */
+               ppir_delete_if_orphan(node->block, child);
+               child = new;
                comp->var_nodes[ns->ssa->index] = child;
             }
             break;
index a5748a22200eb8d240292d644f342c8ddbfd02de..bf713f80715be7e547aa3dcf2e644d98db17c8ff 100644 (file)
@@ -669,6 +669,27 @@ ppir_node_clone_load(ppir_block *block, ppir_node *node)
    return &new_lnode->node;
 }
 
+void
+ppir_delete_if_orphan(ppir_block *block, ppir_node *node)
+{
+   ppir_dest *dest = ppir_node_get_dest(node);
+   if (!dest)
+      return;
+
+   ppir_node_foreach_succ_safe(node, dep) {
+      ppir_node *succ = dep->succ;
+      for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
+         ppir_src *src = ppir_node_get_src(succ, i);
+         if (!src)
+            continue;
+         if (ppir_node_target_equal(src, dest))
+            return;
+      }
+   }
+
+   ppir_node_delete(node);
+}
+
 ppir_node *ppir_node_clone(ppir_block *block, ppir_node *node)
 {
    switch (node->op) {
index 6b550a3c9d16f4da66afeb98da72e558dfa9fbf4..592fa6cf8a528ebaf6737f2731b115a50c0fa0b4 100644 (file)
@@ -396,6 +396,7 @@ void ppir_node_print_prog(ppir_compiler *comp);
 void ppir_node_replace_child(ppir_node *parent, ppir_node *old_child, ppir_node *new_child);
 void ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src);
 void ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred);
+void ppir_delete_if_orphan(ppir_block *block, ppir_node *node);
 ppir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred);
 ppir_node *ppir_node_clone(ppir_block *block, ppir_node *node);
 /* Assumes that node successors are in the same block */