#include "PreRA_Scheduler.h" #include "RISCv64LLIR.h" #include #include #include #include #define MAX_SCHEDULING_BLOCK_SIZE 1000 // 严格限制调度块大小 namespace sysy { char PreRA_Scheduler::ID = 0; // 检查指令是否是加载指令 (LW, LD) static 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) static bool isStoreInstr(MachineInstr *instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::SH || opcode == RVOpcodes::SB; } // 检查指令是否为分支指令 static bool isBranchInstr(MachineInstr *instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE || opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE || opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU; } // 检查指令是否为跳转指令 static bool isJumpInstr(MachineInstr *instr) { RVOpcodes opcode = instr->getOpcode(); return opcode == RVOpcodes::J; } // 检查指令是否为返回指令 static bool isReturnInstr(MachineInstr *instr) { return instr->getOpcode() == RVOpcodes::RET; } // 检查指令是否为调用指令 static bool isCallInstr(MachineInstr *instr) { return instr->getOpcode() == RVOpcodes::CALL; } // 检查指令是否为块终结指令(必须保持在块尾) static bool isTerminatorInstr(MachineInstr *instr) { return isBranchInstr(instr) || isJumpInstr(instr) || isReturnInstr(instr); } // 检查指令是否有副作用(需要谨慎处理) static bool hasSideEffect(MachineInstr *instr) { return isStoreInstr(instr) || isCallInstr(instr) || isTerminatorInstr(instr); } // 检查指令是否涉及内存操作 static bool hasMemoryAccess(MachineInstr *instr) { return isLoadInstr(instr) || isStoreInstr(instr); } // 获取内存访问位置信息 struct MemoryLocation { unsigned base_reg; int64_t offset; bool is_valid; MemoryLocation() : base_reg(0), offset(0), is_valid(false) {} MemoryLocation(unsigned base, int64_t off) : base_reg(base), offset(off), is_valid(true) {} bool operator==(const MemoryLocation &other) const { return is_valid && other.is_valid && base_reg == other.base_reg && offset == other.offset; } }; // 缓存指令分析信息 struct InstrInfo { std::unordered_set defined_regs; std::unordered_set used_regs; MemoryLocation mem_location; bool is_load; bool is_store; bool is_terminator; bool is_call; bool has_side_effect; bool has_memory_access; InstrInfo() : is_load(false), is_store(false), is_terminator(false), is_call(false), has_side_effect(false), has_memory_access(false) {} }; // 指令信息缓存 static std::unordered_map instr_info_cache; // 获取指令定义的虚拟寄存器 - 优化版本 static std::unordered_set getDefinedVirtualRegisters(MachineInstr *instr) { std::unordered_set defined_regs; RVOpcodes opcode = instr->getOpcode(); // CALL指令可能定义返回值寄存器 if (opcode == RVOpcodes::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->getVRegNum()); } } return defined_regs; } // 存储指令和终结指令不定义寄存器 if (isStoreInstr(instr) || isTerminatorInstr(instr)) { 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->getVRegNum()); } } return defined_regs; } // 获取指令使用的虚拟寄存器 - 优化版本 static std::unordered_set getUsedVirtualRegisters(MachineInstr *instr) { std::unordered_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->getVRegNum()); } } } return used_regs; } // 存储指令和终结指令:所有操作数都是使用的 if (isStoreInstr(instr) || isTerminatorInstr(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->getVRegNum()); } } 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()->getVRegNum()); } } } 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->getVRegNum()); } } 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()->getVRegNum()); } } } return used_regs; } // 获取内存访问位置 static MemoryLocation getMemoryLocation(MachineInstr *instr) { if (!isLoadInstr(instr) && !isStoreInstr(instr)) { return MemoryLocation(); } 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 MemoryLocation(mem_op->getBase()->getVRegNum(), mem_op->getOffset()->getValue()); } } } return MemoryLocation(); } // 预计算并缓存指令信息 static const InstrInfo& getInstrInfo(MachineInstr *instr) { auto it = instr_info_cache.find(instr); if (it != instr_info_cache.end()) { return it->second; } InstrInfo& info = instr_info_cache[instr]; info.defined_regs = getDefinedVirtualRegisters(instr); info.used_regs = getUsedVirtualRegisters(instr); info.mem_location = getMemoryLocation(instr); info.is_load = isLoadInstr(instr); info.is_store = isStoreInstr(instr); info.is_terminator = isTerminatorInstr(instr); info.is_call = isCallInstr(instr); info.has_side_effect = hasSideEffect(instr); info.has_memory_access = hasMemoryAccess(instr); return info; } // 检查两个内存位置是否可能别名 static bool mayAlias(const MemoryLocation &loc1, const MemoryLocation &loc2) { if (!loc1.is_valid || !loc2.is_valid) { return true; // 保守处理:未知位置可能别名 } // 不同基址寄存器,保守假设可能别名 if (loc1.base_reg != loc2.base_reg) { return true; } // 相同基址寄存器,检查偏移 return loc1.offset == loc2.offset; } // 检查两个指令之间是否存在数据依赖 - 优化版本 static bool hasDataDependency(MachineInstr *first, MachineInstr *second) { const InstrInfo& info_first = getInstrInfo(first); const InstrInfo& info_second = getInstrInfo(second); // RAW依赖: second读取first写入的寄存器 for (const auto ® : info_first.defined_regs) { if (info_second.used_regs.find(reg) != info_second.used_regs.end()) { return true; } } // WAR依赖: second写入first读取的寄存器 for (const auto ® : info_first.used_regs) { if (info_second.defined_regs.find(reg) != info_second.defined_regs.end()) { return true; } } // WAW依赖: 两个指令写入同一寄存器 for (const auto ® : info_first.defined_regs) { if (info_second.defined_regs.find(reg) != info_second.defined_regs.end()) { return true; } } return false; } // 检查两个指令之间是否存在内存依赖 - 优化版本 static bool hasMemoryDependency(MachineInstr *first, MachineInstr *second) { const InstrInfo& info_first = getInstrInfo(first); const InstrInfo& info_second = getInstrInfo(second); if (!info_first.has_memory_access || !info_second.has_memory_access) { return false; } // 如果至少有一个是存储指令,需要检查别名 if (info_first.is_store || info_second.is_store) { return mayAlias(info_first.mem_location, info_second.mem_location); } return false; // 两个加载指令之间没有依赖 } // 检查两个指令之间是否存在控制依赖 - 优化版本 static bool hasControlDependency(MachineInstr *first, MachineInstr *second) { const InstrInfo& info_first = getInstrInfo(first); const InstrInfo& info_second = getInstrInfo(second); // 终结指令与任何其他指令都有控制依赖 if (info_first.is_terminator) { return true; // first是终结指令,second不能移动到first之前 } if (info_second.is_terminator) { return false; // second是终结指令,可以保持在后面 } // CALL指令具有控制副作用,但可以参与有限的调度 if (info_first.is_call || info_second.is_call) { // CALL指令之间保持顺序 if (info_first.is_call && info_second.is_call) { return true; } // 其他情况允许调度(通过数据依赖控制) } return false; } // 综合检查两个指令是否可以交换 - 优化版本 static bool canSwapInstructions(MachineInstr *first, MachineInstr *second) { // 检查所有类型的依赖 if (hasDataDependency(first, second) || hasDataDependency(second, first)) { return false; } if (hasMemoryDependency(first, second)) { return false; } if (hasControlDependency(first, second) || hasControlDependency(second, first)) { return false; } return true; } // 找到基本块中的调度边界 - 优化版本 static std::vector findSchedulingBoundaries(const std::vector &instrs) { std::vector boundaries; boundaries.reserve(instrs.size() / 10); // 预估边界数量 boundaries.push_back(0); // 起始边界 for (size_t i = 0; i < instrs.size(); i++) { const InstrInfo& info = getInstrInfo(instrs[i]); // 终结指令前后都是边界 if (info.is_terminator) { if (i > 0) boundaries.push_back(i); if (i + 1 < instrs.size()) boundaries.push_back(i + 1); } // 跳转目标标签也可能是边界(这里简化处理) } boundaries.push_back(instrs.size()); // 结束边界 // 去重并排序 std::sort(boundaries.begin(), boundaries.end()); boundaries.erase(std::unique(boundaries.begin(), boundaries.end()), boundaries.end()); return boundaries; } // 在单个调度区域内进行指令调度 - 优化版本 static void scheduleRegion(std::vector &instrs, size_t start, size_t end) { if (end - start <= 1) { return; // 区域太小,无需调度 } // 保守的调度策略: // 1. 只对小规模区域进行调度 // 2. 优先将加载指令向前调度,以隐藏内存延迟 // 3. 确保不破坏数据依赖和内存依赖 // 简单的调度算法:只尝试将加载指令尽可能前移 for (size_t i = start + 1; i < end; i++) { const InstrInfo& info = getInstrInfo(instrs[i]); if (info.is_load) { // 尝试将加载指令向前移动 for (size_t j = i; j > start; j--) { // 检查是否可以与前一条指令交换 if (canSwapInstructions(instrs[j - 1], instrs[j])) { std::swap(instrs[j - 1], instrs[j]); } else { // 一旦遇到依赖关系就停止移动 break; } } } } } static void scheduleBlock(MachineBasicBlock *mbb) { auto &instructions = mbb->getInstructions(); if (instructions.size() <= 1 || instructions.size() > MAX_SCHEDULING_BLOCK_SIZE) { return; } // 清理缓存,避免无效指针 instr_info_cache.clear(); // 构建指令列表 std::vector instr_list; instr_list.reserve(instructions.size()); // 预分配容量 for (auto &instr : instructions) { instr_list.push_back(instr.get()); } // 预计算所有指令信息 for (auto* instr : instr_list) { getInstrInfo(instr); } // 找到调度边界 std::vector boundaries = findSchedulingBoundaries(instr_list); // 在每个调度区域内进行局部调度 for (size_t i = 0; i < boundaries.size() - 1; i++) { size_t region_start = boundaries[i]; size_t region_end = boundaries[i + 1]; scheduleRegion(instr_list, region_start, region_end); } // 重建指令序列 std::unordered_map> instr_map; instr_map.reserve(instructions.size()); // 预分配容量 for (auto &instr : instructions) { instr_map[instr.get()] = std::move(instr); } instructions.clear(); instructions.reserve(instr_list.size()); // 预分配容量 for (auto *instr : instr_list) { instructions.push_back(std::move(instr_map[instr])); } } bool PreRA_Scheduler::runOnFunction(Function *F, AnalysisManager &AM) { return false; } void PreRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) { for (auto &mbb : mfunc->getBlocks()) { scheduleBlock(mbb.get()); } // 清理全局缓存 instr_info_cache.clear(); } } // namespace sysy