pan/midgard: Replace mir_is_live_after with new pass

Now that we have live_out calculated per block as metadata, calculating
liveness of an instruction at a given point in the program becomes O(n)
to the size of the block worst-case, rather than O(n) the program.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
Alyssa Rosenzweig
2019-10-03 21:42:09 -04:00
parent 39a4b3ebe9
commit dcd2f26b98

View File

@@ -21,11 +21,6 @@
* SOFTWARE.
*/
/* mir_is_live_after performs liveness analysis on the MIR, used primarily
* as part of register allocation. TODO: Algorithmic improvements for
* compiler performance (this is the worst algorithm possible -- see
* backlog with Connor on IRC) */
#include "compiler.h"
#include "util/u_memory.h"
@@ -49,6 +44,14 @@ liveness_kill(uint8_t *live, unsigned node, unsigned max, unsigned mask)
live[node] &= ~mask;
}
static bool
liveness_get(uint8_t *live, unsigned node, unsigned max) {
if (node >= max)
return false;
return live[node];
}
/* Updates live_in for a single instruction */
void
@@ -183,52 +186,15 @@ mir_invalidate_liveness(compiler_context *ctx)
}
}
/* 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;
/* Within this block, check if it's overwritten first */
unsigned overwritten_mask = 0;
mir_foreach_instr_in_block(succ, ins) {
/* Did we read any components that we haven't overwritten yet? */
if (mir_mask_of_read_components(ins, src) & ~overwritten_mask)
return true;
/* If written-before-use, we're gone */
if (ins->dest == src)
overwritten_mask |= ins->mask;
}
/* ...and also, check *its* successors */
if (is_live_after_successors(ctx, succ, src))
return true;
}
/* Welp. We're really not live. */
return false;
}
bool
mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src)
{
assert(ctx->metadata & MIDGARD_METADATA_LIVENESS);
mir_compute_liveness(ctx);
/* Check whether we're live in the successors */
if (liveness_get(block->live_out, src, ctx->temp_count))
return true;
/* Check the rest of the block for liveness */
@@ -237,13 +203,5 @@ mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instructi
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;
}
return succ;
return false;
}