[backend]调整了后端pass的顺序

This commit is contained in:
Lixuanwang
2025-07-29 16:15:01 +08:00
parent 8deb4ed076
commit 32bdc17dc3
2 changed files with 94 additions and 97 deletions

View File

@@ -1,4 +1,4 @@
#include "include/PrologueEpilogueInsertion.h"
#include "PrologueEpilogueInsertion.h"
namespace sysy {
@@ -6,114 +6,111 @@ char PrologueEpilogueInsertionPass::ID = 0;
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
// 最终计算总栈帧大小。
// 完全遵循 AsmPrinter 中的计算逻辑
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size +
16; // 为 ra 和 s0 固定的16字节
// 保持栈指针16字节对齐
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size;
if (aligned_stack_size == 0) {
return; // 无需插入序言/尾声
}
// 只有在需要分配栈空间时才生成指令
if (aligned_stack_size > 0) {
// --- 1. 插入序言 ---
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
// --- 1. 插入序言 ---
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
// [修复] 创建一个临时 vector 来存放所有序言指令,以避免迭代器失效
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
// 严格按照 AsmPrinter 的打印顺序来创建和组织指令
// 1. addi sp, sp, -aligned_stack_size
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
prologue_instrs.push_back(std::move(alloc_stack));
// a. addi sp, sp, -aligned_stack_size
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
prologue_instrs.push_back(std::move(alloc_stack));
// 2. sd ra, (aligned_stack_size - 8)(sp)
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
save_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
prologue_instrs.push_back(std::move(save_ra));
// b. sd ra, offset(sp)
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
save_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
prologue_instrs.push_back(std::move(save_ra));
// 3. sd s0, (aligned_stack_size - 16)(sp)
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
save_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
prologue_instrs.push_back(std::move(save_fp));
// 4. addi s0, sp, aligned_stack_size
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
prologue_instrs.push_back(std::move(set_fp));
// c. sd s0, offset(sp)
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
save_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
prologue_instrs.push_back(std::move(save_fp));
// d. addi s0, sp, aligned_stack_size
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
prologue_instrs.push_back(std::move(set_fp));
// 确定插入点(在函数名标签之后)
auto insert_pos = entry_instrs.begin();
// [重要] 这里我们不再需要跳过LABEL因为AsmPrinter将不再打印函数名标签
// 第一个基本块的标签就是函数入口
// 一次性将所有序言指令插入
if (!prologue_instrs.empty()) {
entry_instrs.insert(insert_pos,
std::make_move_iterator(prologue_instrs.begin()),
std::make_move_iterator(prologue_instrs.end()));
}
// 确定插入点(在函数名标签之后)
auto insert_pos = entry_instrs.begin();
if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) {
insert_pos++;
}
// 一次性将所有序言指令插入,安全且高效
if (!prologue_instrs.empty()) {
entry_instrs.insert(insert_pos,
std::make_move_iterator(prologue_instrs.begin()),
std::make_move_iterator(prologue_instrs.end()));
}
// --- 2. 插入尾声 ---
for (auto& mbb : mfunc->getBlocks()) {
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
// --- 2. 插入尾声 ---
for (auto& mbb : mfunc->getBlocks()) {
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
// [修复] 创建一个临时 vector 来存放所有尾声指令
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
// 同样严格按照 AsmPrinter 的打印顺序
// 1. ld ra, (aligned_stack_size - 8)(sp)
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
restore_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
epilogue_instrs.push_back(std::move(restore_ra));
// a. ld ra, offset(sp)
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
restore_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
epilogue_instrs.push_back(std::move(restore_ra));
// 2. ld s0, (aligned_stack_size - 16)(sp)
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
restore_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
epilogue_instrs.push_back(std::move(restore_fp));
// b. ld s0, offset(sp)
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
restore_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
epilogue_instrs.push_back(std::move(restore_fp));
// 3. addi sp, sp, aligned_stack_size
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
epilogue_instrs.push_back(std::move(dealloc_stack));
// c. addi sp, sp, aligned_stack_size
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
epilogue_instrs.push_back(std::move(dealloc_stack));
// 在 RET 指令前一次性插入所有尾声指令
if (!epilogue_instrs.empty()) {
mbb->getInstructions().insert(it,
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
if (!epilogue_instrs.empty()) {
mbb->getInstructions().insert(it,
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
}
// 处理完一个基本块中的RET后迭代器已失效需跳出
goto next_block;
}
// 处理完当前基本块的RET后即可跳出内层循环
break;
}
next_block:;
}
}
}

View File

@@ -124,14 +124,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
// 阶段 3.3: 清理产生的大立即数
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 4: 窥孔优化 (Peephole Optimization)
PeepholeOptimizer peephole;
peephole.runOnMachineFunction(mfunc.get());
@@ -140,6 +132,14 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
// 阶段 3.3: 清理产生的大立即数
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());