From c031a53a784d9f1d9349068fe9ad0b15c71e6ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Sat, 25 Jan 2025 08:56:18 +0100 Subject: [PATCH] r300: copy propagate constant swizzles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example: SIN temp[1].x, temp[0].x___; MOV temp[1].y, none._1__; ADD temp[2].xyz, temp[1].xy__, const[0].ww__; could be transformed into SIN temp[1].x, temp[0].x___; ADD temp[0].xyz, temp[1].x1__, const[0].ww__; Shader-db RV410: total instructions in shared programs: 112613 -> 112451 (-0.14%) instructions in affected programs: 15613 -> 15451 (-1.04%) helped: 148 HURT: 1 total temps in shared programs: 18149 -> 18129 (-0.11%) temps in affected programs: 297 -> 277 (-6.73%) helped: 21 HURT: 2 total cycles in shared programs: 169432 -> 169273 (-0.09%) cycles in affected programs: 17779 -> 17620 (-0.89%) helped: 145 HURT: 4 RV530: total instructions in shared programs: 128650 -> 128443 (-0.16%) instructions in affected programs: 21647 -> 21440 (-0.96%) helped: 206 HURT: 4 total temps in shared programs: 17014 -> 17010 (-0.02%) temps in affected programs: 216 -> 212 (-1.85%) helped: 11 HURT: 6 total cycles in shared programs: 190719 -> 190523 (-0.10%) cycles in affected programs: 28892 -> 28696 (-0.68%) helped: 203 HURT: 8 Signed-off-by: Pavel Ondračka Reviewed-by: Filip Gawin Part-of: --- .../drivers/r300/compiler/radeon_optimize.c | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/gallium/drivers/r300/compiler/radeon_optimize.c b/src/gallium/drivers/r300/compiler/radeon_optimize.c index 46b1745b921..f0cdee0838e 100644 --- a/src/gallium/drivers/r300/compiler/radeon_optimize.c +++ b/src/gallium/drivers/r300/compiler/radeon_optimize.c @@ -1321,6 +1321,77 @@ merge_A0_loads(struct radeon_compiler *c, struct rc_instruction *inst, bool is_A } } +/** + * Search for instructions where we could copy propagate the constant swizzle + * to the reader, for example the following sequence + * + * SIN temp[1].x, temp[0].x___; + * MOV temp[1].y, none._1__; + * ADD temp[2].xyz, temp[1].xy__, const[0].ww__; + * + * could be transformed into + * + * SIN temp[1].x, temp[0].x___; + * ADD temp[0].xyz, temp[1].x1__, const[0].ww__; + */ +static void +copy_propagate_constant_swizzle(struct radeon_compiler *c, struct rc_instruction *inst) +{ + unsigned int orig_dst_reg = inst->U.I.DstReg.Index; + unsigned int orig_dst_wmask = inst->U.I.DstReg.WriteMask; + + struct rc_instruction *cur = inst; + while (cur != &c->Program.Instructions) { + cur = cur->Next; + const struct rc_opcode_info *opcode = rc_get_opcode_info(cur->U.I.Opcode); + + /* Keep it simple for now and stop when encountering any control flow. */ + if (opcode->IsFlowControl) + break; + + /* We should not see the original destination overwritten (within a control flow block). + * If that happens, we don't have SSA-like anymore and several later assumptions would + * be broken. */ + assert(orig_dst_reg != cur->U.I.DstReg.Index || RC_FILE_TEMPORARY != cur->U.I.DstReg.File || + (orig_dst_wmask & cur->U.I.DstReg.WriteMask) == 0); + + for (unsigned int src = 0; src < opcode->NumSrcRegs; src++) { + if (cur->U.I.SrcReg[src].File == RC_FILE_TEMPORARY && + cur->U.I.SrcReg[src].Index == orig_dst_reg && + rc_swizzle_to_writemask(cur->U.I.SrcReg[src].Swizzle) & orig_dst_wmask) { + + /* Construct the new swizzle. */ + unsigned new_swizzle = cur->U.I.SrcReg[src].Swizzle; + unsigned negate = 0; + for (unsigned chan = 0; chan < 4; chan++) { + unsigned swz = GET_SWZ(new_swizzle, chan); + unsigned swz_to_propagate = GET_SWZ(inst->U.I.SrcReg[0].Swizzle, swz); + if (swz_to_propagate > RC_SWIZZLE_W && swz_to_propagate < RC_SWIZZLE_UNUSED) { + SET_SWZ(new_swizzle, chan, swz_to_propagate); + negate |= inst->U.I.SrcReg[0].Negate & (1 << swz); + } + } + struct rc_src_register new_src = cur->U.I.SrcReg[src]; + new_src.Swizzle = new_swizzle; + new_src.Negate ^= negate; + if (!c->SwizzleCaps->IsNative(cur->U.I.Opcode, new_src)) + continue; + + cur->U.I.SrcReg[src] = new_src; + } + } + } + + /* Now check if we can delete the original MOV. Specifically if we still have some + * readers left. + */ + struct rc_reader_data readers; + readers.ExitOnAbort = 0; + rc_get_readers(c, inst, &readers, NULL, NULL, NULL); + if (readers.ReaderCount == 0) + rc_remove_instruction(inst); +} + /** * According to the GLSL spec, round is only 1.30 and up * so the only reason why we should ever see round is if it actually @@ -1420,6 +1491,17 @@ rc_optimize(struct radeon_compiler *c, void *user) } } + /* Copy propagate constant swizzles */ + inst = c->Program.Instructions.Next; + while (inst != &c->Program.Instructions) { + struct rc_instruction *cur = inst; + inst = inst->Next; + if (cur->U.I.Opcode == RC_OPCODE_MOV && cur->U.I.SrcReg[0].File == RC_FILE_NONE && + cur->U.I.DstReg.File == RC_FILE_TEMPORARY) { + copy_propagate_constant_swizzle(c, cur); + } + } + if (c->type != RC_FRAGMENT_PROGRAM) { return; }