simple constant fold

This commit is contained in:
ridethepig 2023-06-15 23:23:53 +08:00
parent 40ac8b9d65
commit 07a078b80e
7 changed files with 214 additions and 97 deletions

View File

@ -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
View 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
coalescedNodesu,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;
};
}

View File

@ -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
coalescedNodesu,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
View 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

View File

@ -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
View 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());
}
}
}

View File

@ -1,4 +1,4 @@
#include "pass.h"
#include "mc_pass.h"
namespace CompSysY {