[backend-IRC]初步构建新的寄存器分配器
This commit is contained in:
@@ -8,6 +8,7 @@ add_library(riscv64_backend_lib STATIC
|
||||
Handler/CalleeSavedHandler.cpp
|
||||
Handler/LegalizeImmediates.cpp
|
||||
Handler/PrologueEpilogueInsertion.cpp
|
||||
Handler/EliminateFrameIndices.cpp
|
||||
Optimize/Peephole.cpp
|
||||
Optimize/PostRA_Scheduler.cpp
|
||||
Optimize/PreRA_Scheduler.cpp
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace sysy {
|
||||
|
||||
char CalleeSavedHandler::ID = 0;
|
||||
|
||||
// 辅助函数,用于判断一个物理寄存器是否为浮点寄存器
|
||||
static bool is_fp_reg(PhysicalReg reg) {
|
||||
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
|
||||
}
|
||||
@@ -20,100 +19,72 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
|
||||
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
|
||||
std::set<PhysicalReg> used_callee_saved;
|
||||
|
||||
// 1. 扫描所有指令,找出被使用的callee-saved寄存器
|
||||
// 这个Pass在RegAlloc之后运行,所以可以访问到物理寄存器
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
for (auto& instr : mbb->getInstructions()) {
|
||||
for (auto& op : instr->getOperands()) {
|
||||
|
||||
auto check_and_insert_reg = [&](RegOperand* reg_op) {
|
||||
if (reg_op && !reg_op->isVirtual()) {
|
||||
PhysicalReg preg = reg_op->getPReg();
|
||||
|
||||
// 检查整数 s1-s11
|
||||
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) {
|
||||
used_callee_saved.insert(preg);
|
||||
}
|
||||
// 检查浮点 fs0-fs11 (f8,f9,f18-f27)
|
||||
else if ((preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) || (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27)) {
|
||||
used_callee_saved.insert(preg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (op->getKind() == MachineOperand::KIND_REG) {
|
||||
check_and_insert_reg(static_cast<RegOperand*>(op.get()));
|
||||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
||||
check_and_insert_reg(static_cast<MemOperand*>(op.get())->getBase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const std::set<PhysicalReg>& used_callee_saved = frame_info.used_callee_saved_regs;
|
||||
|
||||
if (used_callee_saved.empty()) {
|
||||
frame_info.callee_saved_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 计算并更新 frame_info
|
||||
frame_info.callee_saved_size = used_callee_saved.size() * 8;
|
||||
|
||||
// 为了布局确定性和恢复顺序一致,对寄存器排序
|
||||
// 1. 计算大小并排序,以便确定地生成代码
|
||||
frame_info.callee_saved_size = used_callee_saved.size() * 8; // 每个寄存器占8字节
|
||||
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
|
||||
std::sort(sorted_regs.begin(), sorted_regs.end());
|
||||
|
||||
// 3. 在函数序言中插入保存指令
|
||||
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){ return static_cast<int>(a) < static_cast<int>(b); });
|
||||
frame_info.callee_saved_regs_to_store = sorted_regs; // 保存排序后的列表
|
||||
|
||||
// 2. 在函数序言中插入保存指令
|
||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||
auto& entry_instrs = entry_block->getInstructions();
|
||||
// 插入点在函数入口标签之后,或者就是最开始
|
||||
auto insert_pos = entry_instrs.begin();
|
||||
if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) {
|
||||
insert_pos = std::next(insert_pos);
|
||||
}
|
||||
|
||||
// 确保插入在任何栈分配指令之后,但在其他代码之前。
|
||||
// PrologueEpilogueInsertionPass 会处理最终顺序,这里我们先插入。
|
||||
|
||||
std::vector<std::unique_ptr<MachineInstr>> save_instrs;
|
||||
// [关键] 从局部变量区域之后开始分配空间
|
||||
int current_offset = - (16 + frame_info.locals_size);
|
||||
int current_offset = -16; // 栈布局: [ra, s0] 在最顶层,然后是callee-saved
|
||||
|
||||
for (PhysicalReg reg : sorted_regs) {
|
||||
// s0/fp 已经在序言中由 PrologueEpilogueInsertionPass 特殊处理,这里跳过
|
||||
if (reg == PhysicalReg::S0) continue;
|
||||
|
||||
current_offset -= 8;
|
||||
RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
|
||||
|
||||
auto save_instr = std::make_unique<MachineInstr>(save_op);
|
||||
save_instr->addOperand(std::make_unique<RegOperand>(reg));
|
||||
save_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
|
||||
std::make_unique<ImmOperand>(current_offset)
|
||||
std::make_unique<RegOperand>(PhysicalReg::SP), // 基址为 SP
|
||||
std::make_unique<ImmOperand>(0) // 偏移量将在PEI中修正
|
||||
));
|
||||
save_instrs.push_back(std::move(save_instr));
|
||||
}
|
||||
|
||||
if (!save_instrs.empty()) {
|
||||
// 在序言的开头插入保存指令(PEI会后续调整它们的偏移)
|
||||
entry_instrs.insert(insert_pos,
|
||||
std::make_move_iterator(save_instrs.begin()),
|
||||
std::make_move_iterator(save_instrs.end()));
|
||||
}
|
||||
|
||||
// 4. 在函数结尾(ret之前)插入恢复指令
|
||||
// 3. 在函数结尾(ret之前)插入恢复指令
|
||||
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>> restore_instrs;
|
||||
// [关键] 使用与保存时完全相同的逻辑来计算偏移量
|
||||
current_offset = - (16 + frame_info.locals_size);
|
||||
current_offset = -16;
|
||||
|
||||
for (PhysicalReg reg : sorted_regs) {
|
||||
// 以相反的顺序恢复寄存器
|
||||
for (auto reg_it = sorted_regs.rbegin(); reg_it != sorted_regs.rend(); ++reg_it) {
|
||||
PhysicalReg reg = *reg_it;
|
||||
if (reg == PhysicalReg::S0) continue;
|
||||
|
||||
current_offset -= 8;
|
||||
RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
|
||||
|
||||
auto restore_instr = std::make_unique<MachineInstr>(restore_op);
|
||||
restore_instr->addOperand(std::make_unique<RegOperand>(reg));
|
||||
restore_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(current_offset)
|
||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||
std::make_unique<ImmOperand>(0) // 偏移量同样由PEI修正
|
||||
));
|
||||
restore_instrs.push_back(std::move(restore_instr));
|
||||
}
|
||||
@@ -129,5 +100,4 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
next_block_label:;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
157
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
157
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "EliminateFrameIndices.h"
|
||||
#include "RISCv64ISel.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
unsigned EliminateFrameIndicesPass::getTypeSizeInBytes(Type* type) {
|
||||
if (!type) {
|
||||
assert(false && "Cannot get size of a null type.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type->getKind()) {
|
||||
case Type::kInt:
|
||||
case Type::kFloat:
|
||||
return 4;
|
||||
case Type::kPointer:
|
||||
return 8;
|
||||
case Type::kArray: {
|
||||
auto arrayType = type->as<ArrayType>();
|
||||
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
|
||||
}
|
||||
default:
|
||||
assert(false && "Unsupported type for size calculation.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
Function* F = mfunc->getFunc();
|
||||
RISCv64ISel* isel = mfunc->getISel();
|
||||
|
||||
// 1. 为栈传递的参数计算偏移量
|
||||
if (F) {
|
||||
int arg_idx = 0;
|
||||
for (Argument* arg : F->getArguments()) {
|
||||
// 只关心第8个索引及之后的参数 (即第9个参数开始)
|
||||
if (arg_idx >= 8) {
|
||||
// 第一个栈参数(idx=8)在0(s0), 第二个(idx=9)在8(s0)
|
||||
int offset = (arg_idx - 8) * 8;
|
||||
unsigned vreg = isel->getVReg(arg);
|
||||
frame_info.alloca_offsets[vreg] = offset;
|
||||
}
|
||||
arg_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 为局部变量分配空间,起始点在 [ra, s0] (16字节) 之后
|
||||
int local_var_offset = 16;
|
||||
|
||||
// 处理局部变量 (AllocaInst)
|
||||
if(F) { // 确保函数指针有效
|
||||
for (auto& bb : F->getBasicBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
|
||||
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
|
||||
int size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
// RISC-V要求栈地址8字节对齐
|
||||
size = (size + 7) & ~7;
|
||||
if (size == 0) size = 8; // 至少分配8字节
|
||||
|
||||
local_var_offset += size;
|
||||
unsigned alloca_vreg = isel->getVReg(alloca);
|
||||
// 局部变量使用相对于s0的负向偏移
|
||||
frame_info.alloca_offsets[alloca_vreg] = -local_var_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录仅由AllocaInst分配的局部变量的总大小
|
||||
frame_info.locals_size = local_var_offset - 16;
|
||||
|
||||
// 3. 遍历所有机器指令,将伪指令展开为真实指令
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
|
||||
for (auto& instr_ptr : mbb->getInstructions()) {
|
||||
RVOpcodes opcode = instr_ptr->getOpcode();
|
||||
|
||||
if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D || opcode == RVOpcodes::FRAME_LOAD_F) {
|
||||
RVOpcodes real_load_op;
|
||||
if (opcode == RVOpcodes::FRAME_LOAD_W) real_load_op = RVOpcodes::LW;
|
||||
else if (opcode == RVOpcodes::FRAME_LOAD_D) real_load_op = RVOpcodes::LD;
|
||||
else real_load_op = RVOpcodes::FLW;
|
||||
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||
|
||||
// 展开为: addi addr_vreg, s0, offset
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
// 展开为: lw/ld/flw dest_vreg, 0(addr_vreg)
|
||||
auto load_instr = std::make_unique<MachineInstr>(real_load_op);
|
||||
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
load_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(addr_vreg),
|
||||
std::make_unique<ImmOperand>(0)));
|
||||
new_instructions.push_back(std::move(load_instr));
|
||||
|
||||
} else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D || opcode == RVOpcodes::FRAME_STORE_F) {
|
||||
RVOpcodes real_store_op;
|
||||
if (opcode == RVOpcodes::FRAME_STORE_W) real_store_op = RVOpcodes::SW;
|
||||
else if (opcode == RVOpcodes::FRAME_STORE_D) real_store_op = RVOpcodes::SD;
|
||||
else real_store_op = RVOpcodes::FSW;
|
||||
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||
|
||||
// 展开为: addi addr_vreg, s0, offset
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
// 展开为: sw/sd/fsw src_vreg, 0(addr_vreg)
|
||||
auto store_instr = std::make_unique<MachineInstr>(real_store_op);
|
||||
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
store_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(addr_vreg),
|
||||
std::make_unique<ImmOperand>(0)));
|
||||
new_instructions.push_back(std::move(store_instr));
|
||||
|
||||
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) {
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
|
||||
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
} else {
|
||||
new_instructions.push_back(std::move(instr_ptr));
|
||||
}
|
||||
}
|
||||
mbb->getInstructions() = std::move(new_instructions);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "PrologueEpilogueInsertion.h"
|
||||
#include "RISCv64ISel.h"
|
||||
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
||||
#include <algorithm>
|
||||
|
||||
namespace sysy {
|
||||
@@ -8,10 +7,11 @@ namespace sysy {
|
||||
char PrologueEpilogueInsertionPass::ID = 0;
|
||||
|
||||
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
|
||||
// 1. 删除 KEEPALIVE 伪指令
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
auto& instrs = mbb->getInstructions();
|
||||
|
||||
// 使用标准的 Erase-Remove Idiom 来删除满足条件的元素
|
||||
instrs.erase(
|
||||
std::remove_if(instrs.begin(), instrs.end(),
|
||||
[](const std::unique_ptr<MachineInstr>& instr) {
|
||||
@@ -22,39 +22,28 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
);
|
||||
}
|
||||
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
Function* F = mfunc->getFunc();
|
||||
RISCv64ISel* isel = mfunc->getISel();
|
||||
|
||||
// [关键] 获取寄存器分配的结果 (vreg -> preg 的映射)
|
||||
// RegAlloc Pass 必须已经运行过
|
||||
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
|
||||
|
||||
// 完全遵循 AsmPrinter 中的计算逻辑
|
||||
int total_stack_size = frame_info.locals_size +
|
||||
frame_info.spill_size +
|
||||
frame_info.callee_saved_size +
|
||||
16; // 为 ra 和 s0 固定的16字节
|
||||
|
||||
int aligned_stack_size = (total_stack_size + 15) & ~15;
|
||||
// 2. 计算最终的栈帧总大小
|
||||
// 总大小 = [ra, s0] + [被调用者保存寄存器] + [局部变量] + [溢出槽] + [调用其他函数的参数区]
|
||||
// 假设调用参数区大小为0,因为它是在call指令周围动态分配和释放的
|
||||
int total_stack_size = 16 + frame_info.callee_saved_size + frame_info.locals_size + frame_info.spill_size;
|
||||
int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐
|
||||
frame_info.total_size = aligned_stack_size;
|
||||
|
||||
// 只有在需要分配栈空间时才生成指令
|
||||
// 只有在需要分配栈空间时才生成序言/尾声
|
||||
if (aligned_stack_size > 0) {
|
||||
// --- 1. 插入序言 ---
|
||||
// --- 3. 插入序言 ---
|
||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||
auto& entry_instrs = entry_block->getInstructions();
|
||||
|
||||
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
||||
|
||||
// 1. addi sp, sp, -aligned_stack_size
|
||||
// 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)
|
||||
// b. 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>(
|
||||
@@ -63,7 +52,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(save_ra));
|
||||
|
||||
// 3. sd s0, (aligned_stack_size - 16)(sp)
|
||||
// c. 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>(
|
||||
@@ -72,66 +61,25 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(save_fp));
|
||||
|
||||
// 4. addi s0, sp, aligned_stack_size
|
||||
// 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));
|
||||
|
||||
// --- 在s0设置完毕后,使用物理寄存器加载栈参数 ---
|
||||
if (F && isel) {
|
||||
int arg_idx = 0;
|
||||
for (Argument* arg : F->getArguments()) {
|
||||
if (arg_idx >= 8) {
|
||||
unsigned vreg = isel->getVReg(arg);
|
||||
|
||||
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
|
||||
int offset = frame_info.alloca_offsets.at(vreg);
|
||||
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
|
||||
Type* arg_type = arg->getType();
|
||||
// 将序言指令插入到函数入口
|
||||
entry_instrs.insert(entry_instrs.begin(),
|
||||
std::make_move_iterator(prologue_instrs.begin()),
|
||||
std::make_move_iterator(prologue_instrs.end()));
|
||||
|
||||
if (arg_type->isFloat()) {
|
||||
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
|
||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(load_arg));
|
||||
} else {
|
||||
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
|
||||
auto load_arg = std::make_unique<MachineInstr>(load_op);
|
||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(load_arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
arg_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// 确定插入点
|
||||
auto insert_pos = entry_instrs.begin();
|
||||
|
||||
// 一次性将所有序言指令插入
|
||||
if (!prologue_instrs.empty()) {
|
||||
entry_instrs.insert(insert_pos,
|
||||
std::make_move_iterator(prologue_instrs.begin()),
|
||||
std::make_move_iterator(prologue_instrs.end()));
|
||||
}
|
||||
|
||||
// --- 2. 插入尾声 (此部分逻辑保持不变) ---
|
||||
// --- 4. 插入尾声 ---
|
||||
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;
|
||||
|
||||
// 1. ld ra
|
||||
// a. ld ra
|
||||
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>(
|
||||
@@ -140,7 +88,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
epilogue_instrs.push_back(std::move(restore_ra));
|
||||
|
||||
// 2. ld s0
|
||||
// b. ld s0
|
||||
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>(
|
||||
@@ -149,24 +97,39 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
epilogue_instrs.push_back(std::move(restore_fp));
|
||||
|
||||
// 3. addi sp, sp, aligned_stack_size
|
||||
// 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));
|
||||
|
||||
if (!epilogue_instrs.empty()) {
|
||||
mbb->getInstructions().insert(it,
|
||||
std::make_move_iterator(epilogue_instrs.begin()),
|
||||
std::make_move_iterator(epilogue_instrs.end()));
|
||||
}
|
||||
mbb->getInstructions().insert(it,
|
||||
std::make_move_iterator(epilogue_instrs.begin()),
|
||||
std::make_move_iterator(epilogue_instrs.end()));
|
||||
it++; // 跳过刚插入的指令和原有的RET
|
||||
goto next_block;
|
||||
}
|
||||
}
|
||||
next_block:;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 5. [新增] 修正所有基于S0的内存访问偏移量 ---
|
||||
// CalleeSaved, Alloca, Spill 的偏移量都是相对于S0的负向偏移
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
for (auto& instr : mbb->getInstructions()) {
|
||||
if (instr->getOperands().empty() || instr->getOperands().back()->getKind() != MachineOperand::KIND_MEM) {
|
||||
continue;
|
||||
}
|
||||
auto mem_op = static_cast<MemOperand*>(instr->getOperands().back().get());
|
||||
if (mem_op->getBase()->isVirtual() || mem_op->getBase()->getPReg() != PhysicalReg::S0) {
|
||||
continue;
|
||||
}
|
||||
// 此时所有基于S0的偏移量都是负数,无需再次调整
|
||||
// 之前的RegAlloc/CalleeSavedHandler已经计算好了正确的相对于S0的偏移
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -115,13 +115,21 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
// 第一次调试打印输出
|
||||
std::stringstream ss1;
|
||||
RISCv64AsmPrinter printer1(mfunc.get());
|
||||
printer1.run(ss1, true);
|
||||
std::stringstream ss_after_isel;
|
||||
if (DEBUG) {
|
||||
RISCv64AsmPrinter printer_isel(mfunc.get());
|
||||
printer_isel.run(ss_after_isel, true);
|
||||
std::cout << ss_after_isel.str();
|
||||
}
|
||||
|
||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
PreRA_Scheduler scheduler;
|
||||
scheduler.runOnMachineFunction(mfunc.get());
|
||||
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
||||
// 这个Pass必须在寄存器分配之前运行
|
||||
EliminateFrameIndicesPass efi_pass;
|
||||
efi_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// // 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
// PreRA_Scheduler scheduler;
|
||||
// scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
@@ -131,9 +139,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
CalleeSavedHandler callee_handler;
|
||||
callee_handler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 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;
|
||||
@@ -143,7 +151,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
PrologueEpilogueInsertionPass pei_pass;
|
||||
pei_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3.3: 清理产生的大立即数
|
||||
// 阶段 3.3: 大立即数合法化
|
||||
LegalizeImmediatesPass legalizer;
|
||||
legalizer.runOnMachineFunction(mfunc.get());
|
||||
|
||||
@@ -151,7 +159,11 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
|
||||
|
||||
if (DEBUG) {
|
||||
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
|
||||
<< ss_after_isel.str();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user