From 81624a6a187e556c4fa2b48d2cf83cf10b8b153b Mon Sep 17 00:00:00 2001 From: LeandroLP23 Date: Thu, 8 Oct 2026 10:59:30 +0200 Subject: [PATCH] refactor(recompiler): share the control flow helpers toHexString, contains, intersectSorted, addUnique, sortUnique, remapId, remapIds and rebuildPredecessors were defined with identical bodies in the anonymous namespaces of two of ControlFlowGraph.cpp, GraphBuilder.cpp and Structurizer.cpp. They are now declared in ControlFlowHelpers.hpp, which only these three files include, and defined in ControlFlowGraph.cpp. Co-Authored-By: Claude Opus 5.5 --- .../ControlFlow/ControlFlowHelpers.hpp | 22 +++++++++ .../ControlFlow/src/ControlFlowGraph.cpp | 42 +++++++++++++++- .../ControlFlow/src/GraphBuilder.cpp | 44 +---------------- .../ControlFlow/src/Structurizer.cpp | 48 +------------------ 4 files changed, 64 insertions(+), 92 deletions(-) create mode 100644 core/shader/recompiler/ControlFlow/include/ControlFlow/ControlFlowHelpers.hpp diff --git a/core/shader/recompiler/ControlFlow/include/ControlFlow/ControlFlowHelpers.hpp b/core/shader/recompiler/ControlFlow/include/ControlFlow/ControlFlowHelpers.hpp new file mode 100644 index 000000000..ced80a638 --- /dev/null +++ b/core/shader/recompiler/ControlFlow/include/ControlFlow/ControlFlowHelpers.hpp @@ -0,0 +1,22 @@ +#ifndef CORE_SHADER_RECOMPILIER_CONTROLFLOW_INCLUDE_CONTROLFLOW_CONTROLFLOWHELPERS_HPP +#define CORE_SHADER_RECOMPILIER_CONTROLFLOW_INCLUDE_CONTROLFLOW_CONTROLFLOWHELPERS_HPP + +#include "ControlFlow/ControlFlowGraph.hpp" +#include +#include +#include + +namespace ShaderRecompiler { + +std::string toHexString(std::uint32_t value); +bool contains(const std::vector& values, std::uint32_t value); +std::vector intersectSorted(const std::vector& first, const std::vector& second); +void addUnique(std::vector& values, std::uint32_t value); +void sortUnique(std::vector& values); +std::uint32_t remapId(std::uint32_t id, const std::vector& idMap); +void remapIds(std::vector& values, const std::vector& idMap); +void rebuildPredecessors(ControlFlowGraph& graph); + +} + +#endif diff --git a/core/shader/recompiler/ControlFlow/src/ControlFlowGraph.cpp b/core/shader/recompiler/ControlFlow/src/ControlFlowGraph.cpp index 12ebb915d..a0894ce95 100644 --- a/core/shader/recompiler/ControlFlow/src/ControlFlowGraph.cpp +++ b/core/shader/recompiler/ControlFlow/src/ControlFlowGraph.cpp @@ -1,4 +1,5 @@ #include "ControlFlow/ControlFlowGraph.hpp" +#include "ControlFlow/ControlFlowHelpers.hpp" #include #include #include @@ -7,8 +8,6 @@ namespace ShaderRecompiler { -namespace { - std::string toHexString(std::uint32_t value) { char buffer[11]; std::snprintf(buffer, sizeof(buffer), "0x%08x", value); @@ -25,6 +24,45 @@ std::vector intersectSorted(const std::vector& fir return result; } +void addUnique(std::vector& values, std::uint32_t value) { + if (std::find(values.begin(), values.end(), value) == values.end()) { + values.push_back(value); + } +} + +void sortUnique(std::vector& values) { + std::sort(values.begin(), values.end()); + values.erase(std::unique(values.begin(), values.end()), values.end()); +} + +std::uint32_t remapId(std::uint32_t id, const std::vector& idMap) { + return id != InvalidControlFlowId && id < idMap.size() ? idMap[id] : id; +} + +void remapIds(std::vector& values, const std::vector& idMap) { + for (auto& value : values) { + value = remapId(value, idMap); + } + sortUnique(values); +} + +void rebuildPredecessors(ControlFlowGraph& graph) { + for (auto& block : graph.blocks) { + block.predecessors.clear(); + sortUnique(block.successors); + } + for (const auto& block : graph.blocks) { + for (const auto successor : block.successors) { + addUnique(graph.blocks[successor].predecessors, block.id); + } + } + for (auto& block : graph.blocks) { + sortUnique(block.predecessors); + } +} + +namespace { + std::string joinIds(const std::vector& values) { std::string text; for (std::size_t i = 0; i < values.size(); ++i) { diff --git a/core/shader/recompiler/ControlFlow/src/GraphBuilder.cpp b/core/shader/recompiler/ControlFlow/src/GraphBuilder.cpp index cfcb917ff..5fe3c089b 100644 --- a/core/shader/recompiler/ControlFlow/src/GraphBuilder.cpp +++ b/core/shader/recompiler/ControlFlow/src/GraphBuilder.cpp @@ -1,4 +1,5 @@ #include "ControlFlow/GraphBuilder.hpp" +#include "ControlFlow/ControlFlowHelpers.hpp" #include #include #include @@ -12,38 +13,10 @@ namespace ShaderRecompiler { namespace { -std::string toHexString(std::uint32_t value) { - char buffer[11]; - std::snprintf(buffer, sizeof(buffer), "0x%08x", value); - return std::string(buffer); -} - std::uint32_t instructionEndProgramCounter(const RdnaInstruction& instruction) { return instruction.programCounter + instruction.wordCount * 4u; } -void addUnique(std::vector& values, std::uint32_t value) { - if (std::find(values.begin(), values.end(), value) == values.end()) { - values.push_back(value); - } -} - -void sortUnique(std::vector& values) { - std::sort(values.begin(), values.end()); - values.erase(std::unique(values.begin(), values.end()), values.end()); -} - -std::uint32_t remapId(std::uint32_t id, const std::vector& idMap) { - return id != InvalidControlFlowId && id < idMap.size() ? idMap[id] : id; -} - -void remapIds(std::vector& values, const std::vector& idMap) { - for (auto& value : values) { - value = remapId(value, idMap); - } - sortUnique(values); -} - std::uint32_t estimatedSpirvWords(const RdnaInstruction& instruction) { switch (instruction.op) { case RdnaOpcode::VReadfirstlaneB32: @@ -408,21 +381,6 @@ BranchCondition conditionForOpcode(RdnaOpcode opcode) { throw std::logic_error("unreachable branch condition for opcode " + std::to_string(static_cast(opcode))); } -void rebuildPredecessors(ControlFlowGraph& graph) { - for (auto& block : graph.blocks) { - block.predecessors.clear(); - sortUnique(block.successors); - } - for (const auto& block : graph.blocks) { - for (const auto successor : block.successors) { - addUnique(graph.blocks[successor].predecessors, block.id); - } - } - for (auto& block : graph.blocks) { - sortUnique(block.predecessors); - } -} - void pruneUnreachableBlocks(ControlFlowGraph& graph) { if (graph.entryBlock >= graph.blocks.size()) { throw std::invalid_argument("control flow graph entry block is out of range"); diff --git a/core/shader/recompiler/ControlFlow/src/Structurizer.cpp b/core/shader/recompiler/ControlFlow/src/Structurizer.cpp index f23bd9258..adc933239 100644 --- a/core/shader/recompiler/ControlFlow/src/Structurizer.cpp +++ b/core/shader/recompiler/ControlFlow/src/Structurizer.cpp @@ -1,4 +1,5 @@ #include "ControlFlow/Structurizer.hpp" +#include "ControlFlow/ControlFlowHelpers.hpp" #include #include #include @@ -19,27 +20,6 @@ std::vector allBlockIds(std::uint32_t count) { return ids; } -std::vector intersectSorted(const std::vector& first, const std::vector& second) { - std::vector result; - std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), std::back_inserter(result)); - return result; -} - -void sortUnique(std::vector& values) { - std::sort(values.begin(), values.end()); - values.erase(std::unique(values.begin(), values.end()), values.end()); -} - -void addUnique(std::vector& values, std::uint32_t value) { - if (std::find(values.begin(), values.end(), value) == values.end()) { - values.push_back(value); - } -} - -bool contains(const std::vector& values, std::uint32_t value) { - return std::find(values.begin(), values.end(), value) != values.end(); -} - bool replaceValue(std::vector& values, std::uint32_t oldValue, std::uint32_t newValue) { bool changed = false; for (auto& value : values) { @@ -73,32 +53,6 @@ bool replaceTerminatorTarget(Terminator& terminator, std::uint32_t oldValue, std return changed; } -std::uint32_t remapId(std::uint32_t id, const std::vector& idMap) { - return id != InvalidControlFlowId && id < idMap.size() ? idMap[id] : id; -} - -void remapIds(std::vector& values, const std::vector& idMap) { - for (auto& value : values) { - value = remapId(value, idMap); - } - sortUnique(values); -} - -void rebuildPredecessors(ControlFlowGraph& graph) { - for (auto& block : graph.blocks) { - block.predecessors.clear(); - sortUnique(block.successors); - } - for (const auto& block : graph.blocks) { - for (const auto successor : block.successors) { - addUnique(graph.blocks[successor].predecessors, block.id); - } - } - for (auto& block : graph.blocks) { - sortUnique(block.predecessors); - } -} - std::vector applyBlockOrder(ControlFlowGraph& graph, std::vector blocks) { std::vector idMap(blocks.size(), InvalidControlFlowId); for (std::uint32_t i = 0; i < blocks.size(); ++i) {