simple constant fold
This commit is contained in:
parent
40ac8b9d65
commit
07a078b80e
@ -1,2 +1,3 @@
|
||||
#pragma once
|
||||
#include "mc_inst.h"
|
||||
#include "mc_inst.h"
|
||||
#include "mc_pass.h"
|
||||
79
include/mc_pass.h
Normal file
79
include/mc_pass.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include "pass_base.h"
|
||||
|
||||
namespace CompSysY {
|
||||
class PassRegAlloc final : public MCPass {
|
||||
public:
|
||||
PassRegAlloc() : MCPass("regalloc") {}
|
||||
virtual void run(const MCModule &module) override;
|
||||
const static int K = 32 - 5; // Not Allocate-able: x0, gp, tp; Reserve: sp, ra
|
||||
// exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4)
|
||||
static inline std::unordered_set<int> _ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
|
||||
private:
|
||||
// 可以按照指令内容(而不是指针地址)来给Move排序,使得算法具有更好的确定性,便于调试
|
||||
struct MvCmp {
|
||||
bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const {
|
||||
if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst;
|
||||
if (lhs->src != rhs->src) return lhs->src < rhs->src;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
/*以下这些集合**各不相交**
|
||||
precolored:机器寄存器集合,每个寄存器都预先指派了一种颜色
|
||||
initial:临时寄存器集合,其中的元素既没有预着色,也没有被处理
|
||||
simplifyWorklist:低度数的传送无关的结点表。
|
||||
freezeWorklist:低度数的传送有关的结点表。
|
||||
spillWorklist:高度数的结点表。
|
||||
spilledNodes:在本轮中要被溢出的结点集合,初始为空。
|
||||
coalescedNodes:已合并的寄存器集合。当合并u,v时,将v加人到这个集合中,u则被放回到某个工作表中(或反之)。
|
||||
coloredNodes :已成功着色的结点集合。
|
||||
selectstack:一个包含从图中删除的临时变量的栈
|
||||
*/
|
||||
void reg_alloc(MFunction *);
|
||||
void build(MFunction *);
|
||||
void add_edge(const MOperand &u, const MOperand &v);
|
||||
void make_work_list(MFunction *func);
|
||||
bool move_related(const MOperand &n);
|
||||
std::set<MInstMove *, MvCmp> node_moves(const MOperand &n);
|
||||
std::set<MOperand> adjacent(const MOperand &n);
|
||||
void decrement_degree(const MOperand &m);
|
||||
void enable_moves(const MOperand &n);
|
||||
void simplify();
|
||||
void coalesce();
|
||||
void add_work_list(const MOperand &u);
|
||||
bool OK(const MOperand &t, const MOperand &r);
|
||||
bool conservative(const std::set<MOperand> &nodes);
|
||||
MOperand get_alias(const MOperand &n);
|
||||
void combine(const MOperand &u, const MOperand &v);
|
||||
void freeze();
|
||||
void freeze_moves(const MOperand &u);
|
||||
void select_spill();
|
||||
void assign_colors(MFunction *func);
|
||||
void rewrite_program(MFunction *func);
|
||||
void clear();
|
||||
void set_color(MFunction *);
|
||||
void apply_coalesced(MFunction *);
|
||||
std::map<MOperand, std::set<MOperand>> adj_list;
|
||||
std::set<std::pair<MOperand, MOperand>> adj_set;
|
||||
std::map<MOperand, unsigned> degree;
|
||||
std::map<MOperand, std::set<MInstMove *, MvCmp>> move_list;
|
||||
std::map<MOperand, MOperand> color;
|
||||
std::map<MOperand, MOperand> alias;
|
||||
std::set<MOperand> initial;
|
||||
std::set<MOperand> simplify_worklist;
|
||||
std::set<MOperand> freeze_worklist;
|
||||
std::set<MOperand> spill_worklist;
|
||||
std::set<MOperand> spilled_nodes;
|
||||
std::set<MOperand> coalesced_nodes;
|
||||
std::set<MOperand> colored_nodes;
|
||||
std::vector<MOperand> select_stack;
|
||||
std::set<MInstMove *, MvCmp> coalesced_moves;
|
||||
std::set<MInstMove *, MvCmp> constrained_moves;
|
||||
std::set<MInstMove *, MvCmp> frozen_moves;
|
||||
std::set<MInstMove *, MvCmp> worklist_moves;
|
||||
std::set<MInstMove *, MvCmp> active_moves;
|
||||
};
|
||||
|
||||
}
|
||||
101
include/pass.h
101
include/pass.h
@ -1,23 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "llir_module.h"
|
||||
#include "machcode.h"
|
||||
|
||||
// #define DEBUG_REGALLOC
|
||||
|
||||
#include "pass_base.h"
|
||||
namespace CompSysY {
|
||||
class Pass {
|
||||
public:
|
||||
std::string pass_name;
|
||||
Pass(const std::string &name) : pass_name(name) {}
|
||||
virtual ~Pass() = default;
|
||||
virtual void run(const Module &module) = 0;
|
||||
};
|
||||
|
||||
class PassSCCP final : public Pass {
|
||||
public:
|
||||
PassSCCP() : Pass("const fold") {}
|
||||
PassSCCP() : Pass("Constant Propagation") {}
|
||||
void run(const Module &module) override;
|
||||
enum class ConstLatTag { Top = 0, Const, Bottom };
|
||||
struct ConstLat {
|
||||
@ -75,86 +62,10 @@ public:
|
||||
void run(const Module &module) override;
|
||||
};
|
||||
|
||||
class MCPass {
|
||||
class PassConstFold final : public Pass {
|
||||
public:
|
||||
std::string pass_name;
|
||||
MCPass(const std::string &name) : pass_name(name) {}
|
||||
|
||||
virtual void run(const MCModule &module) = 0;
|
||||
PassConstFold() : Pass("const fold") {}
|
||||
void run(const Module &module) override;
|
||||
};
|
||||
|
||||
class PassRegAlloc final : public MCPass {
|
||||
public:
|
||||
PassRegAlloc() : MCPass("regalloc") {}
|
||||
virtual void run(const MCModule &module) override;
|
||||
const static int K = 32 - 5; // Not Allocate-able: x0, gp, tp; Reserve: sp, ra
|
||||
// exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4)
|
||||
static inline std::unordered_set<int> _ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
|
||||
private:
|
||||
// 可以按照指令内容(而不是指针地址)来给Move排序,使得算法具有更好的确定性,便于调试
|
||||
struct MvCmp {
|
||||
bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const {
|
||||
if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst;
|
||||
if (lhs->src != rhs->src) return lhs->src < rhs->src;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
/*以下这些集合**各不相交**
|
||||
precolored:机器寄存器集合,每个寄存器都预先指派了一种颜色
|
||||
initial:临时寄存器集合,其中的元素既没有预着色,也没有被处理
|
||||
simplifyWorklist:低度数的传送无关的结点表。
|
||||
freezeWorklist:低度数的传送有关的结点表。
|
||||
spillWorklist:高度数的结点表。
|
||||
spilledNodes:在本轮中要被溢出的结点集合,初始为空。
|
||||
coalescedNodes:已合并的寄存器集合。当合并u,v时,将v加人到这个集合中,u则被放回到某个工作表中(或反之)。
|
||||
coloredNodes :已成功着色的结点集合。
|
||||
selectstack:一个包含从图中删除的临时变量的栈
|
||||
*/
|
||||
void reg_alloc(MFunction *);
|
||||
void build(MFunction *);
|
||||
void add_edge(const MOperand &u, const MOperand &v);
|
||||
void make_work_list(MFunction *func);
|
||||
bool move_related(const MOperand &n);
|
||||
std::set<MInstMove *, MvCmp> node_moves(const MOperand &n);
|
||||
std::set<MOperand> adjacent(const MOperand &n);
|
||||
void decrement_degree(const MOperand &m);
|
||||
void enable_moves(const MOperand &n);
|
||||
void simplify();
|
||||
void coalesce();
|
||||
void add_work_list(const MOperand &u);
|
||||
bool OK(const MOperand &t, const MOperand &r);
|
||||
bool conservative(const std::set<MOperand> &nodes);
|
||||
MOperand get_alias(const MOperand &n);
|
||||
void combine(const MOperand &u, const MOperand &v);
|
||||
void freeze();
|
||||
void freeze_moves(const MOperand &u);
|
||||
void select_spill();
|
||||
void assign_colors(MFunction *func);
|
||||
void rewrite_program(MFunction *func);
|
||||
void clear();
|
||||
void set_color(MFunction *);
|
||||
void apply_coalesced(MFunction *);
|
||||
std::map<MOperand, std::set<MOperand>> adj_list;
|
||||
std::set<std::pair<MOperand, MOperand>> adj_set;
|
||||
std::map<MOperand, unsigned> degree;
|
||||
std::map<MOperand, std::set<MInstMove *, MvCmp>> move_list;
|
||||
std::map<MOperand, MOperand> color;
|
||||
std::map<MOperand, MOperand> alias;
|
||||
std::set<MOperand> initial;
|
||||
std::set<MOperand> simplify_worklist;
|
||||
std::set<MOperand> freeze_worklist;
|
||||
std::set<MOperand> spill_worklist;
|
||||
std::set<MOperand> spilled_nodes;
|
||||
std::set<MOperand> coalesced_nodes;
|
||||
std::set<MOperand> colored_nodes;
|
||||
std::vector<MOperand> select_stack;
|
||||
std::set<MInstMove *, MvCmp> coalesced_moves;
|
||||
std::set<MInstMove *, MvCmp> constrained_moves;
|
||||
std::set<MInstMove *, MvCmp> frozen_moves;
|
||||
std::set<MInstMove *, MvCmp> worklist_moves;
|
||||
std::set<MInstMove *, MvCmp> active_moves;
|
||||
};
|
||||
|
||||
} // namespace CompSysY
|
||||
} // namespace CompSysY
|
||||
|
||||
26
include/pass_base.h
Normal file
26
include/pass_base.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "llir_module.h"
|
||||
#include "mc_inst.h"
|
||||
|
||||
// #define DEBUG_REGALLOC
|
||||
|
||||
namespace CompSysY {
|
||||
class Pass {
|
||||
public:
|
||||
std::string pass_name;
|
||||
Pass(const std::string &name) : pass_name(name) {}
|
||||
virtual ~Pass() = default;
|
||||
virtual void run(const Module &module) = 0;
|
||||
};
|
||||
|
||||
class MCPass {
|
||||
public:
|
||||
std::string pass_name;
|
||||
MCPass(const std::string &name) : pass_name(name) {}
|
||||
|
||||
virtual void run(const MCModule &module) = 0;
|
||||
};
|
||||
|
||||
} // namespace CompSysY
|
||||
@ -114,6 +114,7 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
std::vector<sptr(Pass)> optpasses = {
|
||||
std::make_shared<PassConstFold>(),
|
||||
std::make_shared<PassSCCP>(),
|
||||
};
|
||||
|
||||
|
||||
99
src/pass_const_fold.cpp
Normal file
99
src/pass_const_fold.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "pass.h"
|
||||
|
||||
namespace CompSysY {
|
||||
|
||||
|
||||
static bool foldable(Instruction* inst) {
|
||||
if (InstTag::Add <= inst->tag && inst->tag <= InstTag::Ne) {
|
||||
if (shared_cast<ConstantInt>(inst->operand_list[0]) && shared_cast<ConstantInt>(inst->operand_list[1]))
|
||||
return true;
|
||||
}
|
||||
else if (inst->tag == InstTag::Zext) {
|
||||
if (shared_cast<ConstantInt>(inst->operand_list[0]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static InstBranch *is_cond_br(Instruction *inst) {
|
||||
auto inst_br = dynamic_cast<InstBranch *>(inst);
|
||||
if (inst_br && inst_br->operand_list.size() == 3) {
|
||||
return inst_br;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void rewrite_bb(sptr(BasicBlock) bb, sptr(BasicBlock) pred) {
|
||||
pred->succ_list.remove(bb);
|
||||
auto pred_index = GETINDEX(bb->pred_list, pred);
|
||||
bb->pred_list.remove(pred);
|
||||
for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end();) {
|
||||
auto inst = *itr++;
|
||||
if (!shared_cast<InstPhi>(inst)) break;
|
||||
auto inst_phi = shared_cast<InstPhi>(inst);
|
||||
assert(inst_phi->operand_list.size() > pred_index);
|
||||
inst_phi->operand_list.erase(inst_phi->operand_list.begin() + pred_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void compute(Function* func) {
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto inst : bb->inst_list) {
|
||||
if (!foldable(inst.get())) continue;
|
||||
if (inst->use_list.empty()) continue;
|
||||
auto val = [&](int op) {
|
||||
if (auto const_op = dynamic_cast<ConstantInt *>(inst->operand_list[op].get())) {
|
||||
return const_op->value;
|
||||
}
|
||||
assert(0);
|
||||
};
|
||||
changed = true;
|
||||
int result = 0;
|
||||
TypePtr_t type = TypeHelper::TYPE_I32;
|
||||
switch (inst->tag) {
|
||||
case InstTag::Add: result = val(0) + val(1); break;
|
||||
case InstTag::Sub: result = val(0) - val(1); break;
|
||||
case InstTag::Mod: result = val(0) % val(1); break;
|
||||
case InstTag::Mul: result = val(0) * val(1); break;
|
||||
case InstTag::Div: result = val(0) / val(1); break;
|
||||
case InstTag::Lt: result = val(0) < val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Le: result = val(0) <= val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Ge: result = val(0) >= val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Gt: result = val(0) > val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Eq: result = val(0) == val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Ne: result = val(0) != val(1); type = TypeHelper::TYPE_I1; break;
|
||||
case InstTag::Zext: result = val(0); break;
|
||||
default: break;
|
||||
}
|
||||
inst->u_replace_users(ConstantInt::New(result, type));
|
||||
inst->u_remove_from_usees();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto bb : func->bb_list) {
|
||||
for(auto inst : bb->inst_list) {
|
||||
if (!is_cond_br(inst.get())) continue;
|
||||
if (!shared_cast<ConstantInt>(inst->operand_list[0])) continue;
|
||||
auto cond = shared_cast<ConstantInt>(inst->operand_list[0])->value;
|
||||
auto target = shared_cast<BasicBlock>(cond ? inst->operand_list[1] : inst->operand_list[2]);
|
||||
auto dead_target = shared_cast<BasicBlock>(!cond ? inst->operand_list[1] : inst->operand_list[2]);
|
||||
assert(target && dead_target);
|
||||
inst->operand_list.clear();
|
||||
inst->add_operand(target);
|
||||
rewrite_bb(dead_target, inst->parent_bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PassConstFold::run(const Module &module) {
|
||||
LOG(INFO) << "Run pass " << pass_name;
|
||||
for (auto func : module.function_list) {
|
||||
if (func->is_libfunc()) continue;
|
||||
compute(func.get());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
#include "pass.h"
|
||||
#include "mc_pass.h"
|
||||
|
||||
namespace CompSysY {
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user