[backend]在后端主函数中添加了调试逻辑

This commit is contained in:
Lixuanwang
2025-08-04 18:17:09 +08:00
parent 72b06c67ca
commit b5f14d9385

View File

@@ -1,10 +1,13 @@
#include "RISCv64Backend.h"
#include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h"
#include "RISCv64LinearScan.h" // <--- 新增此行
#include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h"
#include <sstream>
#include <future> // <--- 新增此行
#include <chrono> // <--- 新增此行
#include <iostream> // <--- 新增此行,用于打印超时警告
namespace sysy {
// 顶层入口
@@ -193,7 +196,8 @@ std::string RISCv64CodeGen::module_gen() {
}
std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 ===
if (DEBUG) {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
@@ -206,9 +210,8 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
if (DEBUG) {
std::cout << ss_after_isel.str();
}
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
@@ -232,13 +235,144 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
DivStrengthReduction div_strength_reduction;
div_strength_reduction.runOnMachineFunction(mfunc.get());
// 阶段 2.1: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get());
// // 阶段 2.1: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
DEBUG = 1;
// DEEPERDEBUG = 1;
// 阶段 3: 物理寄存器分配 (带超时回退机制)
/*
* [临时修改]
* 为了优先测试线性扫描分配器,暂时注释掉图着色分配器及其超时逻辑。
* 原始逻辑是:优先使用图着色,超时(20s)后回退到线性扫描。
* 在线性扫描分配器测试稳定后,可以恢复此处的代码。
*/
/*
// 首先尝试图着色分配器
if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n";
RISCv64RegAlloc gc_alloc(mfunc.get());
// 异步执行图着色分配
auto future = std::async(std::launch::async, [&gc_alloc]{
gc_alloc.run();
});
// 等待最多20秒
auto status = future.wait_for(std::chrono::seconds(20));
if (status == std::future_status::timeout) {
// 超时,切换到线性扫描分配器
std::cerr << "Warning: Graph coloring register allocation timed out for function '"
<< func->getName()
<< "'. Switching to Linear Scan allocator."
<< std::endl;
// 注意由于无法安全地停止gc_alloc线程我们只能放弃它的结果。
// 在此项目中我们假设超时后原mfunc状态未被严重破坏
// 或者线性扫描会基于isel后的状态重新开始。
// 为了安全我们应该用一个新的mfunc或者重置mfunc状态
// 但在这里我们简化处理直接在同一个mfunc上运行线性扫描。
RISCv64LinearScan ls_alloc(mfunc.get());
ls_alloc.run();
} else {
// 图着色成功完成
if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n";
// future.get()会重新抛出在线程中发生的任何异常
future.get();
}
*/
// [临时修改] 直接调用线性扫描分配器进行测试
std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n";
RISCv64LinearScan ls_alloc(mfunc.get());
ls_alloc.run();
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
return ss.str();
} else {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
std::stringstream ss_after_eli;
printer_isel.run(ss_after_eli, true);
std::cerr << "====== LLIR after eliminate frame indices ======\n"
<< ss_after_eli.str();
}
// // 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
// DivStrengthReduction div_strength_reduction;
// div_strength_reduction.runOnMachineFunction(mfunc.get());
// // 阶段 2.1: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
// RISCv64RegAlloc reg_alloc(mfunc.get());
// reg_alloc.run();
// [临时修改] 直接调用线性扫描分配器进行测试
std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n";
RISCv64LinearScan ls_alloc(mfunc.get());
ls_alloc.run();
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
@@ -254,9 +388,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 4: 窥孔优化 (Peephole Optimization)
PeepholeOptimizer peephole;
peephole.runOnMachineFunction(mfunc.get());
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler;
@@ -276,7 +410,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
printer.run(ss);
return ss.str();
}
}
} // namespace sysy