pan/midgard: Move RA's liveness analysis into midgard_liveness.c
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Thu, 3 Oct 2019 20:10:03 +0000 (16:10 -0400)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 4 Oct 2019 02:29:50 +0000 (22:29 -0400)
There are unfortunately two distinct liveness analysis passes in the
compiler right now -- one good (but complex) pass used by RA based on
solving data flow equations, and one awful (but simple) pass used for
dead code elimination and bundling based on an abstract walk of the AST.

Let's move RA's pass into shared code so we can work on unifying.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/panfrost/midgard/compiler.h
src/panfrost/midgard/midgard_liveness.c
src/panfrost/midgard/midgard_ra.c

index 66cb34f9db508e678a4c634e7ca70f2cbcc89d24..5d5c26e3db95642d9bc0076d05a04510b22acb20 100644 (file)
@@ -604,6 +604,8 @@ struct ra_graph;
 void mir_lower_special_reads(compiler_context *ctx);
 struct ra_graph* allocate_registers(compiler_context *ctx, bool *spilled);
 void install_registers(compiler_context *ctx, struct ra_graph *g);
+void mir_liveness_ins_update(uint8_t *live, midgard_instruction *ins, unsigned max);
+void mir_compute_liveness(compiler_context *ctx);
 bool mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src);
 
 void mir_create_pipeline_registers(compiler_context *ctx);
index 4766603a885a4841f43cb85fe648608869928c98..ebc6390fe4059f4db8b11f87312fc7f737d09001 100644 (file)
  * backlog with Connor on IRC) */
 
 #include "compiler.h"
+#include "util/u_memory.h"
+
+/* Routines for liveness analysis */
+
+static void
+liveness_gen(uint8_t *live, unsigned node, unsigned max, unsigned mask)
+{
+        if (node >= max)
+                return;
+
+        live[node] |= mask;
+}
+
+static void
+liveness_kill(uint8_t *live, unsigned node, unsigned max, unsigned mask)
+{
+        if (node >= max)
+                return;
+
+        live[node] &= ~mask;
+}
+
+/* Updates live_in for a single instruction */
+
+void
+mir_liveness_ins_update(uint8_t *live, midgard_instruction *ins, unsigned max)
+{
+        /* live_in[s] = GEN[s] + (live_out[s] - KILL[s]) */
+
+        liveness_kill(live, ins->dest, max, ins->mask);
+
+        mir_foreach_src(ins, src) {
+                unsigned node = ins->src[src];
+                unsigned mask = mir_mask_of_read_components(ins, node);
+
+                liveness_gen(live, node, max, mask);
+        }
+}
+
+/* live_out[s] = sum { p in succ[s] } ( live_in[p] ) */
+
+static void
+liveness_block_live_out(compiler_context *ctx, midgard_block *blk)
+{
+        mir_foreach_successor(blk, succ) {
+                for (unsigned i = 0; i < ctx->temp_count; ++i)
+                        blk->live_out[i] |= succ->live_in[i];
+        }
+}
+
+/* Liveness analysis is a backwards-may dataflow analysis pass. Within a block,
+ * we compute live_out from live_in. The intrablock pass is linear-time. It
+ * returns whether progress was made. */
+
+static bool
+liveness_block_update(compiler_context *ctx, midgard_block *blk)
+{
+        bool progress = false;
+
+        liveness_block_live_out(ctx, blk);
+
+        uint8_t *live = mem_dup(blk->live_out, ctx->temp_count);
+
+        mir_foreach_instr_in_block_rev(blk, ins)
+                mir_liveness_ins_update(live, ins, ctx->temp_count);
+
+        /* To figure out progress, diff live_in */
+
+        for (unsigned i = 0; (i < ctx->temp_count) && !progress; ++i)
+                progress |= (blk->live_in[i] != live[i]);
+
+        free(blk->live_in);
+        blk->live_in = live;
+
+        return progress;
+}
+
+/* Globally, liveness analysis uses a fixed-point algorithm based on a
+ * worklist. We initialize a work list with the exit block. We iterate the work
+ * list to compute live_in from live_out for each block on the work list,
+ * adding the predecessors of the block to the work list if we made progress.
+ */
+
+void
+mir_compute_liveness(compiler_context *ctx)
+{
+        /* List of midgard_block */
+        struct set *work_list = _mesa_set_create(ctx,
+                        _mesa_hash_pointer,
+                        _mesa_key_pointer_equal);
+
+        /* Allocate */
+
+        mir_foreach_block(ctx, block) {
+                block->live_in = calloc(ctx->temp_count, 1);
+                block->live_out = calloc(ctx->temp_count, 1);
+        }
+
+        /* Initialize the work list with the exit block */
+        struct set_entry *cur;
+
+        midgard_block *exit = mir_exit_block(ctx);
+        cur = _mesa_set_add(work_list, exit);
+
+        /* Iterate the work list */
+
+        do {
+                /* Pop off a block */
+                midgard_block *blk = (struct midgard_block *) cur->key;
+                _mesa_set_remove(work_list, cur);
+
+                /* Update its liveness information */
+                bool progress = liveness_block_update(ctx, blk);
+
+                /* If we made progress, we need to process the predecessors */
+
+                if (progress || (blk == exit)) {
+                        mir_foreach_predecessor(blk, pred)
+                                _mesa_set_add(work_list, pred);
+                }
+        } while((cur = _mesa_set_next_entry(work_list, NULL)) != NULL);
+}
 
 /* Determine if a variable is live in the successors of a block */
 static bool
index 11bef79a42c6c8d6c4e9f49b36d0efeec2ef81c5..211c4f4d4974fd0c31673a7e37d0054f80feea83 100644 (file)
@@ -26,7 +26,6 @@
 #include "midgard_ops.h"
 #include "util/register_allocate.h"
 #include "util/u_math.h"
-#include "util/u_memory.h"
 
 /* For work registers, we can subdivide in various ways. So we create
  * classes for the various sizes and conflict accordingly, keeping in
@@ -541,129 +540,13 @@ mir_lower_special_reads(compiler_context *ctx)
         free(texw);
 }
 
-/* Routines for liveness analysis */
-
-static void
-liveness_gen(uint8_t *live, unsigned node, unsigned max, unsigned mask)
-{
-        if (node >= max)
-                return;
-
-        live[node] |= mask;
-}
-
-static void
-liveness_kill(uint8_t *live, unsigned node, unsigned max, unsigned mask)
-{
-        if (node >= max)
-                return;
-
-        live[node] &= ~mask;
-}
-
-/* Updates live_in for a single instruction */
-
-static void
-liveness_ins_update(uint8_t *live, midgard_instruction *ins, unsigned max)
-{
-        /* live_in[s] = GEN[s] + (live_out[s] - KILL[s]) */
-
-        liveness_kill(live, ins->dest, max, ins->mask);
-
-        mir_foreach_src(ins, src) {
-                unsigned node = ins->src[src];
-                unsigned mask = mir_mask_of_read_components(ins, node);
-
-                liveness_gen(live, node, max, mask);
-        }
-}
-
-/* live_out[s] = sum { p in succ[s] } ( live_in[p] ) */
-
-static void
-liveness_block_live_out(compiler_context *ctx, midgard_block *blk)
-{
-        mir_foreach_successor(blk, succ) {
-                for (unsigned i = 0; i < ctx->temp_count; ++i)
-                        blk->live_out[i] |= succ->live_in[i];
-        }
-}
-
-/* Liveness analysis is a backwards-may dataflow analysis pass. Within a block,
- * we compute live_out from live_in. The intrablock pass is linear-time. It
- * returns whether progress was made. */
-
-static bool
-liveness_block_update(compiler_context *ctx, midgard_block *blk)
-{
-        bool progress = false;
-
-        liveness_block_live_out(ctx, blk);
-
-        uint8_t *live = mem_dup(blk->live_out, ctx->temp_count);
-
-        mir_foreach_instr_in_block_rev(blk, ins)
-                liveness_ins_update(live, ins, ctx->temp_count);
-
-        /* To figure out progress, diff live_in */
-
-        for (unsigned i = 0; (i < ctx->temp_count) && !progress; ++i)
-                progress |= (blk->live_in[i] != live[i]);
-
-        free(blk->live_in);
-        blk->live_in = live;
-
-        return progress;
-}
-
-/* Globally, liveness analysis uses a fixed-point algorithm based on a
- * worklist. We initialize a work list with the exit block. We iterate the work
- * list to compute live_in from live_out for each block on the work list,
- * adding the predecessors of the block to the work list if we made progress.
- */
-
 static void
-mir_compute_liveness(
+mir_compute_interference(
                 compiler_context *ctx,
                 struct ra_graph *g)
 {
-        /* List of midgard_block */
-        struct set *work_list;
-
-        work_list = _mesa_set_create(ctx,
-                        _mesa_hash_pointer,
-                        _mesa_key_pointer_equal);
-
-        /* Allocate */
-
-        mir_foreach_block(ctx, block) {
-                block->live_in = calloc(ctx->temp_count, 1);
-                block->live_out = calloc(ctx->temp_count, 1);
-        }
-
-        /* Initialize the work list with the exit block */
-        struct set_entry *cur;
-
-        midgard_block *exit = mir_exit_block(ctx);
-        cur = _mesa_set_add(work_list, exit);
-
-        /* Iterate the work list */
-
-        do {
-                /* Pop off a block */
-                midgard_block *blk = (struct midgard_block *) cur->key;
-                _mesa_set_remove(work_list, cur);
-
-                /* Update its liveness information */
-                bool progress = liveness_block_update(ctx, blk);
-
-                /* If we made progress, we need to process the predecessors */
-
-                if (progress || (blk == exit)) {
-                        mir_foreach_predecessor(blk, pred)
-                                _mesa_set_add(work_list, pred);
-                }
-        } while((cur = _mesa_set_next_entry(work_list, NULL)) != NULL);
+        /* First, we need liveness information to be computed per block */
+        mir_compute_liveness(ctx);
 
         /* Now that every block has live_in/live_out computed, we can determine
          * interference by walking each block linearly. Take live_out at the
@@ -690,7 +573,7 @@ mir_compute_liveness(
                         }
 
                         /* Update live_in */
-                        liveness_ins_update(live, ins, ctx->temp_count);
+                        mir_liveness_ins_update(live, ins, ctx->temp_count);
                 }
 
                 free(live);
@@ -796,7 +679,7 @@ allocate_registers(compiler_context *ctx, bool *spilled)
                 ra_set_node_class(g, i, classes[class]);
         }
 
-        mir_compute_liveness(ctx, g);
+        mir_compute_interference(ctx, g);
 
         if (!ra_allocate(g)) {
                 *spilled = true;