perf(mir): Peephole 增强——StoreGlobal→LoadGlobal 跨指令转发 + 冗余 adrp 消除

全局变量前向替换不再只检查相邻指令,可跨越不冲突的中间指令扫描。
添加冗余 adrp 检测(同一符号+同一寄存器,中间无重定义则删除)。
lzk
lzkk 2 days ago
parent 00c489f0be
commit e1944acc6b

@ -256,29 +256,120 @@ namespace mir
}
}
// 全局变量 StoreGlobal → LoadGlobal 同一符号转发
// 消除冗余 adrp同一符号、同一寄存器的重复 adrp
if (!changed)
{
for (auto it = insts.begin(); it != insts.end(); ++it)
{
if (it->GetOpcode() == Opcode::StoreGlobal)
if (it->GetOpcode() != Opcode::LoadAddr) continue;
const auto &a_ops = it->GetOperands();
if (a_ops.size() < 2 || a_ops[1].GetKind() != Operand::Kind::Symbol) continue;
PhysReg base = a_ops[0].GetReg();
const std::string &sym = a_ops[1].GetSymbol();
auto scan = std::next(it);
while (scan != insts.end())
{
auto next = std::next(it);
if (next != insts.end() && IsGlobalFwdStoreLoad(*it, *next))
auto op = scan->GetOpcode();
if (op == Opcode::Call) break; // call 可能 clobber 寄存器
// 检查是否重定义了 base 寄存器
const auto &m_ops = scan->GetOperands();
if (!m_ops.empty() && m_ops[0].GetKind() == Operand::Kind::Reg &&
m_ops[0].GetReg() == base)
{
const auto &s_ops = it->GetOperands();
const auto &l_ops = next->GetOperands();
// 若已是同一寄存器则直接删除 load否则用 MovReg 替代
if (s_ops[0].GetKind() == l_ops[0].GetKind() &&
s_ops[0].GetKind() == Operand::Kind::Reg &&
s_ops[0].GetReg() == l_ops[0].GetReg())
next = insts.erase(next);
else
*next = MachineInstr(Opcode::MovReg, {l_ops[0], s_ops[0]});
changed = true;
// 如果是同一符号的 LoadAddr删除冗余的 adrp
if (op == Opcode::LoadAddr && m_ops.size() >= 2 &&
m_ops[1].GetKind() == Operand::Kind::Symbol &&
m_ops[1].GetSymbol() == sym)
{
scan = insts.erase(scan);
changed = true;
break;
}
// base 寄存器被其他指令重定义,停止扫描
break;
}
++scan;
}
if (changed) break;
}
}
// 全局变量 StoreGlobal → LoadGlobal 同一符号转发(含跨指令前向扫描)
if (!changed)
{
for (auto it = insts.begin(); it != insts.end(); ++it)
{
if (it->GetOpcode() != Opcode::StoreGlobal)
continue;
const auto &s_ops = it->GetOperands();
if (s_ops.size() < 2 || s_ops[1].GetKind() != Operand::Kind::Symbol)
continue;
const std::string &sym = s_ops[1].GetSymbol();
PhysReg stored_reg = s_ops[0].GetReg();
// 向前扫描,跳过不冲突的指令,寻找同一符号的 LoadGlobal
auto scan = std::next(it);
while (scan != insts.end())
{
auto op = scan->GetOpcode();
// Call 可能修改任意全局变量,停止扫描
if (op == Opcode::Call) break;
// 遇到同一符号的 StoreGlobal → 值被覆盖,停止扫描
if (op == Opcode::StoreGlobal)
{
const auto &ss_ops = scan->GetOperands();
if (ss_ops.size() >= 2 &&
ss_ops[1].GetKind() == Operand::Kind::Symbol &&
ss_ops[1].GetSymbol() == sym)
break;
}
// 若中间指令重定义了 store 的源寄存器,无法转发,停止扫描
bool reg_clobbered = false;
if (s_ops[0].GetKind() == Operand::Kind::Reg)
{
const auto &m_ops = scan->GetOperands();
if (!m_ops.empty() && m_ops[0].GetKind() == Operand::Kind::Reg &&
m_ops[0].GetReg() == stored_reg)
{
switch (op)
{
case Opcode::MovImm: case Opcode::MovReg:
case Opcode::AddRR: case Opcode::SubRR:
case Opcode::MulRR: case Opcode::DivRR: case Opcode::ModRR:
case Opcode::AndRR: case Opcode::OrRR: case Opcode::XorRR:
case Opcode::ShlRR: case Opcode::ShrRR: case Opcode::AsrRR:
case Opcode::NegRR: case Opcode::LoadStack:
case Opcode::LoadGlobal: case Opcode::LoadMem:
case Opcode::Csel: case Opcode::Csneg:
case Opcode::Uxtw: case Opcode::Sxtw:
case Opcode::Madd: case Opcode::Smull: case Opcode::Msub:
reg_clobbered = true; break;
default: break;
}
}
}
if (reg_clobbered) break;
// 找到同一符号的 LoadGlobal
if (op == Opcode::LoadGlobal)
{
const auto &l_ops = scan->GetOperands();
if (l_ops.size() >= 2 &&
l_ops[1].GetKind() == Operand::Kind::Symbol &&
l_ops[1].GetSymbol() == sym)
{
if (l_ops[0].GetKind() == Operand::Kind::Reg &&
l_ops[0].GetReg() == stored_reg)
scan = insts.erase(scan);
else
*scan = MachineInstr(Opcode::MovReg, {l_ops[0], s_ops[0]});
changed = true;
break;
}
}
++scan;
}
if (changed) break;
}
}

Loading…
Cancel
Save