[backend]引入浮点数支持,但目前寄存器分配存在问题

This commit is contained in:
Lixuanwang
2025-07-30 15:07:29 +08:00
parent 860ebcd447
commit dd38bdc133
10 changed files with 748 additions and 199 deletions

View File

@@ -10,9 +10,10 @@
namespace sysy {
RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
// 1. 初始化可分配的整数寄存器池
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, /*PhysicalReg::T5,*/PhysicalReg::T6,
PhysicalReg::T4, /*PhysicalReg::T5,*/ PhysicalReg::T6, // T5是大立即数传送寄存器
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
@@ -20,21 +21,27 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
// 创建一个包含所有通用整数寄存器的临时列表
const std::vector<PhysicalReg> all_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
// 2. 初始化可分配的浮点寄存器池
allocable_fp_regs = {
// 浮点临时寄存器 ft0-ft11
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3,
PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F28, PhysicalReg::F29, PhysicalReg::F30, PhysicalReg::F31,
// 浮点参数/返回值寄存器 fa0-fa7
PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13,
PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17,
// 浮点保存寄存器 fs0-fs11
PhysicalReg::F8, PhysicalReg::F9,
PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21,
PhysicalReg::F22, PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25,
PhysicalReg::F26, PhysicalReg::F27
};
// 映射物理寄存器到特殊的虚拟寄存器ID用于干扰图中的物理寄存器节点
// 确保这些特殊ID不会与vreg_counter生成的常规虚拟寄存器ID冲突
for (PhysicalReg preg : all_int_regs) {
preg_to_vreg_id_map[preg] = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID) + static_cast<unsigned>(preg);
// 3. 映射所有物理寄存器包括整数、浮点和特殊寄存器到特殊的虚拟寄存器ID
// 这是为了让活跃性分析和干扰图构建能够统一处理所有类型的寄存器
for (int i = 0; i < static_cast<int>(PhysicalReg::PHYS_REG_START_ID); ++i) {
auto preg = static_cast<PhysicalReg>(i);
preg_to_vreg_id_map[preg] = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID) + i;
}
}
@@ -82,35 +89,38 @@ void RISCv64RegAlloc::handleCallingConvention() {
RISCv64ISel* isel = MFunc->getISel();
// --- 部分1处理函数传入参数的预着色 ---
// 获取函数的Argument对象列表
if (F) {
auto& args = F->getArguments();
// RISC-V RV64G调用约定前8个整型/指针参数通过 a0-a7 传递
int arg_idx = 0;
// 遍历 Argument* 列表
for (Argument* arg : args) {
if (arg_idx >= 8) {
break;
}
// 获取该 Argument 对象对应的虚拟寄存器ID
// 通过 MachineFunction -> RISCv64ISel -> vreg_map 来获取
const auto& vreg_map_from_isel = MFunc->getISel()->getVRegMap();
assert(vreg_map_from_isel.count(arg) && "Argument not found in ISel's vreg_map!");
// 1. 获取该 Argument 对象对应的虚拟寄存器
unsigned vreg = isel->getVReg(arg);
// 2. 根据参数索引,确定对应的物理寄存器 (a0, a1, ...)
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + arg_idx);
// 3. 在 color_map 中,将 vreg "预着色" 为对应的物理寄存器
color_map[vreg] = preg;
// [修改] 为整数参数和浮点参数分别维护索引
int int_arg_idx = 0;
int float_arg_idx = 0;
arg_idx++;
for (Argument* arg : args) {
// [修改] 根据参数类型决定使用哪个寄存器池和索引
if (arg->getType()->isFloat()) {
// --- 处理浮点参数 ---
if (float_arg_idx >= 8) continue; // fa0-fa7
unsigned vreg = isel->getVReg(arg);
// 浮点参数使用 fa10-fa17 (在RISC-V ABI中对应F10-F17)
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + float_arg_idx);
color_map[vreg] = preg;
float_arg_idx++;
} else {
// --- 处理整数/指针参数 (原有逻辑) ---
if (int_arg_idx >= 8) continue; // a0-a7
unsigned vreg = isel->getVReg(arg);
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx);
color_map[vreg] = preg;
int_arg_idx++;
}
}
}
// // --- 部分2[新逻辑] 遍历所有指令,为CALL指令的返回值预着色为 a0 ---
// // 这是为了强制寄存器分配器知道call的结果物理上出现在a0寄存器。
// --- 部分2为CALL指令的返回值预着色 ---
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr : mbb->getInstructions()) {
if (instr->getOpcode() == RVOpcodes::CALL) {
@@ -121,11 +131,17 @@ void RISCv64RegAlloc::handleCallingConvention() {
auto reg_op = static_cast<RegOperand*>(instr->getOperands().front().get());
if (reg_op->isVirtual()) {
unsigned ret_vreg = reg_op->getVRegNum();
// 强制将这个虚拟寄存器预着色为 a0
color_map[ret_vreg] = PhysicalReg::A0;
if (DEBUG) {
std::cout << "[DEBUG] Pre-coloring vreg" << ret_vreg
<< " to a0 for CALL instruction." << std::endl;
// [修改] 检查返回值的类型,预着色到 a0 或 fa0
assert(MFunc->getISel()->getVRegValueMap().count(ret_vreg) && "Return vreg not found in value map!");
Value* ret_val = MFunc->getISel()->getVRegValueMap().at(ret_vreg);
if (ret_val->getType()->isFloat()) {
// 浮点返回值预着色到 fa0 (F10)
color_map[ret_vreg] = PhysicalReg::F10;
} else {
// 整数/指针返回值预着色到 a0
color_map[ret_vreg] = PhysicalReg::A0;
}
}
}
@@ -218,6 +234,30 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(load_instr));
} else if (opcode == RVOpcodes::FRAME_LOAD_F) {
// 展开浮点加载伪指令
RVOpcodes real_load_op = RVOpcodes::FLW; // 对应的真实指令是 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();
// 展开为: 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));
// 展开为: 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) {
// 确定要生成的真实存储指令是 sw 还是 sd
RVOpcodes real_store_op = (opcode == RVOpcodes::FRAME_STORE_W) ? RVOpcodes::SW : RVOpcodes::SD;
@@ -243,6 +283,30 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(store_instr));
} else if (opcode == RVOpcodes::FRAME_STORE_F) {
// 展开浮点存储伪指令
RVOpcodes real_store_op = RVOpcodes::FSW; // 对应的真实指令是 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();
// 展开为: 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));
// 展开为: 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();
@@ -277,7 +341,7 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
// 1. 特殊指令的 `is_def` 标志调整
// 这些指令的第一个寄存器操作数是源操作数 (use),而不是目标操作数 (def)。
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW ||
opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU ||
@@ -324,6 +388,27 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
}
return; // CALL 指令处理完毕
}
// 2.1 浮点比较指令添加特殊规则
// 它们的源操作数是浮点寄存器,但目标操作数是整数寄存器
if (opcode == RVOpcodes::FEQ_S || opcode == RVOpcodes::FLT_S || opcode == RVOpcodes::FLE_S) {
auto& operands = instr->getOperands();
// Def: 第一个操作数 (整数vreg)
if (operands[0]->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(operands[0].get());
if(reg_op->isVirtual()) def.insert(reg_op->getVRegNum());
}
// Use: 第二、三个操作数 (浮点vreg)
if (operands[1]->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(operands[1].get());
if(reg_op->isVirtual()) use.insert(reg_op->getVRegNum());
}
if (operands[2]->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(operands[2].get());
if(reg_op->isVirtual()) use.insert(reg_op->getVRegNum());
}
return; // 处理完毕
}
// 3. 对其他所有指令的通用处理逻辑 [已重构和修复]
for (const auto& op : instr->getOperands()) {
@@ -351,7 +436,7 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
}
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
// [保持不变] 内存操作数的处理逻辑看起来是正确的
// 内存操作数的处理逻辑看起来是正确的
auto mem_op = static_cast<MemOperand*>(op.get());
auto base_reg = mem_op->getBase();
if (base_reg->isVirtual()) {
@@ -364,7 +449,7 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
}
// 对于存储内存指令 (SW, SD),要存储的值(第一个操作数)也是 `use`
if ((opcode == RVOpcodes::SW || opcode == RVOpcodes::SD) &&
if ((opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW) &&
!instr->getOperands().empty() &&
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto src_reg_op = static_cast<RegOperand*>(instr->getOperands().front().get());
@@ -605,28 +690,53 @@ void RISCv64RegAlloc::buildInterferenceGraph() {
}
// CALL 指令会定义(杀死)所有调用者保存的寄存器。
// 因此,所有调用者保存的物理寄存器都与 CALL 指令的 live_out 中的所有变量冲突。
const std::vector<PhysicalReg>& caller_saved_regs = getCallerSavedIntRegs();
for (PhysicalReg cs_reg : caller_saved_regs) {
if (preg_to_vreg_id_map.count(cs_reg)) {
unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg); // 获取物理寄存器对应的特殊vreg ID
// 辅助函数用于判断一个vreg是整数类型还是浮点类型
auto is_fp_vreg = [&](unsigned vreg) {
if (vreg_to_value_map.count(vreg)) {
return vreg_to_value_map.at(vreg)->getType()->isFloat();
}
// 对于ISel创建的、没有直接IR Value对应的临时vreg
// 默认其为整数类型。这是一个合理的兜底策略。
return false;
};
// --- 处理整数寄存器干扰 ---
const std::vector<PhysicalReg>& caller_saved_int_regs = getCallerSavedIntRegs();
for (PhysicalReg cs_reg : caller_saved_int_regs) {
// 确保物理寄存器在映射表中,我们已在构造函数中保证了这一点
unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg);
// 将这个物理寄存器节点与 CALL 指令的 live_out 中的所有虚拟寄存器添加干扰边。
for (unsigned live_vreg_out : live_out) {
if (cs_vreg_id != live_vreg_out) { // 避免自己和自己干扰
// [新增调试逻辑] 打印添加的干扰边及其原因
for (unsigned live_vreg_out : live_out) {
// 只为整数vreg添加与整数preg的干扰
if (!is_fp_vreg(live_vreg_out)) {
if (cs_vreg_id != live_vreg_out) {
if (DEEPDEBUG && interference_graph[cs_vreg_id].find(live_vreg_out) == interference_graph[cs_vreg_id].end()) {
std::cerr << " Edge (CALL) : preg(" << static_cast<int>(cs_reg) << ") <-> %vreg" << live_vreg_out << "\n";
std::cerr << " Edge (CALL, Int): preg(" << static_cast<int>(cs_reg) << ") <-> %vreg" << live_vreg_out << "\n";
}
interference_graph[cs_vreg_id].insert(live_vreg_out);
interference_graph[live_vreg_out].insert(cs_vreg_id);
}
}
} else {
// 如果物理寄存器没有对应的特殊虚拟寄存器ID可能是因为它不是调用者保存的寄存器。
// 这种情况通常不应该发生,但我们可以在这里添加一个警告或错误处理。
if (DEEPDEBUG) {
std::cerr << "Warning: Physical register " << static_cast<int>(cs_reg)
<< " does not have a corresponding special vreg ID.\n";
}
}
// --- 处理浮点寄存器干扰 ---
const std::vector<PhysicalReg>& caller_saved_fp_regs = getCallerSavedFpRegs();
for (PhysicalReg cs_reg : caller_saved_fp_regs) {
unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg);
for (unsigned live_vreg_out : live_out) {
// 只为浮点vreg添加与浮点preg的干扰
if (is_fp_vreg(live_vreg_out)) {
if (cs_vreg_id != live_vreg_out) {
// 添加与整数版本一致的调试代码
if (DEEPDEBUG && interference_graph[cs_vreg_id].find(live_vreg_out) == interference_graph[cs_vreg_id].end()) {
std::cerr << " Edge (CALL, FP): preg(" << static_cast<int>(cs_reg) << ") <-> %vreg" << live_vreg_out << "\n";
}
interference_graph[cs_vreg_id].insert(live_vreg_out);
interference_graph[live_vreg_out].insert(cs_vreg_id);
}
}
}
}
@@ -650,34 +760,70 @@ void RISCv64RegAlloc::colorGraph() {
return interference_graph[a].size() > interference_graph[b].size();
});
// [调试] 辅助函数用于判断一个vreg是整数还是浮点类型并打印详细诊断信息
auto is_fp_vreg = [&](unsigned vreg) {
if (DEEPDEBUG) {
std::cout << " [Debug is_fp_vreg] Checking vreg" << vreg << ": ";
}
if (vreg_to_value_map.count(vreg)) {
Value* val = vreg_to_value_map.at(vreg);
bool is_float = val->getType()->isFloat();
if (DEEPDEBUG) {
std::cout << "Found in map. Value is '" << val->getName()
<< "', Type is " << (is_float ? "FLOAT" : "INT")
<< ". Returning " << (is_float ? "true" : "false") << ".\n";
}
return is_float;
}
if (DEEPDEBUG) {
std::cout << "NOT found in vreg_to_value_map. Defaulting to INT. Returning false.\n";
}
// 对于ISel创建的、没有直接IR Value对应的临时vreg默认其为整数类型。
return false;
};
// 着色
for (unsigned vreg : sorted_vregs) {
std::set<PhysicalReg> used_colors;
for (unsigned neighbor_id : interference_graph.at(vreg)) {
// --- 关键改进 (来自 rec 分支) ---
// 情况 1: 邻居是一个已经被着色的虚拟寄存器
// ... (收集邻居颜色的逻辑保持不变) ...
if (color_map.count(neighbor_id)) {
used_colors.insert(color_map.at(neighbor_id));
}
// 情况 2: 邻居本身就是一个代表物理寄存器的节点
else if (neighbor_id >= static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID)) {
// 从特殊ID反向解析出是哪个物理寄存器
PhysicalReg neighbor_preg = static_cast<PhysicalReg>(neighbor_id - static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID));
used_colors.insert(neighbor_preg);
}
}
bool is_float = is_fp_vreg(vreg);
const auto& allocable_regs = is_float ? allocable_fp_regs : allocable_int_regs;
// [调试] 打印着色决策过程
if (DEBUG) {
std::cout << "[DEBUG] Coloring %vreg" << vreg
<< ": Type is " << (is_float ? "FLOAT" : "INT")
<< ", choosing from " << (is_float ? "Float" : "Integer") << " pool.\n";
}
bool colored = false;
for (PhysicalReg preg : allocable_int_regs) {
for (PhysicalReg preg : allocable_regs) {
if (used_colors.find(preg) == used_colors.end()) {
color_map[vreg] = preg;
colored = true;
if (DEBUG) {
RISCv64AsmPrinter p(MFunc); // For regToString
std::cout << " -> Assigned to physical register: " << p.regToString(preg) << "\n";
}
break;
}
}
if (!colored) {
spilled_vregs.insert(vreg);
if (DEBUG) {
std::cout << " -> FAILED to color. Spilling.\n";
}
}
}
}
@@ -686,7 +832,7 @@ void RISCv64RegAlloc::rewriteFunction() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = frame_info.locals_size;
// --- FIX 1: 动态计算溢出槽大小 ---
// --- 动态计算溢出槽大小 ---
// 根据溢出虚拟寄存器的真实类型,为其在栈上分配正确大小的空间。
for (unsigned vreg : spilled_vregs) {
// 从反向映射中查找 vreg 对应的 IR Value
@@ -704,23 +850,40 @@ void RISCv64RegAlloc::rewriteFunction() {
}
frame_info.spill_size = current_offset - frame_info.locals_size;
// 定义专用的溢出寄存器
const PhysicalReg INT_SPILL_REG = PhysicalReg::T6; // t6
const PhysicalReg FP_SPILL_REG = PhysicalReg::F7; // ft7
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);
// --- FIX 2: 为溢出的 'use' 操作数插入正确的加载指令 ---
// --- 为溢出的 'use' 操作数插入正确的加载指令 ---
for (unsigned vreg : use) {
if (spilled_vregs.count(vreg)) {
// 同样地,根据 vreg 的类型决定使用 lw 还是 ld
assert(vreg_to_value_map.count(vreg));
Value* val = vreg_to_value_map.at(vreg);
RVOpcodes load_op = val->getType()->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
// 根据vreg类型决定加载指令(lw/ld/flw)和目标物理寄存器(t6/ft7)
RVOpcodes load_op;
PhysicalReg target_preg;
if (val->getType()->isFloat()) {
load_op = RVOpcodes::FLW;
target_preg = FP_SPILL_REG;
} else if (val->getType()->isPointer()) {
load_op = RVOpcodes::LD;
target_preg = INT_SPILL_REG;
} else {
load_op = RVOpcodes::LW;
target_preg = INT_SPILL_REG;
}
int offset = frame_info.spill_offsets.at(vreg);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(vreg));
load->addOperand(std::make_unique<RegOperand>(target_preg)); // 加载到专用溢出寄存器
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
@@ -731,17 +894,29 @@ void RISCv64RegAlloc::rewriteFunction() {
new_instructions.push_back(std::move(instr_ptr));
// --- FIX 3: 为溢出的 'def' 操作数插入正确的存储指令 ---
// --- 为溢出的 'def' 操作数插入正确的存储指令 ---
for (unsigned vreg : def) {
if (spilled_vregs.count(vreg)) {
// 根据 vreg 的类型决定使用 sw 还是 sd
assert(vreg_to_value_map.count(vreg));
Value* val = vreg_to_value_map.at(vreg);
RVOpcodes store_op = val->getType()->isPointer() ? RVOpcodes::SD : RVOpcodes::SW;
// 根据vreg类型决定存储指令(sw/sd/fsw)和源物理寄存器(t6/ft7)
RVOpcodes store_op;
PhysicalReg src_preg;
if (val->getType()->isFloat()) {
store_op = RVOpcodes::FSW;
src_preg = FP_SPILL_REG;
} else if (val->getType()->isPointer()) {
store_op = RVOpcodes::SD;
src_preg = INT_SPILL_REG;
} else {
store_op = RVOpcodes::SW;
src_preg = INT_SPILL_REG;
}
int offset = frame_info.spill_offsets.at(vreg);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(vreg));
store->addOperand(std::make_unique<RegOperand>(src_preg)); // 从专用溢出寄存器存储
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
@@ -757,40 +932,29 @@ void RISCv64RegAlloc::rewriteFunction() {
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
// 情况一:操作数本身就是一个寄存器 (例如 add rd, rs1, rs2 中的所有操作数)
if(op_ptr->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op_ptr.get());
// 定义一个处理寄存器操作数的 lambda 函数
auto process_reg_op = [&](RegOperand* reg_op) {
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (color_map.count(vreg)) {
PhysicalReg preg = color_map.at(vreg);
reg_op->setPReg(preg);
reg_op->setPReg(color_map.at(vreg));
} else if (spilled_vregs.count(vreg)) {
// 如果vreg被溢出,替换为专用溢出物理寄存器t6
reg_op->setPReg(PhysicalReg::T6);
}
}
}
// 情况二:操作数是一个内存地址 (例如 lw rd, offset(rs1) 中的 offset(rs1))
else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
// 获取内存操作数内部的“基址寄存器”
auto base_reg_op = mem_op->getBase();
// 对这个基址寄存器,执行与情况一完全相同的替换逻辑
if(base_reg_op->isVirtual()){
unsigned vreg = base_reg_op->getVRegNum();
if(color_map.count(vreg)) {
// 如果基址vreg被成功着色替换
PhysicalReg preg = color_map.at(vreg);
base_reg_op->setPReg(preg);
} else if (spilled_vregs.count(vreg)) {
// 如果基址vreg被溢出替换为t6
base_reg_op->setPReg(PhysicalReg::T6);
// 根据vreg类型,替换为对应的专用溢出寄存器
assert(vreg_to_value_map.count(vreg));
Value* val = vreg_to_value_map.at(vreg);
if (val->getType()->isFloat()) {
reg_op->setPReg(FP_SPILL_REG);
} else {
reg_op->setPReg(INT_SPILL_REG);
}
}
}
};
if(op_ptr->getKind() == MachineOperand::KIND_REG) {
process_reg_op(static_cast<RegOperand*>(op_ptr.get()));
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
process_reg_op(static_cast<MemOperand*>(op_ptr.get())->getBase());
}
}
}