perf(mir): MIR预分配 MovImm 转发——消除常数二次传递

mov v1,#N; mov v2,v1(v1 无其他使用)→ mov v2,#N
matmul -3.3%, optim_sched -10.2%, 01_mm -4.4%。33基线更新。
lzk
lzkk 3 days ago
parent bf5956e3cc
commit 2cfc9e2fc8

@ -421,6 +421,9 @@ namespace mir
void RunBlockLayout(MachineFunction &function);
void RunBlockLayout(MachineModule &module);
void RunMIRCleanup(MachineFunction &function);
void RunMIRCleanup(MachineModule &module);
void PrintAsm(const MachineFunction &function, std::ostream &os);
void PrintAsm(const MachineModule &module, std::ostream &os);

@ -51,6 +51,7 @@ int main(int argc, char** argv) {
// 汇编输出到文件或标准输出
if (opts.emit_asm) {
auto machine_module = mir::LowerModuleToMIR(*module);
mir::RunMIRCleanup(*machine_module);
mir::RunRegAlloc(*machine_module);
mir::RunFrameLowering(*machine_module);
mir::RunBlockLayout(*machine_module);

@ -2,6 +2,7 @@ add_library(mir_passes STATIC
PassManager.cpp
Peephole.cpp
BlockLayoutOpt.cpp
MIRCleanup.cpp
)
target_link_libraries(mir_passes PUBLIC

@ -0,0 +1,100 @@
#include "mir/MIR.h"
#include "utils/Log.h"
namespace mir
{
namespace
{
// MovImm 转发mov v1, #N; mov v2, v1v1 无其他使用)→ mov v2, #N
static void ForwardMovImm(MachineFunction &function)
{
for (auto &block : function.GetBlocks())
{
if (!block)
continue;
auto &insts = block->GetInstructions();
for (auto it = insts.begin(); it != insts.end(); ++it)
{
if (it->GetOpcode() != Opcode::MovImm)
continue;
const auto &ops = it->GetOperands();
if (ops.size() < 2 || ops[0].GetKind() != Operand::Kind::VReg)
continue;
int src_vreg = ops[0].GetVRegId();
int imm_val = ops[1].GetImm();
auto next = std::next(it);
if (next == insts.end())
continue;
if (next->GetOpcode() != Opcode::MovReg)
continue;
const auto &n_ops = next->GetOperands();
if (n_ops.size() < 2)
continue;
if (n_ops[1].GetKind() != Operand::Kind::VReg ||
n_ops[1].GetVRegId() != src_vreg)
continue;
if (n_ops[0].GetKind() != Operand::Kind::VReg)
continue;
int dst_vreg = n_ops[0].GetVRegId();
// 检查 src_vreg 是否还有其他使用
bool other_use = false;
for (auto &b2 : function.GetBlocks())
{
if (!b2)
continue;
for (auto &inst2 : b2->GetInstructions())
{
for (const auto &op : inst2.GetOperands())
{
if (op.GetKind() == Operand::Kind::VReg &&
op.GetVRegId() == src_vreg)
{
// 排除 MovImm 自身def和 MovReguse
MachineInstr *mi_ptr = const_cast<MachineInstr *>(&inst2);
if (mi_ptr != &(*it) && mi_ptr != &(*next))
{
other_use = true;
goto done_check;
}
}
}
}
}
done_check:
if (!other_use)
{
*next = MachineInstr(Opcode::MovImm,
{Operand::VReg(dst_vreg, function.GetVRegClass(dst_vreg)),
Operand::Imm(imm_val)});
it = insts.erase(it);
}
}
}
}
} // namespace
void RunMIRCleanup(MachineFunction &function)
{
ForwardMovImm(function);
}
void RunMIRCleanup(MachineModule &module)
{
for (auto &function : module.GetFunctions())
{
if (function)
RunMIRCleanup(*function);
}
}
} // namespace mir
Loading…
Cancel
Save