416 lines
13 KiB
C++
416 lines
13 KiB
C++
#include "PostRA_Scheduler.h"
|
||
#include <algorithm>
|
||
#include <unordered_map>
|
||
#include <unordered_set>
|
||
#include <vector>
|
||
#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;
|
||
}
|
||
|
||
// 预计算指令信息的缓存
|
||
static std::unordered_map<MachineInstr *, InstrRegInfo> instr_info_cache;
|
||
|
||
// 获取指令定义的寄存器 - 优化版本
|
||
std::unordered_set<PhysicalReg> getDefinedRegisters(MachineInstr *instr) {
|
||
std::unordered_set<PhysicalReg> 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<RegOperand *>(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<RegOperand *>(instr->getOperands().front().get());
|
||
if (!reg_op->isVirtual()) {
|
||
defined_regs.insert(reg_op->getPReg());
|
||
}
|
||
}
|
||
|
||
return defined_regs;
|
||
}
|
||
|
||
// 获取指令使用的寄存器 - 优化版本
|
||
std::unordered_set<PhysicalReg> getUsedRegisters(MachineInstr *instr) {
|
||
std::unordered_set<PhysicalReg> 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<RegOperand *>(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<RegOperand *>(op.get());
|
||
if (!reg_op->isVirtual()) {
|
||
used_regs.insert(reg_op->getPReg());
|
||
}
|
||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
||
auto mem_op = static_cast<MemOperand *>(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<RegOperand *>(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<RegOperand *>(op.get());
|
||
if (!reg_op->isVirtual()) {
|
||
used_regs.insert(reg_op->getPReg());
|
||
}
|
||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
||
auto mem_op = static_cast<MemOperand *>(op.get());
|
||
if (!mem_op->getBase()->isVirtual()) {
|
||
used_regs.insert(mem_op->getBase()->getPReg());
|
||
}
|
||
}
|
||
}
|
||
return used_regs;
|
||
}
|
||
|
||
// 获取内存访问的基址和偏移
|
||
|
||
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<MemOperand *>(op.get());
|
||
if (!mem_op->getBase()->isVirtual()) {
|
||
return MemoryAccess(mem_op->getBase()->getPReg(),
|
||
mem_op->getOffset()->getValue());
|
||
}
|
||
}
|
||
}
|
||
|
||
return MemoryAccess();
|
||
}
|
||
|
||
// 预计算指令信息
|
||
InstrRegInfo &getInstrInfo(MachineInstr *instr) {
|
||
auto it = instr_info_cache.find(instr);
|
||
if (it != instr_info_cache.end()) {
|
||
return it->second;
|
||
}
|
||
|
||
InstrRegInfo &info = instr_info_cache[instr];
|
||
info.defined_regs = getDefinedRegisters(instr);
|
||
info.used_regs = getUsedRegisters(instr);
|
||
info.is_load = isLoadInstr(instr);
|
||
info.is_store = isStoreInstr(instr);
|
||
info.is_control_flow = isControlFlowInstr(instr);
|
||
info.mem_access = getMemoryAccess(instr);
|
||
|
||
return info;
|
||
}
|
||
|
||
// 检查内存依赖 - 优化版本
|
||
bool hasMemoryDependency(const InstrRegInfo &info1, const InstrRegInfo &info2) {
|
||
// 如果都不是内存指令,没有内存依赖
|
||
if (!info1.is_load && !info1.is_store && !info2.is_load && !info2.is_store) {
|
||
return false;
|
||
}
|
||
|
||
const MemoryAccess &mem1 = info1.mem_access;
|
||
const MemoryAccess &mem2 = info2.mem_access;
|
||
|
||
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 info1.is_store || info2.is_store;
|
||
}
|
||
|
||
// 不同内存位置通常没有依赖,但为了安全起见,
|
||
// 如果涉及store指令,我们需要更保守
|
||
if (info1.is_store && info2.is_load) {
|
||
// 保守处理:不同store和load之间可能有别名
|
||
return false; // 这里可以根据需要调整策略
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 检查两个指令之间是否存在依赖关系 - 优化版本
|
||
bool hasDependency(MachineInstr *instr1, MachineInstr *instr2) {
|
||
const InstrRegInfo &info1 = getInstrInfo(instr1);
|
||
const InstrRegInfo &info2 = getInstrInfo(instr2);
|
||
|
||
// 检查RAW依赖:instr1定义的寄存器是否被instr2使用
|
||
for (const auto ® : info1.defined_regs) {
|
||
if (info2.used_regs.find(reg) != info2.used_regs.end()) {
|
||
return true; // RAW依赖 - instr2读取instr1写入的值
|
||
}
|
||
}
|
||
|
||
// 检查WAR依赖:instr1使用的寄存器是否被instr2定义
|
||
for (const auto ® : info1.used_regs) {
|
||
if (info2.defined_regs.find(reg) != info2.defined_regs.end()) {
|
||
return true; // WAR依赖 - instr2覆盖instr1需要的值
|
||
}
|
||
}
|
||
|
||
// 检查WAW依赖:两个指令定义相同寄存器
|
||
for (const auto ® : info1.defined_regs) {
|
||
if (info2.defined_regs.find(reg) != info2.defined_regs.end()) {
|
||
return true; // WAW依赖 - 两条指令写入同一寄存器
|
||
}
|
||
}
|
||
|
||
// 检查内存依赖
|
||
if (hasMemoryDependency(info1, info2)) {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 检查是否可以安全地将instr1和instr2交换位置 - 优化版本
|
||
bool canSwapInstructions(MachineInstr *instr1, MachineInstr *instr2) {
|
||
const InstrRegInfo &info1 = getInstrInfo(instr1);
|
||
const InstrRegInfo &info2 = getInstrInfo(instr2);
|
||
|
||
// 不能移动控制流指令
|
||
if (info1.is_control_flow || info2.is_control_flow) {
|
||
return false;
|
||
}
|
||
|
||
// 检查双向依赖关系
|
||
return !hasDependency(instr1, instr2) && !hasDependency(instr2, instr1);
|
||
}
|
||
|
||
// 新增:验证调度结果的正确性 - 优化版本
|
||
void validateSchedule(const std::vector<MachineInstr *> &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];
|
||
|
||
const InstrRegInfo &info_earlier = getInstrInfo(earlier);
|
||
const InstrRegInfo &info_later = getInstrInfo(later);
|
||
|
||
// 检查是否存在被违反的依赖关系
|
||
// 检查RAW依赖
|
||
for (const auto ® : info_earlier.defined_regs) {
|
||
if (info_later.used_regs.find(reg) != info_later.used_regs.end()) {
|
||
// 这是正常的依赖关系,earlier应该在later之前
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 检查内存依赖
|
||
if (hasMemoryDependency(info_earlier, info_later)) {
|
||
const MemoryAccess &mem1 = info_earlier.mem_access;
|
||
const MemoryAccess &mem2 = info_later.mem_access;
|
||
|
||
if (mem1.valid && mem2.valid && mem1.base_reg == mem2.base_reg &&
|
||
mem1.offset == mem2.offset) {
|
||
if (info_earlier.is_store && info_later.is_load) {
|
||
// Store->Load依赖,顺序正确
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 在基本块内对指令进行调度优化 - 优化版本
|
||
void scheduleBlock(MachineBasicBlock *mbb) {
|
||
auto &instructions = mbb->getInstructions();
|
||
if (instructions.size() <= 1)
|
||
return;
|
||
if (instructions.size() > MAX_SCHEDULING_BLOCK_SIZE) {
|
||
return; // 跳过超大块,防止卡住
|
||
}
|
||
|
||
// 清理缓存,避免无效指针
|
||
instr_info_cache.clear();
|
||
|
||
std::vector<MachineInstr *> instr_list;
|
||
instr_list.reserve(instructions.size()); // 预分配容量
|
||
for (auto &instr : instructions) {
|
||
instr_list.push_back(instr.get());
|
||
}
|
||
|
||
// 预计算所有指令的信息
|
||
for (auto *instr : instr_list) {
|
||
getInstrInfo(instr);
|
||
}
|
||
|
||
// 使用更严格的调度策略,避免破坏依赖关系
|
||
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];
|
||
|
||
const InstrRegInfo &info1 = getInstrInfo(instr1);
|
||
const InstrRegInfo &info2 = getInstrInfo(instr2);
|
||
|
||
// 只进行非常保守的优化
|
||
bool should_swap = false;
|
||
|
||
// 策略1: 将load指令提前,减少load-use延迟
|
||
if (info2.is_load && !info1.is_load && !info1.is_store) {
|
||
should_swap = canSwapInstructions(instr1, instr2);
|
||
}
|
||
// 策略2: 将非关键store指令延后,为其他指令让路
|
||
else if (info1.is_store && !info2.is_load && !info2.is_store) {
|
||
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::unordered_map<MachineInstr *, std::unique_ptr<MachineInstr>> 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 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());
|
||
}
|
||
|
||
// 清理全局缓存
|
||
instr_info_cache.clear();
|
||
}
|
||
|
||
} // namespace sysy
|