[backend]修复了简单图着色分配器在一些样例中的问题
This commit is contained in:
@ -17,7 +17,7 @@ RISCv64SimpleRegAlloc::RISCv64SimpleRegAlloc(MachineFunction* mfunc) : MFunc(mfu
|
||||
// T5 被大立即数传送逻辑保留
|
||||
// T2, T3, T4 被本分配器保留为专用的溢出/临时寄存器
|
||||
allocable_int_regs = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, /* T2,T3,T4,T5 reserved */ PhysicalReg::T6,
|
||||
PhysicalReg::T0, PhysicalReg::T1, /* T2,T3,T4,T5,T6 reserved */
|
||||
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
|
||||
PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
|
||||
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
|
||||
@ -221,27 +221,6 @@ void RISCv64SimpleRegAlloc::handleCallingConvention() {
|
||||
int_arg_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 2. 为CALL指令的返回值预着色 ---
|
||||
for (auto& mbb : MFunc->getBlocks()) {
|
||||
for (auto& instr : mbb->getInstructions()) {
|
||||
if (instr->getOpcode() == RVOpcodes::CALL && !instr->getOperands().empty()) {
|
||||
auto& first_op = instr->getOperands().front();
|
||||
if (first_op->getKind() == MachineOperand::KIND_REG) {
|
||||
auto reg_op = static_cast<RegOperand*>(first_op.get());
|
||||
if (reg_op->isVirtual()) {
|
||||
unsigned ret_vreg = reg_op->getVRegNum();
|
||||
auto [type, size] = getTypeAndSize(ret_vreg);
|
||||
if (type == Type::kFloat) {
|
||||
color_map[ret_vreg] = PhysicalReg::F10; // fa0
|
||||
} else {
|
||||
color_map[ret_vreg] = PhysicalReg::A0; // a0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RISCv64SimpleRegAlloc::analyzeLiveness() {
|
||||
@ -511,15 +490,13 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
||||
}
|
||||
frame_info.spill_size = -(current_offset - frame_info.locals_end_offset);
|
||||
|
||||
// 步骤 2: 遍历所有指令,对CALL指令和普通指令进行分别处理
|
||||
// 步骤 2: 遍历所有指令,对CALL指令做简化处理
|
||||
for (auto& mbb : MFunc->getBlocks()) {
|
||||
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
|
||||
for (auto& instr_ptr : mbb->getInstructions()) {
|
||||
|
||||
if (instr_ptr->getOpcode() != RVOpcodes::CALL) {
|
||||
// --- 对于非CALL的普通指令,此逻辑已是正确的 ---
|
||||
// (此部分代码与上一版相同,保持不变)
|
||||
std::vector<PhysicalReg> int_spill_pool = {PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6};
|
||||
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;
|
||||
@ -600,102 +577,36 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// --- 对于CALL指令,使用修正后的、完全区分类型的序列化逻辑 ---
|
||||
// --- 对于CALL指令,只处理其自身和返回值,不再处理参数 ---
|
||||
const PhysicalReg INT_TEMP_REG = PhysicalReg::T6;
|
||||
const PhysicalReg FP_TEMP_REG = PhysicalReg::F7;
|
||||
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
int int_arg_idx = 0;
|
||||
int fp_arg_idx = 0;
|
||||
bool label_found = false;
|
||||
|
||||
for (const auto& op : operands) {
|
||||
if (op->getKind() == MachineOperand::KIND_LABEL) {
|
||||
label_found = true;
|
||||
continue;
|
||||
}
|
||||
if (!label_found) continue;
|
||||
|
||||
unsigned vreg = static_cast<RegOperand*>(op.get())->getVRegNum();
|
||||
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>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(vreg))
|
||||
));
|
||||
new_instructions.push_back(std::move(load));
|
||||
} else {
|
||||
source_reg = color_map.at(vreg);
|
||||
}
|
||||
|
||||
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>(source_reg));
|
||||
new_instructions.push_back(std::move(mv));
|
||||
} else {
|
||||
// --- 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) // Simplified offset
|
||||
));
|
||||
new_instructions.push_back(std::move(store));
|
||||
}
|
||||
int_arg_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 克隆CALL指令本身,只保留标签操作数
|
||||
auto new_call = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
||||
for(const auto& op : operands) {
|
||||
if(op->getKind() == MachineOperand::KIND_LABEL) {
|
||||
for (const auto& op : instr_ptr->getOperands()) {
|
||||
if (op->getKind() == MachineOperand::KIND_LABEL) {
|
||||
new_call->addOperand(std::make_unique<LabelOperand>(*static_cast<const LabelOperand*>(op.get())));
|
||||
break;
|
||||
// 注意:只添加第一个标签,防止ISel的错误导致多个标签
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_instructions.push_back(std::move(new_call));
|
||||
|
||||
if(operands.front()->getKind() == MachineOperand::KIND_REG) {
|
||||
// 2. 只处理返回值(def)的溢出和移动
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
if (!operands.empty() && 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;
|
||||
PhysicalReg result_reg_abi = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0;
|
||||
|
||||
if(spilled_vregs.count(def_vreg)) {
|
||||
if (spilled_vregs.count(def_vreg)) {
|
||||
// 返回值被溢出:a0/fa0 -> temp -> 溢出槽
|
||||
PhysicalReg temp_reg = type == Type::kFloat ? FP_TEMP_REG : INT_TEMP_REG;
|
||||
// --- 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);
|
||||
|
||||
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));
|
||||
mv_from_abi->addOperand(std::make_unique<RegOperand>(result_reg_abi));
|
||||
new_instructions.push_back(std::move(mv_from_abi));
|
||||
|
||||
auto store = std::make_unique<MachineInstr>(store_op);
|
||||
@ -706,9 +617,10 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
||||
));
|
||||
new_instructions.push_back(std::move(store));
|
||||
} else {
|
||||
// 返回值未溢出:a0/fa0 -> 已着色的物理寄存器
|
||||
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));
|
||||
mv_to_dest->addOperand(std::make_unique<RegOperand>(result_reg_abi));
|
||||
new_instructions.push_back(std::move(mv_to_dest));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user