panfrost: Respect backwards branches in RA

Fixes a bunch of issues with looping. Honestly, I'm not sure why loops
worked at all before.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2019-04-21 03:29:47 +00:00
parent 7d45bd9c91
commit c0fb2605dc
1 changed files with 69 additions and 14 deletions

View File

@ -169,9 +169,28 @@ typedef struct midgard_block {
/* Number of quadwords _actually_ emitted, as determined after scheduling */
unsigned quadword_count;
struct midgard_block *next_fallthrough;
/* Successors: always one forward (the block after us), maybe
* one backwards (for a backward branch). No need for a second
* forward, since graph traversal would get there eventually
* anyway */
struct midgard_block *successors[2];
unsigned nr_successors;
/* The successors pointer form a graph, and in the case of
* complex control flow, this graph has a cycles. To aid
* traversal during liveness analysis, we have a visited?
* boolean for passes to use as they see fit, provided they
* clean up later */
bool visited;
} midgard_block;
static void
midgard_block_add_successor(midgard_block *block, midgard_block *successor)
{
block->successors[block->nr_successors++] = successor;
assert(block->nr_successors <= ARRAY_SIZE(block->successors));
}
/* Helpers to generate midgard_instruction's using macro magic, since every
* driver seems to do it that way */
@ -1868,26 +1887,58 @@ midgard_is_live_in_instr(midgard_instruction *ins, int src)
return false;
}
/* Determine if a variable is live in the successors of a block */
static bool
is_live_after_successors(compiler_context *ctx, midgard_block *bl, int src)
{
for (unsigned i = 0; i < bl->nr_successors; ++i) {
midgard_block *succ = bl->successors[i];
/* If we already visited, the value we're seeking
* isn't down this path (or we would have short
* circuited */
if (succ->visited) continue;
/* Otherwise (it's visited *now*), check the block */
succ->visited = true;
mir_foreach_instr_in_block(succ, ins) {
if (midgard_is_live_in_instr(ins, src))
return true;
}
/* ...and also, check *its* successors */
if (is_live_after_successors(ctx, succ, src))
return true;
}
/* Welp. We're really not live. */
return false;
}
static bool
is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src)
{
/* Check the rest of the block for liveness */
mir_foreach_instr_in_block_from(block, ins, mir_next_op(start)) {
if (midgard_is_live_in_instr(ins, src))
return true;
}
/* Check the rest of the blocks for liveness */
mir_foreach_block_from(ctx, mir_next_block(block), b) {
mir_foreach_instr_in_block(b, ins) {
if (midgard_is_live_in_instr(ins, src))
return true;
}
/* Check the rest of the blocks for liveness recursively */
bool succ = is_live_after_successors(ctx, block, src);
mir_foreach_block(ctx, block) {
block->visited = false;
}
/* TODO: How does control flow interact in complex shaders? */
return false;
return succ;
}
static void
@ -3234,7 +3285,7 @@ emit_blend_epilogue(compiler_context *ctx)
static midgard_block *
emit_block(compiler_context *ctx, nir_block *block)
{
midgard_block *this_block = malloc(sizeof(midgard_block));
midgard_block *this_block = calloc(sizeof(midgard_block), 1);
list_addtail(&this_block->link, &ctx->blocks);
this_block->is_scheduled = false;
@ -3243,6 +3294,10 @@ emit_block(compiler_context *ctx, nir_block *block)
ctx->texture_index[0] = -1;
ctx->texture_index[1] = -1;
/* Add us as a successor to the block we are following */
if (ctx->current_block)
midgard_block_add_successor(ctx->current_block, this_block);
/* Set up current block */
list_inithead(&this_block->instructions);
ctx->current_block = this_block;
@ -3272,9 +3327,6 @@ emit_block(compiler_context *ctx, nir_block *block)
}
}
/* Fallthrough save */
this_block->next_fallthrough = ctx->previous_source_block;
if (block == nir_start_block(ctx->func->impl))
ctx->initial_block = this_block;
@ -3355,6 +3407,9 @@ emit_loop(struct compiler_context *ctx, nir_loop *nloop)
br_back.branch.target_block = start_idx;
emit_mir_instruction(ctx, br_back);
/* Mark down that branch in the graph */
midgard_block_add_successor(ctx->current_block, start_block);
/* Find the index of the block about to follow us (note: we don't add
* one; blocks are 0-indexed so we get a fencepost problem) */
int break_block_idx = ctx->block_count;