From a667e1bb6ddaafedcd1db16e1ff520c805338a9c Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 16 Jul 2021 18:18:08 -0400 Subject: [PATCH] pan/bi: Copy liveness routines back We'll diverge shortly. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/bifrost/bi_liveness.c | 115 +++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 8 deletions(-) diff --git a/src/panfrost/bifrost/bi_liveness.c b/src/panfrost/bifrost/bi_liveness.c index 1e4bfcbae3d..9ac03da3e68 100644 --- a/src/panfrost/bifrost/bi_liveness.c +++ b/src/panfrost/bifrost/bi_liveness.c @@ -23,6 +23,13 @@ */ #include "compiler.h" +#include "util/u_memory.h" +#include "util/list.h" +#include "util/set.h" + +/* 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. */ void bi_liveness_ins_update(uint16_t *live, bi_instr *ins, unsigned max) @@ -30,8 +37,10 @@ bi_liveness_ins_update(uint16_t *live, bi_instr *ins, unsigned max) /* live_in[s] = GEN[s] + (live_out[s] - KILL[s]) */ bi_foreach_dest(ins, d) { - pan_liveness_kill(live, bi_get_node(ins->dest[d]), max, - bi_writemask(ins, d)); + unsigned node = bi_get_node(ins->dest[d]); + + if (node < max) + live[node] &= ~bi_writemask(ins, d); } bi_foreach_src(ins, src) { @@ -40,14 +49,58 @@ bi_liveness_ins_update(uint16_t *live, bi_instr *ins, unsigned max) uint16_t mask = (rmask << ins->src[src].offset); unsigned node = bi_get_node(ins->src[src]); - pan_liveness_gen(live, node, max, mask); + if (node < max) + live[node] |= mask; } } -static void -bi_liveness_ins_update_wrap(uint16_t *live, void *ins, unsigned max) +static bool +liveness_block_update(pan_block *blk, unsigned temp_count) { - bi_liveness_ins_update(live, (bi_instr *) ins, max); + bool progress = false; + + /* live_out[s] = sum { p in succ[s] } ( live_in[p] ) */ + pan_foreach_successor(blk, succ) { + for (unsigned i = 0; i < temp_count; ++i) + blk->live_out[i] |= succ->live_in[i]; + } + + uint16_t *live = ralloc_array(blk, uint16_t, temp_count); + memcpy(live, blk->live_out, temp_count * sizeof(uint16_t)); + + pan_foreach_instr_in_block_rev(blk, ins) + bi_liveness_ins_update(live, (bi_instr *) ins, temp_count); + + /* To figure out progress, diff live_in */ + + for (unsigned i = 0; (i < temp_count) && !progress; ++i) + progress |= (blk->live_in[i] != live[i]); + + ralloc_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 +free_liveness(struct list_head *blocks) +{ + list_for_each_entry(pan_block, block, blocks, link) { + if (block->live_in) + ralloc_free(block->live_in); + + if (block->live_out) + ralloc_free(block->live_out); + + block->live_in = NULL; + block->live_out = NULL; + } } void @@ -56,7 +109,53 @@ bi_compute_liveness(bi_context *ctx) if (ctx->has_liveness) return; - pan_compute_liveness(&ctx->blocks, bi_max_temp(ctx), bi_liveness_ins_update_wrap); + unsigned temp_count = bi_max_temp(ctx); + + /* Set of pan_block */ + struct set *work_list = _mesa_set_create(NULL, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + + struct set *visited = _mesa_set_create(NULL, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + + /* Free any previous liveness, and allocate */ + + free_liveness(&ctx->blocks); + + list_for_each_entry(pan_block, block, &ctx->blocks, link) { + block->live_in = rzalloc_array(block, uint16_t, temp_count); + block->live_out = rzalloc_array(block, uint16_t, temp_count); + } + + /* Initialize the work list with the exit block */ + struct set_entry *cur; + + cur = _mesa_set_add(work_list, pan_exit_block(&ctx->blocks)); + + /* Iterate the work list */ + + do { + /* Pop off a block */ + pan_block *blk = (struct pan_block *) cur->key; + _mesa_set_remove(work_list, cur); + + /* Update its liveness information */ + bool progress = liveness_block_update(blk, temp_count); + + /* If we made progress, we need to process the predecessors */ + + if (progress || !_mesa_set_search(visited, blk)) { + pan_foreach_predecessor(blk, pred) + _mesa_set_add(work_list, pred); + } + + _mesa_set_add(visited, blk); + } while((cur = _mesa_set_next_entry(work_list, NULL)) != NULL); + + _mesa_set_destroy(visited, NULL); + _mesa_set_destroy(work_list, NULL); ctx->has_liveness = true; } @@ -67,7 +166,7 @@ void bi_invalidate_liveness(bi_context *ctx) { if (ctx->has_liveness) - pan_free_liveness(&ctx->blocks); + free_liveness(&ctx->blocks); ctx->has_liveness = false; }