[peephole]添加7项窥孔优化规则初步测试生效成功,有待进一步检查,TODO: 指令调度优化

This commit is contained in:
2025-07-26 21:44:14 +08:00
parent 9bea4d5343
commit 78dee0d72a

View File

@ -1,43 +1,667 @@
#include "RISCv64Passes.h"
#include <iostream>
// #include <iostream>
#include <functional>
namespace sysy {
// --- 寄存器分配前优化 ---
void PreRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
void PreRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) {
// TODO: 在此实现寄存器分配前的指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行重排。
//
// 实现思路:
// 1. 分析每个基本块内指令的数据依赖关系,构建依赖图(DAG)。
// 2. 根据目标处理器的流水线特性(指令延迟等),使用列表调度等算法对指令进行重排。
// 2.
// 根据目标处理器的流水线特性(指令延迟等),使用列表调度等算法对指令进行重排。
// 3. 此时操作的是虚拟寄存器,只存在真依赖,调度自由度最大。
//
// std::cout << "Running Pre-RA Instruction Scheduler..." << std::endl;
}
// --- 寄存器分配后优化 ---
void PeepholeOptimizer::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现窥孔优化。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行扫描和替换。
//
// 实现思路:
// 1. 维护一个大小固定例如3-5条指令的滑动窗口。
// 2. 识别特定的冗余模式,例如:
// - `mv a0, a1` 后紧跟 `mv a1, a0` (可消除的交换)
// - `sw t0, 12(s0)` 后紧跟 `lw t1, 12(s0)` (冗余加载)
// - 强度削减: `mul x, x, 2` -> `slli x, x, 1`
// 3. 识别后直接修改MachineInstr列表删除、替换或插入指令
//
// std::cout << "Running Post-RA Peephole Optimizer..." << std::endl;
void PeepholeOptimizer::runOnMachineFunction(MachineFunction *mfunc) {
if (!mfunc)
return;
using namespace sysy;
// areRegsEqual: 检查两个寄存器操作数是否相等(考虑虚拟和物理寄存器)。
auto areRegsEqual = [](RegOperand *r1, RegOperand *r2) {
if (!r1 || !r2 || r1->isVirtual() != r2->isVirtual()) {
return false;
}
if (r1->isVirtual()) {
return r1->getVRegNum() == r2->getVRegNum();
} else {
return r1->getPReg() == r2->getPReg();
}
};
// 改进的 isRegUsedLater 函数 - 更完整和准确的实现
auto isRegUsedLater =
[&](const std::vector<std::unique_ptr<MachineInstr>> &instrs,
RegOperand *reg, size_t start_idx) -> bool {
for (size_t j = start_idx; j < instrs.size(); ++j) {
auto *instr = instrs[j].get();
auto opcode = instr->getOpcode();
// 检查所有操作数
for (size_t k = 0; k < instr->getOperands().size(); ++k) {
bool isDefOperand = false;
// 更完整的定义操作数判断逻辑
if (k == 0) { // 第一个操作数通常是目标寄存器
switch (opcode) {
// 算术和逻辑指令 - 第一个操作数是定义
case RVOpcodes::MV:
case RVOpcodes::ADDI:
case RVOpcodes::SLLI:
case RVOpcodes::SRLI:
case RVOpcodes::SRAI:
case RVOpcodes::SLTI:
case RVOpcodes::SLTIU:
case RVOpcodes::XORI:
case RVOpcodes::ORI:
case RVOpcodes::ANDI:
case RVOpcodes::ADD:
case RVOpcodes::SUB:
case RVOpcodes::SLL:
case RVOpcodes::SLT:
case RVOpcodes::SLTU:
case RVOpcodes::XOR:
case RVOpcodes::SRL:
case RVOpcodes::SRA:
case RVOpcodes::OR:
case RVOpcodes::AND:
case RVOpcodes::MUL:
case RVOpcodes::DIV:
case RVOpcodes::REM:
case RVOpcodes::LW:
case RVOpcodes::LH:
case RVOpcodes::LB:
case RVOpcodes::LHU:
case RVOpcodes::LBU:
// 存储指令 - 第一个操作数是使用(要存储的值)
case RVOpcodes::SW:
case RVOpcodes::SH:
case RVOpcodes::SB:
// 分支指令 - 第一个操作数是使用
case RVOpcodes::BEQ:
case RVOpcodes::BNE:
case RVOpcodes::BLT:
case RVOpcodes::BGE:
case RVOpcodes::BLTU:
case RVOpcodes::BGEU:
// 跳转指令 - 可能使用寄存器
case RVOpcodes::JALR:
isDefOperand = false;
break;
default:
// 对于未知指令,保守地假设第一个操作数可能是使用
isDefOperand = false;
break;
}
}
// 如果不是定义操作数,检查是否使用了目标寄存器
if (!isDefOperand) {
if (instr->getOperands()[k]->getKind() == MachineOperand::KIND_REG) {
auto *use_reg =
static_cast<RegOperand *>(instr->getOperands()[k].get());
if (areRegsEqual(reg, use_reg))
return true;
}
// 检查内存操作数中的基址寄存器
if (instr->getOperands()[k]->getKind() == MachineOperand::KIND_MEM) {
auto *mem =
static_cast<MemOperand *>(instr->getOperands()[k].get());
if (areRegsEqual(reg, mem->getBase()))
return true;
}
}
}
}
return false;
};
// 检查寄存器是否在指令中被重新定义(用于更精确的分析)
auto isRegRedefinedAt =
[](MachineInstr *instr, RegOperand *reg,
const std::function<bool(RegOperand *, RegOperand *)> &areRegsEqual)
-> bool {
if (instr->getOperands().empty())
return false;
auto opcode = instr->getOpcode();
// 只有当第一个操作数是定义操作数时才检查
switch (opcode) {
case RVOpcodes::MV:
case RVOpcodes::ADDI:
case RVOpcodes::ADD:
case RVOpcodes::SUB:
case RVOpcodes::MUL:
case RVOpcodes::LW:
// ... 其他定义指令
if (instr->getOperands()[0]->getKind() == MachineOperand::KIND_REG) {
auto *def_reg =
static_cast<RegOperand *>(instr->getOperands()[0].get());
return areRegsEqual(reg, def_reg);
}
break;
default:
break;
}
return false;
};
// 检查是否为存储-加载模式,支持不同大小的访问
auto isStoreLoadPattern = [](MachineInstr *store_instr,
MachineInstr *load_instr) -> bool {
auto store_op = store_instr->getOpcode();
auto load_op = load_instr->getOpcode();
// 检查存储-加载对应关系
return (store_op == RVOpcodes::SW && load_op == RVOpcodes::LW) || // 32位
(store_op == RVOpcodes::SH &&
load_op == RVOpcodes::LH) || // 16位有符号
(store_op == RVOpcodes::SH &&
load_op == RVOpcodes::LHU) || // 16位无符号
(store_op == RVOpcodes::SB &&
load_op == RVOpcodes::LB) || // 8位有符号
(store_op == RVOpcodes::SB &&
load_op == RVOpcodes::LBU) || // 8位无符号
(store_op == RVOpcodes::SD && load_op == RVOpcodes::LD); // 64位
};
// 检查两个内存访问是否访问相同的内存位置
auto areMemoryAccessesEqual =
[&areRegsEqual](MachineInstr *store_instr, MemOperand *store_mem,
MachineInstr *load_instr, MemOperand *load_mem) -> bool {
// 基址寄存器必须相同
if (!areRegsEqual(store_mem->getBase(), load_mem->getBase())) {
return false;
}
// 偏移量必须相同
if (store_mem->getOffset()->getValue() !=
load_mem->getOffset()->getValue()) {
return false;
}
// 检查访问大小是否兼容
auto store_op = store_instr->getOpcode();
auto load_op = load_instr->getOpcode();
// 获取访问大小(字节数)
auto getAccessSize = [](RVOpcodes opcode) -> int {
switch (opcode) {
case RVOpcodes::LB:
case RVOpcodes::LBU:
case RVOpcodes::SB:
return 1; // 8位
case RVOpcodes::LH:
case RVOpcodes::LHU:
case RVOpcodes::SH:
return 2; // 16位
case RVOpcodes::LW:
case RVOpcodes::SW:
return 4; // 32位
case RVOpcodes::LD:
case RVOpcodes::SD:
return 8; // 64位
default:
return -1; // 未知
}
};
int store_size = getAccessSize(store_op);
int load_size = getAccessSize(load_op);
// 只有访问大小完全匹配时才能进行优化
// 这避免了部分重叠访问的复杂情况
return store_size > 0 && store_size == load_size;
};
// 简单的内存别名分析:检查两个内存访问之间是否可能有冲突的内存操作
auto isMemoryAccessSafe =
[&](const std::vector<std::unique_ptr<MachineInstr>> &instrs,
size_t store_idx, size_t load_idx, MemOperand *mem) -> bool {
// 检查存储和加载之间是否有可能影响内存的指令
for (size_t j = store_idx + 1; j < load_idx; ++j) {
auto *between_instr = instrs[j].get();
auto between_op = between_instr->getOpcode();
// 检查是否有其他内存写入操作
switch (between_op) {
case RVOpcodes::SW:
case RVOpcodes::SH:
case RVOpcodes::SB:
case RVOpcodes::SD: {
// 如果有其他存储操作,需要检查是否可能访问相同的内存
if (between_instr->getOperands().size() >= 2 &&
between_instr->getOperands()[1]->getKind() ==
MachineOperand::KIND_MEM) {
auto *other_mem =
static_cast<MemOperand *>(between_instr->getOperands()[1].get());
// 保守的别名分析:如果使用不同的基址寄存器,假设可能别名
if (!areRegsEqual(mem->getBase(), other_mem->getBase())) {
return false; // 可能的别名,不安全
}
// 如果基址相同但偏移量不同,检查是否重叠
int64_t offset1 = mem->getOffset()->getValue();
int64_t offset2 = other_mem->getOffset()->getValue();
// 获取访问大小来检查重叠
auto getAccessSize = [](RVOpcodes opcode) -> int {
switch (opcode) {
case RVOpcodes::SB:
return 1;
case RVOpcodes::SH:
return 2;
case RVOpcodes::SW:
return 4;
case RVOpcodes::SD:
return 8;
default:
return 4; // 默认假设4字节
}
};
int size1 = getAccessSize(RVOpcodes::SW); // 从原存储指令推断
int size2 = getAccessSize(between_op);
// 检查内存区域是否重叠
bool overlaps =
!(offset1 + size1 <= offset2 || offset2 + size2 <= offset1);
if (overlaps) {
return false; // 内存重叠,不安全
}
}
break;
}
// 函数调用可能有副作用
case RVOpcodes::JAL:
case RVOpcodes::JALR:
return false; // 函数调用可能修改内存,不安全
// 原子操作或其他可能修改内存的指令
// 根据具体的RISC-V扩展添加更多指令
default:
// 对于未知指令,采用保守策略
// 可以根据具体需求调整
break;
}
}
return true; // 没有发现潜在的内存冲突
};
// isPowerOfTwo: 检查数值是否为2的幂次并返回其指数。
auto isPowerOfTwo = [](int64_t n) -> int {
if (n <= 0 || (n & (n - 1)) != 0)
return -1;
int shift = 0;
while (n > 1) {
n >>= 1;
shift++;
}
return shift;
};
for (auto &mbb_uptr : mfunc->getBlocks()) {
auto &mbb = *mbb_uptr;
auto &instrs = mbb.getInstructions();
if (instrs.size() < 2)
continue; // 基本块至少需要两条指令进行窥孔
// 遍历指令序列进行窥孔优化
for (size_t i = 0; i + 1 < instrs.size();) {
auto *mi1 = instrs[i].get();
auto *mi2 = instrs[i + 1].get();
bool changed = false;
// 1. 消除冗余交换移动: mv a, b; mv b, a -> mv a, b
if (mi1->getOpcode() == RVOpcodes::MV &&
mi2->getOpcode() == RVOpcodes::MV) {
if (mi1->getOperands().size() == 2 && mi2->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_REG) {
auto *dst1 = static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *src1 = static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *dst2 = static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *src2 = static_cast<RegOperand *>(mi2->getOperands()[1].get());
if (areRegsEqual(dst1, src2) && areRegsEqual(src1, dst2)) {
instrs.erase(instrs.begin() + i + 1); // 移除第二条指令
changed = true;
}
}
}
}
// 2. 冗余加载消除: sw t0, offset(base); lw t1, offset(base) -> 替换或消除
// lw 添加ld sd支持
else if (isStoreLoadPattern(mi1, mi2)) {
if (mi1->getOperands().size() == 2 && mi2->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_MEM &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_MEM) {
auto *store_val =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *store_mem =
static_cast<MemOperand *>(mi1->getOperands()[1].get());
auto *load_val =
static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *load_mem =
static_cast<MemOperand *>(mi2->getOperands()[1].get());
// 检查内存访问是否匹配(基址、偏移量和访问大小)
if (areMemoryAccessesEqual(mi1, store_mem, mi2, load_mem)) {
// 进行简单的内存别名分析
if (isMemoryAccessSafe(instrs, i, i + 1, store_mem)) {
if (areRegsEqual(store_val, load_val)) {
// sw r1, mem; lw r1, mem -> 消除冗余的lw
instrs.erase(instrs.begin() + i + 1);
changed = true;
} else {
// sw r1, mem; lw r2, mem -> 替换lw为mv r2, r1
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::MV);
newInstr->addOperand(std::make_unique<RegOperand>(*load_val));
newInstr->addOperand(
std::make_unique<RegOperand>(*store_val));
instrs[i + 1] = std::move(newInstr);
changed = true;
}
}
}
}
}
}
// 3. 强度削减: mul y, x, 2^n -> slli y, x, n
else if (mi1->getOpcode() == RVOpcodes::MUL &&
mi1->getOperands().size() == 3) {
auto *dst_op = mi1->getOperands()[0].get();
auto *src1_op = mi1->getOperands()[1].get();
auto *src2_op = mi1->getOperands()[2].get();
if (dst_op->getKind() == MachineOperand::KIND_REG) {
auto *dst_reg = static_cast<RegOperand *>(dst_op);
RegOperand *src_reg = nullptr;
int shift = -1;
if (src1_op->getKind() == MachineOperand::KIND_REG &&
src2_op->getKind() == MachineOperand::KIND_IMM) {
shift =
isPowerOfTwo(static_cast<ImmOperand *>(src2_op)->getValue());
if (shift >= 0)
src_reg = static_cast<RegOperand *>(src1_op);
} else if (src1_op->getKind() == MachineOperand::KIND_IMM &&
src2_op->getKind() == MachineOperand::KIND_REG) {
shift =
isPowerOfTwo(static_cast<ImmOperand *>(src1_op)->getValue());
if (shift >= 0)
src_reg = static_cast<RegOperand *>(src2_op);
}
if (src_reg && shift >= 0 &&
shift <= 31) { // RISC-V 移位量限制 (0-31)
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::SLLI);
newInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
newInstr->addOperand(std::make_unique<RegOperand>(*src_reg));
newInstr->addOperand(std::make_unique<ImmOperand>(shift));
instrs[i] = std::move(newInstr);
changed = true;
}
}
}
// 4. 地址计算优化: addi dst, base, imm1; lw/sw val, imm2(dst) -> lw/sw
// val, (imm1+imm2)(base)
else if (mi1->getOpcode() == RVOpcodes::ADDI &&
mi1->getOperands().size() == 3) {
auto opcode2 = mi2->getOpcode();
if (opcode2 == RVOpcodes::LW || opcode2 == RVOpcodes::SW) {
if (mi2->getOperands().size() == 2 &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_MEM &&
mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_IMM) {
auto *addi_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *addi_base =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *addi_imm =
static_cast<ImmOperand *>(mi1->getOperands()[2].get());
auto *mem_op =
static_cast<MemOperand *>(mi2->getOperands()[1].get());
auto *mem_base = mem_op->getBase();
auto *mem_imm = mem_op->getOffset();
// 检查 ADDI 的目标寄存器是否是内存操作的基址
if (areRegsEqual(addi_dst, mem_base)) {
// 改进的使用检查:考虑寄存器可能在后续被重新定义的情况
bool canOptimize = true;
// 检查从 i+2 开始的指令
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果寄存器被重新定义,那么它后面的使用就不相关了
if (isRegRedefinedAt(later_instr, addi_dst, areRegsEqual)) {
break; // 寄存器被重新定义,可以安全优化
}
// 如果寄存器被使用,则不能优化
if (isRegUsedLater(instrs, addi_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
int64_t new_offset = addi_imm->getValue() + mem_imm->getValue();
// 检查新偏移量是否符合 RISC-V 12位有符号立即数范围
if (new_offset >= -2048 && new_offset <= 2047) {
auto new_mem_op = std::make_unique<MemOperand>(
std::make_unique<RegOperand>(*addi_base),
std::make_unique<ImmOperand>(new_offset));
mi2->getOperands()[1] = std::move(new_mem_op);
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
}
}
// 5. 冗余移动指令消除: mv x, y; op z, x, ... -> op z, y, ... (如果 x
// 之后不再使用)
else if (mi1->getOpcode() == RVOpcodes::MV &&
mi1->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG) {
auto *mv_dst = static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *mv_src = static_cast<RegOperand *>(mi1->getOperands()[1].get());
// 检查第二条指令是否使用了 mv 的目标寄存器
std::vector<size_t> use_positions;
for (size_t k = 1; k < mi2->getOperands().size(); ++k) {
if (mi2->getOperands()[k]->getKind() == MachineOperand::KIND_REG) {
auto *use_reg =
static_cast<RegOperand *>(mi2->getOperands()[k].get());
if (areRegsEqual(mv_dst, use_reg)) {
use_positions.push_back(k);
}
}
// 也检查内存操作数中的基址寄存器
else if (mi2->getOperands()[k]->getKind() ==
MachineOperand::KIND_MEM) {
auto *mem =
static_cast<MemOperand *>(mi2->getOperands()[k].get());
if (areRegsEqual(mv_dst, mem->getBase())) {
// 对于内存操作数我们需要创建新的MemOperand
auto new_mem = std::make_unique<MemOperand>(
std::make_unique<RegOperand>(*mv_src),
std::make_unique<ImmOperand>(mem->getOffset()->getValue()));
mi2->getOperands()[k] = std::move(new_mem);
use_positions.push_back(k); // 标记已处理
}
}
}
if (!use_positions.empty()) {
// 改进的后续使用检查
bool canOptimize = true;
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果寄存器被重新定义,后续使用就不相关了
if (isRegRedefinedAt(later_instr, mv_dst, areRegsEqual)) {
break;
}
// 检查是否还有其他使用
if (isRegUsedLater(instrs, mv_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
// 替换所有寄存器使用(内存操作数已在上面处理)
for (size_t pos : use_positions) {
if (mi2->getOperands()[pos]->getKind() ==
MachineOperand::KIND_REG) {
mi2->getOperands()[pos] =
std::make_unique<RegOperand>(*mv_src);
}
}
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
// 6. 连续加法指令合并: addi t1, t0, imm1; addi t2, t1, imm2 -> addi t2,
// t0, (imm1+imm2)
else if (mi1->getOpcode() == RVOpcodes::ADDI &&
mi2->getOpcode() == RVOpcodes::ADDI) {
if (mi1->getOperands().size() == 3 && mi2->getOperands().size() == 3) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_IMM &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[2]->getKind() == MachineOperand::KIND_IMM) {
auto *addi1_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *addi1_src =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *addi1_imm =
static_cast<ImmOperand *>(mi1->getOperands()[2].get());
auto *addi2_dst =
static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *addi2_src =
static_cast<RegOperand *>(mi2->getOperands()[1].get());
auto *addi2_imm =
static_cast<ImmOperand *>(mi2->getOperands()[2].get());
// 检查第一个ADDI的目标是否是第二个ADDI的源
if (areRegsEqual(addi1_dst, addi2_src)) {
// 改进的中间寄存器使用检查
bool canOptimize = true;
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果中间寄存器被重新定义,后续使用不相关
if (isRegRedefinedAt(later_instr, addi1_dst, areRegsEqual)) {
break;
}
// 检查是否有其他使用
if (isRegUsedLater(instrs, addi1_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
int64_t new_imm = addi1_imm->getValue() + addi2_imm->getValue();
// 检查新立即数范围
if (new_imm >= -2048 && new_imm <= 2047) {
auto newInstr =
std::make_unique<MachineInstr>(RVOpcodes::ADDI);
newInstr->addOperand(
std::make_unique<RegOperand>(*addi2_dst));
newInstr->addOperand(
std::make_unique<RegOperand>(*addi1_src));
newInstr->addOperand(std::make_unique<ImmOperand>(new_imm));
instrs[i + 1] = std::move(newInstr);
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
}
}
// 7. ADD with zero optimization: add r1, r2, zero -> mv r1, r2
else if (mi1->getOpcode() == RVOpcodes::ADD &&
mi1->getOperands().size() == 3) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_REG) {
auto *add_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *add_src1 =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *add_src2 =
static_cast<RegOperand *>(mi1->getOperands()[2].get());
// 检查第二个源操作数是否为ZERO寄存器
if (!add_src2->isVirtual() &&
add_src2->getPReg() == PhysicalReg::ZERO) {
// 创建新的 MV 指令
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::MV);
newInstr->addOperand(std::make_unique<RegOperand>(*add_dst));
newInstr->addOperand(std::make_unique<RegOperand>(*add_src1));
instrs[i] = std::move(newInstr);
changed = true;
}
}
}
// 根据是否发生变化调整遍历索引
if (!changed) {
++i; // 没有优化,继续检查下一对指令
} else {
// 发生变化,适当回退以捕获新的优化机会。
// 这是一种安全的回退策略,可以触发连锁优化,且不会导致无限循环。
if (i > 0) {
--i;
}
}
}
}
}
void PostRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
void PostRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) {
// TODO: 在此实现寄存器分配后的局部指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 重点关注由寄存器分配器插入的spill/fill代码。