[backend]解决了数组访存地址计算问题,加入了参数控制的中端、后端调试选项
This commit is contained in:
@ -6,8 +6,6 @@
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
|
||||
#define DEBUG 0
|
||||
#define DEEPDEBUG 0
|
||||
namespace sysy {
|
||||
|
||||
// 可用于分配的寄存器
|
||||
@ -390,48 +388,118 @@ std::vector<std::unique_ptr<RISCv64CodeGen::DAGNode>> RISCv64CodeGen::build_dag(
|
||||
// 但它本身不应该有 result_vreg,因为不映射到物理寄存器。
|
||||
create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage);
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
|
||||
auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage); // 调用成员函数版 create_node
|
||||
auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage);
|
||||
|
||||
// 获取要存储的值
|
||||
DAGNode* val_node = get_operand_node(store->getValue(), value_to_node, nodes_storage); // 传递参数
|
||||
DAGNode* val_node = get_operand_node(store->getValue(), value_to_node, nodes_storage);
|
||||
|
||||
// 获取内存位置的指针 (基地址)
|
||||
Value* ptr_ir = store->getPointer();
|
||||
DAGNode* ptr_node = get_operand_node(ptr_ir, value_to_node, nodes_storage); // 传递参数
|
||||
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);
|
||||
|
||||
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);
|
||||
index_node->users.push_back(store_node);
|
||||
// === 修改开始:处理带索引的 StoreInst ===
|
||||
if (store->getNumIndices() > 0) {
|
||||
if (DEBUG) std::cerr << "处理带索引的 StoreInst: " << store->getNumIndices() << " 个索引\n";
|
||||
|
||||
// 假设只有一个索引
|
||||
Value* index_ir = store->getIndex(0); // 获取索引 IR Value*
|
||||
DAGNode* index_node = get_operand_node(index_ir, value_to_node, nodes_storage); // 索引 DAG 节点
|
||||
|
||||
// 1. 获取元素大小的 ConstantValue * (例如 4 字节)
|
||||
// ConstantValue::get 返回裸指针,其生命周期由 IR 框架自身管理(假定是单例或池化)。
|
||||
Value* const_4_value_ir = ConstantValue::get(4);
|
||||
// 为这个常量创建一个 DAGNode
|
||||
DAGNode* size_node = create_node(DAGNode::CONSTANT, const_4_value_ir, value_to_node, nodes_storage);
|
||||
|
||||
|
||||
// 2. 创建一个 BINARY (MUL) 节点来计算字节偏移量 (index * element_size)
|
||||
// BinaryInst 构造函数是 protected 的,需要通过静态工厂方法创建
|
||||
Instruction* dummy_mul_inst_raw_ptr = BinaryInst::create(BinaryInst::kMul, Type::getIntType(), index_ir, const_4_value_ir, bb);
|
||||
// 将所有权转移到成员变量 temp_instructions_storage
|
||||
temp_instructions_storage.push_back(std::unique_ptr<Instruction>(dummy_mul_inst_raw_ptr)); // 存储临时的 Instruction
|
||||
|
||||
// 为这个新的 BinaryInst 创建一个 DAGNode,它的类型是 DAGNode::BINARY
|
||||
DAGNode* byte_offset_node = create_node(DAGNode::BINARY, dummy_mul_inst_raw_ptr, value_to_node, nodes_storage);
|
||||
|
||||
byte_offset_node->operands.push_back(index_node);
|
||||
byte_offset_node->operands.push_back(size_node);
|
||||
index_node->users.push_back(byte_offset_node);
|
||||
size_node->users.push_back(byte_offset_node);
|
||||
|
||||
|
||||
// 3. 创建一个 BINARY (ADD) 节点来计算最终地址 (base_address + byte_offset)
|
||||
// 创建另一个临时的 BinaryInst。
|
||||
Instruction* dummy_add_inst_raw_ptr = BinaryInst::create(BinaryInst::kAdd, Type::getIntType(), ptr_ir, dummy_mul_inst_raw_ptr, bb);
|
||||
temp_instructions_storage.push_back(std::unique_ptr<Instruction>(dummy_add_inst_raw_ptr)); // 存储临时的 Instruction
|
||||
|
||||
// 为这个新的 BinaryInst 创建一个 DAGNode
|
||||
DAGNode* final_addr_node = create_node(DAGNode::BINARY, dummy_add_inst_raw_ptr, value_to_node, nodes_storage);
|
||||
|
||||
final_addr_node->operands.push_back(ptr_node);
|
||||
final_addr_node->operands.push_back(byte_offset_node);
|
||||
ptr_node->users.push_back(final_addr_node);
|
||||
byte_offset_node->users.push_back(final_addr_node);
|
||||
|
||||
// 现在,STORE 节点的操作数是要存储的值和最终地址
|
||||
store_node->operands.push_back(final_addr_node);
|
||||
final_addr_node->users.push_back(store_node);
|
||||
|
||||
} else { // 原始的非索引 StoreInst 处理
|
||||
store_node->operands.push_back(ptr_node);
|
||||
ptr_node->users.push_back(store_node);
|
||||
}
|
||||
// === 修改结束 ===
|
||||
|
||||
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage); // 调用成员函数版 create_node
|
||||
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage);
|
||||
|
||||
// 获取内存位置的指针 (基地址)
|
||||
Value* ptr_ir = load->getPointer();
|
||||
DAGNode* ptr_node = get_operand_node(ptr_ir, value_to_node, nodes_storage); // 传递参数
|
||||
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 ===
|
||||
if (load->getNumIndices() > 0) {
|
||||
// 假设只有一个索引
|
||||
Value* index_ir = load->getIndex(0);
|
||||
DAGNode* index_node = get_operand_node(index_ir, value_to_node, nodes_storage);
|
||||
|
||||
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);
|
||||
// 1. 获取元素大小的 ConstantValue * (例如 4 字节)
|
||||
Value* const_4_value_ir = ConstantValue::get(4);
|
||||
DAGNode* size_node = create_node(DAGNode::CONSTANT, const_4_value_ir, value_to_node, nodes_storage);
|
||||
|
||||
// 2. 创建一个 BINARY (MUL) 节点来计算字节偏移量 (index * element_size)
|
||||
Instruction* dummy_mul_inst_raw_ptr = BinaryInst::create(BinaryInst::kMul, Type::getIntType(), index_ir, const_4_value_ir, bb);
|
||||
temp_instructions_storage.push_back(std::unique_ptr<Instruction>(dummy_mul_inst_raw_ptr)); // 存储临时的 Instruction
|
||||
|
||||
DAGNode* byte_offset_node = create_node(DAGNode::BINARY, dummy_mul_inst_raw_ptr, value_to_node, nodes_storage);
|
||||
|
||||
byte_offset_node->operands.push_back(index_node);
|
||||
byte_offset_node->operands.push_back(size_node);
|
||||
index_node->users.push_back(byte_offset_node);
|
||||
size_node->users.push_back(byte_offset_node);
|
||||
|
||||
// 3. 创建一个 BINARY (ADD) 节点来计算最终地址 (base_address + byte_offset)
|
||||
Instruction* dummy_add_inst_raw_ptr = BinaryInst::create(BinaryInst::kAdd, Type::getIntType(), ptr_ir, dummy_mul_inst_raw_ptr, bb);
|
||||
temp_instructions_storage.push_back(std::unique_ptr<Instruction>(dummy_add_inst_raw_ptr)); // 存储临时的 Instruction
|
||||
|
||||
DAGNode* final_addr_node = create_node(DAGNode::BINARY, dummy_add_inst_raw_ptr, value_to_node, nodes_storage);
|
||||
|
||||
final_addr_node->operands.push_back(ptr_node);
|
||||
final_addr_node->operands.push_back(byte_offset_node);
|
||||
ptr_node->users.push_back(final_addr_node);
|
||||
byte_offset_node->users.push_back(final_addr_node);
|
||||
|
||||
// 现在,LOAD 节点的操作数是最终地址
|
||||
load_node->operands.push_back(final_addr_node);
|
||||
final_addr_node->users.push_back(load_node);
|
||||
|
||||
} else { // 原始的非索引 LoadInst 处理
|
||||
load_node->operands.push_back(ptr_node);
|
||||
ptr_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<BinaryInst*>(inst)) {
|
||||
if (value_to_node.count(bin)) continue; // CSE
|
||||
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
#include <iostream>
|
||||
#include <functional> // For std::function
|
||||
|
||||
extern int DEBUG;
|
||||
extern int DEEPDEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv64CodeGen {
|
||||
@ -110,6 +113,8 @@ private:
|
||||
std::map<Value*, DAGNode*>& value_to_node,
|
||||
std::vector<std::unique_ptr<DAGNode>>& nodes_storage
|
||||
);
|
||||
|
||||
std::vector<std::unique_ptr<Instruction>> temp_instructions_storage; // 用于存储 build_dag 中创建的临时 BinaryInst
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
@ -883,6 +883,10 @@ public:
|
||||
assert(false);
|
||||
}
|
||||
} ///< 根据指令类型进行二元计算,eval template模板实现
|
||||
static BinaryInst* create(Kind kind, Type *type, Value *lhs, Value *rhs, BasicBlock *parent, const std::string &name = "") {
|
||||
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象,所以写了个public的方法。
|
||||
return new BinaryInst(kind, type, lhs, rhs, parent, name);
|
||||
}
|
||||
}; // class BinaryInst
|
||||
|
||||
//! The return statement
|
||||
|
||||
@ -18,6 +18,9 @@ using namespace antlr4;
|
||||
// #include "LLVMIRGenerator.h"
|
||||
using namespace sysy;
|
||||
|
||||
int DEBUG = 0;
|
||||
int DEEPDEBUG = 0;
|
||||
|
||||
static string argStopAfter;
|
||||
static string argInputFile;
|
||||
static bool argFormat = false;
|
||||
@ -27,7 +30,7 @@ void usage(int code = EXIT_FAILURE) {
|
||||
"Supported options:\n"
|
||||
" -h \tprint help message and exit\n";
|
||||
" -f \tpretty-format the input file\n";
|
||||
" -s {ast,ir,asm,llvmir}\tstop after generating AST/IR/Assembly\n";
|
||||
" -s {ast,ir,asm,llvmir,asmd,ird}\tstop after generating AST/IR/Assembly\n";
|
||||
cerr << msg;
|
||||
exit(code);
|
||||
}
|
||||
@ -80,10 +83,16 @@ int main(int argc, char **argv) {
|
||||
// visit AST to generate IR
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
if (argStopAfter == "ir") {
|
||||
if (argStopAfter == "ir" || argStopAfter == "ird") {
|
||||
if (argStopAfter == "ird") {
|
||||
DEBUG = 1;
|
||||
}
|
||||
auto moduleIR = generator.get();
|
||||
SysYPrinter printer(moduleIR);
|
||||
printer.printIR();
|
||||
if (DEBUG) {
|
||||
cout << "=== Original IR ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
auto builder = generator.getBuilder();
|
||||
SysYOptPre optPre(moduleIR, builder);
|
||||
optPre.SysYOptimizateAfterIR();
|
||||
@ -91,19 +100,35 @@ int main(int argc, char **argv) {
|
||||
cfa.init();
|
||||
ActiveVarAnalysis ava;
|
||||
ava.init(moduleIR);
|
||||
printer.printIR();
|
||||
|
||||
|
||||
if (DEBUG) {
|
||||
cout << "=== After CFA & AVA ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
DeadCodeElimination dce(moduleIR, &cfa, &ava);
|
||||
dce.runDCEPipeline();
|
||||
|
||||
if (DEBUG) {
|
||||
cout << "=== After 1st DCE ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava);
|
||||
mem2reg.mem2regPipeline();
|
||||
printer.printIR();
|
||||
if (DEBUG) {
|
||||
cout << "=== After Mem2Reg ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
Reg2Mem reg2mem(moduleIR, builder);
|
||||
reg2mem.DeletePhiInst();
|
||||
printer.printIR();
|
||||
if (DEBUG) {
|
||||
cout << "=== After Reg2Mem ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
dce.runDCEPipeline();
|
||||
if (DEBUG) {
|
||||
cout << "=== After 2nd DCE ===\n";
|
||||
printer.printIR();
|
||||
}
|
||||
cout << "=== Final IR ===\n";
|
||||
printer.printIR();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -111,7 +136,11 @@ int main(int argc, char **argv) {
|
||||
auto module = generator.get();
|
||||
sysy::RISCv64CodeGen codegen(module);
|
||||
string asmCode = codegen.code_gen();
|
||||
if (argStopAfter == "asm") {
|
||||
if (argStopAfter == "asm" || argStopAfter == "asmd") {
|
||||
if (argStopAfter == "asmd") {
|
||||
DEBUG = 1;
|
||||
DEEPDEBUG = 1;
|
||||
}
|
||||
cout << asmCode << endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user