Add code to remove unused phis, converting to pruned SSA form, to avoid
authorDavid Given <dg@cowlark.com>
Wed, 12 Oct 2016 19:50:12 +0000 (21:50 +0200)
committerDavid Given <dg@cowlark.com>
Wed, 12 Oct 2016 19:50:12 +0000 (21:50 +0200)
confusing the register allocator later.

mach/proto/mcg/mcg.h
mach/proto/mcg/pass_removedeadphis.c [new file with mode: 0644]
mach/proto/mcg/procedure.c

index 5678858..0df947d 100644 (file)
@@ -112,6 +112,7 @@ extern void pass_live_vreg_analysis(void);
 extern void pass_promote_float_ops(struct procedure* proc);
 extern void pass_register_allocator(void);
 extern void pass_remove_dead_blocks(struct procedure* proc);
+extern void pass_remove_dead_phis(void);
 extern void pass_split_critical_edges(struct procedure* proc);
 
 extern FILE* outputfile;
diff --git a/mach/proto/mcg/pass_removedeadphis.c b/mach/proto/mcg/pass_removedeadphis.c
new file mode 100644 (file)
index 0000000..b8b61fb
--- /dev/null
@@ -0,0 +1,88 @@
+#include "mcg.h"
+
+static ARRAYOF(struct ir) phis;
+static bool changed;
+
+static void collect_phis(struct basicblock* bb)
+{
+    int i;
+
+    for (i=0; i<bb->irs.count; i++)
+    {
+        struct ir* ir = bb->irs.item[i];
+        if (ir->opcode == IR_PHI)
+            array_append(&phis, ir);
+    }
+}
+
+static bool ir_walker_cb(struct ir* ir, void* user)
+{
+    if (ir->left)
+        array_remove(&phis, ir->left);
+    if (ir->right)
+        array_remove(&phis, ir->right);
+
+    return false;
+}
+
+static void remove_referenced_phis(struct basicblock* bb)
+{
+    int i, j;
+
+    for (i=0; i<bb->irs.count; i++)
+    {
+        struct ir* ir = bb->irs.item[i];
+        switch (ir->opcode)
+        {
+            case IR_PHI:
+                for (j=0; j<ir->u.phivalue.count; j++)
+                    array_remove(&phis, ir->u.phivalue.item[j].right);
+                break;
+
+            default:
+                ir_walk(ir, ir_walker_cb, NULL);
+                break;
+        }
+    }
+}
+
+static void purge_unused_phis(struct basicblock* bb)
+{
+    int i;
+    
+    for (i=0; i<bb->irs.count; i++)
+    {
+        struct ir* ir = bb->irs.item[i];
+        if ((ir->opcode == IR_PHI) && (array_contains(&phis, ir)))
+        {
+            array_remove(&bb->irs, ir);
+            i--;
+            changed = true;
+        }
+    }
+}
+
+void pass_remove_dead_phis(void)
+{
+    int i;
+    
+    do
+    {
+        changed = false;
+
+        phis.count = 0;
+        for (i=0; i<cfg.preorder.count; i++)
+            collect_phis(cfg.preorder.item[i]);
+
+        for (i=0; i<cfg.preorder.count; i++)
+            remove_referenced_phis(cfg.preorder.item[i]);
+
+        for (i=0; i<cfg.preorder.count; i++)
+            purge_unused_phis(cfg.preorder.item[i]);
+    }
+    while (changed);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
+
index 35b986f..af05f80 100644 (file)
@@ -159,9 +159,9 @@ void procedure_compile(struct procedure* proc)
 {
        int i;
 
+    pass_group_irs(proc);
        print_blocks('1', proc);
 
-    pass_group_irs(proc);
     /* Passes from here on must preserve IR grouping */
 
     pass_eliminate_trivial_blocks(proc);
@@ -180,6 +180,7 @@ void procedure_compile(struct procedure* proc)
     print_blocks('4', proc);
     pass_convert_locals_to_ssa(proc);
     print_blocks('5', proc);
+    pass_remove_dead_phis();
     pass_promote_float_ops(proc);
     print_blocks('6', proc);