first sysy2asm all function pass

This commit is contained in:
ridethepig 2023-06-14 17:37:08 +08:00
parent 988534f446
commit 6bf4093bfb
13 changed files with 408 additions and 296 deletions

5
.vscode/launch.json vendored
View File

@ -9,8 +9,9 @@
"request": "launch",
"name": "Debug",
"program": "${workspaceFolder}/build/sysy",
"args": ["../sysytests/functional_2022/28_while_test3.sy", "-S", "-o", "build/my.s", "-O1", "-emit-llvm"],
// "args": ["../sysytests/functional_2021/069_greatest_common_divisor.sy", "-S", "-o", "build/my.s", "-O1", "-emit-llvm"],
"args" : ["-S", "../sysytests/functional_2022/88_many_params2.sy", "-o", "build/my.s", "-emit-llvm", "-O1"],
"cwd": "${workspaceFolder}"
}
},
]
}

View File

@ -45,15 +45,16 @@ inline sptr(DST) strict_shared_cast(SRC src) {
throw GrammarException(__FILE__, __LINE__, (message)); \
} while (0)
#define sysy_assert(cond) \
do { \
if (!(cond)) throw GrammarException(__FILE__, __LINE__, #cond); \
} while (0)
#define DEF_PTR_T(type) \
class type; \
typedef std::shared_ptr<type> type##Ptr_t
#define GET_MACRO(_1, _2, NAME, ...) NAME
#define _sysy_assert1(expr) assert(expr)
#define _sysy_assert2(expr, info) \
(static_cast<bool>(expr) ? void(0) : ([&]() { info }(), __assert_fail(#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)))
#define sysy_assert(...) GET_MACRO(__VA_ARGS__, _sysy_assert2, _sysy_assert1)(__VA_ARGS__)
namespace CompSysY {
template <typename T>

View File

@ -116,7 +116,7 @@ public:
int type_size = 0; // = dim_size * size(elem_type)
ArrayType() : Type(TypeTag::ArrayType) {}
ArrayType(TypePtr_t element_type, int element_count)
: Type(TypeTag::ArrayType), elem_count(element_count), elem_type(element_type) {}
: Type(TypeTag::ArrayType), elem_type(element_type), elem_count(element_count) {}
static std::shared_ptr<ArrayType> build_from_list(const std::vector<int> &dim_list) {
TypePtr_t array_type = TypeHelper::TYPE_I32;
sysy_assert(dim_list.size() != 0);

View File

@ -95,8 +95,6 @@ inline const char *enum_to_string(const MOpTag &tag) {
return _str_tab[(unsigned)tag];
}
// TODO Basic idea: value = id of globalvar in glob_list
class MOperand {
public:
MOpTag op_type = MOpTag::Invalid;
@ -140,8 +138,8 @@ public:
bool is_precolored() const {
return op_type == MOpTag::PreColor;
}
bool need_clr() const {
return is_precolored() || op_type == MOpTag::Virt;
bool is_virt() const {
return op_type == MOpTag::Virt;
}
bool is_imm() const {
return op_type == MOpTag::Imm;
@ -152,7 +150,7 @@ public:
bool is_reg() const {
return op_type == MOpTag::PreColor || op_type == MOpTag::Virt || op_type == MOpTag::Colored;
}
std::string to_string();
std::string to_string() const;
};
struct MOperandHash {
@ -206,6 +204,9 @@ inline MInstTag inverse_cond(MInstTag src_tag) {
}
}
// Instruction insertion type
enum class InsType { Before, After, Head, Tail };
class MInst {
public:
MInstTag inst_tag;
@ -215,11 +216,18 @@ public:
// 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() = 0;
virtual std::vector<MOperand> get_use() = 0;
virtual std::vector<MOperand> get_def() const = 0;
virtual std::vector<MOperand> get_use() const = 0;
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);
};
class MBasicBlock {
@ -260,8 +268,7 @@ public:
std::vector<sptr(GlobalVar)> global_list;
std::unordered_map<sptr(GlobalVar), int> global_id_map;
void IR2MC(const Module &ir_module);
void MC2ASM(std::ostream &ostr) const;
bool debug1 = false;
void MC2ASM(std::ostream &ostr, bool debug = false) const;
};
class MInstBinary : public MInst {
@ -271,14 +278,24 @@ public:
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) {
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);
parent_bb->inst_list.push_back(inst);
inst->width = width;
MInst::PostNew(inst, parent_bb, ins_ty);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
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);
return inst;
}
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
};
class MInstJump : public MInst {
@ -291,8 +308,11 @@ public:
parent_bb->inst_list.push_back(inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
};
class MInstBranch : public MInst {
@ -307,8 +327,11 @@ public:
parent_bb->inst_list.push_back(inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
};
class MInstLoad : public MInst {
@ -334,8 +357,8 @@ public:
inst->width = width;
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
};
class MInstStore : public MInst {
@ -361,8 +384,8 @@ public:
inst->width = width;
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
};
class MInstMove : public MInst {
@ -387,8 +410,8 @@ public:
parent_bb->inst_list.insert(rel_inst_itr, inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
};
// class MInstSymbol : public MInst {
@ -417,8 +440,11 @@ public:
parent_bb->inst_list.push_back(inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
};
class MInstComment : public MInst {
@ -430,8 +456,17 @@ public:
parent_bb->inst_list.push_back(inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
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);
return inst;
}
virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() const override;
};
class MInstCall : public MInst {
@ -443,12 +478,9 @@ public:
parent_bb->inst_list.push_back(inst);
return inst;
}
virtual std::vector<MOperand> get_def() override;
virtual std::vector<MOperand> get_use() override;
virtual std::vector<MOperand> get_def() 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);
void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use);
void set_bb_def_use(sptr(MFunction) func);
} // namespace CompSysY

View File

@ -15,13 +15,13 @@ public:
virtual void run(const Module &module) = 0;
};
class PassMem2Reg : public Pass {
class PassMem2Reg final : public Pass {
public:
PassMem2Reg() : Pass("mem2reg") {}
virtual void run(const Module &module) override;
};
class PassBuildCFG : public Pass {
class PassBuildCFG final : public Pass {
public:
PassBuildCFG() : Pass("build_cfg") {}
virtual void run(const Module &module) override;
@ -35,12 +35,23 @@ public:
virtual void run(const MCModule &module) = 0;
};
class PassRegAlloc : public MCPass {
class PassRegAlloc final : public MCPass {
public:
PassRegAlloc() : MCPass("regalloc") {}
virtual void run(const MCModule &module) override;
const static int K = 32 - 5; // Not Allocate-able: x0, gp, tp; Reserve: sp, ra
// exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4)
static inline std::unordered_set<int> _ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
private:
struct MvCmp {
bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const {
if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst;
if (lhs->src != rhs->src) return lhs->src < rhs->src;
return false;
}
};
/*以下这些集合**各不相交**
precolored
initial
@ -57,7 +68,7 @@ private:
void add_edge(const MOperand &u, const MOperand &v);
void make_work_list(sptr(MFunction) func);
bool move_related(const MOperand &n);
std::set<sptr(MInstMove)> node_moves(const MOperand &n);
std::set<MInstMove *, MvCmp> node_moves(const MOperand &n);
std::set<MOperand> adjacent(const MOperand &n);
void decrement_degree(const MOperand &m);
void enable_moves(const MOperand &n);
@ -66,17 +77,18 @@ private:
void add_work_list(const MOperand &u);
bool OK(const MOperand &t, const MOperand &r);
bool conservative(const std::set<MOperand> &nodes);
MOperand get_alias(MOperand n);
MOperand get_alias(const MOperand &n);
void combine(const MOperand &u, const MOperand &v);
void freeze();
void freeze_moves(const MOperand &u);
void select_spill();
void assign_colors(sptr(MFunction) func);
void rewrite_program(sptr(MFunction) func);
void clear();
std::map<MOperand, std::set<MOperand>> adj_list;
std::set<std::pair<MOperand, MOperand>> adj_set;
std::map<MOperand, unsigned> degree;
std::map<MOperand, std::set<sptr(MInstMove)>> move_list;
std::map<MOperand, std::set<MInstMove *, MvCmp>> move_list;
std::map<MOperand, MOperand> color;
std::map<MOperand, MOperand> alias;
std::set<MOperand> initial;
@ -87,13 +99,12 @@ private:
std::set<MOperand> coalesced_nodes;
std::set<MOperand> colored_nodes;
std::vector<MOperand> select_stack;
std::set<sptr(MInstMove)> coalesced_moves;
std::set<sptr(MInstMove)> constrained_moves;
std::set<sptr(MInstMove)> frozen_moves;
std::set<sptr(MInstMove)> worklist_moves;
std::set<sptr(MInstMove)> active_moves;
void clear();
std::set<MInstMove *, MvCmp> coalesced_moves;
std::set<MInstMove *, MvCmp> constrained_moves;
std::set<MInstMove *, MvCmp> frozen_moves;
std::set<MInstMove *, MvCmp> worklist_moves;
std::set<MInstMove *, MvCmp> active_moves;
std::map<MOperand, int> spill_space;
};
} // namespace CompSysY

View File

@ -118,6 +118,7 @@ class Compiler:
log_file = open(log, "a+")
Print_C.print_procedure(f"Generating {asm}")
completed = subprocess.run(sy_asm_instr.format(asm=asm, sy=sy).split(), stdout=log_file, stderr=log_file, bufsize=1)
# print(sy_asm_instr.format(asm=asm, sy=sy))
log_file.close()
if completed.returncode != 0:
Print_C.print_error(f"Generate {bin} failed! See {log}")
@ -233,7 +234,7 @@ scheme_ref = {
scheme_my = {
"name": "my",
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1",
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1 -no-asm",
"ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}",
"asm_obj": "as --32 {asm} -o {obj}",
"obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}",

View File

@ -5,15 +5,15 @@ namespace CompSysY {
static void _bitwise_and(std::vector<bool> &op1, const std::vector<bool> &op2) {
for (int i = 0; i < op1.size(); ++i) {
op1[i] = op1[i] & op2[i];
op1[i] = op1[i] && op2[i];
}
}
static void _bitwise_set(std::vector<bool> &op1, int l, int r, bool val) {
for (int i = l; i < r; ++i) {
op1[i] = val;
}
}
// static void _bitwise_set(std::vector<bool> &op1, int l, int r, bool val) {
// for (int i = l; i < r; ++i) {
// op1[i] = val;
// }
// }
static void _gen_dom_level(BasicBlockPtr_t bb, int level) {
bb->dom_level = level;
@ -28,7 +28,6 @@ void gen_dominance(FunctionPtr_t func) {
// Basic iterative idea: Dom(n) = {n} union (intersect Dom(pred(n)))
std::vector<BasicBlockPtr_t> bb_list;
const int N = func->bb_list.size();
auto itr = func->bb_list.begin();
for (auto basicblock : func->bb_list) {
basicblock->idom_set.clear();
basicblock->DOM_set.clear();
@ -46,7 +45,6 @@ void gen_dominance(FunctionPtr_t func) {
bool changed = true;
while (changed) {
changed = false;
int i = 0;
for (int i = 1; i < N; ++i) {
auto cur_bb = bb_list[i];
std::vector<bool> temp(N, 1);

View File

@ -76,6 +76,7 @@ int main(int argc, const char **argv) {
defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%levshort%vlevel %loc %msg");
defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, "%levshort %msg");
defaultConf.setGlobally(el::ConfigurationType::ToFile, "false");
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::reconfigureLogger("default", defaultConf);
#pragma endregion
@ -141,9 +142,7 @@ int main(int argc, const char **argv) {
// asm before reg alloc
auto virt_asm_file = output_file.substr(0, output_file.rfind(".")) + "_virt.asm";
std::ofstream ofs_virt_asm_file(virt_asm_file);
mc_module.debug1 = true;
mc_module.MC2ASM(ofs_virt_asm_file);
mc_module.debug1 = false;
mc_module.MC2ASM(ofs_virt_asm_file, true);
ofs_virt_asm_file.close();
std::vector<sptr(MCPass)> mc_passes = {std::make_shared<PassRegAlloc>()};

View File

@ -158,11 +158,11 @@ static void emit_cmp(std::ostream &ostr, sptr(MInstBinary) inst) {
break;
case MInstTag::Eq:
ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl;
ostr << fmt::format("\tseqz\t{}, {}, 1", rd, rd) << endl;
ostr << fmt::format("\tseqz\t{}, {}", rd, rd) << endl;
break;
case MInstTag::Ne:
ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl;
ostr << fmt::format("\tsnez\t{}, {}, 1", rd, rd) << endl;
ostr << fmt::format("\tsnez\t{}, {}", rd, rd) << endl;
break;
default: assert(0);
}
@ -225,6 +225,9 @@ static void emit_load(std::ostream &ostr, sptr(MInstLoad) inst) {
}
static void emit_store(std::ostream &ostr, sptr(MInstStore) inst) {
if (!(inst->offset.is_imm() && !inst->addr.is_imm() && !inst->data.is_imm())) {
LOG(ERROR) << "shit";
}
assert(inst->offset.is_imm() && !inst->addr.is_imm() && !inst->data.is_imm());
auto data = inst->data.to_string();
auto offset = inst->offset.to_string();
@ -284,6 +287,9 @@ static void emit_array(std::ostream &ostr, sptr(ConstantArr) arr) {
zero_cnt++;
}
}
if (zero_cnt) {
ostr << fmt::format("\t.zero\t{}\n", zero_cnt * 4);
}
}
static void stack_postprocess(sptr(MFunction) func) {
@ -368,14 +374,14 @@ void emit_function(std::ostream &ostr, sptr(MFunction) func) {
ostr << fmt::format("/* -- End Function {} --*/", func->ir_func->name) << endl;
}
void MCModule::MC2ASM(std::ostream &ostr) const {
void MCModule::MC2ASM(std::ostream &ostr, bool debug) const {
// header, specifying align and arch
ostr << "\t.text\n"
<< "\t.attribute\t4,\t16\n"
<< "\t.attribute\t5,\t\"rv64i2p0_m2p0_f2p0_d2p0\"\n";
ostr << "\t.file\t\"" << this->file_name << "\"\n" << endl;
for (auto func : this->function_list) {
if (!debug1) stack_postprocess(func);
if (!debug) stack_postprocess(func);
emit_function(ostr, func);
}

View File

@ -14,12 +14,17 @@ static auto gen_imm(int imm, sptr(MBasicBlock) mc_bb, bool force_reg = false) {
return operand;
}
// load to register, should use pseudo `mv`
// TODO TrivialCompiler added a opt trick here, insert before a control tansfer?
// ! TrivialCompiler added a opt trick here, insert before a control tansfer?
// * No, it is for phi elimination, in case you insert after a jump, which break the bb
if (imm == 0) {
return MOperand::PreClrReg(RV64Reg::x0);
}
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
auto inst_move = MInstMove::New(mc_bb);
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());
else
inst_move = MInstMove::New(mc_bb);
inst_move->src = operand;
inst_move->dst = vr;
return vr;
@ -62,7 +67,12 @@ static MOperand value2moperand(
width = 4;
else if (shared_cast<PointerType>(fparam->type))
width = XLEN;
auto inst_load = MInstLoad::New(mc_bb, width); // ld vr, (i-8)*8(sp)
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);
else
inst_load = MInstLoad::New(mc_bb, width);
// auto inst_move = MInstMove::New(inst_load); // lui vr_t,
inst_load->addr = MOperand::PreClrReg(RV64Reg::sp);
inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN);
@ -72,10 +82,10 @@ static MOperand value2moperand(
return vr;
}
else if (auto glob = shared_cast<GlobalVar>(ir_value)) {
auto itr = val2mop.find(ir_value);
if (itr != val2mop.end()) {
return itr->second;
}
// auto itr = val2mop.find(ir_value);
// if (itr != val2mop.end()) {
// return itr->second;
// }
// auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true);
// auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
// val2mop.insert({ir_value, vr});
@ -86,7 +96,7 @@ static MOperand value2moperand(
if (force_reg) {
auto inst_la = MInstMove::New(mc_bb);
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->src = op_glob;
return vr;
@ -129,7 +139,7 @@ void MCModule::IR2MC(const Module &ir_module) {
this->function_list.push_back(mc_func);
mc_func->ir_func = func;
mc_func->id = fn_id_cnt++;
bb_id_cnt = 0;
// copy pred/succ info
std::unordered_map<sptr(BasicBlock), sptr(MBasicBlock)> bb_ir2mc;
for (auto bb : func->bb_list) {
@ -174,10 +184,10 @@ 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_li = MInstStore::New(mc_bb, width);
mc_li->addr = addr;
mc_li->data = data;
mc_li->offset = MOperand::Imm(0);
auto mc_st = MInstStore::New(mc_bb, width);
mc_st->addr = addr;
mc_st->data = data;
mc_st->offset = MOperand::Imm(0);
continue;
}
if (auto gep = shared_cast<InstGEP>(inst)) {
@ -278,7 +288,7 @@ void MCModule::IR2MC(const Module &ir_module) {
auto target_func = cal->operand_list[0];
int nparams = cal->operand_list.size() - 1;
for (int i = 1; i < cal->operand_list.size(); ++i) {
auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op);
auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true);
if (i <= 8) {
auto inst_move = MInstMove::New(mc_bb);
inst_move->src = rparam;
@ -295,7 +305,7 @@ void MCModule::IR2MC(const Module &ir_module) {
}
if (nparams > 8) {
// sp -= (n-8)*8
auto add_inst = new MInstBinary(MInstTag::Sub, mc_bb);
auto add_inst = MInstBinary::New(MInstTag::Sub, mc_bb, 8);
add_inst->dst = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb);
@ -306,7 +316,7 @@ void MCModule::IR2MC(const Module &ir_module) {
if (nparams > 8) {
// sp += (n-8)*8
auto add_inst = new MInstBinary(MInstTag::Add, mc_bb);
auto add_inst = MInstBinary::New(MInstTag::Add, mc_bb, 8);
add_inst->dst = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb);
@ -465,8 +475,6 @@ void MCModule::IR2MC(const Module &ir_module) {
LOG(WARNING) << "Condition without branch";
}
}
// else if (InstTag::And <= bin->tag && bin->tag <= InstTag::Or)
else {
MInstTag minst_tag;
switch (bin->tag) {
case InstTag::Add: minst_tag = MInstTag::Add; break;
@ -489,7 +497,6 @@ void MCModule::IR2MC(const Module &ir_module) {
inst_bin->dst = dst;
inst_bin->op1 = mc_op1;
inst_bin->op2 = mc_op2;
}
continue;
}
if (auto zxt = shared_cast<InstZext>(inst)) {
@ -535,12 +542,16 @@ void MCModule::IR2MC(const Module &ir_module) {
par_mv_pred.insert({pred_mc_bb, {vr, phi_src_op}});
}
}
for (auto &pmv : par_mv_cur) {
auto inst_mv = MInstMove::New(mc_bb, true);
inst_mv->src = pmv.src;
inst_mv->dst = pmv.dst;
}
for (auto &pmv_pair : par_mv_pred) {
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());
inst_mv->src = pmv_pair.second.src;
inst_mv->dst = pmv_pair.second.dst;
@ -549,65 +560,6 @@ 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 cal = shared_cast<MInstCall>(inst)) {
// arg-occupied regs get implicitly used here
for (int i = 0; i < cal->ir_func->fparam_list.size() && i < 8; ++i) {
use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i)));
}
// caller-saved regs should also be considered as re-defined
// a0-a7
for (int i = 0; i < 8; ++i) {
def.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i)));
}
def.push_back(MOperand::PreClrReg(RV64Reg::t0));
def.push_back(MOperand::PreClrReg(RV64Reg::t1));
def.push_back(MOperand::PreClrReg(RV64Reg::t2));
def.push_back(MOperand::PreClrReg(RV64Reg::t3));
def.push_back(MOperand::PreClrReg(RV64Reg::t4));
def.push_back(MOperand::PreClrReg(RV64Reg::t5));
def.push_back(MOperand::PreClrReg(RV64Reg::t6));
def.push_back(MOperand::PreClrReg(RV64Reg::ra));
return;
}
if (auto br = shared_cast<MInstBranch>(inst)) {
use.push_back(br->op1);
use.push_back(br->op2);
return;
}
if (auto bin = shared_cast<MInstReturn>(inst)) {
use.push_back(MOperand::PreClrReg(RV64Reg::a0));
return;
}
// if (auto sym = shared_cast<MInstSymbol>(inst)) {
// def.push_back(sym->dst);
// return;
// }
}
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);
@ -643,24 +595,4 @@ void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector
// }
}
void set_bb_def_use(sptr(MFunction) func) {
for (auto bb : func->bb_list) {
bb->def.clear();
bb->use.clear();
auto add_def = [&](MOperand &def) {
if (def.need_clr()) bb->def.insert(def);
};
auto add_use = [&](MOperand &use) {
if (use.need_clr()) bb->use.insert(use);
};
for (auto inst : bb->inst_list) {
std::vector<MOperand> def;
std::vector<MOperand> use;
get_inst_defuse(inst, def, use);
for (auto &elem : def) add_def(elem);
for (auto &elem : use) add_use(elem);
}
}
}
} // namespace CompSysY

View File

@ -3,11 +3,11 @@
namespace CompSysY {
std::string MBasicBlock::to_string() {
std::string str = "LBB" + std::to_string(parent_func->id) + "_" + std::to_string(id);
std::string str = "L_BB" + std::to_string(parent_func->id) + "_" + std::to_string(id);
return str;
}
std::string MOperand::to_string() {
std::string MOperand::to_string() const {
std::string ret;
switch (op_type) {
case MOpTag::Imm: ret = fmt::format("{}", value); break;
@ -20,85 +20,117 @@ std::string MOperand::to_string() {
return ret;
}
std::vector<MOperand> MInstBinary::get_def() {
std::vector<MOperand> MInstBinary::get_def() const {
return {dst};
}
std::vector<MOperand> MInstJump::get_def() {
std::vector<MOperand> MInstJump::get_def() const {
return {};
}
std::vector<MOperand> MInstBranch::get_def() {
std::vector<MOperand> MInstBranch::get_def() const {
return {};
}
std::vector<MOperand> MInstLoad::get_def() {
std::vector<MOperand> MInstLoad::get_def() const {
return {dst};
}
std::vector<MOperand> MInstStore::get_def() {
std::vector<MOperand> MInstStore::get_def() const {
return {};
}
std::vector<MOperand> MInstMove::get_def() {
std::vector<MOperand> MInstMove::get_def() const {
return {dst};
}
std::vector<MOperand> MInstReturn::get_def() {
std::vector<MOperand> MInstReturn::get_def() const {
return {};
}
std::vector<MOperand> MInstComment::get_def() {
std::vector<MOperand> MInstComment::get_def() const {
return {};
}
std::vector<MOperand> MInstCall::get_def() {
std::vector<MOperand> def;
std::vector<MOperand> MInstCall::get_def() const {
// caller-saved regs should also be considered as re-defined
// a0-a7
for (int i = 0; i < 8; ++i) {
def.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i)));
}
def.push_back(MOperand::PreClrReg(RV64Reg::t0));
def.push_back(MOperand::PreClrReg(RV64Reg::t1));
def.push_back(MOperand::PreClrReg(RV64Reg::t2));
def.push_back(MOperand::PreClrReg(RV64Reg::t3));
def.push_back(MOperand::PreClrReg(RV64Reg::t4));
def.push_back(MOperand::PreClrReg(RV64Reg::t5));
def.push_back(MOperand::PreClrReg(RV64Reg::t6));
def.push_back(MOperand::PreClrReg(RV64Reg::ra));
return def;
return {
MOperand::PreClrReg(RV64Reg::a0),
MOperand::PreClrReg(RV64Reg::a1),
MOperand::PreClrReg(RV64Reg::a2),
MOperand::PreClrReg(RV64Reg::a3),
MOperand::PreClrReg(RV64Reg::a4),
MOperand::PreClrReg(RV64Reg::a5),
MOperand::PreClrReg(RV64Reg::a6),
MOperand::PreClrReg(RV64Reg::a7),
MOperand::PreClrReg(RV64Reg::t0),
MOperand::PreClrReg(RV64Reg::t1),
MOperand::PreClrReg(RV64Reg::t2),
MOperand::PreClrReg(RV64Reg::t3),
MOperand::PreClrReg(RV64Reg::t4),
MOperand::PreClrReg(RV64Reg::t5),
MOperand::PreClrReg(RV64Reg::t6),
MOperand::PreClrReg(RV64Reg::ra),
};
}
std::vector<MOperand> MInstBinary::get_use() {
return {op1, op2};
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() {
std::vector<MOperand> MInstJump::get_use() const {
return {};
}
std::vector<MOperand> MInstBranch::get_use() {
return {op1, op2};
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> MInstLoad::get_use() {
std::vector<MOperand> MInstLoad::get_use() const {
// addr must be reg, offset must not be reg
return {addr};
}
std::vector<MOperand> MInstStore::get_use() {
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> MInstMove::get_use() {
return {src};
std::vector<MOperand> MInstMove::get_use() const {
std::vector<MOperand> use;
if (src.is_reg()) use.push_back(src);
return use;
}
std::vector<MOperand> MInstReturn::get_use() {
std::vector<MOperand> MInstReturn::get_use() const {
return {MOperand::PreClrReg(RV64Reg::a0)};
}
std::vector<MOperand> MInstComment::get_use() {
std::vector<MOperand> MInstComment::get_use() const {
return {};
}
std::vector<MOperand> MInstCall::get_use() {
std::vector<MOperand> MInstCall::get_use() const {
// arg-occupied regs get implicitly used here
std::vector<MOperand> use;
for (int i = 0; i < ir_func->fparam_list.size() && i < 8; ++i) {
use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i)));
}
return use;
}
void MInst::PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty) {
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;
default: sysy_assert(0);
}
}
void MInst::PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty) {
switch (ins_ty) {
case InsType::Before:
case InsType::After:
default: sysy_assert(0);
}
}
} // namespace CompSysY

View File

@ -13,17 +13,34 @@ static std::set<T> set_union(const std::set<T> &u1, const std::set<T> &u2) {
pred/succ和前面LLIR里面的定义一致
def和use集合bb里面定值/使
def[bb] = {var | var is assigned in this bb}
use[bb] = {var | var is used in this bb }
def[inst] = {var | var is assigned in this inst}
B中定值B中没有被引用的变量的集合
use[inst] = {var | var is used in this inst }
B中引用B中没有被定值的变量集合
live(on one edge) edge通向var的一个usedef
live-in in-edge上都是live的
live-out out-edge上都是live的
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) {
// 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);
}
for (auto &d : inst->get_def()) {
if (!ASSOC_FOUND(bb->use, d)) bb->def.insert(d);
}
}
}
// this will be run for multiple times, thus have to clear
for (auto bb : func->bb_list) {
bb->livein = bb->use;
@ -49,6 +66,19 @@ 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;
@ -113,37 +143,36 @@ void PassRegAlloc::build(sptr(MFunction) func) {
// forall I \in instructions(b) in reversed-order
for (auto inst_it = bb->inst_list.rbegin(); inst_it != bb->inst_list.rend(); ++inst_it) {
// if isMoveInst(I)
std::vector<MOperand> def_I;
std::vector<MOperand> use_I;
get_inst_defuse(*inst_it, def_I, use_I);
std::vector<MOperand> def_I = (*inst_it)->get_def();
std::vector<MOperand> use_I = (*inst_it)->get_use();
if (auto inst_mv = shared_cast<MInstMove>(*inst_it)) {
if (inst_mv->dst.need_clr() && inst_mv->src.need_clr()) {
// make sure it is a reg-reg move
if (use_I.size()) {
// live <- live - use(I)
live.erase(inst_mv->src);
// forall n in def(I) UNION use(I)
// moveList[n] <- moveList[n] UNION {I}
move_list[inst_mv->dst].insert(inst_mv);
move_list[inst_mv->src].insert(inst_mv);
move_list[inst_mv->dst].insert(inst_mv.get());
move_list[inst_mv->src].insert(inst_mv.get());
// worklistMoves <- worklistMoves UNION {I}
worklist_moves.insert(inst_mv);
worklist_moves.insert(inst_mv.get());
}
}
// live <- live UNION def(I)
for (auto &d : def_I) {
if (d.need_clr()) live.insert(d);
live.insert(d);
}
// forall d in def(I)
for (auto &d : def_I) {
if (!d.need_clr()) continue;
// forall l in live
for (auto &l : live) add_edge(l, d);
}
// live <- use(I) UNION (live - def(I))
for (auto &d : def_I) {
if (d.need_clr()) live.erase(d);
live.erase(d);
}
for (auto &u : use_I) {
if (u.need_clr()) live.insert(u);
live.insert(u);
}
}
}
@ -163,9 +192,7 @@ void PassRegAlloc::make_work_list(sptr(MFunction) func) {
else // 低度数mv无关节点表
simplifyWorklist <- simplifyWorklist U {n}
*/
// initial 其实就是所有的虚拟寄存器
for (auto i = 0; i < func->virt_reg_cnt; ++i) {
auto vr = MOperand::VirtReg(i);
for (auto vr : initial) {
if (degree[vr] >= K) {
spill_worklist.insert(vr);
}
@ -176,10 +203,11 @@ void PassRegAlloc::make_work_list(sptr(MFunction) func) {
simplify_worklist.insert(vr);
}
}
initial.clear();
}
// movelist[n] INTERSECT (activemoves UNION worklistmoves)
std::set<sptr(MInstMove)> PassRegAlloc::node_moves(const MOperand &n) {
std::set<MInstMove *, PassRegAlloc::MvCmp> PassRegAlloc::node_moves(const MOperand &n) {
// for empty set, it does not even exists, so do not use `.at(n)`
auto ret = move_list[n];
for (auto itr = ret.begin(); itr != ret.end();) {
@ -247,12 +275,13 @@ void PassRegAlloc::simplify() {
simplify_worklist.erase(simplify_worklist.begin());
select_stack.push_back(n);
auto adjacent_n = adjacent(n);
for (auto &m : adjacent_n) {
for (auto const &m : adjacent_n) {
decrement_degree(m);
}
}
void PassRegAlloc::coalesce() {
// for any t in Adjacent(v), s.t. OK(t,u)
auto _adj_ok = [&](const MOperand &u, const MOperand &v) -> bool {
auto adj_v = adjacent(v);
for (auto &t : adj_v)
@ -260,9 +289,11 @@ void PassRegAlloc::coalesce() {
return true;
};
auto m = *worklist_moves.begin();
auto u = get_alias(m->dst);
auto v = get_alias(m->src);
if (v.op_type == MOpTag::PreColor) {
auto u = get_alias(m->dst); // x
auto v = get_alias(m->src); // y
// if y in precolored then (u, v) = (y, x)
// else (u,v)=(x,y)
if (v.is_precolored()) {
std::swap(u, v);
}
worklist_moves.erase(m);
@ -270,12 +301,12 @@ void PassRegAlloc::coalesce() {
coalesced_moves.insert(m);
add_work_list(u);
}
else if (v.op_type == MOpTag::PreColor || ASSOC_FOUND(adj_set, std::make_pair(u, v))) {
else if (v.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(u, v))) {
constrained_moves.insert(m);
add_work_list(u);
add_work_list(v);
}
else if ((u.op_type == MOpTag::PreColor && _adj_ok(u, v)) || (u.op_type != MOpTag::PreColor && conservative(set_union(adjacent(u), adjacent(v))))) {
else if ((u.is_precolored() && _adj_ok(u, v)) || (!u.is_precolored() && conservative(set_union(adjacent(u), adjacent(v))))) {
coalesced_moves.insert(m);
combine(u, v);
add_work_list(u);
@ -285,19 +316,27 @@ void PassRegAlloc::coalesce() {
}
}
// 把一个节点放回去继续简化
void PassRegAlloc::add_work_list(const MOperand &u) {
if (u.op_type != MOpTag::PreColor && !move_related(u) && degree.at(u) < K) {
if (!u.is_precolored() && !move_related(u) && degree.at(u) < K) {
freeze_worklist.erase(u);
simplify_worklist.insert(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.op_type == MOpTag::PreColor || ASSOC_FOUND(adj_set, std::make_pair(t, r));
return degree[t] < K || t.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(t, r));
}
MOperand PassRegAlloc::get_alias(MOperand n) {
while (ASSOC_FOUND(coalesced_nodes, n)) n = alias[n];
/*
if n in coalescedNodes then
GetAlias(alias[n])
else n
*/
MOperand PassRegAlloc::get_alias(const MOperand &n) {
if (ASSOC_FOUND(coalesced_nodes, n)) return get_alias(alias[n]);
return n;
}
@ -318,10 +357,8 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
coalesced_nodes.insert(v);
alias[v] = u;
// movelist[u] <- movelist[u] UNION movelist[v]
auto &movelist_u = move_list.at(u);
auto &movelist_v = move_list.at(v);
for (auto mv : movelist_v) {
movelist_u.insert(mv);
for (auto mv : move_list.at(v)) {
move_list[u].insert(mv);
}
// TODO: TrivialCompiler skipped the enablemoves below
enable_moves(v);
@ -344,9 +381,10 @@ void PassRegAlloc::freeze() {
void PassRegAlloc::freeze_moves(const MOperand &u) {
for (auto &m : node_moves(u)) {
auto x = get_alias(m->src);
auto v = get_alias(m->dst);
if (v == get_alias(u)) v = x;
auto &x = m->dst;
auto &y = m->src;
auto v = get_alias(y);
if (v == get_alias(u)) v = get_alias(x);
active_moves.erase(m);
frozen_moves.insert(m);
if (node_moves(v).empty() && degree[v] < K) {
@ -366,25 +404,24 @@ void PassRegAlloc::select_spill() {
}
}
// TODO: heuristic to be improved, other than simply select the max degree
spill_worklist.erase(m);
simplify_worklist.insert(m);
freeze_moves(m);
spill_worklist.erase(m);
}
void PassRegAlloc::assign_colors(sptr(MFunction) func) {
while (!select_stack.empty()) {
auto n = select_stack.back();
select_stack.pop_back();
// exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4)
std::unordered_set<int> ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
// directly copy from pre-defined ok_colors
std::unordered_set<int> ok_colors = _ok_colors;
for (auto &w : adj_list[n]) {
auto alias = get_alias(w);
if (alias.op_type == MOpTag::PreColor || alias.op_type == MOpTag::Colored) {
if (alias.op_type == MOpTag::PreColor) {
ok_colors.erase(alias.value);
}
else if (ASSOC_FOUND(color, alias)) {
auto color_alias = color[alias];
else if (ASSOC_FOUND(colored_nodes, alias)) {
auto color_alias = color.at(alias);
ok_colors.erase(color_alias.value);
}
}
@ -403,23 +440,16 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) {
else
color[n] = color[n_alias];
}
// 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);
}
}
}
}
void PassRegAlloc::rewrite_program(sptr(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) {
@ -432,13 +462,13 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
get_inst_defuse(inst, def, use);
for (auto d : def) {
if (*d != v) continue;
if (vr < 0) vr = func->virt_reg_cnt++;
if (vr < 0) vr = gen_tmp_reg();
d->value = vr;
lastdef = inst;
}
for (auto u : use) {
if (*u != v) continue;
if (vr < 0) vr = func->virt_reg_cnt++;
if (vr < 0) vr = gen_tmp_reg();
u->value = vr;
if (!lastdef && !firstuse) firstuse = inst;
}
@ -446,13 +476,15 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
}
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(func->virt_reg_cnt++);
inst_mv->dst = MOperand::VirtReg(gen_tmp_reg());
return inst_mv->dst;
}
};
@ -471,12 +503,56 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
}
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);
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);
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);
cmt->comment = fmt::format("spill def {} to stack", d->to_string());
d->value = vr.value;
}
for (auto u : use) {
if (*u != v) continue;
auto vr = MOperand::VirtReg(func->virt_reg_cnt++);
new_temps.insert(vr);
auto inst_ld = MInstLoad::New(inst, XLEN);
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);
cmt->comment = fmt::format("load from spilled use {}", u->to_string());
u->value = vr.value;
}
}
}
func->stack_size += XLEN;
}
#endif
spilled_nodes.clear();
initial = colored_nodes;
initial.insert(coalesced_nodes.begin(), coalesced_nodes.end());
initial.insert(new_temps.begin(), new_temps.end());
colored_nodes.clear();
coalesced_nodes.clear();
}
/*
Internal util for initialize data structures
*/
void PassRegAlloc::clear() {
// initial.clear();
adj_list.clear();
adj_set.clear();
degree.clear();
@ -495,9 +571,11 @@ 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});
for (int reg = 0; reg < 32; ++reg) {
degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF});
}
}
/*
@ -516,10 +594,13 @@ void emit_function(std::ostream &ostr, sptr(MFunction) func);
void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
clear();
set_bb_def_use(func);
liveness_analysis(func);
// std::ofstream dbg("dbgfunc.asm", std::ios::app);
// emit_function(dbg, func);
// dbg.close();
build(func);
make_work_list(func);
LOG(TRACE) << "Simplify start for " << func->ir_func->name;
bool flag = true;
do {
flag = false;
@ -527,15 +608,15 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
simplify();
flag = true;
}
if (!worklist_moves.empty()) {
else if (!worklist_moves.empty()) {
coalesce();
flag = true;
}
if (!freeze_worklist.empty()) {
else if (!freeze_worklist.empty()) {
freeze();
flag = true;
}
if (!spill_worklist.empty()) {
else if (!spill_worklist.empty()) {
select_spill();
flag = true;
}
@ -544,7 +625,6 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
assign_colors(func);
if (!spilled_nodes.empty()) {
rewrite_program(func);
emit_function(std::cout, func);
reg_alloc(func);
}
}
@ -552,7 +632,27 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
void PassRegAlloc::run(const MCModule &module) {
for (auto func : module.function_list) {
LOG(INFO) << "Run " << pass_name << " for func " << func->ir_func->name;
// 初始化initial集合为所有的虚拟寄存器
initial.clear();
for (int i = 0; i < func->virt_reg_cnt; ++i) {
auto vr = MOperand::VirtReg(i);
initial.insert(vr);
}
reg_alloc(func);
// 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);
}
}
}
}
}

View File

@ -416,7 +416,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << "to ";
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << " to ";
}
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
@ -511,7 +511,6 @@ void Visitor::llir_gen(std::ostream &ostr) {
<< " " << init_value->value << std::endl;
}
else if (global_var_type->pointed_type->type_tag == Type::TypeTag::ArrayType) {
// sysy_assert(global_var->)
auto array_type = std::dynamic_pointer_cast<ArrayType>(global_var_type->pointed_type);
auto init_value = std::dynamic_pointer_cast<ConstantArr>(global_var->init_value);
if (init_value != nullptr) {