From 986015bc0964c7a02d375c5bfd6927bc8e27de7d Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 14 Jun 2026 11:59:39 +0200 Subject: [PATCH] feat(furc/ssa): implement copy propagation Refs: #2 --- furc/include/furc/front/ssa.hpp | 2 + furc/src/front/ssa.cpp | 55 ++++++++++++++++++++++++++ furlang/include/furlang/ir/operand.hpp | 4 +- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/furc/include/furc/front/ssa.hpp b/furc/include/furc/front/ssa.hpp index 76299a7..fa83f78 100644 --- a/furc/include/furc/front/ssa.hpp +++ b/furc/include/furc/front/ssa.hpp @@ -24,6 +24,8 @@ private: static void dead_code_elimination(const std::unique_ptr& func); + static void copy_propagation(const std::unique_ptr& func); + static void dfs_rpo(furlang::ir::block_index block, const block_map_t& successors, std::unordered_set& visited, diff --git a/furc/src/front/ssa.cpp b/furc/src/front/ssa.cpp index 809cc5d..be5f55d 100644 --- a/furc/src/front/ssa.cpp +++ b/furc/src/front/ssa.cpp @@ -21,6 +21,8 @@ void ssa::optimize(furlang::ir::module& mod) { ssa::optimize(func); ssa::constant_propagation(func); ssa::dead_code_elimination(func); + ssa::copy_propagation(func); + ssa::dead_code_elimination(func); } } @@ -534,6 +536,59 @@ void ssa::dead_code_elimination(const std::unique_ptr& fu } } +void ssa::copy_propagation(const std::unique_ptr& func) { + using block_idx = furlang::ir::block_index; + using reg_t = furlang::ir::register_operand; + + std::unordered_map aliasMap; + + std::function findRep = [&](const reg_t& reg) -> reg_t { + auto it = aliasMap.find(reg); + if (it == aliasMap.end()) return reg; + reg_t act = findRep(it->second); + aliasMap[reg] = act; + return act; + }; + + for (block_idx blockIdx = 0; blockIdx < func->blocks().size(); ++blockIdx) { + const auto& block = func->blocks()[blockIdx]; + for (auto& instr : block->instructions()) { + if (instr->type() != furlang::ir::instruction_t::Assign) continue; + auto& srcOp = *instr->sources().front(); + if (srcOp.type() != furlang::ir::operand_t::Register || + instr->destination().type() != furlang::ir::operand_t::Register) + continue; + reg_t dstReg = instr->destination().reg(); + reg_t srcReg = srcOp.reg(); + reg_t repSrc = findRep(srcReg); + reg_t repDst = findRep(dstReg); + if (repSrc == repDst) continue; + aliasMap[repDst] = repSrc; + } + } + + for (block_idx blockIdx = 0; blockIdx < func->blocks().size(); ++blockIdx) { + const auto& block = func->blocks()[blockIdx]; + for (auto& instr : block->instructions()) { + for (auto& op : instr->sources()) { + if (op->type() != furlang::ir::operand_t::Register) continue; + op->reg() = findRep(op->reg()); + } + if (instr->type() != furlang::ir::instruction_t::Phi) continue; + auto& phi = dynamic_cast(*instr); + for (auto& [op, label] : phi.labels()) { + if (op.type() != furlang::ir::operand_t::Register) continue; + op.reg() = findRep(op.reg()); + } + } + + for (auto& op : block->exit()->sources()) { + if (op->type() != furlang::ir::operand_t::Register) continue; + op->reg() = findRep(op->reg()); + } + } +} + void ssa::dfs_rpo(furlang::ir::block_index block, const block_map_t& successors, std::unordered_set& visited, diff --git a/furlang/include/furlang/ir/operand.hpp b/furlang/include/furlang/ir/operand.hpp index ed29c6b..633afac 100644 --- a/furlang/include/furlang/ir/operand.hpp +++ b/furlang/include/furlang/ir/operand.hpp @@ -29,9 +29,11 @@ using register_t = std::uint32_t; * @see operand_t::Register */ struct register_operand { - register_t reg; + register_t reg = 0; std::uint32_t ver = 0; + register_operand() = default; + register_operand(register_t reg) : reg(reg) {}