[backend]正在修复h/39
This commit is contained in:
@ -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();
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user