From 6a183a9ffd1baa0abe4ed1da74a55dd004341c0d Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 21 Sep 2022 23:23:14 -0400 Subject: [PATCH] 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 Part-of: --- src/asahi/compiler/agx_compile.c | 6 ++---- src/asahi/compiler/agx_compiler.h | 14 +++++++++++++ src/asahi/compiler/agx_liveness.c | 24 ++++++---------------- src/asahi/compiler/agx_register_allocate.c | 9 ++------ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 721f4e3e30e..1baa479243a 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -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); } } diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index 7d9cd1b5b0f..d84deecd8d0 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -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. */ diff --git a/src/asahi/compiler/agx_liveness.c b/src/asahi/compiler/agx_liveness.c index 1088e0ae5ee..ccb89dcef69 100644 --- a/src/asahi/compiler/agx_liveness.c +++ b/src/asahi/compiler/agx_liveness.c @@ -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); } diff --git a/src/asahi/compiler/agx_register_allocate.c b/src/asahi/compiler/agx_register_allocate.c index 0c6cbd0a700..9f1b689ebb9 100644 --- a/src/asahi/compiler/agx_register_allocate.c +++ b/src/asahi/compiler/agx_register_allocate.c @@ -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];