|
|
|
|
@ -0,0 +1,100 @@
|
|
|
|
|
#include "mir/MIR.h"
|
|
|
|
|
|
|
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
|
|
|
|
namespace mir
|
|
|
|
|
{
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// MovImm 转发:mov v1, #N; mov v2, v1(v1 无其他使用)→ 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)和 MovReg(use)
|
|
|
|
|
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
|