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", "request": "launch",
"name": "Debug", "name": "Debug",
"program": "${workspaceFolder}/build/sysy", "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}" "cwd": "${workspaceFolder}"
} },
] ]
} }

View File

@ -45,15 +45,16 @@ inline sptr(DST) strict_shared_cast(SRC src) {
throw GrammarException(__FILE__, __LINE__, (message)); \ throw GrammarException(__FILE__, __LINE__, (message)); \
} while (0) } while (0)
#define sysy_assert(cond) \
do { \
if (!(cond)) throw GrammarException(__FILE__, __LINE__, #cond); \
} while (0)
#define DEF_PTR_T(type) \ #define DEF_PTR_T(type) \
class type; \ class type; \
typedef std::shared_ptr<type> type##Ptr_t 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 { namespace CompSysY {
template <typename T> template <typename T>

View File

@ -116,7 +116,7 @@ public:
int type_size = 0; // = dim_size * size(elem_type) int type_size = 0; // = dim_size * size(elem_type)
ArrayType() : Type(TypeTag::ArrayType) {} ArrayType() : Type(TypeTag::ArrayType) {}
ArrayType(TypePtr_t element_type, int element_count) 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) { static std::shared_ptr<ArrayType> build_from_list(const std::vector<int> &dim_list) {
TypePtr_t array_type = TypeHelper::TYPE_I32; TypePtr_t array_type = TypeHelper::TYPE_I32;
sysy_assert(dim_list.size() != 0); 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]; return _str_tab[(unsigned)tag];
} }
// TODO Basic idea: value = id of globalvar in glob_list
class MOperand { class MOperand {
public: public:
MOpTag op_type = MOpTag::Invalid; MOpTag op_type = MOpTag::Invalid;
@ -140,8 +138,8 @@ public:
bool is_precolored() const { bool is_precolored() const {
return op_type == MOpTag::PreColor; return op_type == MOpTag::PreColor;
} }
bool need_clr() const { bool is_virt() const {
return is_precolored() || op_type == MOpTag::Virt; return op_type == MOpTag::Virt;
} }
bool is_imm() const { bool is_imm() const {
return op_type == MOpTag::Imm; return op_type == MOpTag::Imm;
@ -152,7 +150,7 @@ public:
bool is_reg() const { bool is_reg() const {
return op_type == MOpTag::PreColor || op_type == MOpTag::Virt || op_type == MOpTag::Colored; return op_type == MOpTag::PreColor || op_type == MOpTag::Virt || op_type == MOpTag::Colored;
} }
std::string to_string(); std::string to_string() const;
}; };
struct MOperandHash { 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 { class MInst {
public: public:
MInstTag inst_tag; MInstTag inst_tag;
@ -215,11 +216,18 @@ public:
// 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;
sptr(MBasicBlock) parent_bb; sptr(MBasicBlock) parent_bb;
MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : inst_tag(tag), parent_bb(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() = 0; virtual std::vector<MOperand> get_def() const = 0;
virtual std::vector<MOperand> get_use() = 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 { class MBasicBlock {
@ -260,8 +268,7 @@ public:
std::vector<sptr(GlobalVar)> global_list; std::vector<sptr(GlobalVar)> global_list;
std::unordered_map<sptr(GlobalVar), int> global_id_map; std::unordered_map<sptr(GlobalVar), int> global_id_map;
void IR2MC(const Module &ir_module); void IR2MC(const Module &ir_module);
void MC2ASM(std::ostream &ostr) const; void MC2ASM(std::ostream &ostr, bool debug = false) const;
bool debug1 = false;
}; };
class MInstBinary : public MInst { class MInstBinary : public MInst {
@ -271,14 +278,24 @@ public:
MOperand op2; MOperand op2;
MInstBinary(MInstTag type, sptr(MBasicBlock) parent_bb) : MInst(type, parent_bb) {} 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); auto inst = make_shared<MInstBinary>(type, parent_bb);
parent_bb->inst_list.push_back(inst);
inst->width = width; inst->width = width;
MInst::PostNew(inst, parent_bb, ins_ty);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, bool insert_after = false) {
virtual std::vector<MOperand> get_use() override; 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 { class MInstJump : public MInst {
@ -291,8 +308,11 @@ public:
parent_bb->inst_list.push_back(inst); parent_bb->inst_list.push_back(inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
}; };
class MInstBranch : public MInst { class MInstBranch : public MInst {
@ -307,8 +327,11 @@ public:
parent_bb->inst_list.push_back(inst); parent_bb->inst_list.push_back(inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
}; };
class MInstLoad : public MInst { class MInstLoad : public MInst {
@ -334,8 +357,8 @@ public:
inst->width = width; inst->width = width;
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
}; };
class MInstStore : public MInst { class MInstStore : public MInst {
@ -361,8 +384,8 @@ public:
inst->width = width; inst->width = width;
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
}; };
class MInstMove : public MInst { class MInstMove : public MInst {
@ -387,8 +410,8 @@ public:
parent_bb->inst_list.insert(rel_inst_itr, inst); parent_bb->inst_list.insert(rel_inst_itr, inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
}; };
// class MInstSymbol : public MInst { // class MInstSymbol : public MInst {
@ -417,8 +440,11 @@ public:
parent_bb->inst_list.push_back(inst); parent_bb->inst_list.push_back(inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() override; virtual std::vector<MOperand> get_use() const override;
bool is_transfer() const override {
return true;
}
}; };
class MInstComment : public MInst { class MInstComment : public MInst {
@ -430,8 +456,17 @@ public:
parent_bb->inst_list.push_back(inst); parent_bb->inst_list.push_back(inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; static sptr(MInstComment) New(sptr(MInst) rel_inst, bool insert_after = false) {
virtual std::vector<MOperand> get_use() override; 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 { class MInstCall : public MInst {
@ -443,12 +478,9 @@ public:
parent_bb->inst_list.push_back(inst); parent_bb->inst_list.push_back(inst);
return inst; return inst;
} }
virtual std::vector<MOperand> get_def() override; virtual std::vector<MOperand> get_def() const override;
virtual std::vector<MOperand> get_use() 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 get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use);
void set_bb_def_use(sptr(MFunction) func);
} // namespace CompSysY } // namespace CompSysY

View File

@ -15,13 +15,13 @@ public:
virtual void run(const Module &module) = 0; virtual void run(const Module &module) = 0;
}; };
class PassMem2Reg : public Pass { class PassMem2Reg final : public Pass {
public: public:
PassMem2Reg() : Pass("mem2reg") {} PassMem2Reg() : Pass("mem2reg") {}
virtual void run(const Module &module) override; virtual void run(const Module &module) override;
}; };
class PassBuildCFG : public Pass { class PassBuildCFG final : public Pass {
public: public:
PassBuildCFG() : Pass("build_cfg") {} PassBuildCFG() : Pass("build_cfg") {}
virtual void run(const Module &module) override; virtual void run(const Module &module) override;
@ -35,12 +35,23 @@ public:
virtual void run(const MCModule &module) = 0; virtual void run(const MCModule &module) = 0;
}; };
class PassRegAlloc : public MCPass { class PassRegAlloc final : public MCPass {
public: public:
PassRegAlloc() : MCPass("regalloc") {} PassRegAlloc() : MCPass("regalloc") {}
virtual void run(const MCModule &module) override; virtual void run(const MCModule &module) override;
const static int K = 32 - 5; // Not Allocate-able: x0, gp, tp; Reserve: sp, ra 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: 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 precolored
initial initial
@ -57,7 +68,7 @@ private:
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(sptr(MFunction) func);
bool move_related(const MOperand &n); 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); std::set<MOperand> adjacent(const MOperand &n);
void decrement_degree(const MOperand &m); void decrement_degree(const MOperand &m);
void enable_moves(const MOperand &n); void enable_moves(const MOperand &n);
@ -66,17 +77,18 @@ private:
void add_work_list(const MOperand &u); void add_work_list(const MOperand &u);
bool OK(const MOperand &t, const MOperand &r); bool OK(const MOperand &t, const MOperand &r);
bool conservative(const std::set<MOperand> &nodes); 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 combine(const MOperand &u, const MOperand &v);
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(sptr(MFunction) func);
void rewrite_program(sptr(MFunction) func); void rewrite_program(sptr(MFunction) func);
void clear();
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;
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> color;
std::map<MOperand, MOperand> alias; std::map<MOperand, MOperand> alias;
std::set<MOperand> initial; std::set<MOperand> initial;
@ -87,13 +99,12 @@ private:
std::set<MOperand> coalesced_nodes; std::set<MOperand> coalesced_nodes;
std::set<MOperand> colored_nodes; std::set<MOperand> colored_nodes;
std::vector<MOperand> select_stack; std::vector<MOperand> select_stack;
std::set<sptr(MInstMove)> coalesced_moves; std::set<MInstMove *, MvCmp> coalesced_moves;
std::set<sptr(MInstMove)> constrained_moves; std::set<MInstMove *, MvCmp> constrained_moves;
std::set<sptr(MInstMove)> frozen_moves; std::set<MInstMove *, MvCmp> frozen_moves;
std::set<sptr(MInstMove)> worklist_moves; std::set<MInstMove *, MvCmp> worklist_moves;
std::set<sptr(MInstMove)> active_moves; std::set<MInstMove *, MvCmp> active_moves;
std::map<MOperand, int> spill_space;
void clear();
}; };
} // namespace CompSysY } // namespace CompSysY

View File

@ -118,6 +118,7 @@ class Compiler:
log_file = open(log, "a+") log_file = open(log, "a+")
Print_C.print_procedure(f"Generating {asm}") 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) 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() log_file.close()
if completed.returncode != 0: if completed.returncode != 0:
Print_C.print_error(f"Generate {bin} failed! See {log}") Print_C.print_error(f"Generate {bin} failed! See {log}")
@ -233,7 +234,7 @@ scheme_ref = {
scheme_my = { scheme_my = {
"name": "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}", "ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}",
"asm_obj": "as --32 {asm} -o {obj}", "asm_obj": "as --32 {asm} -o {obj}",
"obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}", "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) { static void _bitwise_and(std::vector<bool> &op1, const std::vector<bool> &op2) {
for (int i = 0; i < op1.size(); ++i) { 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) { // static void _bitwise_set(std::vector<bool> &op1, int l, int r, bool val) {
for (int i = l; i < r; ++i) { // for (int i = l; i < r; ++i) {
op1[i] = val; // op1[i] = val;
} // }
} // }
static void _gen_dom_level(BasicBlockPtr_t bb, int level) { static void _gen_dom_level(BasicBlockPtr_t bb, int level) {
bb->dom_level = 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))) // Basic iterative idea: Dom(n) = {n} union (intersect Dom(pred(n)))
std::vector<BasicBlockPtr_t> bb_list; std::vector<BasicBlockPtr_t> bb_list;
const int N = func->bb_list.size(); const int N = func->bb_list.size();
auto itr = func->bb_list.begin();
for (auto basicblock : func->bb_list) { for (auto basicblock : func->bb_list) {
basicblock->idom_set.clear(); basicblock->idom_set.clear();
basicblock->DOM_set.clear(); basicblock->DOM_set.clear();
@ -46,7 +45,6 @@ void gen_dominance(FunctionPtr_t func) {
bool changed = true; bool changed = true;
while (changed) { while (changed) {
changed = false; changed = false;
int i = 0;
for (int i = 1; i < N; ++i) { for (int i = 1; i < N; ++i) {
auto cur_bb = bb_list[i]; auto cur_bb = bb_list[i];
std::vector<bool> temp(N, 1); 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::Info, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%levshort%vlevel %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.set(el::Level::Trace, el::ConfigurationType::Format, "%levshort %msg");
defaultConf.setGlobally(el::ConfigurationType::ToFile, "false");
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::reconfigureLogger("default", defaultConf); el::Loggers::reconfigureLogger("default", defaultConf);
#pragma endregion #pragma endregion
@ -141,9 +142,7 @@ int main(int argc, const char **argv) {
// asm before reg alloc // asm before reg alloc
auto virt_asm_file = output_file.substr(0, output_file.rfind(".")) + "_virt.asm"; auto virt_asm_file = output_file.substr(0, output_file.rfind(".")) + "_virt.asm";
std::ofstream ofs_virt_asm_file(virt_asm_file); std::ofstream ofs_virt_asm_file(virt_asm_file);
mc_module.debug1 = true; mc_module.MC2ASM(ofs_virt_asm_file, true);
mc_module.MC2ASM(ofs_virt_asm_file);
mc_module.debug1 = false;
ofs_virt_asm_file.close(); ofs_virt_asm_file.close();
std::vector<sptr(MCPass)> mc_passes = {std::make_shared<PassRegAlloc>()}; 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; break;
case MInstTag::Eq: case MInstTag::Eq:
ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl; 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; break;
case MInstTag::Ne: case MInstTag::Ne:
ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl; 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; break;
default: assert(0); 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) { 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()); assert(inst->offset.is_imm() && !inst->addr.is_imm() && !inst->data.is_imm());
auto data = inst->data.to_string(); auto data = inst->data.to_string();
auto offset = inst->offset.to_string(); auto offset = inst->offset.to_string();
@ -284,6 +287,9 @@ static void emit_array(std::ostream &ostr, sptr(ConstantArr) arr) {
zero_cnt++; zero_cnt++;
} }
} }
if (zero_cnt) {
ostr << fmt::format("\t.zero\t{}\n", zero_cnt * 4);
}
} }
static void stack_postprocess(sptr(MFunction) func) { 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; 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 // header, specifying align and arch
ostr << "\t.text\n" ostr << "\t.text\n"
<< "\t.attribute\t4,\t16\n" << "\t.attribute\t4,\t16\n"
<< "\t.attribute\t5,\t\"rv64i2p0_m2p0_f2p0_d2p0\"\n"; << "\t.attribute\t5,\t\"rv64i2p0_m2p0_f2p0_d2p0\"\n";
ostr << "\t.file\t\"" << this->file_name << "\"\n" << endl; ostr << "\t.file\t\"" << this->file_name << "\"\n" << endl;
for (auto func : this->function_list) { for (auto func : this->function_list) {
if (!debug1) stack_postprocess(func); if (!debug) stack_postprocess(func);
emit_function(ostr, 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; return operand;
} }
// load to register, should use pseudo `mv` // 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) { if (imm == 0) {
return MOperand::PreClrReg(RV64Reg::x0); return MOperand::PreClrReg(RV64Reg::x0);
} }
auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); 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->src = operand;
inst_move->dst = vr; inst_move->dst = vr;
return vr; return vr;
@ -62,7 +67,12 @@ static MOperand value2moperand(
width = 4; width = 4;
else if (shared_cast<PointerType>(fparam->type)) else if (shared_cast<PointerType>(fparam->type))
width = XLEN; 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, // auto inst_move = MInstMove::New(inst_load); // lui vr_t,
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);
@ -72,10 +82,10 @@ static MOperand value2moperand(
return vr; return vr;
} }
else if (auto glob = shared_cast<GlobalVar>(ir_value)) { else if (auto glob = shared_cast<GlobalVar>(ir_value)) {
auto itr = val2mop.find(ir_value); // auto itr = val2mop.find(ir_value);
if (itr != val2mop.end()) { // if (itr != val2mop.end()) {
return itr->second; // return itr->second;
} // }
// auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true); // auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true);
// 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});
@ -86,7 +96,7 @@ static MOperand value2moperand(
if (force_reg) { if (force_reg) {
auto inst_la = MInstMove::New(mc_bb); auto inst_la = MInstMove::New(mc_bb);
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;
inst_la->src = op_glob; inst_la->src = op_glob;
return vr; return vr;
@ -129,7 +139,7 @@ void MCModule::IR2MC(const Module &ir_module) {
this->function_list.push_back(mc_func); this->function_list.push_back(mc_func);
mc_func->ir_func = func; mc_func->ir_func = func;
mc_func->id = fn_id_cnt++; mc_func->id = fn_id_cnt++;
bb_id_cnt = 0;
// copy pred/succ info // copy pred/succ info
std::unordered_map<sptr(BasicBlock), sptr(MBasicBlock)> bb_ir2mc; std::unordered_map<sptr(BasicBlock), sptr(MBasicBlock)> bb_ir2mc;
for (auto bb : func->bb_list) { 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); 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_li = MInstStore::New(mc_bb, width); auto mc_st = MInstStore::New(mc_bb, width);
mc_li->addr = addr; mc_st->addr = addr;
mc_li->data = data; mc_st->data = data;
mc_li->offset = MOperand::Imm(0); mc_st->offset = MOperand::Imm(0);
continue; continue;
} }
if (auto gep = shared_cast<InstGEP>(inst)) { 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]; auto target_func = cal->operand_list[0];
int nparams = cal->operand_list.size() - 1; int nparams = cal->operand_list.size() - 1;
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); 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);
inst_move->src = rparam; inst_move->src = rparam;
@ -295,7 +305,7 @@ void MCModule::IR2MC(const Module &ir_module) {
} }
if (nparams > 8) { if (nparams > 8) {
// sp -= (n-8)*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->dst = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp); add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb);
@ -306,7 +316,7 @@ void MCModule::IR2MC(const Module &ir_module) {
if (nparams > 8) { if (nparams > 8) {
// sp += (n-8)*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->dst = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp); add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp);
add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb);
@ -465,31 +475,28 @@ void MCModule::IR2MC(const Module &ir_module) {
LOG(WARNING) << "Condition without branch"; LOG(WARNING) << "Condition without branch";
} }
} }
// else if (InstTag::And <= bin->tag && bin->tag <= InstTag::Or) MInstTag minst_tag;
else { switch (bin->tag) {
MInstTag minst_tag; case InstTag::Add: minst_tag = MInstTag::Add; break;
switch (bin->tag) { case InstTag::Sub: minst_tag = MInstTag::Sub; break;
case InstTag::Add: minst_tag = MInstTag::Add; break; case InstTag::Mul: minst_tag = MInstTag::Mul; break;
case InstTag::Sub: minst_tag = MInstTag::Sub; break; case InstTag::Div: minst_tag = MInstTag::Div; break;
case InstTag::Mul: minst_tag = MInstTag::Mul; break; case InstTag::Mod: minst_tag = MInstTag::Mod; break;
case InstTag::Div: minst_tag = MInstTag::Div; break; case InstTag::Lt: minst_tag = MInstTag::Lt; break;
case InstTag::Mod: minst_tag = MInstTag::Mod; break; case InstTag::Le: minst_tag = MInstTag::Le; break;
case InstTag::Lt: minst_tag = MInstTag::Lt; break; case InstTag::Ge: minst_tag = MInstTag::Ge; break;
case InstTag::Le: minst_tag = MInstTag::Le; break; case InstTag::Gt: minst_tag = MInstTag::Gt; break;
case InstTag::Ge: minst_tag = MInstTag::Ge; break; case InstTag::Eq: minst_tag = MInstTag::Eq; break;
case InstTag::Gt: minst_tag = MInstTag::Gt; break; case InstTag::Ne: minst_tag = MInstTag::Ne; break;
case InstTag::Eq: minst_tag = MInstTag::Eq; break; default: assert(0);
case InstTag::Ne: minst_tag = MInstTag::Ne; break;
default: assert(0);
}
auto dst = value2moperand(inst, mc_bb, mp_val2op);
auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op, true);
auto mc_op2 = value2moperand(op2, mc_bb, mp_val2op, BTWN(minst_tag, MInstTag::Mul, MInstTag::Mod));
auto inst_bin = MInstBinary::New(minst_tag, mc_bb, 4);
inst_bin->dst = dst;
inst_bin->op1 = mc_op1;
inst_bin->op2 = mc_op2;
} }
auto dst = value2moperand(inst, mc_bb, mp_val2op);
auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op, true);
auto mc_op2 = value2moperand(op2, mc_bb, mp_val2op, BTWN(minst_tag, MInstTag::Mul, MInstTag::Mod));
auto inst_bin = MInstBinary::New(minst_tag, mc_bb, 4);
inst_bin->dst = dst;
inst_bin->op1 = mc_op1;
inst_bin->op2 = mc_op2;
continue; continue;
} }
if (auto zxt = shared_cast<InstZext>(inst)) { 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}}); par_mv_pred.insert({pred_mc_bb, {vr, phi_src_op}});
} }
} }
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, true);
inst_mv->src = pmv.src; inst_mv->src = pmv.src;
inst_mv->dst = pmv.dst; inst_mv->dst = pmv.dst;
} }
for (auto &pmv_pair : par_mv_pred) { 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()); auto inst_mv = MInstMove::New(pmv_pair.first->inst_list.back());
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;
@ -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) { void get_inst_defuse(sptr(MInst) inst, std::vector<MOperand *> &def, std::vector<MOperand *> &use) {
if (auto bin = shared_cast<MInstBinary>(inst)) { if (auto bin = shared_cast<MInstBinary>(inst)) {
def.push_back(&bin->dst); 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 } // namespace CompSysY

View File

@ -3,11 +3,11 @@
namespace CompSysY { namespace CompSysY {
std::string MBasicBlock::to_string() { 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; return str;
} }
std::string MOperand::to_string() { std::string MOperand::to_string() const {
std::string ret; std::string ret;
switch (op_type) { switch (op_type) {
case MOpTag::Imm: ret = fmt::format("{}", value); break; case MOpTag::Imm: ret = fmt::format("{}", value); break;
@ -20,85 +20,117 @@ std::string MOperand::to_string() {
return ret; return ret;
} }
std::vector<MOperand> MInstBinary::get_def() { std::vector<MOperand> MInstBinary::get_def() const {
return {dst}; return {dst};
} }
std::vector<MOperand> MInstJump::get_def() { std::vector<MOperand> MInstJump::get_def() const {
return {}; return {};
} }
std::vector<MOperand> MInstBranch::get_def() { std::vector<MOperand> MInstBranch::get_def() const {
return {}; return {};
} }
std::vector<MOperand> MInstLoad::get_def() { std::vector<MOperand> MInstLoad::get_def() const {
return {dst}; return {dst};
} }
std::vector<MOperand> MInstStore::get_def() { std::vector<MOperand> MInstStore::get_def() const {
return {}; return {};
} }
std::vector<MOperand> MInstMove::get_def() { std::vector<MOperand> MInstMove::get_def() const {
return {dst}; return {dst};
} }
std::vector<MOperand> MInstReturn::get_def() { std::vector<MOperand> MInstReturn::get_def() const {
return {}; return {};
} }
std::vector<MOperand> MInstComment::get_def() { std::vector<MOperand> MInstComment::get_def() const {
return {}; return {};
} }
std::vector<MOperand> MInstCall::get_def() { std::vector<MOperand> MInstCall::get_def() const {
std::vector<MOperand> def;
// caller-saved regs should also be considered as re-defined // caller-saved regs should also be considered as re-defined
// a0-a7 return {
for (int i = 0; i < 8; ++i) { MOperand::PreClrReg(RV64Reg::a0),
def.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); MOperand::PreClrReg(RV64Reg::a1),
} MOperand::PreClrReg(RV64Reg::a2),
def.push_back(MOperand::PreClrReg(RV64Reg::t0)); MOperand::PreClrReg(RV64Reg::a3),
def.push_back(MOperand::PreClrReg(RV64Reg::t1)); MOperand::PreClrReg(RV64Reg::a4),
def.push_back(MOperand::PreClrReg(RV64Reg::t2)); MOperand::PreClrReg(RV64Reg::a5),
def.push_back(MOperand::PreClrReg(RV64Reg::t3)); MOperand::PreClrReg(RV64Reg::a6),
def.push_back(MOperand::PreClrReg(RV64Reg::t4)); MOperand::PreClrReg(RV64Reg::a7),
def.push_back(MOperand::PreClrReg(RV64Reg::t5)); MOperand::PreClrReg(RV64Reg::t0),
def.push_back(MOperand::PreClrReg(RV64Reg::t6)); MOperand::PreClrReg(RV64Reg::t1),
def.push_back(MOperand::PreClrReg(RV64Reg::ra)); MOperand::PreClrReg(RV64Reg::t2),
return def; 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() { std::vector<MOperand> MInstBinary::get_use() const {
return {op1, op2}; 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 {}; return {};
} }
std::vector<MOperand> MInstBranch::get_use() { std::vector<MOperand> MInstBranch::get_use() const {
return {op1, op2}; 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}; 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}; return {addr, data};
} }
std::vector<MOperand> MInstMove::get_use() { std::vector<MOperand> MInstMove::get_use() const {
return {src}; 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)}; return {MOperand::PreClrReg(RV64Reg::a0)};
} }
std::vector<MOperand> MInstComment::get_use() { std::vector<MOperand> MInstComment::get_use() const {
return {}; 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; std::vector<MOperand> use;
for (int i = 0; i < ir_func->fparam_list.size() && i < 8; ++i) { for (int i = 0; i < ir_func->fparam_list.size() && i < 8; ++i) {
use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i)));
} }
return use; 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 } // 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里面的定义一致 pred/succ和前面LLIR里面的定义一致
def和use集合bb里面定值/使 def和use集合bb里面定值/使
def[bb] = {var | var is assigned in this bb} def[inst] = {var | var is assigned in this inst}
use[bb] = {var | var is used in this bb } B中定值B中没有被引用的变量的集合
use[inst] = {var | var is used in this inst }
B中引用B中没有被定值的变量集合
live(on one edge) edge通向var的一个usedef live(on one edge) edge通向var的一个usedef
live-in in-edge上都是live的 live-in in-edge上都是live的
live-out out-edge上都是live的 live-out out-edge上都是live的
data-flow equation: 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(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 // this will be run for multiple times, thus have to clear
for (auto bb : func->bb_list) { for (auto bb : func->bb_list) {
bb->livein = bb->use; bb->livein = bb->use;
@ -49,6 +66,19 @@ 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; 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 // forall I \in instructions(b) in reversed-order
for (auto inst_it = bb->inst_list.rbegin(); inst_it != bb->inst_list.rend(); ++inst_it) { for (auto inst_it = bb->inst_list.rbegin(); inst_it != bb->inst_list.rend(); ++inst_it) {
// if isMoveInst(I) // if isMoveInst(I)
std::vector<MOperand> def_I; std::vector<MOperand> def_I = (*inst_it)->get_def();
std::vector<MOperand> use_I; std::vector<MOperand> use_I = (*inst_it)->get_use();
get_inst_defuse(*inst_it, def_I, use_I);
if (auto inst_mv = shared_cast<MInstMove>(*inst_it)) { 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 <- live - use(I)
live.erase(inst_mv->src); live.erase(inst_mv->src);
// forall n in def(I) UNION use(I) // forall n in def(I) UNION use(I)
// moveList[n] <- moveList[n] UNION {I} // moveList[n] <- moveList[n] UNION {I}
move_list[inst_mv->dst].insert(inst_mv); move_list[inst_mv->dst].insert(inst_mv.get());
move_list[inst_mv->src].insert(inst_mv); move_list[inst_mv->src].insert(inst_mv.get());
// worklistMoves <- worklistMoves UNION {I} // worklistMoves <- worklistMoves UNION {I}
worklist_moves.insert(inst_mv); worklist_moves.insert(inst_mv.get());
} }
} }
// live <- live UNION def(I) // live <- live UNION def(I)
for (auto &d : def_I) { for (auto &d : def_I) {
if (d.need_clr()) live.insert(d); live.insert(d);
} }
// forall d in def(I) // forall d in def(I)
for (auto &d : def_I) { for (auto &d : def_I) {
if (!d.need_clr()) continue;
// forall l in live // forall l in live
for (auto &l : live) add_edge(l, d); for (auto &l : live) add_edge(l, d);
} }
// live <- use(I) UNION (live - def(I)) // live <- use(I) UNION (live - def(I))
for (auto &d : def_I) { for (auto &d : def_I) {
if (d.need_clr()) live.erase(d); live.erase(d);
} }
for (auto &u : use_I) { 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无关节点表 else // 低度数mv无关节点表
simplifyWorklist <- simplifyWorklist U {n} simplifyWorklist <- simplifyWorklist U {n}
*/ */
// initial 其实就是所有的虚拟寄存器 for (auto vr : initial) {
for (auto i = 0; i < func->virt_reg_cnt; ++i) {
auto vr = MOperand::VirtReg(i);
if (degree[vr] >= K) { if (degree[vr] >= K) {
spill_worklist.insert(vr); spill_worklist.insert(vr);
} }
@ -176,10 +203,11 @@ void PassRegAlloc::make_work_list(sptr(MFunction) func) {
simplify_worklist.insert(vr); simplify_worklist.insert(vr);
} }
} }
initial.clear();
} }
// movelist[n] INTERSECT (activemoves UNION worklistmoves) // 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)` // for empty set, it does not even exists, so do not use `.at(n)`
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();) {
@ -247,12 +275,13 @@ void PassRegAlloc::simplify() {
simplify_worklist.erase(simplify_worklist.begin()); simplify_worklist.erase(simplify_worklist.begin());
select_stack.push_back(n); select_stack.push_back(n);
auto adjacent_n = adjacent(n); auto adjacent_n = adjacent(n);
for (auto &m : adjacent_n) { for (auto const &m : adjacent_n) {
decrement_degree(m); decrement_degree(m);
} }
} }
void PassRegAlloc::coalesce() { 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_ok = [&](const MOperand &u, const MOperand &v) -> bool {
auto adj_v = adjacent(v); auto adj_v = adjacent(v);
for (auto &t : adj_v) for (auto &t : adj_v)
@ -260,9 +289,11 @@ void PassRegAlloc::coalesce() {
return true; return true;
}; };
auto m = *worklist_moves.begin(); auto m = *worklist_moves.begin();
auto u = get_alias(m->dst); auto u = get_alias(m->dst); // x
auto v = get_alias(m->src); auto v = get_alias(m->src); // y
if (v.op_type == MOpTag::PreColor) { // if y in precolored then (u, v) = (y, x)
// else (u,v)=(x,y)
if (v.is_precolored()) {
std::swap(u, v); std::swap(u, v);
} }
worklist_moves.erase(m); worklist_moves.erase(m);
@ -270,12 +301,12 @@ void PassRegAlloc::coalesce() {
coalesced_moves.insert(m); coalesced_moves.insert(m);
add_work_list(u); 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); constrained_moves.insert(m);
add_work_list(u); add_work_list(u);
add_work_list(v); 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); coalesced_moves.insert(m);
combine(u, v); combine(u, v);
add_work_list(u); add_work_list(u);
@ -285,19 +316,27 @@ void PassRegAlloc::coalesce() {
} }
} }
// 把一个节点放回去继续简化
void PassRegAlloc::add_work_list(const MOperand &u) { 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); freeze_worklist.erase(u);
simplify_worklist.insert(u); simplify_worklist.insert(u);
} }
} }
/*
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.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; return n;
} }
@ -318,10 +357,8 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) {
coalesced_nodes.insert(v); coalesced_nodes.insert(v);
alias[v] = u; alias[v] = u;
// movelist[u] <- movelist[u] UNION movelist[v] // movelist[u] <- movelist[u] UNION movelist[v]
auto &movelist_u = move_list.at(u); for (auto mv : move_list.at(v)) {
auto &movelist_v = move_list.at(v); move_list[u].insert(mv);
for (auto mv : movelist_v) {
movelist_u.insert(mv);
} }
// TODO: TrivialCompiler skipped the enablemoves below // TODO: TrivialCompiler skipped the enablemoves below
enable_moves(v); enable_moves(v);
@ -344,9 +381,10 @@ void PassRegAlloc::freeze() {
void PassRegAlloc::freeze_moves(const MOperand &u) { void PassRegAlloc::freeze_moves(const MOperand &u) {
for (auto &m : node_moves(u)) { for (auto &m : node_moves(u)) {
auto x = get_alias(m->src); auto &x = m->dst;
auto v = get_alias(m->dst); auto &y = m->src;
if (v == get_alias(u)) v = x; auto v = get_alias(y);
if (v == get_alias(u)) v = get_alias(x);
active_moves.erase(m); active_moves.erase(m);
frozen_moves.insert(m); frozen_moves.insert(m);
if (node_moves(v).empty() && degree[v] < K) { 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 // TODO: heuristic to be improved, other than simply select the max degree
spill_worklist.erase(m);
simplify_worklist.insert(m); simplify_worklist.insert(m);
freeze_moves(m); freeze_moves(m);
spill_worklist.erase(m);
} }
void PassRegAlloc::assign_colors(sptr(MFunction) func) { void PassRegAlloc::assign_colors(sptr(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();
// exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4) // directly copy from pre-defined ok_colors
std::unordered_set<int> ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, std::unordered_set<int> ok_colors = _ok_colors;
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
for (auto &w : adj_list[n]) { for (auto &w : adj_list[n]) {
auto alias = get_alias(w); 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); ok_colors.erase(alias.value);
} }
else if (ASSOC_FOUND(color, alias)) { else if (ASSOC_FOUND(colored_nodes, alias)) {
auto color_alias = color[alias]; auto color_alias = color.at(alias);
ok_colors.erase(color_alias.value); ok_colors.erase(color_alias.value);
} }
} }
@ -403,23 +440,16 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) {
else else
color[n] = color[n_alias]; 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) { 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) { 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) {
@ -432,13 +462,13 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
get_inst_defuse(inst, def, use); get_inst_defuse(inst, def, use);
for (auto d : def) { for (auto d : def) {
if (*d != v) continue; if (*d != v) continue;
if (vr < 0) vr = func->virt_reg_cnt++; if (vr < 0) vr = gen_tmp_reg();
d->value = vr; d->value = vr;
lastdef = inst; lastdef = inst;
} }
for (auto u : use) { for (auto u : use) {
if (*u != v) continue; if (*u != v) continue;
if (vr < 0) vr = func->virt_reg_cnt++; if (vr < 0) vr = gen_tmp_reg();
u->value = vr; u->value = vr;
if (!lastdef && !firstuse) firstuse = inst; if (!lastdef && !firstuse) firstuse = inst;
} }
@ -446,13 +476,15 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
} }
auto gen_off = [&](sptr(MInst) inst) { auto gen_off = [&](sptr(MInst) inst) {
auto off_imm = MOperand::Imm(func->stack_size); auto off_imm = MOperand::Imm(func->stack_size);
return off_imm;
if (is_in_imm_range(off_imm.value)) { if (is_in_imm_range(off_imm.value)) {
return off_imm; return off_imm;
} }
else { else {
assert(0); //TODO bug here
auto inst_mv = MInstMove::New(inst); auto inst_mv = MInstMove::New(inst);
inst_mv->src = off_imm; 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; return inst_mv->dst;
} }
}; };
@ -471,12 +503,56 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) {
} }
func->stack_size += XLEN; 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 Internal util for initialize data structures
*/ */
void PassRegAlloc::clear() { void PassRegAlloc::clear() {
// initial.clear();
adj_list.clear(); adj_list.clear();
adj_set.clear(); adj_set.clear();
degree.clear(); degree.clear();
@ -495,9 +571,11 @@ 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) 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) { void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
clear(); clear();
set_bb_def_use(func);
liveness_analysis(func); liveness_analysis(func);
// std::ofstream dbg("dbgfunc.asm", std::ios::app);
// emit_function(dbg, func);
// dbg.close();
build(func); build(func);
make_work_list(func); make_work_list(func);
LOG(TRACE) << "Simplify start for " << func->ir_func->name;
bool flag = true; bool flag = true;
do { do {
flag = false; flag = false;
@ -527,15 +608,15 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
simplify(); simplify();
flag = true; flag = true;
} }
if (!worklist_moves.empty()) { else if (!worklist_moves.empty()) {
coalesce(); coalesce();
flag = true; flag = true;
} }
if (!freeze_worklist.empty()) { else if (!freeze_worklist.empty()) {
freeze(); freeze();
flag = true; flag = true;
} }
if (!spill_worklist.empty()) { else if (!spill_worklist.empty()) {
select_spill(); select_spill();
flag = true; flag = true;
} }
@ -544,7 +625,6 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
assign_colors(func); assign_colors(func);
if (!spilled_nodes.empty()) { if (!spilled_nodes.empty()) {
rewrite_program(func); rewrite_program(func);
emit_function(std::cout, func);
reg_alloc(func); reg_alloc(func);
} }
} }
@ -552,7 +632,27 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) {
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;
// 初始化initial集合为所有的虚拟寄存器
initial.clear();
for (int i = 0; i < func->virt_reg_cnt; ++i) {
auto vr = MOperand::VirtReg(i);
initial.insert(vr);
}
reg_alloc(func); 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])) { if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]); auto op0 = Value::as<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 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])) { else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<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; << " " << init_value->value << std::endl;
} }
else if (global_var_type->pointed_type->type_tag == Type::TypeTag::ArrayType) { 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 array_type = std::dynamic_pointer_cast<ArrayType>(global_var_type->pointed_type);
auto init_value = std::dynamic_pointer_cast<ConstantArr>(global_var->init_value); auto init_value = std::dynamic_pointer_cast<ConstantArr>(global_var->init_value);
if (init_value != nullptr) { if (init_value != nullptr) {