diff --git a/furc/include/furc/front/post_process.hpp b/furc/include/furc/front/post_process.hpp index 56aa0ee..1145fb4 100644 --- a/furc/include/furc/front/post_process.hpp +++ b/furc/include/furc/front/post_process.hpp @@ -16,6 +16,7 @@ public: enum stage { // NOLINT Ssa, Sccp, + Adce, DeSsa, }; public: diff --git a/furc/src/front/post_process.cpp b/furc/src/front/post_process.cpp index 82ad333..31281b2 100644 --- a/furc/src/front/post_process.cpp +++ b/furc/src/front/post_process.cpp @@ -534,6 +534,52 @@ static void sccp_stage(function_context& ctx) { } } +static void adce_stage(function_context& ctx) { + std::unordered_map defMap; + std::unordered_set alive; + std::queue worklist; + + for (block_idx blockIdx = 0; blockIdx < ctx.function->blocks().size(); ++blockIdx) { + const auto& block = ctx.function->blocks()[blockIdx]; + + for (auto& instr : block->instructions()) { + if (instr->has_destination() && instr->destination().type() == furlang::ir::operand_t::Register) { + defMap[instr->destination().reg()] = instr.get(); + } + } + + auto* exit = block->exit().get(); + alive.insert(exit); + worklist.push(exit); + } + + while (!worklist.empty()) { + const auto* instr = worklist.front(); + worklist.pop(); + + for (const auto& op : instr->sources()) { + if (op->type() != furlang::ir::operand_t::Register) continue; + auto src = op->reg(); + + if (defMap.find(src) == defMap.end()) continue; + auto* defInstr = defMap[src]; + if (alive.insert(defInstr).second) { + worklist.push(defInstr); + } + } + } + + for (block_idx blockIdx = 0; blockIdx < ctx.function->blocks().size(); ++blockIdx) { + const auto& block = ctx.function->blocks()[blockIdx]; + auto& instrs = block->instructions(); + + auto it = instrs.begin(); + while (it != instrs.end()) { + it = (alive.find(it->get()) != alive.end()) ? it + 1 : instrs.erase(it); + } + } +} + void post_process::process(furlang::ir::mod& mod) { for (const auto& func : mod.functions()) { if (!func || func->blocks().empty()) continue; @@ -543,6 +589,7 @@ void post_process::process(furlang::ir::mod& mod) { switch (stage) { case Ssa: ssa_stage(ctx); break; case Sccp: sccp_stage(ctx); break; + case Adce: adce_stage(ctx); break; case DeSsa: dessa_stage(ctx); break; } } diff --git a/furc/src/main.cpp b/furc/src/main.cpp index 99f5a88..8865671 100644 --- a/furc/src/main.cpp +++ b/furc/src/main.cpp @@ -37,6 +37,7 @@ int main(void) { furc::front::post_process postProcess; postProcess.push_stage(furc::front::post_process::Ssa); postProcess.push_stage(furc::front::post_process::Sccp); + postProcess.push_stage(furc::front::post_process::Adce); postProcess.push_stage(furc::front::post_process::DeSsa); postProcess.process(mod);