[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

@ -14,23 +14,34 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
// 此 Pass 负责分析、分配栈空间并插入 callee-saved 寄存器的保存/恢复指令。
// 它通过与 FrameInfo 协作,确保为 callee-saved 寄存器分配的空间与局部变量/溢出槽的空间不冲突。
// 这样做可以使生成的 sd/ld 指令能被后续的优化 Pass (如 PostRA-Scheduler) 处理。
StackFrameInfo& frame_info = mfunc->getFrameInfo();
std::set<PhysicalReg> used_callee_saved;
// [修改] 分别记录被使用的整数和浮点被调用者保存寄存器
std::set<PhysicalReg> used_int_callee_saved;
std::set<PhysicalReg> used_fp_callee_saved;
// 1. 扫描所有指令找出被使用的s寄存器 (s1-s11)
// 1. 扫描所有指令找出被使用的s寄存器 (s1-s11) 和 fs寄存器 (fs0-fs11)
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->isVirtual()) {
PhysicalReg preg = reg_op->getPReg();
// [修改] 区分整数和浮点被调用者保存寄存器
// s0 由序言/尾声处理器专门处理,这里不计入
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) {
used_callee_saved.insert(preg);
used_int_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_fp_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) {
@ -40,83 +51,93 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
}
}
if (used_callee_saved.empty()) {
// 如果没有使用任何需要处理的 callee-saved 寄存器,则直接返回
if (used_int_callee_saved.empty() && used_fp_callee_saved.empty()) {
frame_info.callee_saved_size = 0; // 确保大小被初始化
return; // 无需操作
return;
}
// 2. 计算为 callee-saved 寄存器分配的栈空间
// 这里的关键是,偏移的基准点要在局部变量和溢出槽之下。
int callee_saved_size = used_callee_saved.size() * 8;
frame_info.callee_saved_size = callee_saved_size; // 将大小存入 FrameInfo
// 2. 计算为 callee-saved 寄存器分配的栈空间大小
// 每个寄存器在RV64中都占用8字节
int callee_saved_size = (used_int_callee_saved.size() + used_fp_callee_saved.size()) * 8;
frame_info.callee_saved_size = callee_saved_size;
// 3. 计算无冲突的栈偏移
// 栈向下增长,所以偏移是负数。
// ra/s0 占用 -8 和 -16。局部变量和溢出区在它们之下。callee-saved 区在更下方。
// 我们使用相对于 s0 的偏移。s0 将指向栈顶 (sp + total_size)。
int base_offset = -16 - frame_info.locals_size - frame_info.spill_size;
// 为了栈帧布局确定性,对寄存器进行排序
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
std::sort(sorted_regs.begin(), sorted_regs.end());
// 4. 在函数序言插入保存指令
// 3. 在函数序言中插入保存指令
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
auto prologue_end = entry_instrs.begin();
// 插入点通常在函数入口标签之后
auto insert_pos = entry_instrs.begin();
if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) {
insert_pos = std::next(insert_pos);
}
// 找到序言结束的位置通常是addi s0, sp, size之后但为了让优化器看到我们插在更前面
// 合理的位置是在 IR 指令开始之前,即在任何非序言指令(如第一个标签)之前。
// 为简单起见,我们直接插入到块的开头,后续重排 pass 会处理。
// (更优的实现会寻找一个特定的插入点)
// 为了布局确定性,对寄存器进行排序并按序保存
std::vector<PhysicalReg> sorted_int_regs(used_int_callee_saved.begin(), used_int_callee_saved.end());
std::vector<PhysicalReg> sorted_fp_regs(used_fp_callee_saved.begin(), used_fp_callee_saved.end());
std::sort(sorted_int_regs.begin(), sorted_int_regs.end());
std::sort(sorted_fp_regs.begin(), sorted_fp_regs.end());
int current_offset = -16; // ra和s0已占用-8和-16从-24开始分配
int current_offset = base_offset;
for (PhysicalReg reg : sorted_regs) {
// 插入整数保存指令 (sd)
for (PhysicalReg reg : sorted_int_regs) {
current_offset -= 8;
auto sd = std::make_unique<MachineInstr>(RVOpcodes::SD);
sd->addOperand(std::make_unique<RegOperand>(reg));
sd->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
std::make_unique<ImmOperand>(current_offset)
));
// 从头部插入,但要放在函数标签之后
entry_instrs.insert(entry_instrs.begin() + 1, std::move(sd));
entry_instrs.insert(insert_pos, std::move(sd));
}
// 插入浮点保存指令 (fsd)
for (PhysicalReg reg : sorted_fp_regs) {
current_offset -= 8;
auto fsd = std::make_unique<MachineInstr>(RVOpcodes::FSD); // 使用浮点保存指令
fsd->addOperand(std::make_unique<RegOperand>(reg));
fsd->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(current_offset)
));
entry_instrs.insert(insert_pos, std::move(fsd));
}
// 5. 在函数结尾ret之前插入恢复指令,使用反向遍历来避免迭代器失效
// 4. 在函数结尾ret之前插入恢复指令
for (auto& mbb : mfunc->getBlocks()) {
// 使用手动控制的反向循环
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
// 1. 创建一个临时vector来存储所有需要插入的恢复指令
std::vector<std::unique_ptr<MachineInstr>> restore_instrs;
current_offset = -16; // 重置偏移量用于恢复
int current_offset_load = base_offset;
// 以相同的顺序(例如 s1, s2, ...)创建恢复指令
for (PhysicalReg reg : sorted_regs) {
// 恢复整数寄存器 (ld) - 以与保存时相同的顺序
for (PhysicalReg reg : sorted_int_regs) {
current_offset -= 8;
auto ld = std::make_unique<MachineInstr>(RVOpcodes::LD);
ld->addOperand(std::make_unique<RegOperand>(reg));
ld->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(current_offset_load)
std::make_unique<ImmOperand>(current_offset)
));
restore_instrs.push_back(std::move(ld));
current_offset_load -= 8;
mbb->getInstructions().insert(it, std::move(ld));
}
// 2. 使用 make_move_iterator 一次性将所有恢复指令插入到 RET 指令之前
// 这可以高效地转移指令的所有权,并且只让迭代器失效一次。
if (!restore_instrs.empty()) {
mbb->getInstructions().insert(it,
std::make_move_iterator(restore_instrs.begin()),
std::make_move_iterator(restore_instrs.end())
);
// 恢复浮点寄存器 (fld)
for (PhysicalReg reg : sorted_fp_regs) {
current_offset -= 8;
auto fld = std::make_unique<MachineInstr>(RVOpcodes::FLD); // 使用浮点加载指令
fld->addOperand(std::make_unique<RegOperand>(reg));
fld->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(current_offset)
));
mbb->getInstructions().insert(it, std::move(fld));
}
// 找到了RET并处理完毕后就可以跳出内层循环继续寻找下一个基本块
break;
// 处理完一个基本块的RET后迭代器已失效需跳出当前块的循环
goto next_block_label;
}
}
next_block_label:;
}
}

View File

@ -52,6 +52,8 @@ void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
case RVOpcodes::ADDI:
case RVOpcodes::ADDIW: {
auto& operands = instr_ptr->getOperands();
// 确保操作数足够多,以防万一
if (operands.size() < 3) break;
auto imm_op = static_cast<ImmOperand*>(operands.back().get());
if (!isLegalImmediate(imm_op->getValue())) {
@ -73,7 +75,7 @@ void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
add->addOperand(std::move(rd_op));
add->addOperand(std::move(rs1_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
@ -92,7 +94,8 @@ void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
// 处理所有内存加载/存储指令
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD: {
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
case RVOpcodes::FLW: case RVOpcodes::FSW: {
auto& operands = instr_ptr->getOperands();
auto mem_op = static_cast<MemOperand*>(operands.back().get());
auto offset_op = mem_op->getOffset();

View File

@ -7,9 +7,15 @@ namespace sysy {
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
bool isMemoryOp(RVOpcodes opcode) {
switch (opcode) {
// --- 整数加载/存储 (原有逻辑) ---
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
case RVOpcodes::FLW:
case RVOpcodes::FSW:
// 如果未来支持双精度也在这里添加FLD/FSD
// case RVOpcodes::FLD:
// case RVOpcodes::FSD:
return true;
default:
return false;
@ -73,7 +79,9 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::LHU: *OS << "lhu "; break; case RVOpcodes::LBU: *OS << "lbu "; break;
case RVOpcodes::SW: *OS << "sw "; break; case RVOpcodes::SH: *OS << "sh "; break;
case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break;
case RVOpcodes::SD: *OS << "sd "; break;
case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break;
case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break;
case RVOpcodes::FSD: *OS << "fsd "; break;
case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break;
case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break;
case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break;
@ -82,7 +90,20 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::LI: *OS << "li "; break; case RVOpcodes::LA: *OS << "la "; break;
case RVOpcodes::MV: *OS << "mv "; break; case RVOpcodes::NEG: *OS << "neg "; break;
case RVOpcodes::NEGW: *OS << "negw "; break; case RVOpcodes::SEQZ: *OS << "seqz "; break;
case RVOpcodes::SNEZ: *OS << "snez "; break;
case RVOpcodes::SNEZ: *OS << "snez "; break;
case RVOpcodes::FADD_S: *OS << "fadd.s "; break;
case RVOpcodes::FSUB_S: *OS << "fsub.s "; break;
case RVOpcodes::FMUL_S: *OS << "fmul.s "; break;
case RVOpcodes::FDIV_S: *OS << "fdiv.s "; break;
case RVOpcodes::FNEG_S: *OS << "fneg.s "; break;
case RVOpcodes::FEQ_S: *OS << "feq.s "; break;
case RVOpcodes::FLT_S: *OS << "flt.s "; break;
case RVOpcodes::FLE_S: *OS << "fle.s "; break;
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
case RVOpcodes::CALL: { // [核心修改] 为CALL指令添加特殊处理逻辑
*OS << "call ";
// 遍历所有操作数,只寻找并打印函数名标签
@ -117,6 +138,12 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
// It should have been eliminated by RegAlloc
if (!debug) throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
*OS << "frame_addr "; break;
case RVOpcodes::FRAME_LOAD_F:
if (!debug) throw std::runtime_error("FRAME_LOAD_F not eliminated before AsmPrinter");
*OS << "frame_load_f "; break;
case RVOpcodes::FRAME_STORE_F:
if (!debug) throw std::runtime_error("FRAME_STORE_F not eliminated before AsmPrinter");
*OS << "frame_store_f "; break;
default:
throw std::runtime_error("Unknown opcode in AsmPrinter");
}

View File

@ -16,7 +16,7 @@ std::string RISCv64CodeGen::code_gen() {
std::string RISCv64CodeGen::module_gen() {
std::stringstream ss;
// --- [新逻辑] 步骤1将全局变量分为.data和.bss两组 ---
// --- 步骤1将全局变量分为.data和.bss两组 ---
std::vector<GlobalValue*> data_globals;
std::vector<GlobalValue*> bss_globals;
@ -42,7 +42,7 @@ std::string RISCv64CodeGen::module_gen() {
}
}
// --- [新逻辑] 步骤2生成 .bss 段的代码 ---
// --- 步骤2生成 .bss 段的代码 ---
if (!bss_globals.empty()) {
ss << ".bss\n"; // 切换到 .bss 段
for (GlobalValue* global : bss_globals) {
@ -61,14 +61,13 @@ std::string RISCv64CodeGen::module_gen() {
}
}
// --- [旧逻辑保留] 步骤3生成 .data 段的代码 ---
// --- 步骤3生成 .data 段的代码 ---
if (!data_globals.empty()) {
ss << ".data\n"; // 切换到 .data 段
for (GlobalValue* global : data_globals) {
ss << ".globl " << global->getName() << "\n";
ss << global->getName() << ":\n";
const auto& init_values = global->getInitValues();
// 使用您原有的逻辑来处理显式初始化的值
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
auto val = init_values.getValues()[i];
auto count = init_values.getNumbers()[i];
@ -87,7 +86,7 @@ std::string RISCv64CodeGen::module_gen() {
}
}
// --- 处理函数 (.text段) 的逻辑保持不变 ---
// --- 处理函数 (.text段) ---
if (!module->getFunctions().empty()) {
ss << ".text\n";
for (const auto& func_pair : module->getFunctions()) {
@ -99,7 +98,6 @@ std::string RISCv64CodeGen::module_gen() {
return ss.str();
}
// function_gen 现在是包含具体优化名称的、完整的处理流水线
std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 ===

View File

@ -10,7 +10,23 @@ namespace sysy {
// DAG节点定义 (内部实现)
struct RISCv64ISel::DAGNode {
enum NodeKind {ARGUMENT, CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR, UNARY, MEMSET, GET_ELEMENT_PTR};
enum NodeKind {
ARGUMENT,
CONSTANT, // 整数或地址常量
LOAD,
STORE,
BINARY, // 整数二元运算
CALL,
RETURN,
BRANCH,
ALLOCA_ADDR,
UNARY, // 整数一元运算
MEMSET,
GET_ELEMENT_PTR,
FP_CONSTANT, // 浮点常量
FBINARY, // 浮点二元运算 (如 FADD, FSUB, FCMP)
FUNARY, // 浮点一元运算 (如 FCVT, FNEG)
};
NodeKind kind;
Value* value = nullptr;
std::vector<DAGNode*> operands;
@ -29,7 +45,9 @@ unsigned RISCv64ISel::getVReg(Value* val) {
if (vreg_counter == 0) {
vreg_counter = 1; // vreg 0 保留
}
vreg_map[val] = vreg_counter++;
unsigned new_vreg = vreg_counter++;
vreg_map[val] = new_vreg;
vreg_to_value_map[new_vreg] = val;
}
return vreg_map.at(val);
}
@ -161,18 +179,52 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
break;
case DAGNode::FP_CONSTANT: {
// RISC-V没有直接加载浮点立即数的指令
// 标准做法是1. 将浮点数的32位二进制表示加载到一个整数寄存器
// 2. 使用 fmv.w.x 指令将位模式从整数寄存器移动到浮点寄存器
auto const_val = dynamic_cast<ConstantValue*>(node->value);
auto float_vreg = getVReg(const_val);
auto temp_int_vreg = getNewVReg(); // 临时整数虚拟寄存器
float f_val = const_val->getFloat();
// 使用 reinterpret_cast 获取浮点数的32位二进制表示
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
break;
}
case DAGNode::LOAD: {
auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value;
// --- 修改点 ---
// 1. 获取加载结果的类型 (即这个LOAD指令自身的类型)
Type* loaded_type = node->value->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = loaded_type->isPointer() ? RVOpcodes::FRAME_LOAD_D : RVOpcodes::FRAME_LOAD_W;
RVOpcodes real_opcode = loaded_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (loaded_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_LOAD_D;
real_opcode = RVOpcodes::LD;
} else if (loaded_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_LOAD_F;
real_opcode = RVOpcodes::FLW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_LOAD_W;
real_opcode = RVOpcodes::LW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
@ -220,20 +272,51 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
// 区分整数常量和浮点常量
if (val_const->isInt()) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
} else if (val_const->isFloat()) {
// 先将浮点数的位模式加载到整数vreg再用fmv.w.x移到浮点vreg
auto temp_int_vreg = getNewVReg();
auto float_vreg = getVReg(val_const);
float f_val = val_const->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
}
}
auto val_vreg = getVReg(val_to_store);
// --- 修改点 ---
// 1. 获取被存储的值的类型
Type* stored_type = val_to_store->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = stored_type->isPointer() ? RVOpcodes::FRAME_STORE_D : RVOpcodes::FRAME_STORE_W;
RVOpcodes real_opcode = stored_type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW;
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (stored_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_STORE_D;
real_opcode = RVOpcodes::SD;
} else if (stored_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_STORE_F;
real_opcode = RVOpcodes::FSW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_STORE_W;
real_opcode = RVOpcodes::SW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
@ -497,6 +580,109 @@ void RISCv64ISel::selectNode(DAGNode* node) {
break;
}
case DAGNode::FBINARY: {
auto bin = dynamic_cast<BinaryInst*>(node->value);
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(bin->getLhs());
auto rhs_vreg = getVReg(bin->getRhs());
switch (bin->getKind()) {
case Instruction::kFAdd: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FADD_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFSub: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FSUB_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFMul: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMUL_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FDIV_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 浮点比较指令 ---
// 注意:比较结果(0或1)写入的是一个通用整数寄存器(dest_vreg)
case Instruction::kFCmpEQ: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLT: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLE: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 通过交换操作数或组合指令实现其余比较 ---
case Instruction::kFCmpGT: { // a > b 等价于 b < a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpGE: { // a >= b 等价于 b <= a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpNE: { // a != b 等价于 !(a == b)
// 1. 先用 feq.s 比较,结果存入 dest_vreg
auto feq = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
feq->addOperand(std::make_unique<RegOperand>(dest_vreg));
feq->addOperand(std::make_unique<RegOperand>(lhs_vreg));
feq->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(feq));
// 2. 再用 seqz 对结果取反 (如果相等(1)则变0如果不等(0)则变1)
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(seqz));
break;
}
default:
throw std::runtime_error("Unsupported float binary instruction in ISel");
}
break;
}
case DAGNode::UNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
@ -524,6 +710,54 @@ void RISCv64ISel::selectNode(DAGNode* node) {
break;
}
case DAGNode::FUNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) {
case Instruction::kItoF: { // 整数 to 浮点
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFtoI: { // 浮点 to 整数
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFNeg: { // 浮点取负
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FNEG_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 处理位传送指令 ---
case Instruction::kBitItoF: { // 整数位模式 -> 浮点寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kBitFtoI: { // 浮点位模式 -> 整数寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_X_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
break;
}
default:
throw std::runtime_error("Unsupported float unary instruction in ISel");
}
break;
}
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
// 处理函数参数放入a0-a7物理寄存器
@ -870,7 +1104,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv));
}
// --- Step 2: [最终权威版] 遵循LLVM GEP语义迭代计算地址 ---
// --- Step 2: 遵循LLVM GEP语义迭代计算地址 ---
// 初始被索引的类型,是基指针指向的那个类型 (例如, [2 x i32])
Type* current_type = gep->getBasePointer()->getType()->as<PointerType>()->getBaseType();
@ -971,8 +1205,13 @@ RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(Value* val_ir, std::map<Valu
// 规则1如果这个Value已经有对应的节点直接返回
if (value_to_node.count(val_ir)) {
return value_to_node[val_ir];
} else if (dynamic_cast<ConstantValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (auto const_val = dynamic_cast<ConstantValue*>(val_ir)) {
if (const_val->isInt()) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else {
// 为浮点常量创建新的FP_CONSTANT节点
return create_node(DAGNode::FP_CONSTANT, val_ir, value_to_node, nodes_storage);
}
} else if (dynamic_cast<GlobalValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (dynamic_cast<AllocaInst*>(val_ir)) {
@ -1032,6 +1271,17 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));
} else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
if(value_to_node.count(bin)) continue;
if (bin->getKind() == Instruction::kFSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
// 使用isZero()来判断浮点数0.0,比直接比较更健壮
if (const_lhs->isZero()) {
// 这是一个浮点取负操作,创建 FUNARY 节点
auto funary_node = create_node(DAGNode::FUNARY, bin, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
continue; // 处理完毕,跳到下一条指令
}
}
}
if (bin->getKind() == BinaryInst::kSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (const_lhs->getInt() == 0) {
@ -1041,13 +1291,24 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
}
}
}
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
if (bin->getKind() >= Instruction::kFAdd) { // 假设浮点指令枚举值更大
auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage);
fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
} else {
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
}
} else if (auto un = dynamic_cast<UnaryInst*>(inst)) {
if(value_to_node.count(un)) continue;
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
if (un->getKind() >= Instruction::kFNeg) {
auto funary_node = create_node(DAGNode::FUNARY, un, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
} else {
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
}
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
if(value_to_node.count(call)) continue;
auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage);

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());
}
}
}

View File

@ -18,12 +18,12 @@ public:
void printInstruction(MachineInstr* instr, bool debug = false);
// 辅助函数
void setStream(std::ostream& os) { OS = &os; }
// 辅助函数
std::string regToString(PhysicalReg reg);
private:
// 打印各个部分
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);
// 辅助函数
std::string regToString(PhysicalReg reg);
void printOperand(MachineOperand* op);
MachineFunction* MFunc;

View File

@ -19,6 +19,7 @@ public:
unsigned getNewVReg() { return vreg_counter++; }
// 获取 vreg_map 的公共接口
const std::map<Value*, unsigned>& getVRegMap() const { return vreg_map; }
const std::map<unsigned, Value*>& getVRegValueMap() const { return vreg_to_value_map; }
private:
// DAG节点定义作为ISel的内部实现细节
@ -38,6 +39,7 @@ private:
// 用于计算类型大小的辅助函数
unsigned getTypeSizeInBytes(Type* type);
// 打印DAG图以供调试
void print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name);
// 状态
@ -47,6 +49,7 @@ private:
// 映射关系
std::map<Value*, unsigned> vreg_map;
std::map<unsigned, Value*> vreg_to_value_map;
std::map<const BasicBlock*, MachineBasicBlock*> bb_map;
unsigned vreg_counter;

View File

@ -32,7 +32,6 @@ enum class PhysicalReg {
A0, A1, A2, A3, A4, A5, A6, A7,
// --- 浮点寄存器 ---
// (保持您原有的 F0-F31 命名)
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11,
F12, F13, F14, F15, F16, F17, F18, F19, F20, F21,
F22, F23, F24, F25, F26, F27, F28, F29, F30, F31,
@ -64,16 +63,97 @@ enum class RVOpcodes {
CALL,
// 特殊标记,非指令
LABEL,
// 浮点指令 (RISC-V 'F' 扩展)
// 浮点加载与存储
FLW, // flw rd, offset(rs1)
FSW, // fsw rs2, offset(rs1)
FLD, // fld rd, offset(rs1)
FSD, // fsd rs2, offset(rs1)
// 浮点算术运算 (单精度)
FADD_S, // fadd.s rd, rs1, rs2
FSUB_S, // fsub.s rd, rs1, rs2
FMUL_S, // fmul.s rd, rs1, rs2
FDIV_S, // fdiv.s rd, rs1, rs2
// 浮点比较 (单精度)
FEQ_S, // feq.s rd, rs1, rs2 (结果写入整数寄存器rd)
FLT_S, // flt.s rd, rs1, rs2 (less than)
FLE_S, // fle.s rd, rs1, rs2 (less than or equal)
// 浮点转换
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
// 浮点传送/移动
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)
FMV_W_X, // fmv.w.x rd, rs1 (整数寄存器位模式 -> 浮点寄存器)
FMV_X_W, // fmv.x.w rd, rs1 (浮点寄存器位模式 -> 整数寄存器)
FNEG_S, // fneg.s rd, rs (浮点取负)
// 新增伪指令,用于解耦栈帧处理
FRAME_LOAD_W, // 从栈帧加载 32位 Word (对应 lw)
FRAME_LOAD_D, // 从栈帧加载 64位 Doubleword (对应 ld)
FRAME_STORE_W, // 保存 32位 Word 到栈帧 (对应 sw)
FRAME_STORE_D, // 保存 64位 Doubleword 到栈帧 (对应 sd)
FRAME_LOAD_F, // 从栈帧加载单精度浮点数
FRAME_STORE_F, // 将单精度浮点数存入栈帧
FRAME_ADDR, // 获取栈帧变量的地址
};
// 定义一个全局辅助函数或常量,提供调用者保存寄存器列表
const std::vector<PhysicalReg>& getCallerSavedIntRegs();
inline bool isGPR(PhysicalReg reg) {
return reg >= PhysicalReg::ZERO && reg <= PhysicalReg::T6;
}
// 判断一个物理寄存器是否是浮点寄存器 (FPR)
inline bool isFPR(PhysicalReg reg) {
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
}
// 获取所有调用者保存的整数寄存器 (t0-t6, a0-a7)
inline const std::vector<PhysicalReg>& getCallerSavedIntRegs() {
static const std::vector<PhysicalReg> 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
};
return regs;
}
// 获取所有被调用者保存的整数寄存器 (s0-s11)
inline const std::vector<PhysicalReg>& getCalleeSavedIntRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11
};
return regs;
}
// 获取所有调用者保存的浮点寄存器 (ft0-ft11, fa0-fa7)
inline const std::vector<PhysicalReg>& getCallerSavedFpRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3,
PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F10, PhysicalReg::F11, // ft0-ft11 和 fa0-fa7 在标准ABI中重叠
PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15,
PhysicalReg::F16, PhysicalReg::F17
};
return regs;
}
// 获取所有被调用者保存的浮点寄存器 (fs0-fs11)
inline const std::vector<PhysicalReg>& getCalleeSavedFpRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21,
PhysicalReg::F22, PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25,
PhysicalReg::F26, PhysicalReg::F27, PhysicalReg::F28, PhysicalReg::F29,
PhysicalReg::F30, PhysicalReg::F31
};
return regs;
}
class MachineOperand;
class RegOperand;
@ -224,15 +304,6 @@ private:
StackFrameInfo frame_info;
};
inline const std::vector<PhysicalReg>& getCallerSavedIntRegs() {
static const std::vector<PhysicalReg> 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
};
return regs;
}
} // namespace sysy
#endif // RISCV64_LLIR_H

View File

@ -56,6 +56,7 @@ private:
// 可用的物理寄存器池
std::vector<PhysicalReg> allocable_int_regs;
std::vector<PhysicalReg> allocable_fp_regs;
// 存储vreg到IR Value*的反向映射
// 这个map将在run()函数开始时被填充并在rewriteFunction()中使用。