RegAlloc pass all func test
This commit is contained in:
parent
6bf4093bfb
commit
81bd968258
@ -35,7 +35,7 @@ inline sptr(DST) strict_shared_cast(SRC src) {
|
||||
|
||||
#define STD_FIND(container, val) std::find(container.begin(), container.end(), val)
|
||||
#define STD_FOUND(container, val) (STD_FIND(container, val) != container.end())
|
||||
#define ASSOC_FOUND(cont, val) (cont.find(val) != cont.end())
|
||||
#define INSET(cont, val) (cont.find(val) != cont.end())
|
||||
|
||||
#define INF (0x3f3f3f3f)
|
||||
#define BTWN(v, l, r) (l <= v && v <= r)
|
||||
|
||||
@ -205,7 +205,7 @@ inline MInstTag inverse_cond(MInstTag src_tag) {
|
||||
}
|
||||
|
||||
// Instruction insertion type
|
||||
enum class InsType { Before, After, Head, Tail };
|
||||
enum class InsertPos { Before, After, Head, Tail };
|
||||
|
||||
class MInst {
|
||||
public:
|
||||
@ -215,19 +215,27 @@ public:
|
||||
// in other cases, since stack is XLEN-padded, for single signed int variable, ld/lw sd/sw do not make much difference
|
||||
// Similarly, it makes difference when computing address
|
||||
int width = 4;
|
||||
|
||||
std::list<sptr(MInst)>::iterator itr;
|
||||
sptr(MBasicBlock) parent_bb;
|
||||
MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : inst_tag(tag), parent_bb(parent_bb) {}
|
||||
virtual ~MInst() = default;
|
||||
virtual std::vector<MOperand> get_def() const = 0;
|
||||
virtual std::vector<MOperand> get_use() const = 0;
|
||||
virtual ~MInst() = default;
|
||||
virtual std::vector<MOperand> get_def() const {
|
||||
return {};
|
||||
};
|
||||
virtual std::vector<MOperand *> get_def_ptr() {
|
||||
return {};
|
||||
};
|
||||
virtual std::vector<MOperand> get_use() const {
|
||||
return {};
|
||||
};
|
||||
virtual std::vector<MOperand *> get_use_ptr() {
|
||||
return {};
|
||||
};
|
||||
virtual bool is_transfer() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty);
|
||||
static void PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty);
|
||||
static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_pos);
|
||||
static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MInst) rel_inst, InsertPos ins_pos);
|
||||
};
|
||||
|
||||
class MBasicBlock {
|
||||
@ -276,40 +284,35 @@ public:
|
||||
MOperand dst;
|
||||
MOperand op1;
|
||||
MOperand op2;
|
||||
MInstBinary(MInstTag type, sptr(MBasicBlock) parent_bb) : MInst(type, parent_bb) {}
|
||||
|
||||
static sptr(MInstBinary) New(MInstTag type, sptr(MBasicBlock) parent_bb, int width, InsType ins_ty = InsType::Tail) {
|
||||
auto inst = make_shared<MInstBinary>(type, parent_bb);
|
||||
static sptr(MInstBinary)
|
||||
New(MInstTag type, sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos = InsertPos::Tail) {
|
||||
auto inst = make_shared<MInstBinary>();
|
||||
inst->width = width;
|
||||
MInst::PostNew(inst, parent_bb, ins_ty);
|
||||
MInst::PostNew(inst, type, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
auto inst = make_shared<MInstBinary>(type, parent_bb);
|
||||
inst->width = width;
|
||||
auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst);
|
||||
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||
if (insert_after) std::advance(rel_inst_itr, 1);
|
||||
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||
static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, InsertPos ins_pos = InsertPos::Before) {
|
||||
auto inst = make_shared<MInstBinary>();
|
||||
inst->width = width;
|
||||
MInst::PostNew(inst, type, rel_inst, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand *> get_def_ptr() override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||
};
|
||||
|
||||
class MInstJump : public MInst {
|
||||
public:
|
||||
sptr(MBasicBlock) target;
|
||||
MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jmp, parent_bb) {}
|
||||
|
||||
static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) {
|
||||
auto inst = make_shared<MInstJump>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
auto inst = make_shared<MInstJump>();
|
||||
PostNew(inst, MInstTag::Jmp, parent_bb, InsertPos::Tail);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
bool is_transfer() const override {
|
||||
return true;
|
||||
}
|
||||
@ -321,14 +324,13 @@ public:
|
||||
MOperand op1;
|
||||
MOperand op2;
|
||||
MInstTag branch_tag;
|
||||
MInstBranch(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Branch, parent_bb) {}
|
||||
static sptr(MInstBranch) New(sptr(MBasicBlock) parent_bb) {
|
||||
auto inst = make_shared<MInstBranch>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
auto inst = make_shared<MInstBranch>();
|
||||
PostNew(inst, MInstTag::Branch, parent_bb, InsertPos::Tail);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||
bool is_transfer() const override {
|
||||
return true;
|
||||
}
|
||||
@ -339,26 +341,23 @@ public:
|
||||
MOperand dst;
|
||||
MOperand addr;
|
||||
MOperand offset;
|
||||
MInstLoad(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Load, parent_bb) {}
|
||||
|
||||
static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width) {
|
||||
auto inst = make_shared<MInstLoad>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstLoad>();
|
||||
inst->width = width;
|
||||
PostNew(inst, MInstTag::Load, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
auto inst = make_shared<MInstLoad>(parent_bb);
|
||||
auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst);
|
||||
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||
if (insert_after) std::advance(rel_inst_itr, 1);
|
||||
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||
static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstLoad>();
|
||||
inst->width = width;
|
||||
PostNew(inst, MInstTag::Load, rel_inst, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand *> get_def_ptr() override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||
};
|
||||
|
||||
class MInstStore : public MInst {
|
||||
@ -366,81 +365,50 @@ public:
|
||||
MOperand data;
|
||||
MOperand addr;
|
||||
MOperand offset;
|
||||
MInstStore(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Store, parent_bb) {}
|
||||
|
||||
static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width) {
|
||||
auto inst = make_shared<MInstStore>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstStore>();
|
||||
inst->width = width;
|
||||
PostNew(inst, MInstTag::Store, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
auto inst = make_shared<MInstStore>(parent_bb);
|
||||
auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst);
|
||||
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||
if (insert_after) std::advance(rel_inst_itr, 1);
|
||||
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||
static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstStore>();
|
||||
inst->width = width;
|
||||
PostNew(inst, MInstTag::Store, rel_inst, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||
};
|
||||
|
||||
class MInstMove : public MInst {
|
||||
public:
|
||||
MOperand dst;
|
||||
MOperand src;
|
||||
MInstMove(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Move, parent_bb) {}
|
||||
static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
||||
auto inst = make_shared<MInstMove>(parent_bb);
|
||||
if (insert_begin)
|
||||
parent_bb->inst_list.push_front(inst);
|
||||
else
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstMove>();
|
||||
PostNew(inst, MInstTag::Move, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
static sptr(MInstMove) New(sptr(MInst) rel_inst, bool insert_after = false) {
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
auto inst = make_shared<MInstMove>(parent_bb);
|
||||
auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst);
|
||||
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||
if (insert_after) std::advance(rel_inst_itr, 1);
|
||||
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||
static sptr(MInstMove) New(sptr(MInst) rel_inst, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstMove>();
|
||||
PostNew(inst, MInstTag::Move, rel_inst, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand *> get_def_ptr() override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||
};
|
||||
|
||||
// class MInstSymbol : public MInst {
|
||||
// public:
|
||||
// MOperand dst;
|
||||
// sptr(GlobalVar) symbol;
|
||||
// MInstSymbol(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Globsym, parent_bb) {}
|
||||
// static sptr(MInstSymbol) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
||||
// auto inst = make_shared<MInstSymbol>(parent_bb);
|
||||
// if (insert_begin)
|
||||
// parent_bb->inst_list.push_front(inst);
|
||||
// else
|
||||
// parent_bb->inst_list.push_back(inst);
|
||||
// return inst;
|
||||
// }
|
||||
// };
|
||||
|
||||
class MInstReturn : public MInst {
|
||||
public:
|
||||
MInstReturn(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Ret, parent_bb) {}
|
||||
static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
||||
auto inst = make_shared<MInstReturn>(parent_bb);
|
||||
if (insert_begin)
|
||||
parent_bb->inst_list.push_front(inst);
|
||||
else
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstReturn>();
|
||||
PostNew(inst, MInstTag::Ret, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
bool is_transfer() const override {
|
||||
return true;
|
||||
@ -450,37 +418,28 @@ public:
|
||||
class MInstComment : public MInst {
|
||||
public:
|
||||
std::string comment;
|
||||
MInstComment(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Comment, parent_bb) {}
|
||||
static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb) {
|
||||
auto inst = make_shared<MInstComment>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstComment>();
|
||||
PostNew(inst, MInstTag::Comment, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
static sptr(MInstComment) New(sptr(MInst) rel_inst, bool insert_after = false) {
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
auto inst = make_shared<MInstComment>(parent_bb);
|
||||
auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst);
|
||||
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||
if (insert_after) std::advance(rel_inst_itr, 1);
|
||||
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||
static sptr(MInstComment) New(sptr(MInst) rel_inst, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstComment>();
|
||||
PostNew(inst, MInstTag::Comment, rel_inst, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
};
|
||||
|
||||
class MInstCall : public MInst {
|
||||
public:
|
||||
sptr(Function) ir_func;
|
||||
MInstCall(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Call, parent_bb) {}
|
||||
static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb) {
|
||||
auto inst = make_shared<MInstCall>(parent_bb);
|
||||
parent_bb->inst_list.push_back(inst);
|
||||
static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||
auto inst = make_shared<MInstCall>();
|
||||
PostNew(inst, MInstTag::Call, parent_bb, ins_pos);
|
||||
return inst;
|
||||
}
|
||||
virtual std::vector<MOperand> get_def() const override;
|
||||
virtual std::vector<MOperand *> get_def_ptr() override;
|
||||
virtual std::vector<MOperand> get_use() const override;
|
||||
};
|
||||
|
||||
void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use);
|
||||
} // namespace CompSysY
|
||||
@ -45,6 +45,7 @@ public:
|
||||
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;
|
||||
@ -59,14 +60,14 @@ private:
|
||||
freezeWorklist:低度数的传送有关的结点表。
|
||||
spillWorklist:高度数的结点表。
|
||||
spilledNodes:在本轮中要被溢出的结点集合,初始为空。
|
||||
coalescedNodes:已合并的寄存器集合。当合并uV时,将y加人到这个集合中,w则被放回到某个工作表中(或反之)。
|
||||
coalescedNodes:已合并的寄存器集合。当合并u,v时,将v加人到这个集合中,u则被放回到某个工作表中(或反之)。
|
||||
coloredNodes :已成功着色的结点集合。
|
||||
selectstack:一个包含从图中删除的临时变量的栈
|
||||
*/
|
||||
void reg_alloc(sptr(MFunction));
|
||||
void build(sptr(MFunction));
|
||||
void reg_alloc(MFunction *);
|
||||
void build(MFunction *);
|
||||
void add_edge(const MOperand &u, const MOperand &v);
|
||||
void make_work_list(sptr(MFunction) func);
|
||||
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);
|
||||
@ -82,9 +83,11 @@ private:
|
||||
void freeze();
|
||||
void freeze_moves(const MOperand &u);
|
||||
void select_spill();
|
||||
void assign_colors(sptr(MFunction) func);
|
||||
void rewrite_program(sptr(MFunction) func);
|
||||
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;
|
||||
@ -104,7 +107,6 @@ private:
|
||||
std::set<MInstMove *, MvCmp> frozen_moves;
|
||||
std::set<MInstMove *, MvCmp> worklist_moves;
|
||||
std::set<MInstMove *, MvCmp> active_moves;
|
||||
std::map<MOperand, int> spill_space;
|
||||
};
|
||||
|
||||
} // namespace CompSysY
|
||||
@ -63,11 +63,9 @@ int main(int argc, const char **argv) {
|
||||
auto flg_O0 = arg_parser["-O0"] == true;
|
||||
auto emit_llvm = arg_parser["-emit-llvm"] == true;
|
||||
auto no_asm = arg_parser["-no-asm"] == true;
|
||||
// std::cout << source_file << " " << output_file << " " << flg_O1 <<
|
||||
// std::endl;
|
||||
#pragma endregion
|
||||
START_EASYLOGGINGPP(argc, argv);
|
||||
#pragma region Logger
|
||||
START_EASYLOGGINGPP(argc, argv);
|
||||
el::Configurations defaultConf;
|
||||
defaultConf.setToDefault();
|
||||
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%levshort %loc %msg");
|
||||
|
||||
@ -8,12 +8,12 @@ using std::endl;
|
||||
static void bb_debug(std::ostream &ostr, sptr(MBasicBlock) bb) {
|
||||
ostr << "pred:";
|
||||
for (auto item : bb->pred_list) {
|
||||
ostr << "L_BB_" << item->id << ",";
|
||||
ostr << item->to_string() << ",";
|
||||
}
|
||||
ostr << "\n";
|
||||
ostr << "succ:";
|
||||
for (auto item : bb->succ_list) {
|
||||
ostr << "L_BB_" << item->id << ",";
|
||||
ostr << item->to_string() << ",";
|
||||
}
|
||||
ostr << "\n";
|
||||
ostr << "livein:";
|
||||
@ -312,10 +312,14 @@ static void stack_postprocess(sptr(MFunction) func) {
|
||||
|
||||
void emit_function(std::ostream &ostr, sptr(MFunction) func) {
|
||||
// function header
|
||||
ostr << "\t.globl\t" << func->ir_func->name << "\n";
|
||||
ostr << "\t.p2align\t1\n";
|
||||
ostr << "\t.type\t" << func->ir_func->name << ",@function\n";
|
||||
ostr << func->ir_func->name << ":" << endl;
|
||||
ostr << fmt::format(
|
||||
"\t.globl\t{0}\n"
|
||||
"\t.p2align\t1\n"
|
||||
"\t.type\t{0},@function\n"
|
||||
"{0}:",
|
||||
func->ir_func->name
|
||||
)
|
||||
<< endl;
|
||||
// entry code
|
||||
// First push callee-saved regs
|
||||
if (!func->regs_to_save.empty()) {
|
||||
|
||||
@ -22,9 +22,9 @@ static auto gen_imm(int imm, sptr(MBasicBlock) mc_bb, bool force_reg = false) {
|
||||
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||
sptr(MInstMove) inst_move;
|
||||
if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer())
|
||||
inst_move = MInstMove::New(mc_bb->inst_list.back());
|
||||
inst_move = MInstMove::New(mc_bb->inst_list.back(), InsertPos::Before);
|
||||
else
|
||||
inst_move = MInstMove::New(mc_bb);
|
||||
inst_move = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_move->src = operand;
|
||||
inst_move->dst = vr;
|
||||
return vr;
|
||||
@ -50,7 +50,7 @@ static MOperand value2moperand(
|
||||
// according to RV call conv, we can have a0-a7 for params
|
||||
if (fparam_ndx < 8) {
|
||||
// copy param as an vr in func entry
|
||||
auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), true);
|
||||
auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), InsertPos::Head);
|
||||
inst_move->src = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx));
|
||||
inst_move->dst = vr;
|
||||
}
|
||||
@ -59,9 +59,6 @@ static MOperand value2moperand(
|
||||
// this need to be further re-located since sp may have changed
|
||||
// FramePtr won't get used here, for perf reason. Ref:
|
||||
// https://stackoverflow.com/questions/13006371/does-omitting-the-frame-pointers-really-have-a-positive-effect-on-performance-an
|
||||
// TODO Trivial Compiler(THU2020) use an addition move, ~but I am not sure why, deleted temporally~
|
||||
// In-case the stack is too large that exceeds limit of imm field, but We first skip this
|
||||
// auto vr_tmp = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||
int width = 0;
|
||||
if (shared_cast<IntegerType>(fparam->type))
|
||||
width = 4;
|
||||
@ -70,10 +67,10 @@ static MOperand value2moperand(
|
||||
sptr(MInstLoad) inst_load;
|
||||
// ld vr, (i-8)*8(sp)
|
||||
if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer())
|
||||
inst_load = MInstLoad::New(mc_bb->inst_list.back(), width);
|
||||
inst_load = MInstLoad::New(mc_bb->inst_list.back(), width, InsertPos::Before);
|
||||
else
|
||||
inst_load = MInstLoad::New(mc_bb, width);
|
||||
// auto inst_move = MInstMove::New(inst_load); // lui vr_t,
|
||||
inst_load = MInstLoad::New(mc_bb, width, InsertPos::Tail);
|
||||
// TODO offset immediate may exceed range
|
||||
inst_load->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN);
|
||||
inst_load->dst = vr;
|
||||
@ -94,7 +91,7 @@ static MOperand value2moperand(
|
||||
// return vr;
|
||||
auto op_glob = MOperand::Glob(glob);
|
||||
if (force_reg) {
|
||||
auto inst_la = MInstMove::New(mc_bb);
|
||||
auto inst_la = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||
// val2mop.insert({ir_value, vr});
|
||||
inst_la->dst = vr;
|
||||
@ -173,7 +170,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
// width is important when load/store to an array address, so be careful
|
||||
int width = XLEN;
|
||||
if (shared_cast<IntegerType>(ld->type)) width = 4;
|
||||
auto mc_li = MInstLoad::New(mc_bb, width);
|
||||
auto mc_li = MInstLoad::New(mc_bb, width, InsertPos::Tail);
|
||||
mc_li->addr = addr;
|
||||
mc_li->dst = value2moperand(ld, mc_bb, mp_val2op);
|
||||
mc_li->offset = MOperand::Imm(0);
|
||||
@ -184,7 +181,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
auto addr = value2moperand(st->operand_list[1], mc_bb, mp_val2op, true);
|
||||
int width = XLEN;
|
||||
if (shared_cast<IntegerType>(st->operand_list[0]->type)) width = 4;
|
||||
auto mc_st = MInstStore::New(mc_bb, width);
|
||||
auto mc_st = MInstStore::New(mc_bb, width, InsertPos::Tail);
|
||||
mc_st->addr = addr;
|
||||
mc_st->data = data;
|
||||
mc_st->offset = MOperand::Imm(0);
|
||||
@ -208,7 +205,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
|
||||
if ((inst->operand_list.size() < 3 && !index0.value) || (inst->operand_list.size() == 3 && index1.is_imm() && !index1.value)) {
|
||||
// a shortcut for zero gep
|
||||
auto inst_mv = MInstMove::New(mc_bb);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_mv->dst = dst;
|
||||
inst_mv->src = ptr;
|
||||
VLOG(6) << "trivial gep";
|
||||
@ -277,11 +274,11 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
if (auto ret = shared_cast<InstReturn>(inst)) {
|
||||
if (ret->operand_list.size()) {
|
||||
auto retval = value2moperand(ret->operand_list[0], mc_bb, mp_val2op);
|
||||
auto inst_mv = MInstMove::New(mc_bb);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_mv->src = retval;
|
||||
inst_mv->dst = MOperand::PreClrReg(RV64Reg::a0);
|
||||
}
|
||||
MInstReturn::New(mc_bb);
|
||||
MInstReturn::New(mc_bb, InsertPos::Tail);
|
||||
continue;
|
||||
}
|
||||
if (auto cal = shared_cast<InstCall>(inst)) {
|
||||
@ -290,14 +287,14 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
for (int i = 1; i < cal->operand_list.size(); ++i) {
|
||||
auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true);
|
||||
if (i <= 8) {
|
||||
auto inst_move = MInstMove::New(mc_bb);
|
||||
auto inst_move = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_move->src = rparam;
|
||||
inst_move->dst = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i - 1));
|
||||
}
|
||||
else {
|
||||
int st_off = -(nparams - (i - 1)) * XLEN;
|
||||
auto st_off_imm = gen_imm(st_off, mc_bb);
|
||||
auto inst_store = MInstStore::New(mc_bb, XLEN);
|
||||
auto inst_store = MInstStore::New(mc_bb, XLEN, InsertPos::Tail);
|
||||
inst_store->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_store->offset = st_off_imm;
|
||||
inst_store->data = rparam;
|
||||
@ -311,7 +308,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb);
|
||||
}
|
||||
|
||||
auto inst_call = MInstCall::New(mc_bb);
|
||||
auto inst_call = MInstCall::New(mc_bb, InsertPos::Tail);
|
||||
inst_call->ir_func = strict_shared_cast<Function>(cal->operand_list[0]);
|
||||
|
||||
if (nparams > 8) {
|
||||
@ -324,7 +321,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
// handle return value, if exist
|
||||
if (shared_cast<IntegerType>(cal->type)) {
|
||||
auto dst = value2moperand(inst, mc_bb, mp_val2op);
|
||||
auto inst_mv = MInstMove::New(mc_bb);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_mv->src = MOperand::PreClrReg(RV64Reg::a0);
|
||||
inst_mv->dst = dst;
|
||||
}
|
||||
@ -412,7 +409,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
}
|
||||
auto src_imm = gen_imm(res, mc_bb);
|
||||
auto dst = value2moperand(inst, mc_bb, mp_val2op);
|
||||
auto inst_mv = MInstMove::New(mc_bb);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_mv->dst = dst;
|
||||
inst_mv->src = src_imm;
|
||||
continue;
|
||||
@ -503,7 +500,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
// trivial move
|
||||
auto src = value2moperand(zxt->operand_list[0], mc_bb, mp_val2op);
|
||||
auto dst = value2moperand(inst, mc_bb, mp_val2op);
|
||||
auto inst_mv = MInstMove::New(mc_bb);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||
inst_mv->src = src;
|
||||
inst_mv->dst = dst;
|
||||
continue;
|
||||
@ -544,7 +541,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
}
|
||||
|
||||
for (auto &pmv : par_mv_cur) {
|
||||
auto inst_mv = MInstMove::New(mc_bb, true);
|
||||
auto inst_mv = MInstMove::New(mc_bb, InsertPos::Head);
|
||||
inst_mv->src = pmv.src;
|
||||
inst_mv->dst = pmv.dst;
|
||||
}
|
||||
@ -552,7 +549,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
sysy_assert(pmv_pair.first->inst_list.back()->is_transfer(), {
|
||||
LOG(ERROR) << (int)(pmv_pair.first->inst_list.back()->inst_tag) << " " << pmv_pair.first->id;
|
||||
});
|
||||
auto inst_mv = MInstMove::New(pmv_pair.first->inst_list.back());
|
||||
auto inst_mv = MInstMove::New(pmv_pair.first->inst_list.back(), InsertPos::Before);
|
||||
inst_mv->src = pmv_pair.second.src;
|
||||
inst_mv->dst = pmv_pair.second.dst;
|
||||
}
|
||||
@ -560,39 +557,4 @@ void MCModule::IR2MC(const Module &ir_module) {
|
||||
}
|
||||
}
|
||||
|
||||
void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use) {
|
||||
if (auto bin = shared_cast<MInstBinary>(inst)) {
|
||||
def.push_back(&bin->dst);
|
||||
use.push_back(&bin->op1);
|
||||
use.push_back(&bin->op2);
|
||||
return;
|
||||
}
|
||||
if (auto mov = shared_cast<MInstMove>(inst)) {
|
||||
def.push_back(&mov->dst);
|
||||
use.push_back(&mov->src);
|
||||
return;
|
||||
}
|
||||
if (auto ld = shared_cast<MInstLoad>(inst)) {
|
||||
def.push_back(&ld->dst);
|
||||
use.push_back(&ld->addr);
|
||||
use.push_back(&ld->offset);
|
||||
return;
|
||||
}
|
||||
if (auto st = shared_cast<MInstStore>(inst)) {
|
||||
use.push_back(&st->addr);
|
||||
use.push_back(&st->data);
|
||||
use.push_back(&st->offset);
|
||||
return;
|
||||
}
|
||||
if (auto br = shared_cast<MInstBranch>(inst)) {
|
||||
use.push_back(&br->op1);
|
||||
use.push_back(&br->op2);
|
||||
return;
|
||||
}
|
||||
// if (auto sym = shared_cast<MInstSymbol>(inst)) {
|
||||
// def.push_back(&sym->dst);
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
} // namespace CompSysY
|
||||
@ -20,36 +20,30 @@ std::string MOperand::to_string() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#pragma region DEFUSE_UTILS
|
||||
|
||||
std::vector<MOperand> MInstBinary::get_def() const {
|
||||
return {dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstJump::get_def() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstBranch::get_def() const {
|
||||
return {};
|
||||
std::vector<MOperand *> MInstBinary::get_def_ptr() {
|
||||
return {&dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstLoad::get_def() const {
|
||||
return {dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstStore::get_def() const {
|
||||
return {};
|
||||
std::vector<MOperand *> MInstLoad::get_def_ptr() {
|
||||
return {&dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstMove::get_def() const {
|
||||
return {dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstReturn::get_def() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstComment::get_def() const {
|
||||
return {};
|
||||
std::vector<MOperand *> MInstMove::get_def_ptr() {
|
||||
return {&dst};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstCall::get_def() const {
|
||||
@ -74,40 +68,73 @@ std::vector<MOperand> MInstCall::get_def() const {
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<MOperand *> MInstCall::get_def_ptr() {
|
||||
// there is nothing to replace since they are all precolored
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstBinary::get_use() const {
|
||||
std::vector<MOperand> use;
|
||||
if (op1.is_reg()) use.push_back(op1);
|
||||
if (op2.is_reg()) use.push_back(op2);
|
||||
return use;
|
||||
}
|
||||
std::vector<MOperand> MInstJump::get_use() const {
|
||||
return {};
|
||||
|
||||
std::vector<MOperand *> MInstBinary::get_use_ptr() {
|
||||
std::vector<MOperand *> use;
|
||||
if (op1.is_reg()) use.push_back(&op1);
|
||||
if (op2.is_reg()) use.push_back(&op2);
|
||||
return use;
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstBranch::get_use() const {
|
||||
std::vector<MOperand> use;
|
||||
if (op1.is_reg()) use.push_back(op1);
|
||||
if (op2.is_reg()) use.push_back(op2);
|
||||
return use;
|
||||
}
|
||||
|
||||
std::vector<MOperand *> MInstBranch::get_use_ptr() {
|
||||
std::vector<MOperand *> use;
|
||||
if (op1.is_reg()) use.push_back(&op1);
|
||||
if (op2.is_reg()) use.push_back(&op2);
|
||||
return use;
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstLoad::get_use() const {
|
||||
// addr must be reg, offset must not be reg
|
||||
return {addr};
|
||||
}
|
||||
|
||||
std::vector<MOperand *> MInstLoad::get_use_ptr() {
|
||||
return {&addr};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstStore::get_use() const {
|
||||
// both addr and data must be reg, offset must not be reg
|
||||
return {addr, data};
|
||||
}
|
||||
|
||||
std::vector<MOperand *> MInstStore::get_use_ptr() {
|
||||
return {&addr, &data};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstMove::get_use() const {
|
||||
std::vector<MOperand> use;
|
||||
if (src.is_reg()) use.push_back(src);
|
||||
return use;
|
||||
}
|
||||
|
||||
std::vector<MOperand *> MInstMove::get_use_ptr() {
|
||||
std::vector<MOperand *> use;
|
||||
if (src.is_reg()) use.push_back(&src);
|
||||
return use;
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstReturn::get_use() const {
|
||||
return {MOperand::PreClrReg(RV64Reg::a0)};
|
||||
}
|
||||
std::vector<MOperand> MInstComment::get_use() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MOperand> MInstCall::get_use() const {
|
||||
// arg-occupied regs get implicitly used here
|
||||
std::vector<MOperand> use;
|
||||
@ -117,18 +144,25 @@ std::vector<MOperand> MInstCall::get_use() const {
|
||||
return use;
|
||||
}
|
||||
|
||||
void MInst::PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty) {
|
||||
#pragma endregion
|
||||
|
||||
void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_ty) {
|
||||
inst->inst_tag = tag;
|
||||
inst->parent_bb = parent_bb;
|
||||
switch (ins_ty) {
|
||||
case InsType::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break;
|
||||
case InsType::Tail: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); break;
|
||||
case InsertPos::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break;
|
||||
case InsertPos::Tail: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); break;
|
||||
default: sysy_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MInst::PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty) {
|
||||
void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MInst) rel_inst, InsertPos ins_ty) {
|
||||
inst->inst_tag = tag;
|
||||
auto parent_bb = rel_inst->parent_bb;
|
||||
inst->parent_bb = parent_bb;
|
||||
switch (ins_ty) {
|
||||
case InsType::Before:
|
||||
case InsType::After:
|
||||
case InsertPos::Before: inst->itr = parent_bb->inst_list.insert(rel_inst->itr, inst); break;
|
||||
case InsertPos::After: inst->itr = parent_bb->inst_list.insert(std::next(rel_inst->itr), inst); break;
|
||||
default: sysy_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,17 +26,17 @@ data-flow equation:
|
||||
livein[n] = use[n] union (liveout[n] - def[n])
|
||||
liveout[n] = union livein[s], for s in succ[n]
|
||||
*/
|
||||
static void liveness_analysis(sptr(MFunction) func) {
|
||||
static void liveness_analysis(MFunction *func) {
|
||||
// re-set def/use for each bb
|
||||
for (auto bb : func->bb_list) {
|
||||
bb->def.clear();
|
||||
bb->use.clear();
|
||||
for (auto inst : bb->inst_list) {
|
||||
for (auto &u : inst->get_use()) {
|
||||
if (!ASSOC_FOUND(bb->def, u)) bb->use.insert(u);
|
||||
if (!INSET(bb->def, u)) bb->use.insert(u);
|
||||
}
|
||||
for (auto &d : inst->get_def()) {
|
||||
if (!ASSOC_FOUND(bb->use, d)) bb->def.insert(d);
|
||||
if (!INSET(bb->use, d)) bb->def.insert(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,49 +66,8 @@ static void liveness_analysis(sptr(MFunction) func) {
|
||||
}
|
||||
bb->livein = newin;
|
||||
}
|
||||
// std::set<MOperand> outquote = bb->liveout;
|
||||
// std::set<MOperand> inquote = bb->livein;
|
||||
// bb->livein = bb->use;
|
||||
// for (auto elem : bb->liveout) {
|
||||
// if (!ASSOC_FOUND(bb->def, elem)) bb->livein.insert(elem);
|
||||
// }
|
||||
// bb->liveout.clear();
|
||||
// for (auto succ : bb->succ_list) {
|
||||
// bb->liveout.insert(succ->livein.begin(), succ->livein.end());
|
||||
// }
|
||||
// if (bb->liveout != outquote || bb->livein != inquote) {
|
||||
// changed = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
LOG(TRACE) << "Live Analysis done for " << func->ir_func->name;
|
||||
#if 0
|
||||
using std::cout, std::endl;
|
||||
LOG(TRACE) << "SLA info in " << func->ir_func->name;
|
||||
for (auto bb : func->bb_list) {
|
||||
cout << "BB " << bb->ir_bb->name << endl;
|
||||
cout << " def: ";
|
||||
for (auto def : bb->def) {
|
||||
cout << def.to_string() << ", ";
|
||||
}
|
||||
cout << "\n";
|
||||
cout << " use: ";
|
||||
for (auto use : bb->use) {
|
||||
cout << use.to_string() << ", ";
|
||||
}
|
||||
cout << "\n";
|
||||
cout << " livein: ";
|
||||
for (auto livein : bb->livein) {
|
||||
cout << livein.to_string() << ", ";
|
||||
}
|
||||
cout << "\n";
|
||||
cout << " liveout: ";
|
||||
for (auto liveout : bb->liveout) {
|
||||
cout << liveout.to_string() << ", ";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PassRegAlloc::add_edge(const MOperand &u, const MOperand &v) {
|
||||
@ -136,7 +95,7 @@ void PassRegAlloc::add_edge(const MOperand &u, const MOperand &v) {
|
||||
然后move_list是将操作数node映射到对应的mv指令上,在这里就加进去了
|
||||
然后worklist_move是"有可能合并的move指令的集合",这里初始默认认为所有的move都可能合并
|
||||
*/
|
||||
void PassRegAlloc::build(sptr(MFunction) func) {
|
||||
void PassRegAlloc::build(MFunction *func) {
|
||||
for (auto bb : func->bb_list) {
|
||||
// let live = liveout(b)
|
||||
auto live = bb->liveout;
|
||||
@ -181,7 +140,7 @@ void PassRegAlloc::build(sptr(MFunction) func) {
|
||||
/*
|
||||
主要就是把待染色的virt_reg分类
|
||||
*/
|
||||
void PassRegAlloc::make_work_list(sptr(MFunction) func) {
|
||||
void PassRegAlloc::make_work_list(MFunction *func) {
|
||||
/*
|
||||
forall n in initial
|
||||
initial <- initial - {n}
|
||||
@ -212,7 +171,7 @@ std::set<MInstMove *, PassRegAlloc::MvCmp> PassRegAlloc::node_moves(const MOpera
|
||||
auto ret = move_list[n];
|
||||
for (auto itr = ret.begin(); itr != ret.end();) {
|
||||
// not found in either set, then remove from movelist
|
||||
if (!ASSOC_FOUND(active_moves, *itr) && !ASSOC_FOUND(worklist_moves, *itr))
|
||||
if (!INSET(active_moves, *itr) && !INSET(worklist_moves, *itr))
|
||||
itr = ret.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
@ -224,7 +183,7 @@ std::set<MInstMove *, PassRegAlloc::MvCmp> PassRegAlloc::node_moves(const MOpera
|
||||
std::set<MOperand> PassRegAlloc::adjacent(const MOperand &n) {
|
||||
auto ret = adj_list[n];
|
||||
for (auto itr = ret.begin(); itr != ret.end();) {
|
||||
if (STD_FOUND(select_stack, *itr) || ASSOC_FOUND(coalesced_nodes, *itr))
|
||||
if (STD_FOUND(select_stack, *itr) || INSET(coalesced_nodes, *itr))
|
||||
itr = ret.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
@ -239,7 +198,7 @@ bool PassRegAlloc::move_related(const MOperand &n) {
|
||||
void PassRegAlloc::enable_moves(const MOperand &n) {
|
||||
auto node_moves_n = node_moves(n);
|
||||
for (auto &m : node_moves_n) {
|
||||
if (ASSOC_FOUND(active_moves, m)) {
|
||||
if (INSET(active_moves, m)) {
|
||||
active_moves.erase(m);
|
||||
worklist_moves.insert(m);
|
||||
}
|
||||
@ -301,7 +260,7 @@ void PassRegAlloc::coalesce() {
|
||||
coalesced_moves.insert(m);
|
||||
add_work_list(u);
|
||||
}
|
||||
else if (v.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(u, v))) {
|
||||
else if (v.is_precolored() || INSET(adj_set, std::make_pair(u, v))) {
|
||||
constrained_moves.insert(m);
|
||||
add_work_list(u);
|
||||
add_work_list(v);
|
||||
@ -327,7 +286,7 @@ void PassRegAlloc::add_work_list(const MOperand &u) {
|
||||
degree[t] < K || t in precolored || (t,r) in adjSet
|
||||
*/
|
||||
bool PassRegAlloc::OK(const MOperand &t, const MOperand &r) {
|
||||
return degree[t] < K || t.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(t, r));
|
||||
return degree[t] < K || t.is_precolored() || INSET(adj_set, std::make_pair(t, r));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -336,7 +295,7 @@ if n in coalescedNodes then
|
||||
else n
|
||||
*/
|
||||
MOperand PassRegAlloc::get_alias(const MOperand &n) {
|
||||
if (ASSOC_FOUND(coalesced_nodes, n)) return get_alias(alias[n]);
|
||||
if (INSET(coalesced_nodes, n)) return get_alias(alias[n]);
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -349,7 +308,7 @@ bool PassRegAlloc::conservative(const std::set<MOperand> &nodes) {
|
||||
}
|
||||
|
||||
void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
|
||||
if (ASSOC_FOUND(freeze_worklist, v))
|
||||
if (INSET(freeze_worklist, v))
|
||||
freeze_worklist.erase(v);
|
||||
else
|
||||
spill_worklist.erase(v);
|
||||
@ -360,13 +319,12 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
|
||||
for (auto mv : move_list.at(v)) {
|
||||
move_list[u].insert(mv);
|
||||
}
|
||||
// TODO: TrivialCompiler skipped the enablemoves below
|
||||
enable_moves(v);
|
||||
for (auto t : adjacent(v)) {
|
||||
add_edge(t, u);
|
||||
decrement_degree(t);
|
||||
}
|
||||
if (degree.at(u) >= K && ASSOC_FOUND(freeze_worklist, u)) {
|
||||
if (degree.at(u) >= K && INSET(freeze_worklist, u)) {
|
||||
freeze_worklist.erase(u);
|
||||
spill_worklist.insert(u);
|
||||
}
|
||||
@ -409,7 +367,7 @@ void PassRegAlloc::select_spill() {
|
||||
freeze_moves(m);
|
||||
}
|
||||
|
||||
void PassRegAlloc::assign_colors(sptr(MFunction) func) {
|
||||
void PassRegAlloc::assign_colors(MFunction *func) {
|
||||
while (!select_stack.empty()) {
|
||||
auto n = select_stack.back();
|
||||
select_stack.pop_back();
|
||||
@ -420,7 +378,7 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) {
|
||||
if (alias.op_type == MOpTag::PreColor) {
|
||||
ok_colors.erase(alias.value);
|
||||
}
|
||||
else if (ASSOC_FOUND(colored_nodes, alias)) {
|
||||
else if (INSET(colored_nodes, alias)) {
|
||||
auto color_alias = color.at(alias);
|
||||
ok_colors.erase(color_alias.value);
|
||||
}
|
||||
@ -442,84 +400,24 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) {
|
||||
}
|
||||
}
|
||||
|
||||
void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
|
||||
void PassRegAlloc::rewrite_program(MFunction *func) {
|
||||
std::set<MOperand> new_temps;
|
||||
#if 0
|
||||
auto gen_tmp_reg = [&]() {
|
||||
auto vr = func->virt_reg_cnt++;
|
||||
new_temps.insert(MOperand::VirtReg(vr));
|
||||
return vr;
|
||||
};
|
||||
for (auto v : spilled_nodes) {
|
||||
LOG(TRACE) << "Spill node " << v.to_string();
|
||||
for (auto bb : func->bb_list) {
|
||||
sptr(MInst) firstuse = nullptr;
|
||||
sptr(MInst) lastdef = nullptr;
|
||||
int vr = -1;
|
||||
for (auto inst : bb->inst_list) {
|
||||
std::vector<MOperand *> def;
|
||||
std::vector<MOperand *> use;
|
||||
get_inst_defuse(inst, def, use);
|
||||
for (auto d : def) {
|
||||
if (*d != v) continue;
|
||||
if (vr < 0) vr = gen_tmp_reg();
|
||||
d->value = vr;
|
||||
lastdef = inst;
|
||||
}
|
||||
for (auto u : use) {
|
||||
if (*u != v) continue;
|
||||
if (vr < 0) vr = gen_tmp_reg();
|
||||
u->value = vr;
|
||||
if (!lastdef && !firstuse) firstuse = inst;
|
||||
}
|
||||
// TODO: TrivialCompiler count bb size and add intermediate load/store
|
||||
}
|
||||
auto gen_off = [&](sptr(MInst) inst) {
|
||||
auto off_imm = MOperand::Imm(func->stack_size);
|
||||
return off_imm;
|
||||
if (is_in_imm_range(off_imm.value)) {
|
||||
return off_imm;
|
||||
}
|
||||
else {
|
||||
assert(0); //TODO bug here
|
||||
auto inst_mv = MInstMove::New(inst);
|
||||
inst_mv->src = off_imm;
|
||||
inst_mv->dst = MOperand::VirtReg(gen_tmp_reg());
|
||||
return inst_mv->dst;
|
||||
}
|
||||
};
|
||||
if (firstuse) {
|
||||
auto inst_ld = MInstLoad::New(firstuse, XLEN);
|
||||
inst_ld->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_ld->dst = MOperand::VirtReg(vr);
|
||||
inst_ld->offset = gen_off(inst_ld);
|
||||
}
|
||||
if (lastdef) {
|
||||
auto inst_st = MInstStore::New(lastdef, XLEN, true);
|
||||
inst_st->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_st->data = MOperand::VirtReg(vr);
|
||||
inst_st->offset = gen_off(inst_st);
|
||||
}
|
||||
}
|
||||
func->stack_size += XLEN;
|
||||
}
|
||||
#else
|
||||
for (auto v : spilled_nodes) {
|
||||
LOG(TRACE) << "Spill node " << v.to_string();
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto inst : bb->inst_list) {
|
||||
std::vector<MOperand *> def;
|
||||
std::vector<MOperand *> use;
|
||||
get_inst_defuse(inst, def, use);
|
||||
auto def = inst->get_def_ptr();
|
||||
auto use = inst->get_use_ptr();
|
||||
// TODO offset immediate may exceed range
|
||||
for (auto d : def) {
|
||||
if (*d != v) continue;
|
||||
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
||||
new_temps.insert(vr);
|
||||
auto inst_st = MInstStore::New(inst, XLEN, true);
|
||||
auto inst_st = MInstStore::New(inst, XLEN, InsertPos::After);
|
||||
inst_st->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_st->data = vr;
|
||||
inst_st->offset = MOperand::Imm(func->stack_size);
|
||||
auto cmt = MInstComment::New(inst_st);
|
||||
auto cmt = MInstComment::New(inst_st, InsertPos::Before);
|
||||
cmt->comment = fmt::format("spill def {} to stack", d->to_string());
|
||||
d->value = vr.value;
|
||||
}
|
||||
@ -527,11 +425,11 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
|
||||
if (*u != v) continue;
|
||||
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
||||
new_temps.insert(vr);
|
||||
auto inst_ld = MInstLoad::New(inst, XLEN);
|
||||
auto inst_ld = MInstLoad::New(inst, XLEN, InsertPos::Before);
|
||||
inst_ld->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||
inst_ld->dst = vr;
|
||||
inst_ld->offset = MOperand::Imm(func->stack_size);
|
||||
auto cmt = MInstComment::New(inst_ld);
|
||||
auto cmt = MInstComment::New(inst_ld, InsertPos::Before);
|
||||
cmt->comment = fmt::format("load from spilled use {}", u->to_string());
|
||||
u->value = vr.value;
|
||||
}
|
||||
@ -539,7 +437,7 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
|
||||
}
|
||||
func->stack_size += XLEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
spilled_nodes.clear();
|
||||
initial = colored_nodes;
|
||||
initial.insert(coalesced_nodes.begin(), coalesced_nodes.end());
|
||||
@ -571,7 +469,6 @@ void PassRegAlloc::clear() {
|
||||
frozen_moves.clear();
|
||||
worklist_moves.clear();
|
||||
active_moves.clear();
|
||||
spill_space.clear();
|
||||
// pre-define each pre-colored register's degree as inf
|
||||
for (int reg = 0; reg < 32; ++reg) {
|
||||
degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF});
|
||||
@ -590,38 +487,74 @@ if !spilledNodes.empty() then
|
||||
RewriteProgram
|
||||
Main()
|
||||
*/
|
||||
void emit_function(std::ostream &ostr, sptr(MFunction) func);
|
||||
|
||||
void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
|
||||
void PassRegAlloc::apply_coalesced(MFunction *func) {
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end(); ) {
|
||||
auto inst = *itr;
|
||||
auto defs = inst->get_def_ptr();
|
||||
auto uses = inst->get_use_ptr();
|
||||
for (auto def : defs) {
|
||||
if (!INSET(coalesced_nodes, *def)) continue;
|
||||
*def = get_alias(*def);
|
||||
}
|
||||
for (auto use : uses) {
|
||||
if (!INSET(coalesced_nodes, *use)) continue;
|
||||
*use = get_alias(*use);
|
||||
}
|
||||
if (auto mv = shared_cast<MInstMove>(inst)) {
|
||||
if (mv->src == mv->dst) {
|
||||
itr = mv->parent_bb->inst_list.erase(mv->itr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++ itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PassRegAlloc::reg_alloc(MFunction *func) {
|
||||
clear();
|
||||
liveness_analysis(func);
|
||||
// std::ofstream dbg("dbgfunc.asm", std::ios::app);
|
||||
// emit_function(dbg, func);
|
||||
// dbg.close();
|
||||
LOG(TRACE) << "[RegAlloc] LiveAnalysis done";
|
||||
build(func);
|
||||
LOG(TRACE) << "[RegAlloc] ConflictGraph built";
|
||||
make_work_list(func);
|
||||
LOG(TRACE) << "Simplify start for " << func->ir_func->name;
|
||||
bool flag = true;
|
||||
do {
|
||||
flag = false;
|
||||
LOG(TRACE) << "[RegAlloc] Start Simplify";
|
||||
bool first_coalesce = false, first_freeze = false, first_selectspill = false;
|
||||
while (true) {
|
||||
if (!simplify_worklist.empty()) {
|
||||
simplify();
|
||||
flag = true;
|
||||
}
|
||||
else if (!worklist_moves.empty()) {
|
||||
if (!first_coalesce) {
|
||||
LOG(TRACE) << "[RegAlloc] Start coalesce";
|
||||
first_coalesce = true;
|
||||
}
|
||||
coalesce();
|
||||
flag = true;
|
||||
}
|
||||
else if (!freeze_worklist.empty()) {
|
||||
if (!first_freeze) {
|
||||
LOG(TRACE) << "[RegAlloc] Start freeze";
|
||||
first_freeze = true;
|
||||
}
|
||||
freeze();
|
||||
flag = true;
|
||||
}
|
||||
else if (!spill_worklist.empty()) {
|
||||
if (!first_selectspill) {
|
||||
LOG(TRACE) << "[RegAlloc] Start select spill";
|
||||
first_selectspill = true;
|
||||
apply_coalesced(func); // 2m47s(on)/3m6s(off) for 8.*\.sy
|
||||
// For a faster algorithm, keep all the coalesces found before the first call to Select-Spill and rewrite the
|
||||
// program to eliminate the coalesced move instructions and temporaries.
|
||||
}
|
||||
select_spill();
|
||||
flag = true;
|
||||
}
|
||||
} while (flag);
|
||||
LOG(TRACE) << "Simplify done for " << func->ir_func->name;
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG(TRACE) << "[RegAlloc] Start Coloring";
|
||||
assign_colors(func);
|
||||
if (!spilled_nodes.empty()) {
|
||||
rewrite_program(func);
|
||||
@ -629,6 +562,21 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
|
||||
}
|
||||
}
|
||||
|
||||
void PassRegAlloc::set_color(MFunction *func) {
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto inst : bb->inst_list) {
|
||||
auto def = inst->get_def_ptr();
|
||||
auto use = inst->get_use_ptr();
|
||||
for (auto d : def) {
|
||||
if (INSET(color, *d)) *d = color.at(*d);
|
||||
}
|
||||
for (auto u : use) {
|
||||
if (INSET(color, *u)) *u = color.at(*u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PassRegAlloc::run(const MCModule &module) {
|
||||
for (auto func : module.function_list) {
|
||||
LOG(INFO) << "Run " << pass_name << " for func " << func->ir_func->name;
|
||||
@ -638,21 +586,9 @@ void PassRegAlloc::run(const MCModule &module) {
|
||||
auto vr = MOperand::VirtReg(i);
|
||||
initial.insert(vr);
|
||||
}
|
||||
reg_alloc(func);
|
||||
reg_alloc(func.get());
|
||||
// patch all the color info back to the MCIR tree, note the pointer type here
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto inst : bb->inst_list) {
|
||||
std::vector<MOperand *> def;
|
||||
std::vector<MOperand *> use;
|
||||
get_inst_defuse(inst, def, use);
|
||||
for (auto d : def) {
|
||||
if (ASSOC_FOUND(color, *d)) *d = color.at(*d);
|
||||
}
|
||||
for (auto u : use) {
|
||||
if (ASSOC_FOUND(color, *u)) *u = color.at(*u);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_color(func.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user