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_FIND(container, val) std::find(container.begin(), container.end(), val)
|
||||||
#define STD_FOUND(container, val) (STD_FIND(container, val) != container.end())
|
#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 INF (0x3f3f3f3f)
|
||||||
#define BTWN(v, l, r) (l <= v && v <= r)
|
#define BTWN(v, l, r) (l <= v && v <= r)
|
||||||
|
|||||||
@ -205,7 +205,7 @@ inline MInstTag inverse_cond(MInstTag src_tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Instruction insertion type
|
// Instruction insertion type
|
||||||
enum class InsType { Before, After, Head, Tail };
|
enum class InsertPos { Before, After, Head, Tail };
|
||||||
|
|
||||||
class MInst {
|
class MInst {
|
||||||
public:
|
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
|
// 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
|
// Similarly, it makes difference when computing address
|
||||||
int width = 4;
|
int width = 4;
|
||||||
|
|
||||||
std::list<sptr(MInst)>::iterator itr;
|
std::list<sptr(MInst)>::iterator itr;
|
||||||
sptr(MBasicBlock) parent_bb;
|
sptr(MBasicBlock) parent_bb;
|
||||||
MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : inst_tag(tag), parent_bb(parent_bb) {}
|
virtual ~MInst() = default;
|
||||||
virtual ~MInst() = default;
|
virtual std::vector<MOperand> get_def() const {
|
||||||
virtual std::vector<MOperand> get_def() const = 0;
|
return {};
|
||||||
virtual std::vector<MOperand> get_use() const = 0;
|
};
|
||||||
|
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 {
|
virtual bool is_transfer() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty);
|
static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_pos);
|
||||||
static void PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty);
|
static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MInst) rel_inst, InsertPos ins_pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MBasicBlock {
|
class MBasicBlock {
|
||||||
@ -276,40 +284,35 @@ public:
|
|||||||
MOperand dst;
|
MOperand dst;
|
||||||
MOperand op1;
|
MOperand op1;
|
||||||
MOperand op2;
|
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) {
|
static sptr(MInstBinary)
|
||||||
auto inst = make_shared<MInstBinary>(type, parent_bb);
|
New(MInstTag type, sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos = InsertPos::Tail) {
|
||||||
|
auto inst = make_shared<MInstBinary>();
|
||||||
inst->width = width;
|
inst->width = width;
|
||||||
MInst::PostNew(inst, parent_bb, ins_ty);
|
MInst::PostNew(inst, type, parent_bb, ins_pos);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, InsertPos ins_pos = InsertPos::Before) {
|
||||||
auto parent_bb = rel_inst->parent_bb;
|
auto inst = make_shared<MInstBinary>();
|
||||||
auto inst = make_shared<MInstBinary>(type, parent_bb);
|
inst->width = width;
|
||||||
inst->width = width;
|
MInst::PostNew(inst, type, rel_inst, ins_pos);
|
||||||
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);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
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() const override;
|
||||||
|
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MInstJump : public MInst {
|
class MInstJump : public MInst {
|
||||||
public:
|
public:
|
||||||
sptr(MBasicBlock) target;
|
sptr(MBasicBlock) target;
|
||||||
MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jmp, parent_bb) {}
|
|
||||||
|
|
||||||
static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) {
|
static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) {
|
||||||
auto inst = make_shared<MInstJump>(parent_bb);
|
auto inst = make_shared<MInstJump>();
|
||||||
parent_bb->inst_list.push_back(inst);
|
PostNew(inst, MInstTag::Jmp, parent_bb, InsertPos::Tail);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
|
||||||
virtual std::vector<MOperand> get_use() const override;
|
|
||||||
bool is_transfer() const override {
|
bool is_transfer() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -321,14 +324,13 @@ public:
|
|||||||
MOperand op1;
|
MOperand op1;
|
||||||
MOperand op2;
|
MOperand op2;
|
||||||
MInstTag branch_tag;
|
MInstTag branch_tag;
|
||||||
MInstBranch(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Branch, parent_bb) {}
|
|
||||||
static sptr(MInstBranch) New(sptr(MBasicBlock) parent_bb) {
|
static sptr(MInstBranch) New(sptr(MBasicBlock) parent_bb) {
|
||||||
auto inst = make_shared<MInstBranch>(parent_bb);
|
auto inst = make_shared<MInstBranch>();
|
||||||
parent_bb->inst_list.push_back(inst);
|
PostNew(inst, MInstTag::Branch, parent_bb, InsertPos::Tail);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
|
||||||
virtual std::vector<MOperand> get_use() const override;
|
virtual std::vector<MOperand> get_use() const override;
|
||||||
|
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||||
bool is_transfer() const override {
|
bool is_transfer() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -339,26 +341,23 @@ public:
|
|||||||
MOperand dst;
|
MOperand dst;
|
||||||
MOperand addr;
|
MOperand addr;
|
||||||
MOperand offset;
|
MOperand offset;
|
||||||
MInstLoad(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Load, parent_bb) {}
|
|
||||||
|
|
||||||
static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width) {
|
static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) {
|
||||||
auto inst = make_shared<MInstLoad>(parent_bb);
|
auto inst = make_shared<MInstLoad>();
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
inst->width = width;
|
inst->width = width;
|
||||||
|
PostNew(inst, MInstTag::Load, parent_bb, ins_pos);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) {
|
||||||
auto parent_bb = rel_inst->parent_bb;
|
auto inst = make_shared<MInstLoad>();
|
||||||
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);
|
|
||||||
inst->width = width;
|
inst->width = width;
|
||||||
|
PostNew(inst, MInstTag::Load, rel_inst, ins_pos);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
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() const override;
|
||||||
|
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MInstStore : public MInst {
|
class MInstStore : public MInst {
|
||||||
@ -366,81 +365,50 @@ public:
|
|||||||
MOperand data;
|
MOperand data;
|
||||||
MOperand addr;
|
MOperand addr;
|
||||||
MOperand offset;
|
MOperand offset;
|
||||||
MInstStore(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Store, parent_bb) {}
|
|
||||||
|
|
||||||
static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width) {
|
static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) {
|
||||||
auto inst = make_shared<MInstStore>(parent_bb);
|
auto inst = make_shared<MInstStore>();
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
inst->width = width;
|
inst->width = width;
|
||||||
|
PostNew(inst, MInstTag::Store, parent_bb, ins_pos);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, bool insert_after = false) {
|
static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) {
|
||||||
auto parent_bb = rel_inst->parent_bb;
|
auto inst = make_shared<MInstStore>();
|
||||||
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);
|
|
||||||
inst->width = width;
|
inst->width = width;
|
||||||
|
PostNew(inst, MInstTag::Store, rel_inst, ins_pos);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
|
||||||
virtual std::vector<MOperand> get_use() const override;
|
virtual std::vector<MOperand> get_use() const override;
|
||||||
|
virtual std::vector<MOperand *> get_use_ptr() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MInstMove : public MInst {
|
class MInstMove : public MInst {
|
||||||
public:
|
public:
|
||||||
MOperand dst;
|
MOperand dst;
|
||||||
MOperand src;
|
MOperand src;
|
||||||
MInstMove(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Move, parent_bb) {}
|
static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||||
static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
auto inst = make_shared<MInstMove>();
|
||||||
auto inst = make_shared<MInstMove>(parent_bb);
|
PostNew(inst, MInstTag::Move, parent_bb, ins_pos);
|
||||||
if (insert_begin)
|
|
||||||
parent_bb->inst_list.push_front(inst);
|
|
||||||
else
|
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
static sptr(MInstMove) New(sptr(MInst) rel_inst, bool insert_after = false) {
|
static sptr(MInstMove) New(sptr(MInst) rel_inst, InsertPos ins_pos) {
|
||||||
auto parent_bb = rel_inst->parent_bb;
|
auto inst = make_shared<MInstMove>();
|
||||||
auto inst = make_shared<MInstMove>(parent_bb);
|
PostNew(inst, MInstTag::Move, rel_inst, ins_pos);
|
||||||
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);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
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() 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 {
|
class MInstReturn : public MInst {
|
||||||
public:
|
public:
|
||||||
MInstReturn(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Ret, parent_bb) {}
|
static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||||
static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
auto inst = make_shared<MInstReturn>();
|
||||||
auto inst = make_shared<MInstReturn>(parent_bb);
|
PostNew(inst, MInstTag::Ret, parent_bb, ins_pos);
|
||||||
if (insert_begin)
|
|
||||||
parent_bb->inst_list.push_front(inst);
|
|
||||||
else
|
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
|
||||||
virtual std::vector<MOperand> get_use() const override;
|
virtual std::vector<MOperand> get_use() const override;
|
||||||
bool is_transfer() const override {
|
bool is_transfer() const override {
|
||||||
return true;
|
return true;
|
||||||
@ -450,37 +418,28 @@ public:
|
|||||||
class MInstComment : public MInst {
|
class MInstComment : public MInst {
|
||||||
public:
|
public:
|
||||||
std::string comment;
|
std::string comment;
|
||||||
MInstComment(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Comment, parent_bb) {}
|
static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||||
static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb) {
|
auto inst = make_shared<MInstComment>();
|
||||||
auto inst = make_shared<MInstComment>(parent_bb);
|
PostNew(inst, MInstTag::Comment, parent_bb, ins_pos);
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
static sptr(MInstComment) New(sptr(MInst) rel_inst, bool insert_after = false) {
|
static sptr(MInstComment) New(sptr(MInst) rel_inst, InsertPos ins_pos) {
|
||||||
auto parent_bb = rel_inst->parent_bb;
|
auto inst = make_shared<MInstComment>();
|
||||||
auto inst = make_shared<MInstComment>(parent_bb);
|
PostNew(inst, MInstTag::Comment, rel_inst, ins_pos);
|
||||||
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);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
|
||||||
virtual std::vector<MOperand> get_use() const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MInstCall : public MInst {
|
class MInstCall : public MInst {
|
||||||
public:
|
public:
|
||||||
sptr(Function) ir_func;
|
sptr(Function) ir_func;
|
||||||
MInstCall(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Call, parent_bb) {}
|
static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) {
|
||||||
static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb) {
|
auto inst = make_shared<MInstCall>();
|
||||||
auto inst = make_shared<MInstCall>(parent_bb);
|
PostNew(inst, MInstTag::Call, parent_bb, ins_pos);
|
||||||
parent_bb->inst_list.push_back(inst);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
virtual std::vector<MOperand> get_def() const override;
|
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() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use);
|
|
||||||
} // namespace CompSysY
|
} // namespace CompSysY
|
||||||
@ -45,6 +45,7 @@ public:
|
|||||||
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// 可以按照指令内容(而不是指针地址)来给Move排序,使得算法具有更好的确定性,便于调试
|
||||||
struct MvCmp {
|
struct MvCmp {
|
||||||
bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const {
|
bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const {
|
||||||
if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst;
|
if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst;
|
||||||
@ -59,14 +60,14 @@ private:
|
|||||||
freezeWorklist:低度数的传送有关的结点表。
|
freezeWorklist:低度数的传送有关的结点表。
|
||||||
spillWorklist:高度数的结点表。
|
spillWorklist:高度数的结点表。
|
||||||
spilledNodes:在本轮中要被溢出的结点集合,初始为空。
|
spilledNodes:在本轮中要被溢出的结点集合,初始为空。
|
||||||
coalescedNodes:已合并的寄存器集合。当合并uV时,将y加人到这个集合中,w则被放回到某个工作表中(或反之)。
|
coalescedNodes:已合并的寄存器集合。当合并u,v时,将v加人到这个集合中,u则被放回到某个工作表中(或反之)。
|
||||||
coloredNodes :已成功着色的结点集合。
|
coloredNodes :已成功着色的结点集合。
|
||||||
selectstack:一个包含从图中删除的临时变量的栈
|
selectstack:一个包含从图中删除的临时变量的栈
|
||||||
*/
|
*/
|
||||||
void reg_alloc(sptr(MFunction));
|
void reg_alloc(MFunction *);
|
||||||
void build(sptr(MFunction));
|
void build(MFunction *);
|
||||||
void add_edge(const MOperand &u, const MOperand &v);
|
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);
|
bool move_related(const MOperand &n);
|
||||||
std::set<MInstMove *, MvCmp> node_moves(const MOperand &n);
|
std::set<MInstMove *, MvCmp> node_moves(const MOperand &n);
|
||||||
std::set<MOperand> adjacent(const MOperand &n);
|
std::set<MOperand> adjacent(const MOperand &n);
|
||||||
@ -82,9 +83,11 @@ private:
|
|||||||
void freeze();
|
void freeze();
|
||||||
void freeze_moves(const MOperand &u);
|
void freeze_moves(const MOperand &u);
|
||||||
void select_spill();
|
void select_spill();
|
||||||
void assign_colors(sptr(MFunction) func);
|
void assign_colors(MFunction *func);
|
||||||
void rewrite_program(sptr(MFunction) func);
|
void rewrite_program(MFunction *func);
|
||||||
void clear();
|
void clear();
|
||||||
|
void set_color(MFunction *);
|
||||||
|
void apply_coalesced(MFunction *);
|
||||||
std::map<MOperand, std::set<MOperand>> adj_list;
|
std::map<MOperand, std::set<MOperand>> adj_list;
|
||||||
std::set<std::pair<MOperand, MOperand>> adj_set;
|
std::set<std::pair<MOperand, MOperand>> adj_set;
|
||||||
std::map<MOperand, unsigned> degree;
|
std::map<MOperand, unsigned> degree;
|
||||||
@ -104,7 +107,6 @@ private:
|
|||||||
std::set<MInstMove *, MvCmp> frozen_moves;
|
std::set<MInstMove *, MvCmp> frozen_moves;
|
||||||
std::set<MInstMove *, MvCmp> worklist_moves;
|
std::set<MInstMove *, MvCmp> worklist_moves;
|
||||||
std::set<MInstMove *, MvCmp> active_moves;
|
std::set<MInstMove *, MvCmp> active_moves;
|
||||||
std::map<MOperand, int> spill_space;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CompSysY
|
} // namespace CompSysY
|
||||||
@ -63,11 +63,9 @@ int main(int argc, const char **argv) {
|
|||||||
auto flg_O0 = arg_parser["-O0"] == true;
|
auto flg_O0 = arg_parser["-O0"] == true;
|
||||||
auto emit_llvm = arg_parser["-emit-llvm"] == true;
|
auto emit_llvm = arg_parser["-emit-llvm"] == true;
|
||||||
auto no_asm = arg_parser["-no-asm"] == true;
|
auto no_asm = arg_parser["-no-asm"] == true;
|
||||||
// std::cout << source_file << " " << output_file << " " << flg_O1 <<
|
|
||||||
// std::endl;
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
START_EASYLOGGINGPP(argc, argv);
|
|
||||||
#pragma region Logger
|
#pragma region Logger
|
||||||
|
START_EASYLOGGINGPP(argc, argv);
|
||||||
el::Configurations defaultConf;
|
el::Configurations defaultConf;
|
||||||
defaultConf.setToDefault();
|
defaultConf.setToDefault();
|
||||||
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%levshort %loc %msg");
|
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) {
|
static void bb_debug(std::ostream &ostr, sptr(MBasicBlock) bb) {
|
||||||
ostr << "pred:";
|
ostr << "pred:";
|
||||||
for (auto item : bb->pred_list) {
|
for (auto item : bb->pred_list) {
|
||||||
ostr << "L_BB_" << item->id << ",";
|
ostr << item->to_string() << ",";
|
||||||
}
|
}
|
||||||
ostr << "\n";
|
ostr << "\n";
|
||||||
ostr << "succ:";
|
ostr << "succ:";
|
||||||
for (auto item : bb->succ_list) {
|
for (auto item : bb->succ_list) {
|
||||||
ostr << "L_BB_" << item->id << ",";
|
ostr << item->to_string() << ",";
|
||||||
}
|
}
|
||||||
ostr << "\n";
|
ostr << "\n";
|
||||||
ostr << "livein:";
|
ostr << "livein:";
|
||||||
@ -312,10 +312,14 @@ static void stack_postprocess(sptr(MFunction) func) {
|
|||||||
|
|
||||||
void emit_function(std::ostream &ostr, sptr(MFunction) func) {
|
void emit_function(std::ostream &ostr, sptr(MFunction) func) {
|
||||||
// function header
|
// function header
|
||||||
ostr << "\t.globl\t" << func->ir_func->name << "\n";
|
ostr << fmt::format(
|
||||||
ostr << "\t.p2align\t1\n";
|
"\t.globl\t{0}\n"
|
||||||
ostr << "\t.type\t" << func->ir_func->name << ",@function\n";
|
"\t.p2align\t1\n"
|
||||||
ostr << func->ir_func->name << ":" << endl;
|
"\t.type\t{0},@function\n"
|
||||||
|
"{0}:",
|
||||||
|
func->ir_func->name
|
||||||
|
)
|
||||||
|
<< endl;
|
||||||
// entry code
|
// entry code
|
||||||
// First push callee-saved regs
|
// First push callee-saved regs
|
||||||
if (!func->regs_to_save.empty()) {
|
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++);
|
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||||
sptr(MInstMove) inst_move;
|
sptr(MInstMove) inst_move;
|
||||||
if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer())
|
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
|
else
|
||||||
inst_move = MInstMove::New(mc_bb);
|
inst_move = MInstMove::New(mc_bb, InsertPos::Tail);
|
||||||
inst_move->src = operand;
|
inst_move->src = operand;
|
||||||
inst_move->dst = vr;
|
inst_move->dst = vr;
|
||||||
return vr;
|
return vr;
|
||||||
@ -50,7 +50,7 @@ static MOperand value2moperand(
|
|||||||
// according to RV call conv, we can have a0-a7 for params
|
// according to RV call conv, we can have a0-a7 for params
|
||||||
if (fparam_ndx < 8) {
|
if (fparam_ndx < 8) {
|
||||||
// copy param as an vr in func entry
|
// 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->src = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx));
|
||||||
inst_move->dst = vr;
|
inst_move->dst = vr;
|
||||||
}
|
}
|
||||||
@ -59,9 +59,6 @@ static MOperand value2moperand(
|
|||||||
// this need to be further re-located since sp may have changed
|
// this need to be further re-located since sp may have changed
|
||||||
// FramePtr won't get used here, for perf reason. Ref:
|
// 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
|
// 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;
|
int width = 0;
|
||||||
if (shared_cast<IntegerType>(fparam->type))
|
if (shared_cast<IntegerType>(fparam->type))
|
||||||
width = 4;
|
width = 4;
|
||||||
@ -70,10 +67,10 @@ static MOperand value2moperand(
|
|||||||
sptr(MInstLoad) inst_load;
|
sptr(MInstLoad) inst_load;
|
||||||
// ld vr, (i-8)*8(sp)
|
// ld vr, (i-8)*8(sp)
|
||||||
if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer())
|
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
|
else
|
||||||
inst_load = MInstLoad::New(mc_bb, width);
|
inst_load = MInstLoad::New(mc_bb, width, InsertPos::Tail);
|
||||||
// auto inst_move = MInstMove::New(inst_load); // lui vr_t,
|
// TODO offset immediate may exceed range
|
||||||
inst_load->addr = MOperand::PreClrReg(RV64Reg::sp);
|
inst_load->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||||
inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN);
|
inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN);
|
||||||
inst_load->dst = vr;
|
inst_load->dst = vr;
|
||||||
@ -94,7 +91,7 @@ static MOperand value2moperand(
|
|||||||
// return vr;
|
// return vr;
|
||||||
auto op_glob = MOperand::Glob(glob);
|
auto op_glob = MOperand::Glob(glob);
|
||||||
if (force_reg) {
|
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++);
|
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||||
// val2mop.insert({ir_value, vr});
|
// val2mop.insert({ir_value, vr});
|
||||||
inst_la->dst = 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
|
// width is important when load/store to an array address, so be careful
|
||||||
int width = XLEN;
|
int width = XLEN;
|
||||||
if (shared_cast<IntegerType>(ld->type)) width = 4;
|
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->addr = addr;
|
||||||
mc_li->dst = value2moperand(ld, mc_bb, mp_val2op);
|
mc_li->dst = value2moperand(ld, mc_bb, mp_val2op);
|
||||||
mc_li->offset = MOperand::Imm(0);
|
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);
|
auto addr = value2moperand(st->operand_list[1], mc_bb, mp_val2op, true);
|
||||||
int width = XLEN;
|
int width = XLEN;
|
||||||
if (shared_cast<IntegerType>(st->operand_list[0]->type)) width = 4;
|
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->addr = addr;
|
||||||
mc_st->data = data;
|
mc_st->data = data;
|
||||||
mc_st->offset = MOperand::Imm(0);
|
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)) {
|
if ((inst->operand_list.size() < 3 && !index0.value) || (inst->operand_list.size() == 3 && index1.is_imm() && !index1.value)) {
|
||||||
// a shortcut for zero gep
|
// 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->dst = dst;
|
||||||
inst_mv->src = ptr;
|
inst_mv->src = ptr;
|
||||||
VLOG(6) << "trivial gep";
|
VLOG(6) << "trivial gep";
|
||||||
@ -277,11 +274,11 @@ void MCModule::IR2MC(const Module &ir_module) {
|
|||||||
if (auto ret = shared_cast<InstReturn>(inst)) {
|
if (auto ret = shared_cast<InstReturn>(inst)) {
|
||||||
if (ret->operand_list.size()) {
|
if (ret->operand_list.size()) {
|
||||||
auto retval = value2moperand(ret->operand_list[0], mc_bb, mp_val2op);
|
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->src = retval;
|
||||||
inst_mv->dst = MOperand::PreClrReg(RV64Reg::a0);
|
inst_mv->dst = MOperand::PreClrReg(RV64Reg::a0);
|
||||||
}
|
}
|
||||||
MInstReturn::New(mc_bb);
|
MInstReturn::New(mc_bb, InsertPos::Tail);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (auto cal = shared_cast<InstCall>(inst)) {
|
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) {
|
for (int i = 1; i < cal->operand_list.size(); ++i) {
|
||||||
auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true);
|
auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true);
|
||||||
if (i <= 8) {
|
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->src = rparam;
|
||||||
inst_move->dst = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i - 1));
|
inst_move->dst = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i - 1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int st_off = -(nparams - (i - 1)) * XLEN;
|
int st_off = -(nparams - (i - 1)) * XLEN;
|
||||||
auto st_off_imm = gen_imm(st_off, mc_bb);
|
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->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||||
inst_store->offset = st_off_imm;
|
inst_store->offset = st_off_imm;
|
||||||
inst_store->data = rparam;
|
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);
|
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]);
|
inst_call->ir_func = strict_shared_cast<Function>(cal->operand_list[0]);
|
||||||
|
|
||||||
if (nparams > 8) {
|
if (nparams > 8) {
|
||||||
@ -324,7 +321,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
|||||||
// handle return value, if exist
|
// handle return value, if exist
|
||||||
if (shared_cast<IntegerType>(cal->type)) {
|
if (shared_cast<IntegerType>(cal->type)) {
|
||||||
auto dst = value2moperand(inst, 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 = MOperand::PreClrReg(RV64Reg::a0);
|
inst_mv->src = MOperand::PreClrReg(RV64Reg::a0);
|
||||||
inst_mv->dst = dst;
|
inst_mv->dst = dst;
|
||||||
}
|
}
|
||||||
@ -412,7 +409,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
|||||||
}
|
}
|
||||||
auto src_imm = gen_imm(res, mc_bb);
|
auto src_imm = gen_imm(res, mc_bb);
|
||||||
auto dst = value2moperand(inst, 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->dst = dst;
|
inst_mv->dst = dst;
|
||||||
inst_mv->src = src_imm;
|
inst_mv->src = src_imm;
|
||||||
continue;
|
continue;
|
||||||
@ -503,7 +500,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
|||||||
// trivial move
|
// trivial move
|
||||||
auto src = value2moperand(zxt->operand_list[0], mc_bb, mp_val2op);
|
auto src = value2moperand(zxt->operand_list[0], mc_bb, mp_val2op);
|
||||||
auto dst = value2moperand(inst, 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->src = src;
|
||||||
inst_mv->dst = dst;
|
inst_mv->dst = dst;
|
||||||
continue;
|
continue;
|
||||||
@ -544,7 +541,7 @@ void MCModule::IR2MC(const Module &ir_module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &pmv : par_mv_cur) {
|
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->src = pmv.src;
|
||||||
inst_mv->dst = pmv.dst;
|
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(), {
|
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;
|
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->src = pmv_pair.second.src;
|
||||||
inst_mv->dst = pmv_pair.second.dst;
|
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
|
} // namespace CompSysY
|
||||||
@ -20,36 +20,30 @@ std::string MOperand::to_string() const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma region DEFUSE_UTILS
|
||||||
|
|
||||||
std::vector<MOperand> MInstBinary::get_def() const {
|
std::vector<MOperand> MInstBinary::get_def() const {
|
||||||
return {dst};
|
return {dst};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstJump::get_def() const {
|
std::vector<MOperand *> MInstBinary::get_def_ptr() {
|
||||||
return {};
|
return {&dst};
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MOperand> MInstBranch::get_def() const {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstLoad::get_def() const {
|
std::vector<MOperand> MInstLoad::get_def() const {
|
||||||
return {dst};
|
return {dst};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstStore::get_def() const {
|
std::vector<MOperand *> MInstLoad::get_def_ptr() {
|
||||||
return {};
|
return {&dst};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstMove::get_def() const {
|
std::vector<MOperand> MInstMove::get_def() const {
|
||||||
return {dst};
|
return {dst};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstReturn::get_def() const {
|
std::vector<MOperand *> MInstMove::get_def_ptr() {
|
||||||
return {};
|
return {&dst};
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MOperand> MInstComment::get_def() const {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstCall::get_def() const {
|
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> MInstBinary::get_use() const {
|
||||||
std::vector<MOperand> use;
|
std::vector<MOperand> use;
|
||||||
if (op1.is_reg()) use.push_back(op1);
|
if (op1.is_reg()) use.push_back(op1);
|
||||||
if (op2.is_reg()) use.push_back(op2);
|
if (op2.is_reg()) use.push_back(op2);
|
||||||
return use;
|
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> MInstBranch::get_use() const {
|
||||||
std::vector<MOperand> use;
|
std::vector<MOperand> use;
|
||||||
if (op1.is_reg()) use.push_back(op1);
|
if (op1.is_reg()) use.push_back(op1);
|
||||||
if (op2.is_reg()) use.push_back(op2);
|
if (op2.is_reg()) use.push_back(op2);
|
||||||
return use;
|
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 {
|
std::vector<MOperand> MInstLoad::get_use() const {
|
||||||
// addr must be reg, offset must not be reg
|
// addr must be reg, offset must not be reg
|
||||||
return {addr};
|
return {addr};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<MOperand *> MInstLoad::get_use_ptr() {
|
||||||
|
return {&addr};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstStore::get_use() const {
|
std::vector<MOperand> MInstStore::get_use() const {
|
||||||
// both addr and data must be reg, offset must not be reg
|
// both addr and data must be reg, offset must not be reg
|
||||||
return {addr, data};
|
return {addr, data};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<MOperand *> MInstStore::get_use_ptr() {
|
||||||
|
return {&addr, &data};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<MOperand> MInstMove::get_use() const {
|
std::vector<MOperand> MInstMove::get_use() const {
|
||||||
std::vector<MOperand> use;
|
std::vector<MOperand> use;
|
||||||
if (src.is_reg()) use.push_back(src);
|
if (src.is_reg()) use.push_back(src);
|
||||||
return use;
|
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 {
|
std::vector<MOperand> MInstReturn::get_use() const {
|
||||||
return {MOperand::PreClrReg(RV64Reg::a0)};
|
return {MOperand::PreClrReg(RV64Reg::a0)};
|
||||||
}
|
}
|
||||||
std::vector<MOperand> MInstComment::get_use() const {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::vector<MOperand> MInstCall::get_use() const {
|
std::vector<MOperand> MInstCall::get_use() const {
|
||||||
// arg-occupied regs get implicitly used here
|
// arg-occupied regs get implicitly used here
|
||||||
std::vector<MOperand> use;
|
std::vector<MOperand> use;
|
||||||
@ -117,18 +144,25 @@ std::vector<MOperand> MInstCall::get_use() const {
|
|||||||
return use;
|
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) {
|
switch (ins_ty) {
|
||||||
case InsType::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break;
|
case InsertPos::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::Tail: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); break;
|
||||||
default: sysy_assert(0);
|
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) {
|
switch (ins_ty) {
|
||||||
case InsType::Before:
|
case InsertPos::Before: inst->itr = parent_bb->inst_list.insert(rel_inst->itr, inst); break;
|
||||||
case InsType::After:
|
case InsertPos::After: inst->itr = parent_bb->inst_list.insert(std::next(rel_inst->itr), inst); break;
|
||||||
default: sysy_assert(0);
|
default: sysy_assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,17 +26,17 @@ data-flow equation:
|
|||||||
livein[n] = use[n] union (liveout[n] - def[n])
|
livein[n] = use[n] union (liveout[n] - def[n])
|
||||||
liveout[n] = union livein[s], for s in succ[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
|
// re-set def/use for each bb
|
||||||
for (auto bb : func->bb_list) {
|
for (auto bb : func->bb_list) {
|
||||||
bb->def.clear();
|
bb->def.clear();
|
||||||
bb->use.clear();
|
bb->use.clear();
|
||||||
for (auto inst : bb->inst_list) {
|
for (auto inst : bb->inst_list) {
|
||||||
for (auto &u : inst->get_use()) {
|
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()) {
|
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;
|
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) {
|
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指令上,在这里就加进去了
|
然后move_list是将操作数node映射到对应的mv指令上,在这里就加进去了
|
||||||
然后worklist_move是"有可能合并的move指令的集合",这里初始默认认为所有的move都可能合并
|
然后worklist_move是"有可能合并的move指令的集合",这里初始默认认为所有的move都可能合并
|
||||||
*/
|
*/
|
||||||
void PassRegAlloc::build(sptr(MFunction) func) {
|
void PassRegAlloc::build(MFunction *func) {
|
||||||
for (auto bb : func->bb_list) {
|
for (auto bb : func->bb_list) {
|
||||||
// let live = liveout(b)
|
// let live = liveout(b)
|
||||||
auto live = bb->liveout;
|
auto live = bb->liveout;
|
||||||
@ -181,7 +140,7 @@ void PassRegAlloc::build(sptr(MFunction) func) {
|
|||||||
/*
|
/*
|
||||||
主要就是把待染色的virt_reg分类
|
主要就是把待染色的virt_reg分类
|
||||||
*/
|
*/
|
||||||
void PassRegAlloc::make_work_list(sptr(MFunction) func) {
|
void PassRegAlloc::make_work_list(MFunction *func) {
|
||||||
/*
|
/*
|
||||||
forall n in initial
|
forall n in initial
|
||||||
initial <- initial - {n}
|
initial <- initial - {n}
|
||||||
@ -212,7 +171,7 @@ std::set<MInstMove *, PassRegAlloc::MvCmp> PassRegAlloc::node_moves(const MOpera
|
|||||||
auto ret = move_list[n];
|
auto ret = move_list[n];
|
||||||
for (auto itr = ret.begin(); itr != ret.end();) {
|
for (auto itr = ret.begin(); itr != ret.end();) {
|
||||||
// not found in either set, then remove from movelist
|
// 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);
|
itr = ret.erase(itr);
|
||||||
else
|
else
|
||||||
++itr;
|
++itr;
|
||||||
@ -224,7 +183,7 @@ std::set<MInstMove *, PassRegAlloc::MvCmp> PassRegAlloc::node_moves(const MOpera
|
|||||||
std::set<MOperand> PassRegAlloc::adjacent(const MOperand &n) {
|
std::set<MOperand> PassRegAlloc::adjacent(const MOperand &n) {
|
||||||
auto ret = adj_list[n];
|
auto ret = adj_list[n];
|
||||||
for (auto itr = ret.begin(); itr != ret.end();) {
|
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);
|
itr = ret.erase(itr);
|
||||||
else
|
else
|
||||||
++itr;
|
++itr;
|
||||||
@ -239,7 +198,7 @@ bool PassRegAlloc::move_related(const MOperand &n) {
|
|||||||
void PassRegAlloc::enable_moves(const MOperand &n) {
|
void PassRegAlloc::enable_moves(const MOperand &n) {
|
||||||
auto node_moves_n = node_moves(n);
|
auto node_moves_n = node_moves(n);
|
||||||
for (auto &m : node_moves_n) {
|
for (auto &m : node_moves_n) {
|
||||||
if (ASSOC_FOUND(active_moves, m)) {
|
if (INSET(active_moves, m)) {
|
||||||
active_moves.erase(m);
|
active_moves.erase(m);
|
||||||
worklist_moves.insert(m);
|
worklist_moves.insert(m);
|
||||||
}
|
}
|
||||||
@ -301,7 +260,7 @@ void PassRegAlloc::coalesce() {
|
|||||||
coalesced_moves.insert(m);
|
coalesced_moves.insert(m);
|
||||||
add_work_list(u);
|
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);
|
constrained_moves.insert(m);
|
||||||
add_work_list(u);
|
add_work_list(u);
|
||||||
add_work_list(v);
|
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
|
degree[t] < K || t in precolored || (t,r) in adjSet
|
||||||
*/
|
*/
|
||||||
bool PassRegAlloc::OK(const MOperand &t, const MOperand &r) {
|
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
|
else n
|
||||||
*/
|
*/
|
||||||
MOperand PassRegAlloc::get_alias(const MOperand &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;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +308,7 @@ bool PassRegAlloc::conservative(const std::set<MOperand> &nodes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
|
void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
|
||||||
if (ASSOC_FOUND(freeze_worklist, v))
|
if (INSET(freeze_worklist, v))
|
||||||
freeze_worklist.erase(v);
|
freeze_worklist.erase(v);
|
||||||
else
|
else
|
||||||
spill_worklist.erase(v);
|
spill_worklist.erase(v);
|
||||||
@ -360,13 +319,12 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
|
|||||||
for (auto mv : move_list.at(v)) {
|
for (auto mv : move_list.at(v)) {
|
||||||
move_list[u].insert(mv);
|
move_list[u].insert(mv);
|
||||||
}
|
}
|
||||||
// TODO: TrivialCompiler skipped the enablemoves below
|
|
||||||
enable_moves(v);
|
enable_moves(v);
|
||||||
for (auto t : adjacent(v)) {
|
for (auto t : adjacent(v)) {
|
||||||
add_edge(t, u);
|
add_edge(t, u);
|
||||||
decrement_degree(t);
|
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);
|
freeze_worklist.erase(u);
|
||||||
spill_worklist.insert(u);
|
spill_worklist.insert(u);
|
||||||
}
|
}
|
||||||
@ -409,7 +367,7 @@ void PassRegAlloc::select_spill() {
|
|||||||
freeze_moves(m);
|
freeze_moves(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PassRegAlloc::assign_colors(sptr(MFunction) func) {
|
void PassRegAlloc::assign_colors(MFunction *func) {
|
||||||
while (!select_stack.empty()) {
|
while (!select_stack.empty()) {
|
||||||
auto n = select_stack.back();
|
auto n = select_stack.back();
|
||||||
select_stack.pop_back();
|
select_stack.pop_back();
|
||||||
@ -420,7 +378,7 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) {
|
|||||||
if (alias.op_type == MOpTag::PreColor) {
|
if (alias.op_type == MOpTag::PreColor) {
|
||||||
ok_colors.erase(alias.value);
|
ok_colors.erase(alias.value);
|
||||||
}
|
}
|
||||||
else if (ASSOC_FOUND(colored_nodes, alias)) {
|
else if (INSET(colored_nodes, alias)) {
|
||||||
auto color_alias = color.at(alias);
|
auto color_alias = color.at(alias);
|
||||||
ok_colors.erase(color_alias.value);
|
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;
|
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) {
|
for (auto v : spilled_nodes) {
|
||||||
LOG(TRACE) << "Spill node " << v.to_string();
|
LOG(TRACE) << "Spill node " << v.to_string();
|
||||||
for (auto bb : func->bb_list) {
|
for (auto bb : func->bb_list) {
|
||||||
for (auto inst : bb->inst_list) {
|
for (auto inst : bb->inst_list) {
|
||||||
std::vector<MOperand *> def;
|
auto def = inst->get_def_ptr();
|
||||||
std::vector<MOperand *> use;
|
auto use = inst->get_use_ptr();
|
||||||
get_inst_defuse(inst, def, use);
|
// TODO offset immediate may exceed range
|
||||||
for (auto d : def) {
|
for (auto d : def) {
|
||||||
if (*d != v) continue;
|
if (*d != v) continue;
|
||||||
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
||||||
new_temps.insert(vr);
|
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->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||||
inst_st->data = vr;
|
inst_st->data = vr;
|
||||||
inst_st->offset = MOperand::Imm(func->stack_size);
|
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());
|
cmt->comment = fmt::format("spill def {} to stack", d->to_string());
|
||||||
d->value = vr.value;
|
d->value = vr.value;
|
||||||
}
|
}
|
||||||
@ -527,11 +425,11 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
|
|||||||
if (*u != v) continue;
|
if (*u != v) continue;
|
||||||
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
|
||||||
new_temps.insert(vr);
|
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->addr = MOperand::PreClrReg(RV64Reg::sp);
|
||||||
inst_ld->dst = vr;
|
inst_ld->dst = vr;
|
||||||
inst_ld->offset = MOperand::Imm(func->stack_size);
|
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());
|
cmt->comment = fmt::format("load from spilled use {}", u->to_string());
|
||||||
u->value = vr.value;
|
u->value = vr.value;
|
||||||
}
|
}
|
||||||
@ -539,7 +437,7 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
|
|||||||
}
|
}
|
||||||
func->stack_size += XLEN;
|
func->stack_size += XLEN;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
spilled_nodes.clear();
|
spilled_nodes.clear();
|
||||||
initial = colored_nodes;
|
initial = colored_nodes;
|
||||||
initial.insert(coalesced_nodes.begin(), coalesced_nodes.end());
|
initial.insert(coalesced_nodes.begin(), coalesced_nodes.end());
|
||||||
@ -571,7 +469,6 @@ void PassRegAlloc::clear() {
|
|||||||
frozen_moves.clear();
|
frozen_moves.clear();
|
||||||
worklist_moves.clear();
|
worklist_moves.clear();
|
||||||
active_moves.clear();
|
active_moves.clear();
|
||||||
spill_space.clear();
|
|
||||||
// pre-define each pre-colored register's degree as inf
|
// pre-define each pre-colored register's degree as inf
|
||||||
for (int reg = 0; reg < 32; ++reg) {
|
for (int reg = 0; reg < 32; ++reg) {
|
||||||
degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF});
|
degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF});
|
||||||
@ -590,38 +487,74 @@ if !spilledNodes.empty() then
|
|||||||
RewriteProgram
|
RewriteProgram
|
||||||
Main()
|
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();
|
clear();
|
||||||
liveness_analysis(func);
|
liveness_analysis(func);
|
||||||
// std::ofstream dbg("dbgfunc.asm", std::ios::app);
|
LOG(TRACE) << "[RegAlloc] LiveAnalysis done";
|
||||||
// emit_function(dbg, func);
|
|
||||||
// dbg.close();
|
|
||||||
build(func);
|
build(func);
|
||||||
|
LOG(TRACE) << "[RegAlloc] ConflictGraph built";
|
||||||
make_work_list(func);
|
make_work_list(func);
|
||||||
LOG(TRACE) << "Simplify start for " << func->ir_func->name;
|
LOG(TRACE) << "[RegAlloc] Start Simplify";
|
||||||
bool flag = true;
|
bool first_coalesce = false, first_freeze = false, first_selectspill = false;
|
||||||
do {
|
while (true) {
|
||||||
flag = false;
|
|
||||||
if (!simplify_worklist.empty()) {
|
if (!simplify_worklist.empty()) {
|
||||||
simplify();
|
simplify();
|
||||||
flag = true;
|
|
||||||
}
|
}
|
||||||
else if (!worklist_moves.empty()) {
|
else if (!worklist_moves.empty()) {
|
||||||
|
if (!first_coalesce) {
|
||||||
|
LOG(TRACE) << "[RegAlloc] Start coalesce";
|
||||||
|
first_coalesce = true;
|
||||||
|
}
|
||||||
coalesce();
|
coalesce();
|
||||||
flag = true;
|
|
||||||
}
|
}
|
||||||
else if (!freeze_worklist.empty()) {
|
else if (!freeze_worklist.empty()) {
|
||||||
|
if (!first_freeze) {
|
||||||
|
LOG(TRACE) << "[RegAlloc] Start freeze";
|
||||||
|
first_freeze = true;
|
||||||
|
}
|
||||||
freeze();
|
freeze();
|
||||||
flag = true;
|
|
||||||
}
|
}
|
||||||
else if (!spill_worklist.empty()) {
|
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();
|
select_spill();
|
||||||
flag = true;
|
|
||||||
}
|
}
|
||||||
} while (flag);
|
else {
|
||||||
LOG(TRACE) << "Simplify done for " << func->ir_func->name;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG(TRACE) << "[RegAlloc] Start Coloring";
|
||||||
assign_colors(func);
|
assign_colors(func);
|
||||||
if (!spilled_nodes.empty()) {
|
if (!spilled_nodes.empty()) {
|
||||||
rewrite_program(func);
|
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) {
|
void PassRegAlloc::run(const MCModule &module) {
|
||||||
for (auto func : module.function_list) {
|
for (auto func : module.function_list) {
|
||||||
LOG(INFO) << "Run " << pass_name << " for func " << func->ir_func->name;
|
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);
|
auto vr = MOperand::VirtReg(i);
|
||||||
initial.insert(vr);
|
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
|
// patch all the color info back to the MCIR tree, note the pointer type here
|
||||||
for (auto bb : func->bb_list) {
|
set_color(func.get());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user