diff --git a/src/mir/passes/Peephole.cpp b/src/mir/passes/Peephole.cpp index a46ff917..c06f36ae 100644 --- a/src/mir/passes/Peephole.cpp +++ b/src/mir/passes/Peephole.cpp @@ -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; } }