From d06c5efae18bd318716a95fcb4a79f948dbd2cc7 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Wed, 25 Jun 2025 18:56:08 +0800 Subject: [PATCH] [backend] fixed bugs of deadcode elimation --- src/RISCv64Backend.cpp | 44 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/src/RISCv64Backend.cpp b/src/RISCv64Backend.cpp index ef34333..5f3e868 100644 --- a/src/RISCv64Backend.cpp +++ b/src/RISCv64Backend.cpp @@ -1,16 +1,16 @@ -#include "RISCv64Backend.h" // 修改头文件名 +#include "RISCv64Backend.h" #include #include #include #include #include -#include // For std::function +#include #define DEBUG 1 #define DEEPDEBUG 0 namespace sysy { -// 可用于分配的寄存器(整数和浮点) +// 可用于分配的寄存器 const std::vector RISCv64CodeGen::allocable_regs = { // 整数寄存器 PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, @@ -111,7 +111,6 @@ std::string RISCv64CodeGen::code_gen() { } // 模块级代码生成 (处理全局变量和函数) -// 注意:由于 int 和 float 仍然是32位,.word 的使用是正确的。 std::string RISCv64CodeGen::module_gen() { std::stringstream ss; bool has_globals = !module->getGlobals().empty(); @@ -173,7 +172,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) { ss << " mv s0, sp\n"; // 设置新的帧指针 } - // *** 新增的逻辑:处理传入的函数参数 *** // 将传入的寄存器参数 (a0-a7 / f10-f17) 保存到对应的栈槽 (AllocaInst)。 // RV64中,a0-a7是64位寄存器,但我们传入的int/float是32位。 // 使用 sw/fsw 会正确地存储低32位,这是正确的行为。 @@ -227,7 +225,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) { } -// 基本块代码生成 (无修改) +// 基本块代码生成 std::string RISCv64CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx) { std::stringstream ss; @@ -241,15 +239,8 @@ std::string RISCv64CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& else { ss << bb_name << ":\n"; // 基本块标签 } - // !!! 重要的修改:此处不再清除 value_vreg_map 和 vreg_counter。 - // !!! 这些映射在 function_gen -> register_allocation 阶段为整个函数建立。 - // value_vreg_map.clear(); // 移除此行 - // vreg_counter = 0; // 移除此行 // 构建当前基本块的 DAG - // 注意:DAGNode 的唯一性在当前函数范围内是重要的, - // 所以 build_dag 应该返回一个完整的 DAG 节点列表,而不是每次都创建新的。 - // 为了简化,这里仍然按块构建,但需要注意跨块值的使用。 auto dag_nodes_for_bb = build_dag(bb); if (DEBUG) print_dag(dag_nodes_for_bb, bb_name); // 打印 DAG 调试信息 @@ -413,8 +404,10 @@ std::vector> RISCv64CodeGen::build_dag( val_node->users.push_back(store_node); ptr_node->users.push_back(store_node); - // !!! 新增:处理 StoreInst 的 indices + if (store->getNumIndices()) + if (DEBUG) std::cerr << "处理 StoreInst 的 indices: " << store->getNumIndices() << "\n"; // 调试输出 for (int i = 0; i < store->getNumIndices(); ++i) { + if (DEBUG) std::cerr << "处理 StoreInst 的 indices: " << i << "\n"; // 调试输出 Value* index_ir = store->getIndex(i); DAGNode* index_node = get_operand_node(index_ir, value_to_node, nodes_storage); // 传递参数 store_node->operands.push_back(index_node); @@ -430,7 +423,6 @@ std::vector> RISCv64CodeGen::build_dag( load_node->operands.push_back(ptr_node); ptr_node->users.push_back(load_node); - // !!! 新增:处理 LoadInst 的 indices for (int i = 0; i < load->getNumIndices(); ++i) { Value* index_ir = load->getIndex(i); DAGNode* index_node = get_operand_node(index_ir, value_to_node, nodes_storage); // 传递参数 @@ -443,7 +435,6 @@ std::vector> RISCv64CodeGen::build_dag( } else if (auto bin = dynamic_cast(inst)) { if (value_to_node.count(bin)) continue; // CSE - // --- 关键修改:识别 SUB 0, X 或 FSUB 0.0, X 模式为 NEG --- if (bin->getKind() == BinaryInst::kSub || bin->getKind() == BinaryInst::kFSub) { Value* lhs_ir = bin->getLhs(); if (auto const_lhs = dynamic_cast(lhs_ir)) { @@ -468,14 +459,9 @@ std::vector> RISCv64CodeGen::build_dag( } } } - // --- 结束关键修改 --- - // 常规二进制操作 auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage); // 传递参数 - // !!! 移除 lambda 版本的 get_operand_node,现在调用成员函数版本 !!! - // auto get_operand_node = [&](Value* operand_ir) -> DAGNode* { ... }; - DAGNode* lhs_node = get_operand_node(bin->getLhs(), value_to_node, nodes_storage); // 传递参数 DAGNode* rhs_node = get_operand_node(bin->getRhs(), value_to_node, nodes_storage); // 传递参数 @@ -483,6 +469,7 @@ std::vector> RISCv64CodeGen::build_dag( bin_node->operands.push_back(rhs_node); lhs_node->users.push_back(bin_node); rhs_node->users.push_back(bin_node); + } else if (auto un_inst = dynamic_cast(inst)) { if (value_to_node.count(un_inst)) continue; @@ -493,11 +480,10 @@ std::vector> RISCv64CodeGen::build_dag( unary_node->operands.push_back(operand_node); operand_node->users.push_back(unary_node); + } else if (auto call = dynamic_cast(inst)) { if (value_to_node.count(call)) continue; - auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage); // 传递参数 - for (auto arg : call->getArguments()) { auto arg_val_ir = arg->getValue(); DAGNode* arg_node = get_operand_node(arg_val_ir, value_to_node, nodes_storage); // 传递参数 @@ -505,6 +491,7 @@ std::vector> RISCv64CodeGen::build_dag( arg_node->users.push_back(call_node); } } else if (auto ret = dynamic_cast(inst)) { + std::cout << "处理 RETURN 指令: " << ret->getName() << "\n"; // 调试输出 auto ret_node = create_node(DAGNode::RETURN, ret, value_to_node, nodes_storage); // 传递参数 if (ret->hasReturnValue()) { auto val_ir = ret->getReturnValue(); @@ -528,11 +515,10 @@ std::vector> RISCv64CodeGen::build_dag( br_node->inst = "j " + uncond_br->getBlock()->getName(); } } - return nodes_storage; } -// 打印 DAG (保持不变) +// 打印 DAG void RISCv64CodeGen::print_dag(const std::vector>& dag, const std::string& bb_name) { std::cerr << "=== DAG for Basic Block: " << bb_name << " ===\n"; std::set visited; @@ -584,7 +570,6 @@ void RISCv64CodeGen::print_dag(const std::vector>& dag, } visited.insert(node); - if (!node->operands.empty()) { std::cerr << current_indent << " 操作数:\n"; for (auto operand : node->operands) { @@ -609,7 +594,6 @@ void RISCv64CodeGen::print_dag(const std::vector>& dag, std::cerr << "=== DAG 结束 ===\n\n"; } - // 指令选择 void RISCv64CodeGen::select_instructions(DAGNode* node, const RegAllocResult& alloc) { if (!node) return; @@ -905,10 +889,6 @@ void RISCv64CodeGen::emit_instructions(DAGNode* node, std::stringstream& ss, con // 处理虚拟寄存器替换和溢出/加载逻辑 std::string processed_line = line; - - // 注意:这里的替换逻辑比较脆弱,因为 select_instructions 已经直接生成了物理寄存器名 - // 在一个更健壮的系统中,select_instructions 会生成带vreg的指令,而这里会进行替换 - // 当前的实现下,这个替换逻辑大部分时间是空操作,但为了安全保留 // 替换结果虚拟寄存器 (如果此行中存在) if (!node->result_vreg.empty() && alloc.vreg_to_preg.count(node->result_vreg)) { @@ -1083,7 +1063,7 @@ std::map> RISCv64CodeGen::build_interference_ } } } - // --- 新增修复逻辑:处理指令内部操作数之间的干扰 --- + // 对于 store 指令,要存储的值和目标地址指针是同时活跃的,必须互相干扰。 if (auto store = dynamic_cast(inst)) { Value* val_operand = store->getValue();