diff --git a/src/backend/RISCv64/CMakeLists.txt b/src/backend/RISCv64/CMakeLists.txt index 4330e40..c86645e 100644 --- a/src/backend/RISCv64/CMakeLists.txt +++ b/src/backend/RISCv64/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(riscv64_backend_lib STATIC RISCv64ISel.cpp RISCv64LLIR.cpp RISCv64RegAlloc.cpp + RISCv64LinearScan.cpp Handler/CalleeSavedHandler.cpp Handler/LegalizeImmediates.cpp Handler/PrologueEpilogueInsertion.cpp diff --git a/src/backend/RISCv64/RISCv64LinearScan.cpp b/src/backend/RISCv64/RISCv64LinearScan.cpp new file mode 100644 index 0000000..628c512 --- /dev/null +++ b/src/backend/RISCv64/RISCv64LinearScan.cpp @@ -0,0 +1,459 @@ +#include "RISCv64LinearScan.h" +#include "RISCv64LLIR.h" +#include "RISCv64ISel.h" +#include +#include + +extern int DEBUG; + +namespace sysy { + +RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc) + : MFunc(mfunc), + ISel(mfunc->getISel()), + vreg_type_map(ISel->getVRegTypeMap()) { + + // 初始化可用的物理寄存器池,与图着色版本保持一致 + // 整数寄存器 + allocable_int_regs = { + PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, /*T5保留作为大立即数加载寄存器*/ PhysicalReg::T6, + 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, + }; + // 浮点寄存器 + allocable_fp_regs = { + PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7, + PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17, + PhysicalReg::F8, PhysicalReg::F9, 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, + }; + // 新增:识别所有通过寄存器传递的参数,并建立vreg到物理寄存器(preg)的映射 + // 这等同于图着色算法中的“预着色”步骤。 + if (MFunc->getFunc()) { + int int_arg_idx = 0; + int fp_arg_idx = 0; + for (Argument* arg : MFunc->getFunc()->getArguments()) { + unsigned arg_vreg = ISel->getVReg(arg); + if (arg->getType()->isFloat()) { + if (fp_arg_idx < 8) { // fa0-fa7 + auto preg = static_cast(static_cast(PhysicalReg::F10) + fp_arg_idx); + abi_vreg_map[arg_vreg] = preg; + fp_arg_idx++; + } + } else { // 整数或指针 + if (int_arg_idx < 8) { // a0-a7 + auto preg = static_cast(static_cast(PhysicalReg::A0) + int_arg_idx); + abi_vreg_map[arg_vreg] = preg; + int_arg_idx++; + } + } + } + } +} + +void RISCv64LinearScan::run() { + if (DEBUG) std::cerr << "===== Running Linear Scan Register Allocation for function: " << MFunc->getName() << " =====\n"; + + bool changed = true; + while(changed) { + // 1. 准备阶段 + linearizeBlocks(); + computeLiveIntervals(); + + // 2. 执行线性扫描 + changed = linearScan(); + + // 3. 如果有溢出,重写代码,然后下一轮重新开始 + if (changed) { + rewriteProgram(); + if (DEBUG) std::cerr << "--- Spilling detected, re-running linear scan ---\n"; + } + } + + // 4. 将最终分配结果应用到机器指令 + applyAllocation(); + // 5. 收集用到的被调用者保存寄存器 + MFunc->getFrameInfo().vreg_to_preg_map = this->vreg_to_preg_map; + collectUsedCalleeSavedRegs(); + + if (DEBUG) std::cerr << "===== Finished Linear Scan Register Allocation =====\n\n"; +} + +// 步骤 1.1: 对基本块进行线性化,这里我们简单地按现有顺序排列 +void RISCv64LinearScan::linearizeBlocks() { + linear_order_blocks.clear(); + for (auto& mbb : MFunc->getBlocks()) { + linear_order_blocks.push_back(mbb.get()); + } +} + +// 步骤 1.2: 计算活跃区间 +void RISCv64LinearScan::computeLiveIntervals() { + instr_numbering.clear(); + live_intervals.clear(); + unhandled.clear(); + + // a. 对所有指令进行线性编号 + int num = 0; + for (auto* mbb : linear_order_blocks) { + for (auto& instr : mbb->getInstructions()) { + instr_numbering[instr.get()] = num; + num += 2; // 指令编号间隔为2,方便在溢出重写时插入指令 + } + } + + // b. (新逻辑) 遍历所有指令,记录每个vreg首次和末次出现的位置 + std::map> vreg_ranges; // vreg -> {first_instr_num, last_instr_num} + + for (auto* mbb : linear_order_blocks) { + for (auto& instr_ptr : mbb->getInstructions()) { + const MachineInstr* instr = instr_ptr.get(); + int instr_num = instr_numbering.at(instr); + std::set use, def; + getInstrUseDef(instr, use, def); + + // 合并use和def集合,获取本条指令涉及的所有vreg + auto all_vregs = use; + all_vregs.insert(def.begin(), def.end()); + + // 更新每个vreg的区间边界 + for (unsigned vreg : all_vregs) { + if (vreg_ranges.find(vreg) == vreg_ranges.end()) { + // 第一次见到这个vreg,记录首次和末次位置 + vreg_ranges[vreg] = {instr_num, instr_num}; + } else { + // 更新末次位置 + vreg_ranges[vreg].second = std::max(vreg_ranges[vreg].second, instr_num); + } + } + } + } + + // c. 根据记录的边界,创建LiveInterval对象 + for (auto const& [vreg, range] : vreg_ranges) { + live_intervals.emplace(vreg, LiveInterval(vreg)); + live_intervals.at(vreg).start = range.first; + live_intervals.at(vreg).end = range.second; + } + + // d. 将所有计算出的活跃区间放入 unhandled 列表 + for (auto& pair : live_intervals) { + unhandled.push_back(&pair.second); + } + std::sort(unhandled.begin(), unhandled.end(), [](const LiveInterval* a, const LiveInterval* b){ + return a->start < b->start; + }); +} + +// 步骤 2: 线性扫描主算法 +bool RISCv64LinearScan::linearScan() { + // 初始化/重置状态 + active.clear(); + spilled_vregs.clear(); + vreg_to_preg_map.clear(); + free_int_regs.clear(); + free_fp_regs.clear(); + free_int_regs.insert(allocable_int_regs.begin(), allocable_int_regs.end()); + free_fp_regs.insert(allocable_fp_regs.begin(), allocable_fp_regs.end()); + + // 1. 将ABI参数的vreg直接分配给其固定的物理寄存器 + vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end()); + + // 2. 从unhandled列表中移除这些ABI参数区间,并将其加入active列表 + std::vector normal_unhandled; + for(LiveInterval* interval : unhandled) { + if(abi_vreg_map.count(interval->vreg)) { + // 这是一个ABI参数区间,它已经被“预分配” + active.push_back(interval); + // 从空闲池中移除对应的物理寄存器 + PhysicalReg preg = abi_vreg_map.at(interval->vreg); + if (isFPVReg(interval->vreg)) { + free_fp_regs.erase(preg); + } else { + free_int_regs.erase(preg); + } + } else { + // 这是一个普通区间,留待后续处理 + normal_unhandled.push_back(interval); + } + } + unhandled = normal_unhandled; // 更新unhandled列表,只包含普通区间 + + // 3. 对active列表(现在只包含ABI参数)按结束点排序 + std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ + return a->end < b->end; + }); + + for (LiveInterval* current : unhandled) { + // a. 检查并释放 active 列表中已经结束的区间 + std::vector new_active; + for (LiveInterval* active_interval : active) { + if (active_interval->end < current->start) { + // 此区间已结束,释放其物理寄存器 + PhysicalReg preg = vreg_to_preg_map.at(active_interval->vreg); + if (isFPVReg(active_interval->vreg)) free_fp_regs.insert(preg); + else free_int_regs.insert(preg); + } else { + new_active.push_back(active_interval); + } + } + active = new_active; + + // b. 尝试为当前区间分配寄存器 + chooseRegForInterval(current); + } + return !spilled_vregs.empty(); +} + +void RISCv64LinearScan::chooseRegForInterval(LiveInterval* current) { + bool is_fp = isFPVReg(current->vreg); + auto& free_regs = is_fp ? free_fp_regs : free_int_regs; + + if (!free_regs.empty()) { + // 有可用寄存器 + PhysicalReg preg = *free_regs.begin(); + free_regs.erase(free_regs.begin()); + vreg_to_preg_map[current->vreg] = preg; + active.push_back(current); + // 保持 active 列表按结束点排序 + std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ + return a->end < b->end; + }); + } else { + // 没有可用寄存器,需要溢出 + spillAtInterval(current); + } +} + +void RISCv64LinearScan::spillAtInterval(LiveInterval* current) { + // 启发式:比较当前区间和 active 列表中结束点最晚的区间 + LiveInterval* spill_candidate = active.back(); // active已按end排序,最后一个就是结束最晚的 + + if (spill_candidate->end > current->end) { + // active中的区间结束得更晚,溢出它 + PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg); + + // 将被溢出区间的物理寄存器分配给当前区间 + vreg_to_preg_map[current->vreg] = preg; + + // 更新 active 列表 + active.pop_back(); // 移除被溢出的 + active.push_back(current); // 加入当前的 + std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ + return a->end < b->end; + }); + + spilled_vregs.insert(spill_candidate->vreg); + if(DEBUG) std::cerr << " Spilling vreg" << spill_candidate->vreg << " to make room for vreg" << current->vreg << "\n"; + } else { + // 当前区间结束得更晚,直接溢出当前区间 + spilled_vregs.insert(current->vreg); + if(DEBUG) std::cerr << " Spilling current vreg" << current->vreg << "\n"; + } +} + + +// 步骤 3: 重写程序,插入溢出代码 +void RISCv64LinearScan::rewriteProgram() { + StackFrameInfo& frame_info = MFunc->getFrameInfo(); + int spill_offset = frame_info.locals_size; // 溢出区域接在局部变量之后 + + for (unsigned vreg : spilled_vregs) { + if (frame_info.spill_offsets.count(vreg)) continue; // 避免重复分配 + + int size = isFPVReg(vreg) ? 4 : (vreg_type_map.at(vreg)->isPointer() ? 8 : 4); + spill_offset += size; + spill_offset = (spill_offset + 7) & ~7; // 8字节对齐 + frame_info.spill_offsets[vreg] = -(16 + spill_offset); + } + frame_info.spill_size = spill_offset - frame_info.locals_size; + + for (auto& mbb : MFunc->getBlocks()) { + auto& instrs = mbb->getInstructions(); + std::vector> new_instrs; + + for (auto it = instrs.begin(); it != instrs.end(); ++it) { + auto& instr = *it; + std::set use, def; + getInstrUseDef(instr.get(), use, def); + + // 为每个溢出的 use 创建 load + for (unsigned old_vreg : use) { + if (spilled_vregs.count(old_vreg)) { + Type* type = vreg_type_map.at(old_vreg); + unsigned new_temp_vreg = ISel->getNewVReg(type); + + RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW); + auto load = std::make_unique(load_op); + load->addOperand(std::make_unique(new_temp_vreg)); + load->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(old_vreg)) + )); + new_instrs.push_back(std::move(load)); + + // 替换原指令中的 use + for(auto& op : instr->getOperands()) { + if(op->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op.get()); + if(reg_op->isVirtual() && reg_op->getVRegNum() == old_vreg) { + reg_op->setVRegNum(new_temp_vreg); + } + } else if(op->getKind() == MachineOperand::KIND_MEM) { + auto mem_op = static_cast(op.get()); + auto base_reg = mem_op->getBase(); + if(base_reg->isVirtual() && base_reg->getVRegNum() == old_vreg) { + base_reg->setVRegNum(new_temp_vreg); + } + } + } + } + } + + new_instrs.push_back(std::move(instr)); + + // 为每个溢出的 def 创建 store + for (unsigned old_vreg : def) { + if (spilled_vregs.count(old_vreg)) { + Type* type = vreg_type_map.at(old_vreg); + unsigned new_temp_vreg = ISel->getNewVReg(type); + + // 替换原指令中的 def + for(auto& op : new_instrs.back()->getOperands()) { + if(op->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op.get()); + if(reg_op->isVirtual() && reg_op->getVRegNum() == old_vreg) { + reg_op->setVRegNum(new_temp_vreg); + } + } + } + + RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW); + auto store = std::make_unique(store_op); + store->addOperand(std::make_unique(new_temp_vreg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(old_vreg)) + )); + new_instrs.push_back(std::move(store)); + } + } + } + instrs = std::move(new_instrs); + } +} + + +// 步骤 4: 应用最终分配结果 +void RISCv64LinearScan::applyAllocation() { + for (auto& mbb : MFunc->getBlocks()) { + for (auto& instr_ptr : mbb->getInstructions()) { + for (auto& op_ptr : instr_ptr->getOperands()) { + if (op_ptr->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op_ptr.get()); + if (reg_op->isVirtual()) { + unsigned vreg = reg_op->getVRegNum(); + if (vreg_to_preg_map.count(vreg)) { + reg_op->setPReg(vreg_to_preg_map.at(vreg)); + } else { + // 如果一个vreg最终没有颜色,这通常意味着它是一个短生命周期的临时变量 + // 在溢出重写中产生,但在下一轮分配前就被优化掉了。 + // 或者是一个从未被使用的定义。 + // 给他一个临时寄存器以防万一。 + reg_op->setPReg(PhysicalReg::T5); + } + } + } else if (op_ptr->getKind() == MachineOperand::KIND_MEM) { + auto mem_op = static_cast(op_ptr.get()); + auto reg_op = mem_op->getBase(); + if (reg_op->isVirtual()) { + unsigned vreg = reg_op->getVRegNum(); + if (vreg_to_preg_map.count(vreg)) { + reg_op->setPReg(vreg_to_preg_map.at(vreg)); + } else { + reg_op->setPReg(PhysicalReg::T5); + } + } + } + } + } + } +} + +// 辅助函数: 获取指令的use/def集合 (仅虚拟寄存器) +void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set& use, std::set& def) { + // 这个函数与图着色版本中的 getInstrUseDef 逻辑完全相同,此处直接复用 + auto opcode = instr->getOpcode(); + const auto& operands = instr->getOperands(); + + static const std::map, std::vector>> op_info = { + {RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}}, + {RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}}, + {RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}}, + {RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}}, + {RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}}, + {RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}}, + {RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}}, + {RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}}, + {RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}}, + {RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}}, + {RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}}, + {RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}}, + {RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}}, + {RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}}, + {RVOpcodes::RET, {{}, {}}}, {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}}, + {RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}}, + {RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}}, + {RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}}, + {RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}} + }; + + auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set& s) { + if (op->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op); + if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum()); + } else if (op->getKind() == MachineOperand::KIND_MEM) { + auto mem_op = static_cast(op); + auto reg_op = mem_op->getBase(); + if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum()); + } + }; + + if (op_info.count(opcode)) { + const auto& info = op_info.at(opcode); + for (int idx : info.first) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), def); + for (int idx : info.second) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), use); + for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use); + } else if (opcode == RVOpcodes::CALL) { + if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def); + for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[i].get(), use); + } +} + +// 辅助函数: 判断是否为浮点vreg +bool RISCv64LinearScan::isFPVReg(unsigned vreg) const { + return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat(); +} + +// 辅助函数: 收集被使用的被调用者保存寄存器 +void RISCv64LinearScan::collectUsedCalleeSavedRegs() { + StackFrameInfo& frame_info = MFunc->getFrameInfo(); + frame_info.used_callee_saved_regs.clear(); + + const auto& callee_saved_int = getCalleeSavedIntRegs(); + const auto& callee_saved_fp = getCalleeSavedFpRegs(); + std::set callee_saved_set(callee_saved_int.begin(), callee_saved_int.end()); + callee_saved_set.insert(callee_saved_fp.begin(), callee_saved_fp.end()); + callee_saved_set.insert(PhysicalReg::S0); // s0总是被用作帧指针 + + for(const auto& pair : vreg_to_preg_map) { + PhysicalReg preg = pair.second; + if(callee_saved_set.count(preg)) { + frame_info.used_callee_saved_regs.insert(preg); + } + } +} + +} // namespace sysy \ No newline at end of file diff --git a/src/backend/RISCv64/RISCv64RegAlloc.cpp b/src/backend/RISCv64/RISCv64RegAlloc.cpp index 6b2c341..633ecfb 100644 --- a/src/backend/RISCv64/RISCv64RegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64RegAlloc.cpp @@ -55,41 +55,12 @@ void RISCv64RegAlloc::run() { if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n"; - const int MAX_ITERATIONS = 50; - int iteration = 0; - - while (iteration++ < MAX_ITERATIONS) { + while (true) { if (doAllocation()) { break; } else { rewriteProgram(); - if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n"; - - if (iteration >= MAX_ITERATIONS) { - std::cerr << "ERROR: Register allocation failed to converge after " << MAX_ITERATIONS << " iterations\n"; - std::cerr << " Spill worklist size: " << spillWorklist.size() << "\n"; - std::cerr << " Total nodes: " << (initial.size() + coloredNodes.size()) << "\n"; - - // Emergency spill remaining nodes to break the loop - std::cerr << " Emergency spilling remaining spill worklist nodes...\n"; - for (unsigned node : spillWorklist) { - spilledNodes.insert(node); - } - - // Also spill any nodes that didn't get colors - std::set uncolored; - for (unsigned node : initial) { - if (color_map.find(node) == color_map.end()) { - uncolored.insert(node); - } - } - for (unsigned node : uncolored) { - spilledNodes.insert(node); - } - - // Force completion - break; - } + if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation ---\n"; } } diff --git a/src/include/backend/RISCv64/RISCv64LinearScan.h b/src/include/backend/RISCv64/RISCv64LinearScan.h new file mode 100644 index 0000000..23e2d1b --- /dev/null +++ b/src/include/backend/RISCv64/RISCv64LinearScan.h @@ -0,0 +1,81 @@ +#ifndef RISCV64_LINEARSCAN_H +#define RISCV64_LINEARSCAN_H + +#include "RISCv64LLIR.h" +#include "RISCv64ISel.h" +#include +#include +#include +#include + +namespace sysy { + +// 前向声明 +class MachineBasicBlock; +class MachineFunction; +class RISCv64ISel; + +/** + * @brief 表示一个虚拟寄存器的活跃区间。 + * 包含起始和结束指令编号。为了简化,我们不处理有“洞”的区间。 + */ +struct LiveInterval { + unsigned vreg = 0; + int start = -1; + int end = -1; + + LiveInterval(unsigned vreg) : vreg(vreg) {} + + // 用于排序,按起始点从小到大 + bool operator<(const LiveInterval& other) const { + return start < other.start; + } +}; + +class RISCv64LinearScan { +public: + RISCv64LinearScan(MachineFunction* mfunc); + void run(); + +private: + // --- 核心算法流程 --- + void linearizeBlocks(); + void computeLiveIntervals(); + bool linearScan(); + void rewriteProgram(); + void applyAllocation(); + void chooseRegForInterval(LiveInterval* current); + void spillAtInterval(LiveInterval* current); + + // --- 辅助函数 --- + void getInstrUseDef(const MachineInstr* instr, std::set& use, std::set& def); + bool isFPVReg(unsigned vreg) const; + void collectUsedCalleeSavedRegs(); + + MachineFunction* MFunc; + RISCv64ISel* ISel; + + // --- 线性扫描数据结构 --- + std::vector linear_order_blocks; + std::map instr_numbering; + std::map live_intervals; + + std::vector unhandled; + std::vector active; // 活跃且已分配物理寄存器的区间 + + std::set spilled_vregs; // 记录在本轮被决定溢出的vreg + + // --- 寄存器池和分配结果 --- + std::vector allocable_int_regs; + std::vector allocable_fp_regs; + std::set free_int_regs; + std::set free_fp_regs; + std::map vreg_to_preg_map; + std::map abi_vreg_map; + + const std::map& vreg_type_map; +}; + +} // namespace sysy + +#endif // RISCV64_LINEARSCAN_H \ No newline at end of file