@@ -22,6 +22,8 @@ private:
|
|||||||
|
|
||||||
static void constant_propagation(const std::unique_ptr<furlang::ir::function>& func);
|
static void constant_propagation(const std::unique_ptr<furlang::ir::function>& func);
|
||||||
|
|
||||||
|
static void dead_code_elimination(const std::unique_ptr<furlang::ir::function>& func);
|
||||||
|
|
||||||
static void dfs_rpo(furlang::ir::block_index block,
|
static void dfs_rpo(furlang::ir::block_index block,
|
||||||
const block_map_t& successors,
|
const block_map_t& successors,
|
||||||
std::unordered_set<furlang::ir::block_index>& visited,
|
std::unordered_set<furlang::ir::block_index>& visited,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ void ssa::optimize(furlang::ir::module& mod) {
|
|||||||
for (const auto& func : mod.functions()) {
|
for (const auto& func : mod.functions()) {
|
||||||
ssa::optimize(func);
|
ssa::optimize(func);
|
||||||
ssa::constant_propagation(func);
|
ssa::constant_propagation(func);
|
||||||
|
ssa::dead_code_elimination(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,6 +482,58 @@ void ssa::constant_propagation(const std::unique_ptr<furlang::ir::function>& fun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssa::dead_code_elimination(const std::unique_ptr<furlang::ir::function>& func) {
|
||||||
|
using block_idx = furlang::ir::block_index;
|
||||||
|
using reg_t = furlang::ir::register_operand;
|
||||||
|
|
||||||
|
std::unordered_map<reg_t, furlang::ir::instruction*> defMap;
|
||||||
|
std::unordered_set<furlang::ir::instruction*> alive;
|
||||||
|
std::queue<furlang::ir::instruction*> worklist;
|
||||||
|
|
||||||
|
for (block_idx blockIdx = 0; blockIdx < func->blocks().size(); ++blockIdx) {
|
||||||
|
const auto& block = func->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 < func->blocks().size(); ++blockIdx) {
|
||||||
|
const auto& block = func->blocks()[blockIdx];
|
||||||
|
auto& instrs = block->instructions();
|
||||||
|
|
||||||
|
for (auto it = instrs.begin(); it != instrs.end();) {
|
||||||
|
if (alive.find(it->get()) == alive.end()) {
|
||||||
|
it = instrs.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ssa::dfs_rpo(furlang::ir::block_index block,
|
void ssa::dfs_rpo(furlang::ir::block_index block,
|
||||||
const block_map_t& successors,
|
const block_map_t& successors,
|
||||||
std::unordered_set<furlang::ir::block_index>& visited,
|
std::unordered_set<furlang::ir::block_index>& visited,
|
||||||
|
|||||||
@@ -574,6 +574,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
instruction_t type() const override { return instruction_t::Phi; }
|
instruction_t type() const override { return instruction_t::Phi; }
|
||||||
|
|
||||||
|
bool has_destination() const override { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's destination register.
|
* @brief Returns this instruction's destination register.
|
||||||
*
|
*
|
||||||
@@ -588,6 +590,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
const operand& destination() const override { return m_dst; }
|
const operand& destination() const override { return m_dst; }
|
||||||
|
|
||||||
|
std::vector<const operand*> sources() const override {
|
||||||
|
std::vector<const operand*> srcs;
|
||||||
|
srcs.reserve(m_labels.size());
|
||||||
|
for (const auto& [op, _block] : m_labels)
|
||||||
|
srcs.push_back(&op);
|
||||||
|
return srcs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's labels.
|
* @brief Returns this instruction's labels.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user