[backend-llir]修复了许多重构的bug

This commit is contained in:
Lixuanwang
2025-07-19 17:50:14 +08:00
parent d4a6996d74
commit 9528335a04
11 changed files with 513 additions and 497 deletions

View File

@@ -1,11 +1,11 @@
#include "RISCv64RegAlloc.h"
#include "RISCv64ISel.h"
#include <algorithm>
#include <vector>
namespace sysy {
RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
// 初始化可分配的整数寄存器池 (排除特殊用途的)
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
@@ -18,23 +18,113 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
}
void RISCv64RegAlloc::run() {
eliminateFrameIndices();
analyzeLiveness();
buildInterferenceGraph();
colorGraph();
rewriteFunction();
}
void RISCv64RegAlloc::eliminateFrameIndices() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = 0;
Function* F = MFunc->getFunc();
RISCv64ISel* isel = MFunc->getISel();
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
int size = 4;
if (!alloca->getDims().empty()) {
int num_elements = 1;
for (const auto& dim_use : alloca->getDims()) {
if (auto const_dim = dynamic_cast<ConstantValue*>(dim_use->getValue())) {
num_elements *= const_dim->getInt();
}
}
size *= num_elements;
}
current_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca);
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
}
}
}
frame_info.locals_size = current_offset;
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
if (instr_ptr->getOpcode() == RVOpcodes::FRAME_LOAD) {
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();
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));
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(lw));
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_STORE) {
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();
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));
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(src_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(sw));
} else {
new_instructions.push_back(std::move(instr_ptr));
}
}
mbb->getInstructions() = std::move(new_instructions);
}
}
void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def) {
// 这是一个简化的版本实际需要根据RVOpcodes精确定义
// 通常第一个RegOperand是def其余是use
bool is_def = true;
auto opcode = instr->getOpcode();
// 预定义def和use规则
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::RET || opcode == RVOpcodes::J) {
is_def = false;
}
if (opcode == RVOpcodes::CALL) {
// CALL会杀死所有调用者保存寄存器这是一个简化处理
// 同时也使用了传入a0-a7的参数
}
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op.get());
if (reg_op->isVirtual()) {
if (is_def) {
def.insert(reg_op->getVRegNum());
is_def = false; // 假设每条指令最多一个def
is_def = false;
} else {
use.insert(reg_op->getVRegNum());
}
@@ -46,35 +136,16 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
}
}
}
// 特殊处理store和branch指令它们没有显式的def
auto opcode = instr->getOpcode();
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::BNE || opcode == RVOpcodes::BEQ) {
def.clear(); // 清空错误的def
use.clear();
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op.get());
if(reg_op->isVirtual()) use.insert(reg_op->getVRegNum());
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op.get());
if(mem_op->getBase()->isVirtual()) use.insert(mem_op->getBase()->getVRegNum());
}
}
}
}
void RISCv64RegAlloc::analyzeLiveness() {
bool changed = true;
while (changed) {
changed = false;
// 逆序遍历基本块
for (auto it = MFunc->getBlocks().rbegin(); it != MFunc->getBlocks().rend(); ++it) {
auto& mbb = *it;
LiveSet live_out;
for (auto succ : mbb->successors) {
// live_out[B] = Union(live_in[S]) for all S in succ(B)
if (!succ->getInstructions().empty()) {
auto first_instr = succ->getInstructions().front().get();
if (live_in_map.count(first_instr)) {
@@ -83,19 +154,14 @@ void RISCv64RegAlloc::analyzeLiveness() {
}
}
// 逆序遍历指令
for (auto instr_it = mbb->getInstructions().rbegin(); instr_it != mbb->getInstructions().rend(); ++instr_it) {
MachineInstr* instr = instr_it->get();
LiveSet old_live_in = live_in_map[instr];
LiveSet old_live_out = live_out_map[instr];
// 更新 live_out
live_out_map[instr] = live_out;
LiveSet use, def;
getInstrUseDef(instr, use, def);
// live_in[i] = use[i] U (live_out[i] - def[i])
LiveSet live_in = use;
LiveSet diff = live_out;
for (auto vreg : def) {
@@ -104,10 +170,9 @@ void RISCv64RegAlloc::analyzeLiveness() {
live_in.insert(diff.begin(), diff.end());
live_in_map[instr] = live_in;
// 为下一次迭代准备live_out
live_out = live_in;
if (live_in_map[instr] != old_live_in || live_out_map[instr] != old_live_out) {
if (live_in_map[instr] != old_live_in) {
changed = true;
}
}
@@ -117,21 +182,21 @@ void RISCv64RegAlloc::analyzeLiveness() {
void RISCv64RegAlloc::buildInterferenceGraph() {
std::set<unsigned> all_vregs;
// 收集所有虚拟寄存器
for (auto const& [instr, live_set] : live_out_map) {
all_vregs.insert(live_set.begin(), live_set.end());
for (auto& mbb : MFunc->getBlocks()) {
for(auto& instr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr.get(), use, def);
for(auto u : use) all_vregs.insert(u);
for(auto d : def) all_vregs.insert(d);
}
}
// 初始化图
for (auto vreg : all_vregs) {
interference_graph[vreg] = {};
}
for (auto vreg : all_vregs) { interference_graph[vreg] = {}; }
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr : mbb->getInstructions()) {
LiveSet def, use;
getInstrUseDef(instr.get(), use, def);
const LiveSet& live_out = live_out_map.at(instr.get());
for (unsigned d : def) {
@@ -152,21 +217,18 @@ void RISCv64RegAlloc::colorGraph() {
sorted_vregs.push_back(vreg);
}
// 按度数降序排序 (简单贪心策略)
std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) {
return interference_graph[a].size() > interference_graph[b].size();
});
for (unsigned vreg : sorted_vregs) {
std::set<PhysicalReg> used_colors;
// 查找邻居已用的颜色
for (unsigned neighbor : interference_graph.at(vreg)) {
if (color_map.count(neighbor)) {
used_colors.insert(color_map.at(neighbor));
}
}
// 寻找一个可用的颜色
bool colored = false;
for (PhysicalReg preg : allocable_int_regs) {
if (used_colors.find(preg) == used_colors.end()) {
@@ -175,54 +237,47 @@ void RISCv64RegAlloc::colorGraph() {
break;
}
}
if (!colored) {
// 无法分配,需要溢出
spilled_vregs.insert(vreg);
}
}
}
void RISCv64RegAlloc::rewriteFunction() {
// 1. 为所有溢出的vreg分配栈槽
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = frame_info.frame_size; // 假设从现有栈大小后开始分配
int current_offset = frame_info.locals_size;
for (unsigned vreg : spilled_vregs) {
current_offset += 4; // 假设所有溢出变量都占4字节
frame_info.spill_slots[vreg] = -current_offset; // 栈向下增长,所以是负偏移
current_offset += 4;
frame_info.spill_offsets[vreg] = -current_offset;
}
frame_info.frame_size = current_offset;
frame_info.spill_size = current_offset - frame_info.locals_size;
// 2. 遍历所有指令替换vreg并插入spill代码
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr_ptr.get(), use, def);
// 为use的溢出变量插入LOAD
for (unsigned vreg : use) {
if (spilled_vregs.count(vreg)) {
int offset = frame_info.spill_slots.at(vreg);
int offset = frame_info.spill_offsets.at(vreg);
auto load = std::make_unique<MachineInstr>(RVOpcodes::LW);
load->addOperand(std::make_unique<RegOperand>(vreg)); // 临时用vreg号代表稍后替换
load->addOperand(std::make_unique<RegOperand>(vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址用帧指针s0
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
new_instructions.push_back(std::move(load));
}
}
// 添加原始指令
new_instructions.push_back(std::move(instr_ptr));
// 为def的溢出变量插入STORE
for (unsigned vreg : def) {
if (spilled_vregs.count(vreg)) {
int offset = frame_info.spill_slots.at(vreg);
int offset = frame_info.spill_offsets.at(vreg);
auto store = std::make_unique<MachineInstr>(RVOpcodes::SW);
store->addOperand(std::make_unique<RegOperand>(vreg)); // 临时用vreg号代表
store->addOperand(std::make_unique<RegOperand>(vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
@@ -234,7 +289,6 @@ void RISCv64RegAlloc::rewriteFunction() {
mbb->getInstructions() = std::move(new_instructions);
}
// 3. 最后一遍扫描将所有RegOperand从vreg替换为preg
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
@@ -245,8 +299,7 @@ void RISCv64RegAlloc::rewriteFunction() {
if (color_map.count(vreg)) {
reg_op->setPReg(color_map.at(vreg));
} else if (spilled_vregs.count(vreg)) {
// 对于spill的vreg, 使用一个固定的临时寄存器, 比如t6
reg_op->setPReg(PhysicalReg::T6);
reg_op->setPReg(PhysicalReg::T6); // 溢出统一用t6
}
}
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
@@ -254,7 +307,11 @@ void RISCv64RegAlloc::rewriteFunction() {
auto base_reg_op = mem_op->getBase();
if(base_reg_op->isVirtual()){
unsigned vreg = base_reg_op->getVRegNum();
if(color_map.count(vreg)) base_reg_op->setPReg(color_map.at(vreg));
if(color_map.count(vreg)) {
base_reg_op->setPReg(color_map.at(vreg));
} else if (spilled_vregs.count(vreg)) {
base_reg_op->setPReg(PhysicalReg::T6);
}
}
}
}