From b0c86ec07f7103d0e2829bd30c5c54fa0372eed8 Mon Sep 17 00:00:00 2001 From: Scramblrrrr Date: Sat, 10 Oct 2026 15:58:56 -0300 Subject: [PATCH] fix(recompiler): privatize shared continuations before loop gateways --- core/libs/prx/libSceAgcDriver/tests/ControlFlow.cpp | 2 ++ core/libs/prx/libSceAgcDriver/tests/Structurizer.cpp | 1 + core/shader/recompiler/ControlFlow/src/Structurizer.cpp | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libSceAgcDriver/tests/ControlFlow.cpp b/core/libs/prx/libSceAgcDriver/tests/ControlFlow.cpp index 9124a643f..8b1f9f2e3 100644 --- a/core/libs/prx/libSceAgcDriver/tests/ControlFlow.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/ControlFlow.cpp @@ -409,6 +409,8 @@ int main(int argc, char** argv) { return failures == 0 ? 0 : 1; } const std::vector programs{ + {"nested selections share a loop continuation", "Synthetic loop with two nested selections and a shared continue; the inner selection does not dominate the continuation.", + {0x060202ffu, 0x3f800000u, 0x060202ffu, 0x3f810000u, 0x7d880084u, 0xbf870001u, 0xbf820018u, 0x060202ffu, 0x3f820000u, 0x7d880085u, 0xbf87000cu, 0x060202ffu, 0x3f850000u, 0x7d880088u, 0xbf870003u, 0x060202ffu, 0x3f870000u, 0xbf82fff0u, 0x060202ffu, 0x3f860000u, 0x7d880089u, 0xbf87fff9u, 0xbf820008u, 0x060202ffu, 0x3f830000u, 0x7d880086u, 0xbf870001u, 0xbf820003u, 0x060202ffu, 0x3f840000u, 0xbf82fff0u, 0x060202ffu, 0x3f880000u, 0xe0700000u, 0x80000100u, 0xbf810000u}, Split::None}, {"reduced shared exit junction from the public CFG fuzz report", "Public reduced word stream from #2762; synthetic regression, not title data.", {0x060202f2u, 0x060202f4u, 0x7d880084u, 0xbf870001u, 0xbf820011u, 0x060202ffu, 0x3f820000u, 0x7d880085u, 0xbf870005u, 0x060202ffu, 0x3f850000u, 0x7d880088u, 0xbf870009u, 0xbf82fff3u, 0x060202ffu, 0x3f840000u, 0x7d880087u, 0xbf870001u, diff --git a/core/libs/prx/libSceAgcDriver/tests/Structurizer.cpp b/core/libs/prx/libSceAgcDriver/tests/Structurizer.cpp index d2d73a6f5..385d2830e 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Structurizer.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Structurizer.cpp @@ -339,6 +339,7 @@ int main() { auto chain = makeGraph(diamonds); Structurizer{}.Structurize(chain); requireExactPostDominators(chain, "a chain of fifty selections"); + requireStructuredLoop({{1}, {2, 8}, {3, 5}, {4, 8}, {7}, {6, 7}, {7, 8}, {1}, {}}, "nested selections sharing a loop continuation"); auto sharedDiscard = makeGraph({{5, 1}, {4, 2}, {7, 3}, {7, 4}, {5}, {7, 6}, {}, {}}); const std::vector sharedDiscardWords{444, 1944, 68, 1128, 8, 2084, 148, 28}; for (auto& block : sharedDiscard.blocks) { diff --git a/core/shader/recompiler/ControlFlow/src/Structurizer.cpp b/core/shader/recompiler/ControlFlow/src/Structurizer.cpp index d74417014..3cb0b0530 100644 --- a/core/shader/recompiler/ControlFlow/src/Structurizer.cpp +++ b/core/shader/recompiler/ControlFlow/src/Structurizer.cpp @@ -567,7 +567,7 @@ std::uint32_t findSelectionMerge(const ControlFlowGraph& graph, const BasicBlock return globalMerge; } - if (routeLeavingExits && graph.Dominates(block.id, loop->continueBlock) && reachesWithinIteration(graph, *loop, trueTarget, loop->continueBlock) && reachesWithinIteration(graph, *loop, falseTarget, loop->continueBlock)) { + if (routeLeavingExits && reachesWithinIteration(graph, *loop, trueTarget, loop->continueBlock) && reachesWithinIteration(graph, *loop, falseTarget, loop->continueBlock)) { return joinWithinIteration(graph, *loop, trueTarget, falseTarget, loop->continueBlock); } if (isLoopControlGateway(graph, *loop, trueTarget) && graph.Dominates(block.id, trueTarget) && isInsideLoopConstruct(graph, *loop, falseTarget)) {