|
|
// Peephole.cpp - 保守优化版(仅启用安全规则)
|
|
|
#include "mir/MIR.h"
|
|
|
#include <algorithm>
|
|
|
#include <vector>
|
|
|
#include <cstdint>
|
|
|
|
|
|
namespace mir {
|
|
|
namespace {
|
|
|
|
|
|
// 判断两个地址操作数是否指向同一内存位置(考虑栈槽和物理寄存器)
|
|
|
bool SameAddr(const Operand& a, const Operand& b) {
|
|
|
if (a.GetKind() != b.GetKind()) return false;
|
|
|
if (a.GetKind() == Operand::Kind::PhysReg)
|
|
|
return a.GetPhysReg() == b.GetPhysReg();
|
|
|
if (a.GetKind() == Operand::Kind::FrameIndex)
|
|
|
return a.GetFrameIndex() == b.GetFrameIndex();
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 规则2:消除死存储(连续两次存储到同一地址,删除第一次)
|
|
|
// 例如: sw t0, addr; sw t1, addr -> 仅保留第二次存储
|
|
|
bool EliminateDeadStore(std::vector<MachineInstr>& instrs) {
|
|
|
bool changed = false;
|
|
|
for (size_t i = 0; i + 1 < instrs.size(); ) {
|
|
|
auto& inst1 = instrs[i];
|
|
|
auto& inst2 = instrs[i+1];
|
|
|
Opcode op1 = inst1.GetOpcode();
|
|
|
Opcode op2 = inst2.GetOpcode();
|
|
|
bool is_store1 = (op1 == Opcode::Store || op1 == Opcode::StoreFloat);
|
|
|
bool is_store2 = (op2 == Opcode::Store || op2 == Opcode::StoreFloat);
|
|
|
if (is_store1 && is_store2) {
|
|
|
const auto& ops1 = inst1.GetOperands();
|
|
|
const auto& ops2 = inst2.GetOperands();
|
|
|
// 两个存储操作数至少都有两个操作数 [value, addr]
|
|
|
if (ops1.size() >= 2 && ops2.size() >= 2 &&
|
|
|
SameAddr(ops1[1], ops2[1])) {
|
|
|
// 第一次存储被第二次覆盖,删除第一次
|
|
|
instrs.erase(instrs.begin() + i);
|
|
|
changed = true;
|
|
|
continue; // 重新检查当前位置
|
|
|
}
|
|
|
}
|
|
|
++i;
|
|
|
}
|
|
|
return changed;
|
|
|
}
|
|
|
} // anonymous namespace
|
|
|
|
|
|
void RunPeepholeOptimization(MachineFunction& function) {
|
|
|
bool overallChanged = true;
|
|
|
while (overallChanged) {
|
|
|
overallChanged = false;
|
|
|
for (auto& blockPtr : function.GetBlocks()) {
|
|
|
auto& instrs = blockPtr->GetInstructions();
|
|
|
bool changed = false;
|
|
|
// 启用死存储消除
|
|
|
changed |= EliminateDeadStore(instrs);
|
|
|
// changed |= EliminateRedundantStoreLoad(instrs);
|
|
|
if (changed)
|
|
|
overallChanged = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace mir
|