[backend] fixed bugs of deadcode elimation

This commit is contained in:
Lixuanwang
2025-06-25 18:56:08 +08:00
parent 019cb6dc0d
commit d06c5efae1

View File

@ -1,16 +1,16 @@
#include "RISCv64Backend.h" // 修改头文件名
#include "RISCv64Backend.h"
#include <sstream>
#include <algorithm>
#include <stdexcept>
#include <regex>
#include <iomanip>
#include <functional> // For std::function
#include <functional>
#define DEBUG 1
#define DEEPDEBUG 0
namespace sysy {
// 可用于分配的寄存器(整数和浮点)
// 可用于分配的寄存器
const std::vector<RISCv64CodeGen::PhysicalReg> 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<std::unique_ptr<RISCv64CodeGen::DAGNode>> 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<std::unique_ptr<RISCv64CodeGen::DAGNode>> 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<std::unique_ptr<RISCv64CodeGen::DAGNode>> RISCv64CodeGen::build_dag(
} else if (auto bin = dynamic_cast<BinaryInst*>(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<ConstantValue*>(lhs_ir)) {
@ -468,14 +459,9 @@ std::vector<std::unique_ptr<RISCv64CodeGen::DAGNode>> 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<std::unique_ptr<RISCv64CodeGen::DAGNode>> 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<UnaryInst*>(inst)) {
if (value_to_node.count(un_inst)) continue;
@ -493,11 +480,10 @@ std::vector<std::unique_ptr<RISCv64CodeGen::DAGNode>> RISCv64CodeGen::build_dag(
unary_node->operands.push_back(operand_node);
operand_node->users.push_back(unary_node);
} else if (auto call = dynamic_cast<CallInst*>(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<std::unique_ptr<RISCv64CodeGen::DAGNode>> RISCv64CodeGen::build_dag(
arg_node->users.push_back(call_node);
}
} else if (auto ret = dynamic_cast<ReturnInst*>(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<std::unique_ptr<RISCv64CodeGen::DAGNode>> RISCv64CodeGen::build_dag(
br_node->inst = "j " + uncond_br->getBlock()->getName();
}
}
return nodes_storage;
}
// 打印 DAG (保持不变)
// 打印 DAG
void RISCv64CodeGen::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
std::cerr << "=== DAG for Basic Block: " << bb_name << " ===\n";
std::set<DAGNode*> visited;
@ -584,7 +570,6 @@ void RISCv64CodeGen::print_dag(const std::vector<std::unique_ptr<DAGNode>>& 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<std::unique_ptr<DAGNode>>& 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<std::string, std::set<std::string>> RISCv64CodeGen::build_interference_
}
}
}
// --- 新增修复逻辑:处理指令内部操作数之间的干扰 ---
// 对于 store 指令,要存储的值和目标地址指针是同时活跃的,必须互相干扰。
if (auto store = dynamic_cast<StoreInst*>(inst)) {
Value* val_operand = store->getValue();