[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::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
|
||||||
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
|
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: {
|
case RVOpcodes::FLW: case RVOpcodes::FSW: case RVOpcodes::FLD: case RVOpcodes::FSD: {
|
||||||
auto& operands = instr_ptr->getOperands();
|
auto& operands = instr_ptr->getOperands();
|
||||||
auto mem_op = static_cast<MemOperand*>(operands.back().get());
|
auto mem_op = static_cast<MemOperand*>(operands.back().get());
|
||||||
auto offset_op = mem_op->getOffset();
|
auto offset_op = mem_op->getOffset();
|
||||||
|
|||||||
@@ -517,18 +517,15 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
for (auto& instr_ptr : mbb->getInstructions()) {
|
for (auto& instr_ptr : mbb->getInstructions()) {
|
||||||
|
|
||||||
if (instr_ptr->getOpcode() != RVOpcodes::CALL) {
|
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> 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::vector<PhysicalReg> fp_spill_pool = {PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3};
|
||||||
std::map<unsigned, PhysicalReg> vreg_to_preg_map_for_this_instr;
|
std::map<unsigned, PhysicalReg> vreg_to_preg_map_for_this_instr;
|
||||||
|
|
||||||
LiveSet use, def;
|
LiveSet use, def;
|
||||||
getInstrUseDef(instr_ptr.get(), use, def);
|
getInstrUseDef(instr_ptr.get(), use, def);
|
||||||
|
|
||||||
LiveSet all_vregs_in_instr = use;
|
LiveSet all_vregs_in_instr = use;
|
||||||
all_vregs_in_instr.insert(def.begin(), def.end());
|
all_vregs_in_instr.insert(def.begin(), def.end());
|
||||||
|
|
||||||
for(unsigned vreg : all_vregs_in_instr) {
|
for(unsigned vreg : all_vregs_in_instr) {
|
||||||
if (spilled_vregs.count(vreg)) {
|
if (spilled_vregs.count(vreg)) {
|
||||||
auto [type, size] = getTypeAndSize(vreg);
|
auto [type, size] = getTypeAndSize(vreg);
|
||||||
@@ -543,7 +540,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned vreg : use) {
|
for (unsigned vreg : use) {
|
||||||
if (spilled_vregs.count(vreg)) {
|
if (spilled_vregs.count(vreg)) {
|
||||||
PhysicalReg target_preg = vreg_to_preg_map_for_this_instr.at(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));
|
new_instructions.push_back(std::move(load));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
|
auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
|
||||||
for (const auto& op : instr_ptr->getOperands()) {
|
for (const auto& op : instr_ptr->getOperands()) {
|
||||||
const RegOperand* reg_op = nullptr;
|
const RegOperand* reg_op = nullptr;
|
||||||
if (op->getKind() == MachineOperand::KIND_REG) reg_op = static_cast<const RegOperand*>(op.get());
|
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();
|
else if (op->getKind() == MachineOperand::KIND_MEM) reg_op = static_cast<const MemOperand*>(op.get())->getBase();
|
||||||
|
|
||||||
if (reg_op) {
|
if (reg_op) {
|
||||||
PhysicalReg final_preg;
|
PhysicalReg final_preg;
|
||||||
if (reg_op->isVirtual()) {
|
if (reg_op->isVirtual()) {
|
||||||
@@ -591,7 +585,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_instructions.push_back(std::move(new_instr));
|
new_instructions.push_back(std::move(new_instr));
|
||||||
|
|
||||||
for (unsigned vreg : def) {
|
for (unsigned vreg : def) {
|
||||||
if (spilled_vregs.count(vreg)) {
|
if (spilled_vregs.count(vreg)) {
|
||||||
PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg);
|
PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg);
|
||||||
@@ -607,39 +600,32 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// --- 对CALL指令采用序列化溢出处理逻辑 ---
|
// --- 对于CALL指令,使用修正后的、完全区分类型的序列化逻辑 ---
|
||||||
const PhysicalReg INT_TEMP_REG = PhysicalReg::T6; // 选择一个固定的临时寄存器
|
const PhysicalReg INT_TEMP_REG = PhysicalReg::T6;
|
||||||
const PhysicalReg FP_TEMP_REG = PhysicalReg::F0; // 为浮点选择一个
|
const PhysicalReg FP_TEMP_REG = PhysicalReg::F7;
|
||||||
|
|
||||||
auto& operands = instr_ptr->getOperands();
|
auto& operands = instr_ptr->getOperands();
|
||||||
unsigned arg_count = 0;
|
int int_arg_idx = 0;
|
||||||
// CALL指令的操作数布局:[def_vreg], label, [use_vreg1, use_vreg2, ...]
|
int fp_arg_idx = 0;
|
||||||
// 我们需要从标签之后的操作数开始计数
|
|
||||||
bool label_found = false;
|
bool label_found = false;
|
||||||
for(const auto& op : operands) {
|
|
||||||
|
for (const auto& op : operands) {
|
||||||
if (op->getKind() == MachineOperand::KIND_LABEL) {
|
if (op->getKind() == MachineOperand::KIND_LABEL) {
|
||||||
label_found = true;
|
label_found = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!label_found) 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();
|
unsigned vreg = static_cast<RegOperand*>(op.get())->getVRegNum();
|
||||||
if(spilled_vregs.count(vreg)) {
|
auto [type, size] = getTypeAndSize(vreg);
|
||||||
// 1. 从永久溢出槽加载到临时物理寄存器
|
PhysicalReg source_reg;
|
||||||
RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : RVOpcodes::LD;
|
|
||||||
|
if (spilled_vregs.count(vreg)) {
|
||||||
PhysicalReg temp_reg = (type == Type::kFloat) ? FP_TEMP_REG : INT_TEMP_REG;
|
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);
|
auto load = std::make_unique<MachineInstr>(load_op);
|
||||||
load->addOperand(std::make_unique<RegOperand>(temp_reg));
|
load->addOperand(std::make_unique<RegOperand>(temp_reg));
|
||||||
load->addOperand(std::make_unique<MemOperand>(
|
load->addOperand(std::make_unique<MemOperand>(
|
||||||
@@ -647,45 +633,47 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(vreg))
|
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(vreg))
|
||||||
));
|
));
|
||||||
new_instructions.push_back(std::move(load));
|
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) {
|
if (int_arg_idx < 8) {
|
||||||
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
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>(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));
|
new_instructions.push_back(std::move(mv));
|
||||||
} else {
|
} else {
|
||||||
// 对于栈传递的参数,需要一个pass来提前分配caller的栈帧空间
|
// --- FIX 2: Correctly choose SW/SD based on type ---
|
||||||
// 这里我们假设之前的pass已经处理好了sp的偏移
|
RVOpcodes store_op = (type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW;
|
||||||
auto store = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
auto store = std::make_unique<MachineInstr>(store_op);
|
||||||
store->addOperand(std::make_unique<RegOperand>(temp_reg));
|
store->addOperand(std::make_unique<RegOperand>(source_reg));
|
||||||
store->addOperand(std::make_unique<MemOperand>(
|
store->addOperand(std::make_unique<MemOperand>(
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
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));
|
|
||||||
}
|
|
||||||
} 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)
|
|
||||||
));
|
));
|
||||||
new_instructions.push_back(std::move(store));
|
new_instructions.push_back(std::move(store));
|
||||||
}
|
}
|
||||||
|
int_arg_idx++;
|
||||||
}
|
}
|
||||||
arg_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入原始的CALL指令(只保留标签)
|
|
||||||
auto new_call = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
auto new_call = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
||||||
for(const auto& op : operands) {
|
for(const auto& op : operands) {
|
||||||
if(op->getKind() == MachineOperand::KIND_LABEL) {
|
if(op->getKind() == MachineOperand::KIND_LABEL) {
|
||||||
@@ -695,20 +683,20 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
}
|
}
|
||||||
new_instructions.push_back(std::move(new_call));
|
new_instructions.push_back(std::move(new_call));
|
||||||
|
|
||||||
// 处理返回值
|
|
||||||
if(operands.front()->getKind() == MachineOperand::KIND_REG) {
|
if(operands.front()->getKind() == MachineOperand::KIND_REG) {
|
||||||
unsigned def_vreg = static_cast<RegOperand*>(operands.front().get())->getVRegNum();
|
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)) {
|
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;
|
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_from_abi = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
|
||||||
auto mv = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
|
mv_from_abi->addOperand(std::make_unique<RegOperand>(temp_reg));
|
||||||
mv->addOperand(std::make_unique<RegOperand>(temp_reg));
|
mv_from_abi->addOperand(std::make_unique<RegOperand>(result_reg));
|
||||||
mv->addOperand(std::make_unique<RegOperand>(result_reg));
|
new_instructions.push_back(std::move(mv_from_abi));
|
||||||
new_instructions.push_back(std::move(mv));
|
|
||||||
|
|
||||||
auto store = std::make_unique<MachineInstr>(store_op);
|
auto store = std::make_unique<MachineInstr>(store_op);
|
||||||
store->addOperand(std::make_unique<RegOperand>(temp_reg));
|
store->addOperand(std::make_unique<RegOperand>(temp_reg));
|
||||||
@@ -718,12 +706,10 @@ void RISCv64SimpleRegAlloc::rewriteFunction() {
|
|||||||
));
|
));
|
||||||
new_instructions.push_back(std::move(store));
|
new_instructions.push_back(std::move(store));
|
||||||
} else {
|
} else {
|
||||||
auto [type, size] = getTypeAndSize(def_vreg);
|
auto mv_to_dest = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
|
||||||
PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0;
|
mv_to_dest->addOperand(std::make_unique<RegOperand>(color_map.at(def_vreg)));
|
||||||
auto mv = std::make_unique<MachineInstr>(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV);
|
mv_to_dest->addOperand(std::make_unique<RegOperand>(result_reg));
|
||||||
mv->addOperand(std::make_unique<RegOperand>(color_map.at(def_vreg)));
|
new_instructions.push_back(std::move(mv_to_dest));
|
||||||
mv->addOperand(std::make_unique<RegOperand>(result_reg));
|
|
||||||
new_instructions.push_back(std::move(mv));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user