From be386cf23038af79263678b5ec87c132458f8fae Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Fri, 12 Jun 2026 22:07:26 +0200 Subject: [PATCH] feat(furc/ssa): implement renaming Refs: #2 --- furc/src/front/ssa.cpp | 69 ++++++++++++++++++++++++++ furlang/include/furlang/ir/operand.hpp | 7 +++ 2 files changed, 76 insertions(+) diff --git a/furc/src/front/ssa.cpp b/furc/src/front/ssa.cpp index ea25e53..1ed0a0e 100644 --- a/furc/src/front/ssa.cpp +++ b/furc/src/front/ssa.cpp @@ -5,7 +5,9 @@ #include #include +#include #include +#include #include #include #include @@ -27,6 +29,10 @@ void ssa::optimize(const std::unique_ptr& func) { std::unordered_map idoms; + std::unordered_map regVers; + std::unordered_map> regVerStacks; + std::unordered_map> domTree; + for (furlang::ir::block_index i = 0; i < func->blocks().size(); ++i) { const auto& block = func->blocks()[i]; @@ -164,6 +170,69 @@ void ssa::optimize(const std::unique_ptr& func) { block->instructions().emplace(block->instructions().begin(), std::move(phiInstr)); } } + + for (const auto& [block, idom] : idoms) { + if (block != idom) domTree[idom].push_back(block); + } + + std::function renameBlock = [&](furlang::ir::block_index blockIndex) -> void { + std::unordered_map pushed; + + const auto& block = func->blocks()[blockIndex]; + for (auto& instr : block->instructions()) { + if (instr->type() != furlang::ir::instruction_t::Phi) continue; + auto orig = instr->destination().reg(); + std::uint32_t newVer = regVers[orig]++; + instr->destination().reg().ver = newVer; + regVerStacks[orig].push(newVer); + ++pushed[orig]; + } + + for (auto& instr : block->instructions()) { + if (instr->type() == furlang::ir::instruction_t::Phi) continue; + + for (auto& operand : instr->sources()) { + if (operand->type() != furlang::ir::operand_t::Register) continue; + auto orig = operand->reg(); + if (!regVerStacks[orig].empty()) { + operand->reg().ver = regVerStacks[orig].top(); + } + } + + if (instr->has_destination() || instr->destination().type() == furlang::ir::operand_t::Register) { + auto orig = instr->destination().reg(); + std::uint32_t newVer = regVers[orig]++; + instr->destination().reg().ver = newVer; + regVerStacks[orig].push(newVer); + ++pushed[orig]; + } + } + + for (auto succIndex : successors[blockIndex]) { + const auto& succ = func->blocks()[succIndex]; + for (auto& instr : succ->instructions()) { + if (instr->type() != furlang::ir::instruction_t::Phi) break; + auto& phi = dynamic_cast(*instr); + for (auto& [op, bl] : phi.labels()) { + if (bl != blockIndex) continue; + if (regVerStacks[op.reg()].empty()) continue; + op.reg().ver = regVerStacks[op.reg()].top(); + } + } + } + + for (const auto& child : domTree[blockIndex]) { + renameBlock(child); + } + + for (const auto& [reg, count] : pushed) { + for (std::uint32_t i = 0; i < count; ++i) { + regVerStacks[reg].pop(); + } + } + }; + + renameBlock(entry); } void ssa::dfs_rpo(furlang::ir::block_index block, diff --git a/furlang/include/furlang/ir/operand.hpp b/furlang/include/furlang/ir/operand.hpp index 145aa92..81406d9 100644 --- a/furlang/include/furlang/ir/operand.hpp +++ b/furlang/include/furlang/ir/operand.hpp @@ -198,6 +198,13 @@ public: */ operand_t type() const { return m_type; } + /** + * @brief Returns this operand's register value. + * + * @return The register value. + */ + register_operand& reg() { return m_value.reg; } + /** * @brief Returns this operand's register value. *