#include "PostRA_Scheduler.h" #include #include #include #include #define MAX_SCHEDULING_BLOCK_SIZE 10000 // 限制调度块大小,避免过大导致性能问题 namespace sysy { char PostRA_Scheduler::ID = 0; // 检查指令是否是加载指令 (LW, LD) bool isLoadInstr(MachineInstr* instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::LW || opcode == RVOpcodes::LD || opcode == RVOpcodes::LH || opcode == RVOpcodes::LB || opcode == RVOpcodes::LHU || opcode == RVOpcodes::LBU || opcode == RVOpcodes::LWU; } // 检查指令是否是存储指令 (SW, SD) bool isStoreInstr(MachineInstr* instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::SH || opcode == RVOpcodes::SB; } // 检查指令是否为控制流指令 bool isControlFlowInstr(MachineInstr* instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::RET || opcode == RVOpcodes::J || opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE || opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE || opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU || opcode == RVOpcodes::CALL; } // 获取指令定义的寄存器 - 修复版本 std::set getDefinedRegisters(MachineInstr* instr) { std::set defined_regs; RVOpcodes opcode = instr->getOpcode(); // 特殊处理CALL指令 if (opcode == RVOpcodes::CALL) { // CALL指令可能定义返回值寄存器 if (!instr->getOperands().empty() && instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(instr->getOperands().front().get()); if (!reg_op->isVirtual()) { defined_regs.insert(reg_op->getPReg()); } } return defined_regs; } // 存储指令不定义寄存器 if (isStoreInstr(instr)) { return defined_regs; } // 分支指令不定义寄存器 if (opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE || opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE || opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU || opcode == RVOpcodes::J || opcode == RVOpcodes::RET) { return defined_regs; } // 对于其他指令,第一个寄存器操作数通常是定义的 if (!instr->getOperands().empty() && instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(instr->getOperands().front().get()); if (!reg_op->isVirtual()) { defined_regs.insert(reg_op->getPReg()); } } return defined_regs; } // 获取指令使用的寄存器 - 修复版本 std::set getUsedRegisters(MachineInstr* instr) { std::set used_regs; RVOpcodes opcode = instr->getOpcode(); // 特殊处理CALL指令 if (opcode == RVOpcodes::CALL) { bool first_reg_skipped = false; for (const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_REG) { if (!first_reg_skipped) { first_reg_skipped = true; continue; // 跳过返回值寄存器 } auto reg_op = static_cast(op.get()); if (!reg_op->isVirtual()) { used_regs.insert(reg_op->getPReg()); } } } return used_regs; } // 对于存储指令,所有寄存器操作数都是使用的 if (isStoreInstr(instr)) { for (const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(op.get()); if (!reg_op->isVirtual()) { used_regs.insert(reg_op->getPReg()); } } else if (op->getKind() == MachineOperand::KIND_MEM) { auto mem_op = static_cast(op.get()); if (!mem_op->getBase()->isVirtual()) { used_regs.insert(mem_op->getBase()->getPReg()); } } } return used_regs; } // 对于分支指令,所有寄存器操作数都是使用的 if (opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE || opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE || opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU) { for (const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(op.get()); if (!reg_op->isVirtual()) { used_regs.insert(reg_op->getPReg()); } } } return used_regs; } // 对于其他指令,除了第一个寄存器操作数(通常是定义),其余都是使用的 bool first_reg = true; for (const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_REG) { if (first_reg) { first_reg = false; continue; // 跳过第一个寄存器(定义) } auto reg_op = static_cast(op.get()); if (!reg_op->isVirtual()) { used_regs.insert(reg_op->getPReg()); } } else if (op->getKind() == MachineOperand::KIND_MEM) { auto mem_op = static_cast(op.get()); if (!mem_op->getBase()->isVirtual()) { used_regs.insert(mem_op->getBase()->getPReg()); } } } return used_regs; } // 获取内存访问的基址和偏移 struct MemoryAccess { PhysicalReg base_reg; int64_t offset; bool valid; MemoryAccess() : valid(false) {} MemoryAccess(PhysicalReg base, int64_t off) : base_reg(base), offset(off), valid(true) {} }; MemoryAccess getMemoryAccess(MachineInstr* instr) { if (!isLoadInstr(instr) && !isStoreInstr(instr)) { return MemoryAccess(); } // 查找内存操作数 for (const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_MEM) { auto mem_op = static_cast(op.get()); if (!mem_op->getBase()->isVirtual()) { return MemoryAccess(mem_op->getBase()->getPReg(), mem_op->getOffset()->getValue()); } } } return MemoryAccess(); } // 检查内存依赖 - 加强版本 bool hasMemoryDependency(MachineInstr* instr1, MachineInstr* instr2) { // 如果都不是内存指令,没有内存依赖 if (!isLoadInstr(instr1) && !isStoreInstr(instr1) && !isLoadInstr(instr2) && !isStoreInstr(instr2)) { return false; } MemoryAccess mem1 = getMemoryAccess(instr1); MemoryAccess mem2 = getMemoryAccess(instr2); if (!mem1.valid || !mem2.valid) { // 如果无法确定内存访问模式,保守地认为存在依赖 return true; } // 如果访问相同的内存位置 if (mem1.base_reg == mem2.base_reg && mem1.offset == mem2.offset) { // Store->Load: RAW依赖 // Load->Store: WAR依赖 // Store->Store: WAW依赖 return isStoreInstr(instr1) || isStoreInstr(instr2); } // 不同内存位置通常没有依赖,但为了安全起见, // 如果涉及store指令,我们需要更保守 if (isStoreInstr(instr1) && isLoadInstr(instr2)) { // 保守处理:不同store和load之间可能有别名 return false; // 这里可以根据需要调整策略 } return false; } // 检查两个指令之间是否存在依赖关系 - 修复版本 bool hasDependency(MachineInstr* instr1, MachineInstr* instr2) { // 检查RAW依赖:instr1定义的寄存器是否被instr2使用 auto defined_regs1 = getDefinedRegisters(instr1); auto used_regs2 = getUsedRegisters(instr2); for (const auto& reg : defined_regs1) { if (used_regs2.find(reg) != used_regs2.end()) { return true; // RAW依赖 - instr2读取instr1写入的值 } } // 检查WAR依赖:instr1使用的寄存器是否被instr2定义 auto used_regs1 = getUsedRegisters(instr1); auto defined_regs2 = getDefinedRegisters(instr2); for (const auto& reg : used_regs1) { if (defined_regs2.find(reg) != defined_regs2.end()) { return true; // WAR依赖 - instr2覆盖instr1需要的值 } } // 检查WAW依赖:两个指令定义相同寄存器 for (const auto& reg : defined_regs1) { if (defined_regs2.find(reg) != defined_regs2.end()) { return true; // WAW依赖 - 两条指令写入同一寄存器 } } // 检查内存依赖 if (hasMemoryDependency(instr1, instr2)) { return true; } return false; } // 检查是否可以安全地将instr1和instr2交换位置 bool canSwapInstructions(MachineInstr* instr1, MachineInstr* instr2) { // 不能移动控制流指令 if (isControlFlowInstr(instr1) || isControlFlowInstr(instr2)) { return false; } // 检查双向依赖关系 return !hasDependency(instr1, instr2) && !hasDependency(instr2, instr1); } // 新增:验证调度结果的正确性 void validateSchedule(const std::vector& instr_list) { for (int i = 0; i < (int)instr_list.size(); i++) { for (int j = i + 1; j < (int)instr_list.size(); j++) { MachineInstr* earlier = instr_list[i]; MachineInstr* later = instr_list[j]; // 检查是否存在被违反的依赖关系 auto defined_regs = getDefinedRegisters(earlier); auto used_regs = getUsedRegisters(later); // 检查RAW依赖 for (const auto& reg : defined_regs) { if (used_regs.find(reg) != used_regs.end()) { // 这是正常的依赖关系,earlier应该在later之前 continue; } } // 检查内存依赖 if (hasMemoryDependency(earlier, later)) { MemoryAccess mem1 = getMemoryAccess(earlier); MemoryAccess mem2 = getMemoryAccess(later); if (mem1.valid && mem2.valid && mem1.base_reg == mem2.base_reg && mem1.offset == mem2.offset) { if (isStoreInstr(earlier) && isLoadInstr(later)) { // Store->Load依赖,顺序正确 continue; } } } } } } // 在基本块内对指令进行调度优化 - 完全重写版本 void scheduleBlock(MachineBasicBlock* mbb) { auto& instructions = mbb->getInstructions(); if (instructions.size() <= 1) return; if (instructions.size() > MAX_SCHEDULING_BLOCK_SIZE) { return; // 跳过超大块,防止卡住 } std::vector instr_list; for (auto& instr : instructions) { instr_list.push_back(instr.get()); } // 使用更严格的调度策略,避免破坏依赖关系 bool changed = true; int max_iterations = 10; // 限制迭代次数避免死循环 int iteration = 0; while (changed && iteration < max_iterations) { changed = false; iteration++; for (int i = 0; i < (int)instr_list.size() - 1; i++) { MachineInstr* instr1 = instr_list[i]; MachineInstr* instr2 = instr_list[i + 1]; // 只进行非常保守的优化 bool should_swap = false; // 策略1: 将load指令提前,减少load-use延迟 if (isLoadInstr(instr2) && !isLoadInstr(instr1) && !isStoreInstr(instr1)) { should_swap = canSwapInstructions(instr1, instr2); } // 策略2: 将非关键store指令延后,为其他指令让路 else if (isStoreInstr(instr1) && !isLoadInstr(instr2) && !isStoreInstr(instr2)) { should_swap = canSwapInstructions(instr1, instr2); } if (should_swap) { std::swap(instr_list[i], instr_list[i + 1]); changed = true; // 调试输出 // std::cout << "Swapped instructions at positions " << i << " and " << (i+1) << std::endl; } } } // 验证调度结果的正确性 validateSchedule(instr_list); // 将调度后的指令顺序写回 std::map> instr_map; for (auto& instr : instructions) { instr_map[instr.get()] = std::move(instr); } instructions.clear(); for (auto instr : instr_list) { instructions.push_back(std::move(instr_map[instr])); } } bool PostRA_Scheduler::runOnFunction(Function *F, AnalysisManager& AM) { // 这个函数在IR级别运行,但我们需要在机器指令级别运行 // 所以我们返回false,表示没有对IR进行修改 return false; } void PostRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) { // std::cout << "Running Post-RA Local Scheduler... " << std::endl; // 遍历每个机器基本块 for (auto& mbb : mfunc->getBlocks()) { scheduleBlock(mbb.get()); } } } // namespace sysy