|
|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|