[backend]正在修复h/39

This commit is contained in:
Lixuanwang
2025-08-17 22:45:57 +08:00
parent d77aedaf8b
commit b57a3f1953
2 changed files with 58 additions and 72 deletions

View File

@ -95,7 +95,7 @@ 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::FLW: case RVOpcodes::FSW: {
case RVOpcodes::FLW: case RVOpcodes::FSW: case RVOpcodes::FLD: case RVOpcodes::FSD: {
auto& operands = instr_ptr->getOperands();
auto mem_op = static_cast<MemOperand*>(operands.back().get());
auto offset_op = mem_op->getOffset();

View File

@ -517,18 +517,15 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
for (auto& instr_ptr : mbb->getInstructions()) {
if (instr_ptr->getOpcode() != RVOpcodes::CALL) {
// --- 对于非CALL的普通指令使用原始的、更高效的溢出逻辑 ---
// 因为它们的操作数很少,几乎不可能耗尽池
// --- 对于非CALL的普通指令此逻辑已是正确的 ---
// (此部分代码与上一版相同,保持不变)
std::vector<PhysicalReg> int_spill_pool = {PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6};
std::vector<PhysicalReg> fp_spill_pool = {PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3};
std::map<unsigned, PhysicalReg> vreg_to_preg_map_for_this_instr;
LiveSet use, def;
getInstrUseDef(instr_ptr.get(), use, def);
LiveSet all_vregs_in_instr = use;
all_vregs_in_instr.insert(def.begin(), def.end());
for(unsigned vreg : all_vregs_in_instr) {
if (spilled_vregs.count(vreg)) {
auto [type, size] = getTypeAndSize(vreg);
@ -543,7 +540,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
}
}
}
for (unsigned vreg : use) {
if (spilled_vregs.count(vreg)) {
PhysicalReg target_preg = vreg_to_preg_map_for_this_instr.at(vreg);
@ -558,13 +554,11 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
new_instructions.push_back(std::move(load));
}
}
auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
for (const auto& op : instr_ptr->getOperands()) {
const RegOperand* reg_op = nullptr;
if (op->getKind() == MachineOperand::KIND_REG) reg_op = static_cast<const RegOperand*>(op.get());
else if (op->getKind() == MachineOperand::KIND_MEM) reg_op = static_cast<const MemOperand*>(op.get())->getBase();
if (reg_op) {
PhysicalReg final_preg;
if (reg_op->isVirtual()) {
@ -591,7 +585,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
}
}
new_instructions.push_back(std::move(new_instr));
for (unsigned vreg : def) {
if (spilled_vregs.count(vreg)) {
PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg);
@ -607,39 +600,32 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
}
}
} else {
// --- 对CALL指令采用序列化溢出处理逻辑 ---
const PhysicalReg INT_TEMP_REG = PhysicalReg::T6; // 选择一个固定的临时寄存器
const PhysicalReg FP_TEMP_REG = PhysicalReg::F0; // 为浮点选择一个
// --- 对CALL指令,使用修正后的、完全区分类型的序列化逻辑 ---
const PhysicalReg INT_TEMP_REG = PhysicalReg::T6;
const PhysicalReg FP_TEMP_REG = PhysicalReg::F7;
auto& operands = instr_ptr->getOperands();
unsigned arg_count = 0;
// CALL指令的操作数布局[def_vreg], label, [use_vreg1, use_vreg2, ...]
// 我们需要从标签之后的操作数开始计数
int int_arg_idx = 0;
int fp_arg_idx = 0;
bool label_found = false;
for(const auto& op : operands) {
for (const auto& op : operands) {
if (op->getKind() == MachineOperand::KIND_LABEL) {
label_found = true;
continue;
}
if (!label_found) continue;
// 确定参数的最终位置ABI规定
int int_arg_idx = 0;
int fp_arg_idx = 0;
auto [type, size] = getTypeAndSize(static_cast<RegOperand*>(op.get())->getVRegNum());
// 这部分逻辑可以做得更精确但为了简化我们假设参数类型顺序与abi寄存器顺序匹配
// 这是一个简化的假设,但在很多情况下成立
if(type == Type::kFloat) {
fp_arg_idx = arg_count; // Simplified logic
} else {
int_arg_idx = arg_count; // Simplified logic
}
unsigned vreg = static_cast<RegOperand*>(op.get())->getVRegNum();
if(spilled_vregs.count(vreg)) {
// 1. 从永久溢出槽加载到临时物理寄存器
RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : RVOpcodes::LD;
auto [type, size] = getTypeAndSize(vreg);
PhysicalReg source_reg;
if (spilled_vregs.count(vreg)) {
PhysicalReg temp_reg = (type == Type::kFloat) ? FP_TEMP_REG : INT_TEMP_REG;
source_reg = temp_reg;
// --- FIX 1: Correctly choose LW/LD/FLW based on type ---
RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : ((type == Type::kPointer) ? RVOpcodes::LD : RVOpcodes::LW);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(temp_reg));
load->addOperand(std::make_unique<MemOperand>(
@ -647,45 +633,47 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(vreg))
));
new_instructions.push_back(std::move(load));
} else {
source_reg = color_map.at(vreg);
}
// 2. 将临时寄存器的值移动到最终的ABI位置
if (type == Type::kFloat) {
if (fp_arg_idx < 8) {
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv->addOperand(std::make_unique<RegOperand>(static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_arg_idx)));
fmv->addOperand(std::make_unique<RegOperand>(source_reg));
new_instructions.push_back(std::move(fmv));
} else {
auto store = std::make_unique<MachineInstr>(RVOpcodes::FSW);
store->addOperand(std::make_unique<RegOperand>(source_reg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>((int_arg_idx - 8) * 8 + (fp_arg_idx - 8) * 4) // Simplified offset
));
new_instructions.push_back(std::move(store));
}
fp_arg_idx++;
} else {
if (int_arg_idx < 8) {
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx)));
mv->addOperand(std::make_unique<RegOperand>(temp_reg));
mv->addOperand(std::make_unique<RegOperand>(source_reg));
new_instructions.push_back(std::move(mv));
} else {
// 对于栈传递的参数需要一个pass来提前分配caller的栈帧空间
// 这里我们假设之前的pass已经处理好了sp的偏移
auto store = std::make_unique<MachineInstr>(RVOpcodes::SD);
store->addOperand(std::make_unique<RegOperand>(temp_reg));
// --- FIX 2: Correctly choose SW/SD based on type ---
RVOpcodes store_op = (type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW;
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(source_reg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>((int_arg_idx - 8) * 8)
));
new_instructions.push_back(std::move(store));
}
} else { // 如果参数未溢出
PhysicalReg colored_reg = color_map.at(vreg);
if(int_arg_idx < 8) {
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx)));
mv->addOperand(std::make_unique<RegOperand>(colored_reg));
new_instructions.push_back(std::move(mv));
} else {
auto store = std::make_unique<MachineInstr>(RVOpcodes::SD);
store->addOperand(std::make_unique<RegOperand>(colored_reg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>((int_arg_idx - 8) * 8)
std::make_unique<ImmOperand>((int_arg_idx - 8) * 8) // Simplified offset
));
new_instructions.push_back(std::move(store));
}
int_arg_idx++;
}
arg_count++;
}
// 插入原始的CALL指令只保留标签
auto new_call = std::make_unique<MachineInstr>(RVOpcodes::CALL);
for(const auto& op : operands) {
if(op->getKind() == MachineOperand::KIND_LABEL) {
@ -695,20 +683,20 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
}
new_instructions.push_back(std::move(new_call));
// 处理返回值
if(operands.front()->getKind() == MachineOperand::KIND_REG) {
unsigned def_vreg = static_cast<RegOperand*>(operands.front().get())->getVRegNum();
auto [type, size] = getTypeAndSize(def_vreg);
PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0;
if(spilled_vregs.count(def_vreg)) {
auto [type, size] = getTypeAndSize(def_vreg);
PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0;
PhysicalReg temp_reg = type == Type::kFloat ? FP_TEMP_REG : INT_TEMP_REG;
RVOpcodes store_op = type == Type::kFloat ? RVOpcodes::FSW : RVOpcodes::SD;
// --- FIX 3: Correctly choose SW/SD based on type for storing return value ---
RVOpcodes store_op = (type == Type::kFloat) ? RVOpcodes::FSW : ((type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW);
// 由于返回值在 a0/fa0, 我们需要用一个临时寄存器来存储它,以防 a0/fa0 马上被复用
auto mv = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(temp_reg));
mv->addOperand(std::make_unique<RegOperand>(result_reg));
new_instructions.push_back(std::move(mv));
auto mv_from_abi = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
mv_from_abi->addOperand(std::make_unique<RegOperand>(temp_reg));
mv_from_abi->addOperand(std::make_unique<RegOperand>(result_reg));
new_instructions.push_back(std::move(mv_from_abi));
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(temp_reg));
@ -718,12 +706,10 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
));
new_instructions.push_back(std::move(store));
} else {
auto [type, size] = getTypeAndSize(def_vreg);
PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0;
auto mv = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(color_map.at(def_vreg)));
mv->addOperand(std::make_unique<RegOperand>(result_reg));
new_instructions.push_back(std::move(mv));
auto mv_to_dest = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
mv_to_dest->addOperand(std::make_unique<RegOperand>(color_map.at(def_vreg)));
mv_to_dest->addOperand(std::make_unique<RegOperand>(result_reg));
new_instructions.push_back(std::move(mv_to_dest));
}
}
}