[backend]去除了错误的寄存器分配机制
This commit is contained in:
@ -1339,8 +1339,6 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun
|
||||
}
|
||||
}
|
||||
}
|
||||
// 清空临时指令存储
|
||||
temp_instructions_storage.clear();
|
||||
}
|
||||
|
||||
RegAllocResult alloc_result;
|
||||
@ -1379,7 +1377,8 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun
|
||||
alloc_result.stack_map[alloca] = current_stack_offset;
|
||||
current_stack_offset += total_size;
|
||||
}
|
||||
alloc_result.stack_size = current_stack_offset + 16; // 为 ra 和 s0 预留16字节
|
||||
// RV64 修改: 为保存的 ra 和 s0 (各8字节) 预留16字节空间
|
||||
alloc_result.stack_size = current_stack_offset + 16;
|
||||
|
||||
// 活跃性分析
|
||||
std::map<Instruction*, std::set<std::string>> live_sets = liveness_analysis(func);
|
||||
@ -1387,138 +1386,8 @@ RISCv64CodeGen::RegAllocResult RISCv64CodeGen::register_allocation(Function* fun
|
||||
// 构建干扰图
|
||||
std::map<std::string, std::set<std::string>> interference_graph = build_interference_graph(live_sets);
|
||||
|
||||
// 增强生命周期跟踪:记录每个虚拟寄存器的活跃范围
|
||||
std::map<std::string, std::pair<Instruction*, Instruction*>> vreg_lifetimes; // <开始指令, 结束指令>
|
||||
for (const auto& bb_ptr : func->getBasicBlocks()) {
|
||||
for (const auto& inst_ptr : bb_ptr->getInstructions()) {
|
||||
Instruction* inst = inst_ptr.get();
|
||||
if (value_vreg_map.count(inst) && !dynamic_cast<AllocaInst*>(inst)) {
|
||||
std::string vreg = value_vreg_map.at(inst);
|
||||
if (vreg_lifetimes.find(vreg) == vreg_lifetimes.end()) {
|
||||
vreg_lifetimes[vreg].first = inst; // 定义点作为生命周期开始
|
||||
}
|
||||
}
|
||||
for (const auto& operand_use : inst->getOperands()) {
|
||||
Value* operand = operand_use->getValue();
|
||||
if (value_vreg_map.count(operand) && !dynamic_cast<AllocaInst*>(operand)) {
|
||||
std::string vreg = value_vreg_map.at(operand);
|
||||
vreg_lifetimes[vreg].second = inst; // 使用点更新生命周期结束
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 图着色,基于生命周期优化寄存器分配
|
||||
std::map<std::string, PhysicalReg>& vreg_to_preg = alloc_result.vreg_to_preg;
|
||||
vreg_to_preg.clear();
|
||||
|
||||
std::vector<PhysicalReg> 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
|
||||
};
|
||||
std::vector<PhysicalReg> float_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,
|
||||
PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15,
|
||||
PhysicalReg::F16, PhysicalReg::F17, 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
|
||||
};
|
||||
|
||||
auto is_float_vreg = [&](const std::string& vreg) -> bool {
|
||||
for (const auto& pair : value_vreg_map) {
|
||||
if (pair.second == vreg) {
|
||||
if (auto inst = dynamic_cast<Instruction*>(pair.first)) {
|
||||
if (inst->isUnary()) {
|
||||
switch (inst->getKind()) {
|
||||
case Instruction::kFNeg:
|
||||
case Instruction::kFNot:
|
||||
case Instruction::kFtoI:
|
||||
case Instruction::kItoF:
|
||||
case Instruction::kBitFtoI:
|
||||
case Instruction::kBitItoF:
|
||||
return true;
|
||||
default:
|
||||
return inst->getType()->isFloat();
|
||||
}
|
||||
}
|
||||
return inst->getType()->isFloat();
|
||||
} else if (auto constant = dynamic_cast<ConstantValue*>(pair.first)) {
|
||||
return constant->isFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 按活跃范围长度排序虚拟寄存器,优先分配长生命周期的寄存器
|
||||
std::vector<std::pair<std::string, int>> vreg_priorities;
|
||||
for (const auto& vreg_life : vreg_lifetimes) {
|
||||
const std::string& vreg = vreg_life.first;
|
||||
int lifetime_length = std::distance(
|
||||
func->getBasicBlocks().begin(),
|
||||
std::find_if(func->getBasicBlocks().begin(), func->getBasicBlocks().end(),
|
||||
[&](const auto& bb) {
|
||||
return std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
|
||||
[&](const auto& inst) { return inst.get() == vreg_life.second.second; }) != bb->getInstructions().end();
|
||||
})) -
|
||||
std::distance(
|
||||
func->getBasicBlocks().begin(),
|
||||
std::find_if(func->getBasicBlocks().begin(), func->getBasicBlocks().end(),
|
||||
[&](const auto& bb) {
|
||||
return std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
|
||||
[&](const auto& inst) { return inst.get() == vreg_life.second.first; }) != bb->getInstructions().end();
|
||||
}));
|
||||
vreg_priorities.push_back({vreg, lifetime_length});
|
||||
}
|
||||
std::sort(vreg_priorities.begin(), vreg_priorities.end(),
|
||||
[](const auto& a, const auto& b) { return a.second > b.second; });
|
||||
|
||||
// 分配寄存器,考虑生命周期重叠
|
||||
for (const auto& vreg_prio : vreg_priorities) {
|
||||
const std::string& vreg = vreg_prio.first;
|
||||
std::set<PhysicalReg> used_colors;
|
||||
bool is_float = is_float_vreg(vreg);
|
||||
|
||||
// 检查干扰图和生命周期重叠
|
||||
if (interference_graph.count(vreg)) {
|
||||
for (const auto& neighbor_vreg : interference_graph.at(vreg)) {
|
||||
if (vreg_to_preg.count(neighbor_vreg)) {
|
||||
Instruction* neighbor_start = vreg_lifetimes[neighbor_vreg].first;
|
||||
Instruction* neighbor_end = vreg_lifetimes[neighbor_vreg].second;
|
||||
Instruction* current_start = vreg_lifetimes[vreg].first;
|
||||
Instruction* current_end = vreg_lifetimes[vreg].second;
|
||||
|
||||
// 判断生命周期是否重叠
|
||||
if (!(current_end < neighbor_start || current_start > neighbor_end)) {
|
||||
used_colors.insert(vreg_to_preg.at(neighbor_vreg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto& available_regs = is_float ? float_regs : int_regs;
|
||||
bool colored = false;
|
||||
for (PhysicalReg preg : available_regs) {
|
||||
if (used_colors.find(preg) == used_colors.end()) {
|
||||
vreg_to_preg[vreg] = preg;
|
||||
colored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!colored) {
|
||||
std::cerr << "警告: 无法为 " << vreg << " 分配" << (is_float ? "浮点" : "整数") << "寄存器,将溢出到栈。\n";
|
||||
// 溢出处理逻辑待完善
|
||||
}
|
||||
}
|
||||
// 图着色
|
||||
color_graph(alloc_result.vreg_to_preg, interference_graph);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cerr << "=== 寄存器分配结果 (vreg_to_preg) ===\n";
|
||||
|
||||
Reference in New Issue
Block a user