diff --git a/furc/include/furc/front/ssa.hpp b/furc/include/furc/front/ssa.hpp index fa83f78..0c99b78 100644 --- a/furc/include/furc/front/ssa.hpp +++ b/furc/include/furc/front/ssa.hpp @@ -20,6 +20,8 @@ public: private: static void optimize(const std::unique_ptr& func); + static void de_ssa(const std::unique_ptr& func); + static void constant_propagation(const std::unique_ptr& func); static void dead_code_elimination(const std::unique_ptr& func); diff --git a/furc/src/front/ssa.cpp b/furc/src/front/ssa.cpp index be5f55d..8fd8888 100644 --- a/furc/src/front/ssa.cpp +++ b/furc/src/front/ssa.cpp @@ -23,6 +23,7 @@ void ssa::optimize(furlang::ir::module& mod) { ssa::dead_code_elimination(func); ssa::copy_propagation(func); ssa::dead_code_elimination(func); + ssa::de_ssa(func); } } @@ -266,6 +267,38 @@ void ssa::optimize(const std::unique_ptr& func) { renameBlock(entry); } +void ssa::de_ssa(const std::unique_ptr& func) { + using namespace furlang::ir; + + std::unordered_map>> copies; + for (block_index blockIdx = 0; blockIdx < func->blocks().size(); ++blockIdx) { + const auto& block = func->blocks()[blockIdx]; + auto& instrs = block->instructions(); + for (auto it = instrs.begin(); it != instrs.end();) { + if ((*it)->type() != furlang::ir::instruction_t::Phi) { + ++it; + continue; + } + auto& phi = dynamic_cast(**it); + auto dstReg = phi.destination().reg(); + for (auto& [srcOp, label] : phi.labels()) { + copies[label].emplace_back( + std::make_unique(std::move(srcOp), operand::new_reg(dstReg))); + } + it = instrs.erase(it); + } + } + + for (auto& [blockIdx, cpys] : copies) { + if (blockIdx >= func->blocks().size()) continue; + const auto& block = func->blocks()[blockIdx]; + auto& instrs = block->instructions(); + for (auto& copy : cpys) { + instrs.push_back(std::move(copy)); + } + } +} + enum class lattice_t { Top, Constant,