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:
@@ -21,11 +21,6 @@
|
|||||||
* SOFTWARE.
|
* 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 "compiler.h"
|
||||||
#include "util/u_memory.h"
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
@@ -49,6 +44,14 @@ liveness_kill(uint8_t *live, unsigned node, unsigned max, unsigned mask)
|
|||||||
live[node] &= ~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 */
|
/* Updates live_in for a single instruction */
|
||||||
|
|
||||||
void
|
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
|
bool
|
||||||
mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src)
|
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 */
|
/* 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the rest of the blocks for liveness recursively */
|
return false;
|
||||||
|
|
||||||
bool succ = is_live_after_successors(ctx, block, src);
|
|
||||||
|
|
||||||
mir_foreach_block(ctx, block) {
|
|
||||||
block->visited = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return succ;
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user