From c6a932d4b3783943ae06a1c0a6460e1dbd43d89c Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Tue, 11 Feb 2025 09:13:26 +0100 Subject: [PATCH] ir3/ra: handle phis with preferred regs first Handle phis in two groups: first those which already have a preferred reg set and then those without. The second group should be rare but by handling them last, they don't accidentally occupy a preferred reg of another phi, preventing excessive copying in some cases. Signed-off-by: Job Noorman Part-of: --- src/freedreno/ir3/ir3_ra.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index 97e4815318c..1a6377dd821 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -2293,9 +2293,22 @@ handle_block(struct ra_ctx *ctx, struct ir3_block *block) handle_live_in(ctx, reg); } + /* Handle phis in two groups: first those which already have a preferred reg + * set and then those without. The second group should be rare but by + * handling them last, they don't accidentally occupy a preferred reg of + * another phi, preventing excessive copying in some cases. + */ + bool skipped_phi = false; + foreach_instr (instr, &block->instr_list) { if (instr->opc == OPC_META_PHI) { - handle_phi(ctx, instr->dsts[0]); + struct ir3_register *dst = instr->dsts[0]; + + if (dst->merge_set && dst->merge_set->preferred_reg != (physreg_t)~0) { + handle_phi(ctx, dst); + } else { + skipped_phi = true; + } } else if (instr->opc == OPC_META_INPUT || instr->opc == OPC_META_TEX_PREFETCH) { handle_input(ctx, instr); @@ -2304,6 +2317,20 @@ handle_block(struct ra_ctx *ctx, struct ir3_block *block) } } + if (skipped_phi) { + foreach_instr (instr, &block->instr_list) { + if (instr->opc == OPC_META_PHI) { + struct ir3_register *dst = instr->dsts[0]; + + if (!ctx->intervals[dst->name].interval.inserted) { + handle_phi(ctx, dst); + } + } else { + break; + } + } + } + /* After this point, every live-in/phi/input has an interval assigned to * it. We delay actually assigning values until everything has been * allocated, so we can simply ignore any parallel copy entries created