agx: Add iterators for phi/non-phi instructions

We know that phi nodes are always at the start (this is asserted in
agx_validate and a fundamental invariant of SSA form). That means we can
cheaply iterate all n phi nodes forward (or n non-phi nodes backwards)
in O(n) time. We already open code this idiom in a few places, use
common iterators instead so we don't need to justify in random places.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18804>
This commit is contained in:
Alyssa Rosenzweig
2022-09-21 23:23:14 -04:00
committed by Marge Bot
parent d3880a6324
commit 6a183a9ffd
4 changed files with 24 additions and 29 deletions

View File

@@ -1246,10 +1246,8 @@ static void
agx_emit_phis_deferred(agx_context *ctx)
{
agx_foreach_block(ctx, block) {
agx_foreach_instr_in_block(block, I) {
if (I->op == AGX_OPCODE_PHI)
agx_emit_phi_deferred(ctx, block, I);
}
agx_foreach_phi_in_block(block, I)
agx_emit_phi_deferred(ctx, block, I);
}
}

View File

@@ -536,6 +536,20 @@ agx_vec_for_intr(agx_context *ctx, nir_intrinsic_instr *instr)
#define agx_foreach_dest(ins, v) \
for (unsigned v = 0; v < ARRAY_SIZE(ins->dest); ++v)
/* Phis only come at the start so we stop as soon as we hit a non-phi */
#define agx_foreach_phi_in_block(block, v) \
agx_foreach_instr_in_block(block, v) \
if (v->op != AGX_OPCODE_PHI) \
break; \
else
/* Everything else comes after, so we stop as soon as we hit a phi in reverse */
#define agx_foreach_non_phi_in_block_rev(block, v) \
agx_foreach_instr_in_block_rev(block, v) \
if (v->op == AGX_OPCODE_PHI) \
break; \
else
/*
* Find the index of a predecessor, used as the implicit order of phi sources.
*/

View File

@@ -87,16 +87,8 @@ agx_compute_liveness(agx_context *ctx)
/* Update its liveness information */
memcpy(blk->live_in, blk->live_out, words * sizeof(BITSET_WORD));
agx_foreach_instr_in_block_rev(blk, I) {
/* Phi nodes are handled separately, so we skip them. As phi nodes are at
* the beginning and we're iterating backwards, we stop as soon as we hit
* a phi node.
*/
if (I->op == AGX_OPCODE_PHI)
break;
agx_foreach_non_phi_in_block_rev(blk, I)
agx_liveness_ins_update(blk->live_in, I);
}
/* Propagate the live in of the successor (blk) to the live out of
* predecessors.
@@ -110,18 +102,14 @@ agx_compute_liveness(agx_context *ctx)
memcpy(live, blk->live_in, words * sizeof(BITSET_WORD));
/* Kill write */
agx_foreach_instr_in_block(blk, I) {
if (I->op != AGX_OPCODE_PHI) break;
assert(I->dest[0].type == AGX_INDEX_NORMAL);
BITSET_CLEAR(live, I->dest[0].value);
agx_foreach_phi_in_block(blk, phi) {
assert(phi->dest[0].type == AGX_INDEX_NORMAL);
BITSET_CLEAR(live, phi->dest[0].value);
}
/* Make live the corresponding source */
agx_foreach_instr_in_block(blk, I) {
if (I->op != AGX_OPCODE_PHI) break;
agx_index operand = I->src[agx_predecessor_index(blk, *pred)];
agx_foreach_phi_in_block(blk, phi) {
agx_index operand = phi->src[agx_predecessor_index(blk, *pred)];
assert(operand.type == AGX_INDEX_NORMAL);
BITSET_SET(live, operand.value);
}

View File

@@ -221,10 +221,7 @@ agx_insert_parallel_copies(agx_context *ctx, agx_block *block)
agx_foreach_successor(block, succ) {
assert(nr_phi == 0 && "control flow graph has a critical edge");
/* Phi nodes can only come at the start of the block */
agx_foreach_instr_in_block(succ, phi) {
if (phi->op != AGX_OPCODE_PHI) break;
agx_foreach_phi_in_block(succ, phi) {
assert(!any_succ && "control flow graph has a critical edge");
nr_phi++;
}
@@ -242,9 +239,7 @@ agx_insert_parallel_copies(agx_context *ctx, agx_block *block)
unsigned i = 0;
agx_foreach_instr_in_block(succ, phi) {
if (phi->op != AGX_OPCODE_PHI) break;
agx_foreach_phi_in_block(succ, phi) {
agx_index dest = phi->dest[0];
agx_index src = phi->src[pred_index];