diff --git a/include/opt/cfg.h b/include/opt/cfg.h index 874bf51..3cb2dc9 100644 --- a/include/opt/cfg.h +++ b/include/opt/cfg.h @@ -40,6 +40,19 @@ class CFGType { FunctionDefItem *corresponding_func; }; +namespace opt { +class MoveInstruct : public ActionItem { + public: + std::string src_full; + std::string dest_full; + LLVMType ty; + MoveInstruct() = default; + void RecursivePrint([[maybe_unused]] std::ostream &os) const { + throw std::runtime_error("Move instruction is not an actual LLVM IR instruction"); + } +}; +} // namespace opt + template > Container GetCollectionsIntersection(const Container &a, const Container &b, Compare comp = Compare()) { Container result; diff --git a/include/opt/liveanalysis.h b/include/opt/liveanalysis.h index 1b8d375..4e45a3c 100644 --- a/include/opt/liveanalysis.h +++ b/include/opt/liveanalysis.h @@ -33,4 +33,15 @@ class LoadSpilledArgs : public ActionItem { throw std::runtime_error("LoadSpilledArgs instruction is not an actual LLVM IR instruction"); } }; + +class StoreSpilledArgs : public ActionItem { + public: + size_t arg_id; // [8,+inf) + std::string var_full; + LLVMType ty; + StoreSpilledArgs() = default; + void RecursivePrint(std::ostream &os) const { + throw std::runtime_error("StoreSpilledArgs instruction is not an actual LLVM IR instruction"); + } +}; } // namespace opt \ No newline at end of file diff --git a/include/opt/phieliminate.h b/include/opt/phieliminate.h index 2215bae..e3fa16a 100644 --- a/include/opt/phieliminate.h +++ b/include/opt/phieliminate.h @@ -2,17 +2,4 @@ #include "IR/IR_basic.h" #include "cfg.h" -namespace opt { -class MoveInstruct : public ActionItem { - public: - std::string src_full; - std::string dest_full; - LLVMType ty; - MoveInstruct() = default; - void RecursivePrint([[maybe_unused]] std::ostream &os) const { - throw std::runtime_error("Move instruction is not an actual LLVM IR instruction"); - } -}; -} // namespace opt - std::shared_ptr PhiEliminate(std::shared_ptr src); \ No newline at end of file diff --git a/src/opt/liveanalysis.cpp b/src/opt/liveanalysis.cpp index 80d50b0..67a085d 100644 --- a/src/opt/liveanalysis.cpp +++ b/src/opt/liveanalysis.cpp @@ -5,6 +5,7 @@ #include "cfg.h" #include "tools.h" +using namespace opt; void VarCollect(CFGType &cfg, std::vector &id_to_var, std::unordered_map &var_to_id) { for (auto node : cfg.nodes) { auto block = node->corresponding_block; @@ -29,6 +30,15 @@ void VarCollect(CFGType &cfg, std::vector &id_to_var, std::unordere } else if (auto select_act = std::dynamic_pointer_cast(act)) { id_to_var.push_back(select_act->result_full); var_to_id[select_act->result_full] = id_to_var.size() - 1; + } else if (auto move_act = std::dynamic_pointer_cast(act)) { + id_to_var.push_back(move_act->dest_full); + var_to_id[move_act->dest_full] = id_to_var.size() - 1; + } else if (auto force_def_act = std::dynamic_pointer_cast(act)) { + id_to_var.push_back(force_def_act->var_full); + var_to_id[force_def_act->var_full] = id_to_var.size() - 1; + } else if (auto load_spilled_args_act = std::dynamic_pointer_cast(act)) { + id_to_var.push_back(load_spilled_args_act->var_full); + var_to_id[load_spilled_args_act->var_full] = id_to_var.size() - 1; } } } @@ -135,6 +145,29 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector &id_t if (var_to_id.find(select_act->result_full) != var_to_id.end()) { cur_act_def.push_back(var_to_id[select_act->result_full]); } + } else if (auto move_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(move_act->src_full) != var_to_id.end()) { + cur_act_use.push_back(var_to_id[move_act->src_full]); + } + if (var_to_id.find(move_act->dest_full) != var_to_id.end()) { + cur_act_def.push_back(var_to_id[move_act->dest_full]); + } + } else if (auto force_def_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(force_def_act->var_full) != var_to_id.end()) { + cur_act_def.push_back(var_to_id[force_def_act->var_full]); + } + } else if (auto force_use_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(force_use_act->var_full) != var_to_id.end()) { + cur_act_use.push_back(var_to_id[force_use_act->var_full]); + } + } else if (auto load_spilled_args_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(load_spilled_args_act->var_full) != var_to_id.end()) { + cur_act_def.push_back(var_to_id[load_spilled_args_act->var_full]); + } + } else if (auto store_spilled_args_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(store_spilled_args_act->var_full) != var_to_id.end()) { + cur_act_use.push_back(var_to_id[store_spilled_args_act->var_full]); + } } std::sort(cur_act_use.begin(), cur_act_use.end()); std::sort(cur_act_def.begin(), cur_act_def.end()); diff --git a/src/opt/regalloc.cpp b/src/opt/regalloc.cpp index 15a08aa..7fc4e48 100644 --- a/src/opt/regalloc.cpp +++ b/src/opt/regalloc.cpp @@ -1,6 +1,7 @@ #include "regalloc.h" #include "IR/IR_basic.h" #include "liveanalysis.h" +#include "phieliminate.h" #include "tools.h" // RISC-V calling convention compatible @@ -69,6 +70,60 @@ void EnforcePhysicalRegs(CFGType &cfg) { } } // TODO: process caller side + for (auto node : cfg.nodes) { + auto block = node->corresponding_block; + for (auto it_act = block->actions.begin(); it_act != block->actions.end(); ++it_act) { + if (!std::dynamic_pointer_cast(*it_act)) continue; + auto it_next = it_act; + ++it_next; + auto call_act = std::dynamic_pointer_cast(*it_act); + if (!std::holds_alternative(call_act->return_type)) { + auto return_value_collect = std::make_shared(); + return_value_collect->ty = call_act->return_type; + return_value_collect->src_full = "%reg.x10"; + return_value_collect->dest_full = call_act->result_full; + block->actions.insert(it_next, return_value_collect); + call_act->result_full = "%reg.x10"; + } + std::unordered_set caller_saved_regs_to_process; + for (auto reg : caller_saved_regs) { + caller_saved_regs_to_process.insert(reg); + } + for (size_t i = 0; i < call_act->args_val_full.size() & i < 8; i++) { + auto new_move = std::make_shared(); + new_move->ty = call_act->args_ty[i]; + new_move->src_full = call_act->args_val_full[i]; + new_move->dest_full = "%reg." + arg_regs[i]; + block->actions.insert(it_act, new_move); + call_act->args_val_full[i] = "%reg." + arg_regs[i]; + caller_saved_regs_to_process.erase(arg_regs[i]); + } + if (call_act->args_val_full.size() > 8) { + for (size_t i = 8; i < call_act->args_val_full.size(); i++) { + auto new_store = std::make_shared(); + new_store->arg_id = i; + new_store->var_full = call_act->args_val_full[i]; + new_store->ty = call_act->args_ty[i]; + block->actions.insert(it_act, new_store); + } + call_act->args_val_full.resize(8); + call_act->args_ty.resize(8); + } + for (auto reg : caller_saved_regs_to_process) { + auto new_def = std::make_shared(); + new_def->var_full = "%reg." + reg; + new_def->ty = LLVMIRIntType(32); + block->actions.insert(it_act, new_def); + } + for (auto reg : caller_saved_regs) { + auto new_use = std::make_shared(); + new_use->var_full = "%reg." + reg; + block->actions.insert(it_next, new_use); + } + it_act = it_next; + --it_act; + } + } } void ConductRegAllocForFunction([[maybe_unused]] std::shared_ptr func, CFGType &cfg) { EnforcePhysicalRegs(cfg);