|
|
|
|
@ -256,6 +256,56 @@ namespace mir
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ShlRR + AddRR/SubRR → AddShiftRR/SubShiftRR (lsl wA,wB,#n; add wC,wB,wA → add wC,wB,wB,lsl#n)
|
|
|
|
|
if (!changed)
|
|
|
|
|
{
|
|
|
|
|
for (auto it = insts.begin(); it != insts.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (it->GetOpcode() != Opcode::ShlRR) continue;
|
|
|
|
|
auto next = std::next(it);
|
|
|
|
|
if (next == insts.end()) continue;
|
|
|
|
|
if (next->GetOpcode() != Opcode::AddRR && next->GetOpcode() != Opcode::SubRR)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const auto &shl_ops = it->GetOperands();
|
|
|
|
|
const auto &arith_ops = next->GetOperands();
|
|
|
|
|
if (shl_ops.size() < 3 || arith_ops.size() < 3) continue;
|
|
|
|
|
|
|
|
|
|
// shl: [dst(A), src(B), shift_imm]
|
|
|
|
|
// add/sub: [dst(C), src1, src2]
|
|
|
|
|
// 检查 shl 的 dst 是否等于 add/sub 的一个 src,且 shl 的 src 等于 add/sub 的另一个 src
|
|
|
|
|
PhysReg shl_dst = shl_ops[0].GetReg();
|
|
|
|
|
PhysReg shl_src = shl_ops[1].GetReg();
|
|
|
|
|
int shift = shl_ops[2].GetImm();
|
|
|
|
|
|
|
|
|
|
PhysReg arith_src1 = arith_ops[1].GetReg();
|
|
|
|
|
PhysReg arith_src2 = arith_ops[2].GetReg();
|
|
|
|
|
|
|
|
|
|
if (shl_dst == arith_src1 && shl_src == arith_src2)
|
|
|
|
|
{
|
|
|
|
|
// lsl A, B, #n; add C, A, B → add C, B, B, lsl #n
|
|
|
|
|
auto new_op = (next->GetOpcode() == Opcode::AddRR)
|
|
|
|
|
? Opcode::AddShiftRR : Opcode::SubShiftRR;
|
|
|
|
|
*next = MachineInstr(new_op, {arith_ops[0], shl_ops[1], shl_ops[1],
|
|
|
|
|
Operand::Imm(shift)});
|
|
|
|
|
it = insts.erase(it);
|
|
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (shl_dst == arith_src2 && shl_src == arith_src1)
|
|
|
|
|
{
|
|
|
|
|
// lsl A, B, #n; add C, B, A → add C, B, B, lsl #n
|
|
|
|
|
auto new_op = (next->GetOpcode() == Opcode::AddRR)
|
|
|
|
|
? Opcode::AddShiftRR : Opcode::SubShiftRR;
|
|
|
|
|
*next = MachineInstr(new_op, {arith_ops[0], shl_ops[1], shl_ops[1],
|
|
|
|
|
Operand::Imm(shift)});
|
|
|
|
|
it = insts.erase(it);
|
|
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 消除冗余 adrp:同一符号、同一寄存器的重复 adrp
|
|
|
|
|
if (!changed)
|
|
|
|
|
{
|
|
|
|
|
|