forked from KPGPMC/furlang
@@ -24,6 +24,8 @@ private:
|
|||||||
|
|
||||||
static void dead_code_elimination(const std::unique_ptr<furlang::ir::function>& func);
|
static void dead_code_elimination(const std::unique_ptr<furlang::ir::function>& func);
|
||||||
|
|
||||||
|
static void copy_propagation(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,
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ void ssa::optimize(furlang::ir::module& mod) {
|
|||||||
ssa::optimize(func);
|
ssa::optimize(func);
|
||||||
ssa::constant_propagation(func);
|
ssa::constant_propagation(func);
|
||||||
ssa::dead_code_elimination(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<furlang::ir::function>& fu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssa::copy_propagation(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, reg_t> aliasMap;
|
||||||
|
|
||||||
|
std::function<reg_t(const reg_t&)> 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<furlang::ir::phi_instruction&>(*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,
|
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,
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ using register_t = std::uint32_t;
|
|||||||
* @see operand_t::Register
|
* @see operand_t::Register
|
||||||
*/
|
*/
|
||||||
struct register_operand {
|
struct register_operand {
|
||||||
register_t reg;
|
register_t reg = 0;
|
||||||
std::uint32_t ver = 0;
|
std::uint32_t ver = 0;
|
||||||
|
|
||||||
|
register_operand() = default;
|
||||||
|
|
||||||
register_operand(register_t reg)
|
register_operand(register_t reg)
|
||||||
: reg(reg) {}
|
: reg(reg) {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user