[backend]完善后端流水线,本地仅剩h/39不通过

This commit is contained in:
Lixuanwang
2025-08-18 22:14:21 +08:00
parent acb0302a29
commit 0720a622c1
2 changed files with 75 additions and 86 deletions

View File

@@ -198,10 +198,6 @@ std::string RISCv64CodeGen::module_gen() {
}
std::string RISCv64CodeGen::function_gen(Function* func) {
DEBUG = 0;
DEEPDEBUG = 0;
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
@@ -216,7 +212,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
}
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
@@ -229,88 +224,82 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
<< ss_after_eli.str();
}
// // 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
// DivStrengthReduction div_strength_reduction;
// div_strength_reduction.runOnMachineFunction(mfunc.get());
// 阶段 2.1: 除法强度削弱优化 (Division Strength Reduction)
DivStrengthReduction div_strength_reduction;
div_strength_reduction.runOnMachineFunction(mfunc.get());
// // 阶段 2.1: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// 阶段 2.2: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
// 首先尝试图着色分配器
// int fooo = 0;
int fooo = 1;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (fooo) {
RISCv64SimpleRegAlloc simple_alloc(mfunc.get());
simple_alloc.run();
DEBUG = 0;
DEEPDEBUG = 0;
} else
{if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n";
if (!gc_failed) {
RISCv64RegAlloc gc_alloc(mfunc.get());
bool success_gc = gc_alloc.run();
if (!success_gc) {
gc_failed = 1; // 后续不再尝试图着色分配器
std::cerr << "Warning: Graph coloring register allocation failed function '"
<< func->getName()
<< "'. Switching to Linear Scan allocator."
<< std::endl;
RISCv64ISel isel_gc_fallback;
mfunc = isel_gc_fallback.runOnFunction(func);
EliminateFrameIndicesPass efi_pass_gc_fallback;
efi_pass_gc_fallback.runOnMachineFunction(mfunc.get());
RISCv64LinearScan ls_alloc(mfunc.get());
bool success = ls_alloc.run();
if (!success) {
// 如果线性扫描最终失败,则调用基本块分配器作为终极后备
std::cerr << "Info: Linear Scan failed. Switching to Basic Block Allocator as final fallback.\n";
// 注意我们需要在一个“干净”的MachineFunction上运行。
// 最安全的方式是重新运行指令选择。
RISCv64ISel isel_fallback;
mfunc = isel_fallback.runOnFunction(func);
EliminateFrameIndicesPass efi_pass_fallback;
efi_pass_fallback.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
bool allocation_succeeded = false;
// 尝试迭代图着色 (IRC)
if (!irc_failed) {
if (DEBUG) std::cerr << "Attempting Register Allocation with Iterated Register Coloring (IRC)...\n";
RISCv64RegAlloc irc_alloc(mfunc.get());
if (irc_alloc.run()) {
allocation_succeeded = true;
if (DEBUG) std::cerr << "IRC allocation succeeded.\n";
} else {
std::cerr << "Warning: IRC failed for function '" << func->getName()
<< "'. Blacklisting IRC for subsequent functions and falling back.\n";
irc_failed = true; // 拉黑IRC后续函数不再尝试
}
}
// 尝试简单图着色 (SGC) 并设置超时
if (!allocation_succeeded) {
// 如果是从IRC失败回退过来的需要重新创建干净的mfunc和ISel
RISCv64ISel isel_for_sgc;
if (irc_failed) {
if (DEBUG) std::cerr << "Info: Resetting MachineFunction for SGC attempt.\n";
mfunc = isel_for_sgc.runOnFunction(func);
EliminateFrameIndicesPass efi_pass_for_sgc;
efi_pass_for_sgc.runOnMachineFunction(mfunc.get());
}
if (DEBUG) std::cerr << "Attempting Register Allocation with Simple Graph Coloring (SGC)...\n";
bool sgc_completed_in_time = false;
{
RISCv64SimpleRegAlloc sgc_alloc(mfunc.get());
auto future = std::async(std::launch::async, &RISCv64SimpleRegAlloc::run, &sgc_alloc);
std::future_status status = future.wait_for(std::chrono::seconds(20));
if (status == std::future_status::ready) {
try {
future.get(); // 检查是否有异常
sgc_completed_in_time = true;
if (DEBUG) std::cerr << "SGC allocation completed successfully within the time limit.\n";
} catch (const std::exception& e) {
std::cerr << "Error: SGC allocation threw an exception: " << e.what() << std::endl;
}
}
}
if (sgc_completed_in_time) {
allocation_succeeded = true;
} else {
std::cerr << "Warning: SGC allocation timed out or failed for function '" << func->getName()
<< "'. Falling back.\n";
}
}
// 策略三:如果以上所有策略都失败了,则使用基本块分配器 (BBA)
if (!allocation_succeeded) {
// 为BBA准备干净的mfunc和ISel
std::cerr << "Info: Resetting MachineFunction for BBA fallback.\n";
RISCv64ISel isel_for_bba;
mfunc = isel_for_bba.runOnFunction(func);
EliminateFrameIndicesPass efi_pass_for_bba;
efi_pass_for_bba.runOnMachineFunction(mfunc.get());
std::cerr << "Info: Using Basic Block Allocator as final fallback.\n";
RISCv64BasicBlockAlloc bb_alloc(mfunc.get());
bb_alloc.run();
}
} else {
// 图着色成功完成
if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n";
}
} else {
std::cerr << "Info: Graph Coloring allocation failed in last function. Switching to Linear Scan allocator...\n";
RISCv64LinearScan ls_alloc(mfunc.get());
bool success = ls_alloc.run();
if (!success) {
// 如果线性扫描最终失败,则调用基本块分配器作为终极后备
std::cerr << "Info: Linear Scan failed. Switching to Basic Block Allocator as final fallback.\n";
// 注意我们需要在一个“干净”的MachineFunction上运行。
// 最安全的方式是重新运行指令选择。
RISCv64ISel isel_fallback;
mfunc = isel_fallback.runOnFunction(func);
EliminateFrameIndicesPass efi_pass_fallback;
efi_pass_fallback.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
}
RISCv64BasicBlockAlloc bb_alloc(mfunc.get());
bb_alloc.run();
}
}}
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
@@ -326,9 +315,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;

View File

@@ -26,7 +26,7 @@ private:
unsigned getTypeSizeInBytes(Type* type);
Module* module;
bool gc_failed = false;
bool irc_failed = false;
};
} // namespace sysy