diff --git a/src/RISCv64Backend.cpp b/src/RISCv64Backend.cpp index 0935f68..ef34333 100644 --- a/src/RISCv64Backend.cpp +++ b/src/RISCv64Backend.cpp @@ -325,46 +325,68 @@ std::string RISCv64CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& return ss.str(); } +// 辅助函数,用于创建 DAGNode 并管理其所有权 +sysy::RISCv64CodeGen::DAGNode* sysy::RISCv64CodeGen::create_node( + DAGNode::NodeKind kind, + Value* val, + std::map& value_to_node, // 需要外部传入 + std::vector>& nodes_storage // 需要外部传入 +) { + // 优化:如果一个值已经有节点并且它不是控制流/存储/Alloca地址/一元操作,则重用它 (CSE) + // 对于 AllocaInst,我们想创建一个代表其地址的节点,但不一定直接为 AllocaInst 本身分配虚拟寄存器。 + if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::ALLOCA_ADDR && kind != DAGNode::UNARY) { + return value_to_node[val]; + } + + auto node = std::make_unique(kind); + node->value = val; + + // 为产生结果的值分配虚拟寄存器 + if (val && value_vreg_map.count(val) && !dynamic_cast(val)) { // 排除 AllocaInst + node->result_vreg = value_vreg_map.at(val); + } + + DAGNode* raw_node_ptr = node.get(); + nodes_storage.push_back(std::move(node)); // 存储 unique_ptr + + // 仅当 IR Value 表示一个计算值时,才将其映射到创建的 DAGNode + // 且它应该已经在 register_allocation 中被分配了 vreg + if (val && value_vreg_map.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && !dynamic_cast(val)) { + value_to_node[val] = raw_node_ptr; + } + return raw_node_ptr; +} + + +// 辅助函数:获取值的 DAG 节点。 +// 如果 value 已经映射到 DAG 节点,则直接返回。 +// 如果是常量,则创建 CONSTANT 节点。 +// 如果是 AllocaInst,则创建 ALLOCA_ADDR 节点。 +// 否则,假定需要通过 LOAD 获取该值。 +sysy::RISCv64CodeGen::DAGNode* sysy::RISCv64CodeGen::get_operand_node( + Value* val_ir, + std::map& value_to_node, // 接受 value_to_node + std::vector>& nodes_storage // 接受 nodes_storage +) { + if (value_to_node.count(val_ir)) { + return value_to_node[val_ir]; + } else if (auto constant = dynamic_cast(val_ir)) { + return create_node(DAGNode::CONSTANT, constant, value_to_node, nodes_storage); // 调用成员函数版 create_node + } else if (auto alloca = dynamic_cast(val_ir)) { + return create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage); // 调用成员函数版 create_node + } else if (auto global = dynamic_cast(val_ir)) { + // 确保 GlobalValue 也能正确处理,如果 DAGNode::CONSTANT 无法存储 GlobalValue*, + // 则需要新的 DAGNode 类型,例如 DAGNode::GLOBAL_ADDR + return create_node(DAGNode::CONSTANT, global, value_to_node, nodes_storage); // 调用成员函数版 create_node + } + // 这是一个尚未在此块中计算的值,假设它需要加载 (从内存或参数) + return create_node(DAGNode::LOAD, val_ir, value_to_node, nodes_storage); // 调用成员函数版 create_node +} std::vector> RISCv64CodeGen::build_dag(BasicBlock* bb) { std::vector> nodes_storage; // 存储所有 unique_ptr std::map value_to_node; // 将 IR Value* 映射到原始 DAGNode*,用于快速查找 - // 辅助函数,用于创建 DAGNode 并管理其所有权 - auto create_node = [&](DAGNode::NodeKind kind, Value* val = nullptr) -> DAGNode* { - // 优化:如果一个值已经有节点并且它不是控制流/存储/Alloca地址/一元操作,则重用它 (CSE) - // 对于 AllocaInst,我们想创建一个代表其地址的节点,但不一定直接为 AllocaInst 本身分配虚拟寄存器。 - if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::ALLOCA_ADDR && kind != DAGNode::UNARY) { - return value_to_node[val]; - } - - auto node = std::make_unique(kind); - node->value = val; - - // 为产生结果的值分配虚拟寄存器 - // 注意:这里的vreg分配是在每个块中独立进行的,但寄存器分配器是在函数级别运行的 - // 我们在寄存器分配前,已经为整个函数的所有value预分配了vreg - // 此处的逻辑应完全依赖于 register_allocation 阶段已经建立的 value_vreg_map - // 并且 AllocaInst 不应在此处获取 result_vreg,因为它不映射到物理寄存器。 - if (val && value_vreg_map.count(val) && !dynamic_cast(val)) { // 排除 AllocaInst - node->result_vreg = value_vreg_map.at(val); - } - // 如果 val 即使在 value_vreg_map 中存在,但它是 AllocaInst,则不分配 result_vreg。 - // 对于 DAGNode::ALLOCA_ADDR 节点,它的 result_vreg 应该为空,因为其“值”是内存地址, - // 在指令选择时直接转换为 s0 + 偏移量。 - - DAGNode* raw_node_ptr = node.get(); - nodes_storage.push_back(std::move(node)); // 存储 unique_ptr - - // 仅当 IR Value 表示一个计算值时,才将其映射到创建的 DAGNode - // 且它应该已经在 register_allocation 中被分配了 vreg - if (val && value_vreg_map.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && !dynamic_cast(val)) { - value_to_node[val] = raw_node_ptr; - } - return raw_node_ptr; - }; - - for (const auto& inst_ptr : bb->getInstructions()) { auto inst = inst_ptr.get(); @@ -375,194 +397,134 @@ std::vector> RISCv64CodeGen::build_dag( // 我们将 AllocaInst 指针存储在 DAGNode 的 `value` 字段中。 // 修正:AllocaInst 类型的 DAGNode 应该有一个 value 对应 AllocaInst* // 但它本身不应该有 result_vreg,因为不映射到物理寄存器。 - create_node(DAGNode::ALLOCA_ADDR, alloca); + create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage); } else if (auto store = dynamic_cast(inst)) { - auto store_node = create_node(DAGNode::STORE, store); // 将 store inst 绑定到 node + auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage); // 调用成员函数版 create_node // 获取要存储的值 - Value* val_to_store_ir = store->getValue(); - DAGNode* val_node = nullptr; - if (value_to_node.count(val_to_store_ir)) { - val_node = value_to_node[val_to_store_ir]; - } else if (auto constant = dynamic_cast(val_to_store_ir)) { - val_node = create_node(DAGNode::CONSTANT, constant); - } else { // 这是一个尚未在此块中计算的值,假设它需要加载 (从内存或参数) - val_node = create_node(DAGNode::LOAD, val_to_store_ir); - } + DAGNode* val_node = get_operand_node(store->getValue(), value_to_node, nodes_storage); // 传递参数 - // 获取内存位置的指针 + // 获取内存位置的指针 (基地址) Value* ptr_ir = store->getPointer(); - DAGNode* ptr_node = nullptr; - if (value_to_node.count(ptr_ir)) { - ptr_node = value_to_node[ptr_ir]; - } else if (auto alloca = dynamic_cast(ptr_ir)) { - // 如果是alloca,我们应该找到代表它地址的节点 - // 为了简化,如果没找到,就创建一个 - // 修正:AllocaInst 应该直接映射到 ALLOCA_ADDR 节点,其值是 AllocaInst* - ptr_node = create_node(DAGNode::ALLOCA_ADDR, alloca); - } else if (auto global = dynamic_cast(ptr_ir)) { - ptr_node = create_node(DAGNode::CONSTANT, global); // 全局地址将被加载 - } else { // 必须是存储在虚拟寄存器中的指针 - ptr_node = create_node(DAGNode::LOAD, ptr_ir); // 这是一个产生指针的指令 - } + DAGNode* ptr_node = get_operand_node(ptr_ir, value_to_node, nodes_storage); // 传递参数 store_node->operands.push_back(val_node); store_node->operands.push_back(ptr_node); val_node->users.push_back(store_node); ptr_node->users.push_back(store_node); - } else if (auto load = dynamic_cast(inst)) { - if (value_to_node.count(load)) continue; // 共同子表达式消除 (CSE) - auto load_node = create_node(DAGNode::LOAD, load); // 为 load_node 分配 result_vreg 并映射 load - - Value* ptr_ir = load->getPointer(); - DAGNode* ptr_node = nullptr; - if (value_to_node.count(ptr_ir)) { - ptr_node = value_to_node[ptr_ir]; - } else if (auto alloca = dynamic_cast(ptr_ir)) { - // 修正:AllocaInst 应该直接映射到 ALLOCA_ADDR 节点 - ptr_node = create_node(DAGNode::ALLOCA_ADDR, alloca); - } else if (auto global = dynamic_cast(ptr_ir)) { - ptr_node = create_node(DAGNode::CONSTANT, global); // 全局地址将被加载 - } else { // 必须是存储在虚拟寄存器中的指针 - ptr_node = create_node(DAGNode::LOAD, ptr_ir); // 这是一个产生指针的指令 + // !!! 新增:处理 StoreInst 的 indices + for (int i = 0; i < store->getNumIndices(); ++i) { + 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); + index_node->users.push_back(store_node); } + } else if (auto load = dynamic_cast(inst)) { + auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage); // 调用成员函数版 create_node + + // 获取内存位置的指针 (基地址) + Value* ptr_ir = load->getPointer(); + DAGNode* ptr_node = get_operand_node(ptr_ir, value_to_node, nodes_storage); // 传递参数 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); // 传递参数 + load_node->operands.push_back(index_node); + index_node->users.push_back(load_node); + } + + // 关联 load_node 的结果到 value_to_node + value_to_node[load] = load_node; // 这里的 value_to_node 是局部变量,OK } 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)) { // 修正:使用 ConstantValue + if (auto const_lhs = dynamic_cast(lhs_ir)) { bool is_neg = false; - if (const_lhs->getType()->isInt()) { // 整数类型 + if (const_lhs->getType()->isInt()) { if (const_lhs->getInt() == 0) { is_neg = true; } - } else if (const_lhs->getType()->isFloat()) { // 浮点类型 - // 浮点数零的比较需要考虑精度,使用一个小的epsilon + } else if (const_lhs->getType()->isFloat()) { if (std::fabs(const_lhs->getFloat()) < std::numeric_limits::epsilon()) { is_neg = true; } } if (is_neg) { - // 这是一个 neg 操作 (0 - X 或 0.0 - X) - auto unary_node = create_node(DAGNode::UNARY, bin); // 绑定到原 BinaryInst,但类型是 UNARY - Value* operand_ir = bin->getRhs(); // 右操作数是实际被 neg 的值 - DAGNode* operand_node = nullptr; - if (value_to_node.count(operand_ir)) { - operand_node = value_to_node[operand_ir]; - } else if (auto constant = dynamic_cast(operand_ir)) { - operand_node = create_node(DAGNode::CONSTANT, constant); - } else { - operand_node = create_node(DAGNode::LOAD, operand_ir); - } + auto unary_node = create_node(DAGNode::UNARY, bin, value_to_node, nodes_storage); // 传递参数 + Value* operand_ir = bin->getRhs(); + DAGNode* operand_node = get_operand_node(operand_ir, value_to_node, nodes_storage); // 传递参数 unary_node->operands.push_back(operand_node); operand_node->users.push_back(unary_node); - continue; // 已处理,跳过后续的常规 Binary 处理 + continue; } } } // --- 结束关键修改 --- // 常规二进制操作 - auto bin_node = create_node(DAGNode::BINARY, bin); + auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage); // 传递参数 - auto get_operand_node = [&](Value* operand_ir) -> DAGNode* { - if (value_to_node.count(operand_ir)) { - return value_to_node[operand_ir]; - } else if (auto constant = dynamic_cast(operand_ir)) { - return create_node(DAGNode::CONSTANT, constant); - } else { - // 这是一个由另一个指令或参数产生的值,如果不在 map 中,则假设需要加载 - return create_node(DAGNode::LOAD, operand_ir); - } - }; + // !!! 移除 lambda 版本的 get_operand_node,现在调用成员函数版本 !!! + // auto get_operand_node = [&](Value* operand_ir) -> DAGNode* { ... }; - DAGNode* lhs_node = get_operand_node(bin->getLhs()); - DAGNode* rhs_node = get_operand_node(bin->getRhs()); + 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); // 传递参数 bin_node->operands.push_back(lhs_node); 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; // CSE + } else if (auto un_inst = dynamic_cast(inst)) { + if (value_to_node.count(un_inst)) continue; - auto unary_node = create_node(DAGNode::UNARY, un_inst); // 为 unary_node 分配 result_vreg 并映射 un_inst + auto unary_node = create_node(DAGNode::UNARY, un_inst, value_to_node, nodes_storage); // 传递参数 - // 修正:UnaryInst::getOperand() 不接受参数 Value* operand_ir = un_inst->getOperand(); - DAGNode* operand_node = nullptr; - if (value_to_node.count(operand_ir)) { - operand_node = value_to_node[operand_ir]; - } else if (auto constant = dynamic_cast(operand_ir)) { - operand_node = create_node(DAGNode::CONSTANT, constant); - } else { - operand_node = create_node(DAGNode::LOAD, operand_ir); - } + DAGNode* operand_node = get_operand_node(operand_ir, value_to_node, nodes_storage); // 传递参数 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; // CSE (如果结果被重用) + if (value_to_node.count(call)) continue; - auto call_node = create_node(DAGNode::CALL, call); // 如果调用返回一个值,则分配 result_vreg + 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 = nullptr; - if (value_to_node.count(arg_val_ir)) { - arg_node = value_to_node[arg_val_ir]; - } else if (auto constant = dynamic_cast(arg_val_ir)) { - arg_node = create_node(DAGNode::CONSTANT, constant); - } else { - arg_node = create_node(DAGNode::LOAD, arg_val_ir); - } + DAGNode* arg_node = get_operand_node(arg_val_ir, value_to_node, nodes_storage); // 传递参数 call_node->operands.push_back(arg_node); arg_node->users.push_back(call_node); } } else if (auto ret = dynamic_cast(inst)) { - auto ret_node = create_node(DAGNode::RETURN, ret); // 将 return inst 绑定到 node + auto ret_node = create_node(DAGNode::RETURN, ret, value_to_node, nodes_storage); // 传递参数 if (ret->hasReturnValue()) { auto val_ir = ret->getReturnValue(); - DAGNode* val_node = nullptr; - if (value_to_node.count(val_ir)) { - val_node = value_to_node[val_ir]; - } else if (auto constant = dynamic_cast(val_ir)) { - val_node = create_node(DAGNode::CONSTANT, constant); - } else { - val_node = create_node(DAGNode::LOAD, val_ir); - } + DAGNode* val_node = get_operand_node(val_ir, value_to_node, nodes_storage); // 传递参数 ret_node->operands.push_back(val_node); val_node->users.push_back(ret_node); } } else if (auto cond_br = dynamic_cast(inst)) { - auto br_node = create_node(DAGNode::BRANCH, cond_br); // 将 cond_br inst 绑定到 node + auto br_node = create_node(DAGNode::BRANCH, cond_br, value_to_node, nodes_storage); // 传递参数 auto cond_ir = cond_br->getCondition(); if (auto constant_cond = dynamic_cast(cond_ir)) { - // 优化常量条件分支为无条件跳转 br_node->inst = "j " + (constant_cond->getInt() ? cond_br->getThenBlock()->getName() : cond_br->getElseBlock()->getName()); - // 对于直接跳转,不需要操作数 } else { - DAGNode* cond_node = nullptr; - if (value_to_node.count(cond_ir)) { - cond_node = value_to_node[cond_ir]; - } else if (auto bin_cond = dynamic_cast(cond_ir)) { - cond_node = create_node(DAGNode::BINARY, bin_cond); - } else { // 必须是一个需要加载的值 - cond_node = create_node(DAGNode::LOAD, cond_ir); - } + DAGNode* cond_node = get_operand_node(cond_ir, value_to_node, nodes_storage); // 传递参数 br_node->operands.push_back(cond_node); cond_node->users.push_back(br_node); } } else if (auto uncond_br = dynamic_cast(inst)) { - auto br_node = create_node(DAGNode::BRANCH, uncond_br); // 将 uncond_br inst 绑定到 node + auto br_node = create_node(DAGNode::BRANCH, uncond_br, value_to_node, nodes_storage); // 传递参数 br_node->inst = "j " + uncond_br->getBlock()->getName(); } } diff --git a/src/RISCv64Backend.h b/src/RISCv64Backend.h index beea4e2..1762eeb 100644 --- a/src/RISCv64Backend.h +++ b/src/RISCv64Backend.h @@ -93,6 +93,23 @@ private: // 为空标签定义一个伪名称前缀,加上块索引以确保唯一性 const std::string ENTRY_BLOCK_PSEUDO_NAME = "entry_block_"; + + // !!! 修改:get_operand_node 辅助函数现在需要传入 value_to_node 和 nodes_storage 的引用 + // 因为它们是 build_dag 局部管理的 + DAGNode* get_operand_node( + Value* val_ir, + std::map& value_to_node, + std::vector>& nodes_storage + ); + + // !!! 新增:create_node 辅助函数也需要传入 value_to_node 和 nodes_storage 的引用 + // 并且它应该不再是 lambda,而是一个真正的成员函数 + DAGNode* create_node( + DAGNode::NodeKind kind, + Value* val, + std::map& value_to_node, + std::vector>& nodes_storage + ); }; } // namespace sysy