diff --git a/src/RISCv64Backend.cpp b/src/RISCv64Backend.cpp index 8b75715..cdfa30d 100644 --- a/src/RISCv64Backend.cpp +++ b/src/RISCv64Backend.cpp @@ -1044,16 +1044,16 @@ std::string print_set(const std::set& s) { return ss.str(); } -// 活跃性分析(更新以支持浮点指令) -std::map> RISCv64CodeGen::liveness_analysis(Function* func) { - std::map> live_in, live_out; +// 活跃性分析(更新以返回 live_in 和 live_out) +LivenessResult RISCv64CodeGen::liveness_analysis(Function* func) { + LivenessResult result; bool changed = true; // 初始化 live_in 和 live_out for (const auto& bb : func->getBasicBlocks()) { for (const auto& inst_ptr : bb->getInstructions()) { - live_in[inst_ptr.get()] = {}; - live_out[inst_ptr.get()] = {}; + result.live_in[inst_ptr.get()] = {}; + result.live_out[inst_ptr.get()] = {}; } } @@ -1068,11 +1068,15 @@ std::map> RISCv64CodeGen::liveness_analysis( auto bb = it->get(); if (DEEPDEBUG) std::cerr << " 基本块: " << bb->getName() << std::endl; - std::set live_out_for_bb_inst = {}; + // 计算基本块末尾的 live_out 集合,即所有后继基本块 live_in 的并集 + std::set live_out_for_bb; for (const auto& succ_bb : bb->getSuccessors()) { if (!succ_bb->getInstructions().empty()) { Instruction* first_inst_in_succ = succ_bb->getInstructions().front().get(); - live_out_for_bb_inst.insert(live_in[first_inst_in_succ].begin(), live_in[first_inst_in_succ].end()); + if (result.live_in.count(first_inst_in_succ)) { + const auto& succ_live_in = result.live_in.at(first_inst_in_succ); + live_out_for_bb.insert(succ_live_in.begin(), succ_live_in.end()); + } } } @@ -1080,111 +1084,93 @@ std::map> RISCv64CodeGen::liveness_analysis( for (auto inst_it = bb->getInstructions().rbegin(); inst_it != bb->getInstructions().rend(); ++inst_it) { auto inst = inst_it->get(); if (DEEPDEBUG) std::cerr << " 指令 (BB: " << bb->getName() << ", 地址: " << static_cast(inst) << ")" << std::endl; + + std::set current_live_in = result.live_in[inst]; + std::set current_live_out = result.live_out[inst]; + std::set new_live_out; - std::set current_live_in = live_in[inst]; - std::set current_live_out = live_out[inst]; - std::set new_live_out_calc; - - // 计算 live_out + // 计算当前指令的 live_out if (inst_it == bb->getInstructions().rbegin()) { - new_live_out_calc = live_out_for_bb_inst; - if (DEEPDEBUG) std::cerr << " 指令是基本块的最后一条指令,live_out 取自后继基本块 live_in 的并集: " << print_set(new_live_out_calc) << std::endl; + // 对于块中的最后一条指令,其 live_out 是块的 live_out + new_live_out = live_out_for_bb; } else { - auto prev_inst_it = std::prev(inst_it); - new_live_out_calc = live_in[prev_inst_it->get()]; - if (DEEPDEBUG) std::cerr << " 指令不是基本块的最后一条,其 live_out 是其后继指令 live_in: " << print_set(new_live_out_calc) << std::endl; + // 否则,其 live_out 是其后继指令的 live_in + auto next_inst_it = std::prev(inst_it); + new_live_out = result.live_in[next_inst_it->get()]; } std::set use_set, def_set; // 定义 (Def) - if (!inst->getType()->isVoid() && !dynamic_cast(inst) && !dynamic_cast(inst) && - !dynamic_cast(inst) && !dynamic_cast(inst) && !dynamic_cast(inst) && value_vreg_map.count(inst)) { + if (value_vreg_map.count(inst) && !inst->getType()->isVoid() && !dynamic_cast(inst) && !dynamic_cast(inst) && + !dynamic_cast(inst) && !dynamic_cast(inst) && !dynamic_cast(inst)) { def_set.insert(value_vreg_map.at(inst)); - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 定义了虚拟寄存器: " << value_vreg_map.at(inst) << std::endl; } - // 使用 (Use) - 增强对常量的处理 + // 使用 (Use) for (const auto& operand_use : inst->getOperands()) { Value* operand = operand_use->getValue(); if (value_vreg_map.count(operand) && !dynamic_cast(operand)) { use_set.insert(value_vreg_map.at(operand)); - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 使用了虚拟寄存器: " << value_vreg_map.at(operand) << std::endl; - } - // 如果是常量,确保其活跃性被记录 - if (auto constant = dynamic_cast(operand)) { - if (value_vreg_map.count(constant)) { - use_set.insert(value_vreg_map.at(constant)); - if (DEEPDEBUG) std::cerr << " 常量 (值: " << (constant->isInt() ? std::to_string(constant->getInt()) : std::to_string(constant->getFloat())) << ") 使用了虚拟寄存器: " << value_vreg_map.at(constant) << std::endl; - } } } - - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 的 use_set: " << print_set(use_set) << std::endl; - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 的 def_set: " << print_set(def_set) << std::endl; - - // 计算新的 live_in + + // 数据流方程: live_in[i] = use[i] U (live_out[i] - def[i]) std::set new_live_in = use_set; - for (const auto& vreg : new_live_out_calc) { + for (const auto& vreg : new_live_out) { if (def_set.find(vreg) == def_set.end()) { new_live_in.insert(vreg); } } - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 计算出的 new_live_in: " << print_set(new_live_in) << std::endl; - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 当前 live_in: " << print_set(current_live_in) << ", 当前 live_out: " << print_set(current_live_out) << std::endl; - // 如果活跃性集合发生变化,更新并继续迭代 - if (new_live_in != current_live_in || new_live_out_calc != current_live_out) { - live_in[inst] = new_live_in; - live_out[inst] = new_live_out_calc; + if (new_live_in != current_live_in || new_live_out != current_live_out) { + result.live_in[inst] = new_live_in; + result.live_out[inst] = new_live_out; changed = true; - if (DEEPDEBUG) std::cerr << " 指令 (地址: " << static_cast(inst) << ") 活跃性集合发生变化,更新并继续迭代." << std::endl; } } } } - return live_in; + return result; } -// 干扰图构建 (基本保持不变) + +// 干扰图构建 (使用正确的 live_out 集合) std::map> RISCv64CodeGen::build_interference_graph( - const std::map>& live_sets) { + const LivenessResult& liveness) { std::map> graph; - // 确保 live_sets 中所有存在的虚拟寄存器最初都在图中 - for (const auto& pair : live_sets) { - for (const auto& vreg : pair.second) { - graph[vreg] = {}; // 初始化空集合 - } + // 初始化图,确保每个虚拟寄存器都有一个节点 + for (const auto& pair : value_vreg_map) { + graph[pair.second] = {}; } - for (const auto& pair : live_sets) { - auto inst = pair.first; - const auto& live_after_inst = pair.second; // 这实际上是下一条指令/基本块入口的 live_in + // 遍历每条指令来构建干扰 + for (const auto& pair : liveness.live_out) { + Instruction* inst = pair.first; + const auto& live_out_set = pair.second; + // 规则1: 指令定义的结果寄存器与该指令的 live_out 集合中的所有寄存器干扰 std::string defined_vreg; - // 修正:只有当指令结果是需要物理寄存器时才视为定义。 - // AllocaInst 不应在此处处理。 - if (value_vreg_map.count(inst) && !dynamic_cast(inst)) { + if (value_vreg_map.count(inst) && !inst->getType()->isVoid() && !dynamic_cast(inst) && !dynamic_cast(inst) && + !dynamic_cast(inst) && !dynamic_cast(inst) && !dynamic_cast(inst)) { defined_vreg = value_vreg_map.at(inst); } - // 将从 defined vreg 到此时所有其他活跃 vreg 的边添加 if (!defined_vreg.empty()) { - for (const auto& live_vreg : live_after_inst) { - if (live_vreg != defined_vreg) { // 虚拟寄存器不与其自身干扰 + for (const auto& live_vreg : live_out_set) { + if (defined_vreg != live_vreg) { graph[defined_vreg].insert(live_vreg); - graph[live_vreg].insert(defined_vreg); // 对称边 + graph[live_vreg].insert(defined_vreg); } } } - - // 对于 store 指令,要存储的值和目标地址指针是同时活跃的,必须互相干扰。 + + // 规则2: 特殊指令内部的操作数之间也存在干扰 if (auto store = dynamic_cast(inst)) { Value* val_operand = store->getValue(); Value* ptr_operand = store->getPointer(); - if (value_vreg_map.count(val_operand) && value_vreg_map.count(ptr_operand)) { const std::string& val_vreg = value_vreg_map.at(val_operand); const std::string& ptr_vreg = value_vreg_map.at(ptr_operand); @@ -1193,10 +1179,7 @@ std::map> RISCv64CodeGen::build_interference_ graph[ptr_vreg].insert(val_vreg); } } - } - // 可选:为其他有两个或以上源操作数的指令(如 add)添加类似逻辑, - // 确保它们的操作数虚拟寄存器互相干扰。 - else if (auto bin = dynamic_cast(inst)) { + } else if (auto bin = dynamic_cast(inst)) { Value* lhs_operand = bin->getLhs(); Value* rhs_operand = bin->getRhs(); if (value_vreg_map.count(lhs_operand) && value_vreg_map.count(rhs_operand)) { @@ -1204,9 +1187,24 @@ std::map> RISCv64CodeGen::build_interference_ const std::string& rhs_vreg = value_vreg_map.at(rhs_operand); if (lhs_vreg != rhs_vreg) { graph[lhs_vreg].insert(rhs_vreg); - graph[rhs_vreg].insert(rhs_vreg); + graph[rhs_vreg].insert(lhs_vreg); // 修正了原有的笔误 } } + } else if (auto call = dynamic_cast(inst)) { + // 函数调用的所有参数在调用发生时都是活跃的,因此它们相互干扰 + std::vector arg_vregs; + for (auto arg_use : call->getArguments()) { + Value* arg_val = arg_use->getValue(); + if (value_vreg_map.count(arg_val)) { + arg_vregs.push_back(value_vreg_map.at(arg_val)); + } + } + for (size_t i = 0; i < arg_vregs.size(); ++i) { + for (size_t j = i + 1; j < arg_vregs.size(); ++j) { + graph[arg_vregs[i]].insert(arg_vregs[j]); + graph[arg_vregs[j]].insert(arg_vregs[i]); + } + } } } return graph; @@ -1345,7 +1343,7 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun int current_stack_offset = 0; std::set allocas_in_func; - // 收集函数中的所有 AllocaInst + // 为 AllocaInst 计算栈空间并分配偏移量 for (const auto& bb_ptr : func->getBasicBlocks()) { for (const auto& inst_ptr : bb_ptr->getInstructions()) { if (auto alloca = dynamic_cast(inst_ptr.get())) { @@ -1353,21 +1351,15 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun } } } - - // 为每个 AllocaInst 计算栈空间并分配偏移量 for (auto alloca : allocas_in_func) { - int total_size = 4; // 基本元素大小(int 或 float) + int total_size = 4; auto dims = alloca->getDims(); if (!dims.empty()) { int num_elements = 1; for (const auto& dim_use : dims) { Value* dim_value = dim_use->getValue(); if (auto const_dim = dynamic_cast(dim_value)) { - if (const_dim->isInt()) { - num_elements *= const_dim->getInt(); - } else { - throw std::runtime_error("数组维度必须是整数"); - } + num_elements *= const_dim->getInt(); } else { throw std::runtime_error("数组维度必须是编译时常量"); } @@ -1377,14 +1369,14 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun alloc_result.stack_map[alloca] = current_stack_offset; current_stack_offset += total_size; } - // RV64 修改: 为保存的 ra 和 s0 (各8字节) 预留16字节空间 + // 为保存的 ra 和 s0 (各8字节) 预留16字节空间 alloc_result.stack_size = current_stack_offset + 16; // 活跃性分析 - std::map> live_sets = liveness_analysis(func); + LivenessResult liveness = liveness_analysis(func); // 构建干扰图 - std::map> interference_graph = build_interference_graph(live_sets); + std::map> interference_graph = build_interference_graph(liveness); // 图着色 color_graph(alloc_result.vreg_to_preg, interference_graph); @@ -1401,36 +1393,23 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun std::cerr << "Basic Block: " << bb_ptr->getName() << "\n"; for (const auto& inst_ptr : bb_ptr->getInstructions()) { std::cerr << " Inst: " << inst_ptr->getKindString(); - if (!inst_ptr->getName().empty()) { - std::cerr << "(" << inst_ptr->getName() << ")"; + if (!inst_ptr->getName().empty()) std::cerr << "(" << inst_ptr->getName() << ")"; + if (value_vreg_map.count(inst_ptr.get())) std::cerr << " (Def vreg: " << value_vreg_map.at(inst_ptr.get()) << ")"; + + std::cerr << " (Live In: "; + if (liveness.live_in.count(inst_ptr.get())) { + std::cerr << print_set(liveness.live_in.at(inst_ptr.get())); + } else { + std::cerr << "{}"; } - if (value_vreg_map.count(inst_ptr.get())) { - std::cerr << " (Def vreg: " << value_vreg_map.at(inst_ptr.get()) << ")"; - } - std::cerr << " (Live In: {"; - bool first = true; - if (live_sets.count(inst_ptr.get())) { - for (const auto& vreg : live_sets.at(inst_ptr.get())) { - if (!first) std::cerr << ", "; - std::cerr << vreg; - first = false; - } - } - std::cerr << "})\n"; + std::cerr << ")\n"; } } std::cerr << "=== 活跃性分析结果结束 ===\n\n"; std::cerr << "=== 干扰图 ===\n"; for (const auto& pair : interference_graph) { - std::cerr << " " << pair.first << ": {"; - bool first = true; - for (const auto& neighbor : pair.second) { - if (!first) std::cerr << ", "; - std::cerr << neighbor; - first = false; - } - std::cerr << "}\n"; + std::cerr << " " << pair.first << ": " << print_set(pair.second) << "\n"; } std::cerr << "=== 干扰图结束 ===\n\n"; } diff --git a/src/include/RISCv64Backend.h b/src/include/RISCv64Backend.h index f60c665..f929250 100644 --- a/src/include/RISCv64Backend.h +++ b/src/include/RISCv64Backend.h @@ -13,8 +13,16 @@ extern int DEBUG; extern int DEEPDEBUG; + + namespace sysy { +// 为活跃性分析的结果定义一个结构体,以同时持有 live_in 和 live_out 集合 +struct LivenessResult { + std::map> live_in; + std::map> live_out; +}; + class RISCv64CodeGen { public: enum class PhysicalReg { @@ -71,9 +79,8 @@ public: void emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set& emitted_nodes); // Register Allocation related - std::map> liveness_analysis(Function* func); - std::map> build_interference_graph( - const std::map>& live_sets); + LivenessResult liveness_analysis(Function* func); + std::map> build_interference_graph(const LivenessResult& liveness); void color_graph(std::map& vreg_to_preg, const std::map>& interference_graph); RegAllocResult register_allocation(Function* func);