[backend] fixed bugs of deadcode elimation
This commit is contained in:
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user