RegAlloc pass all func test

This commit is contained in:
ridethepig 2023-06-14 20:53:57 +08:00
parent 6bf4093bfb
commit 81bd968258
8 changed files with 259 additions and 364 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
coalescedNodesuV时y加人到这个集合中w则被放回到某个工作表中
coalescedNodesu,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

View File

@ -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");

View File

@ -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()) {

View File

@ -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

View File

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

View File

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