24#define DEBUG_TYPE "aarch64-sme-peephole-opt"
36 return "SME Peephole Optimization pass";
45 bool &HasRemovedAllSMChanges)
const;
49char SMEPeepholeOpt::ID = 0;
54 return MI->getOpcode() == AArch64::MSRpstatePseudo;
98 assert((
MI->getOpcode() == AArch64::MSRpstatesvcrImm1 ||
99 MI->getOpcode() == AArch64::MSRpstatePseudo) &&
100 "Expected MI to be a smstart/smstop instruction");
101 return MI->getOperand(0).getImm() == AArch64SVCR::SVCRSM ||
102 MI->getOperand(0).getImm() == AArch64SVCR::SVCRSMZA;
114 return AArch64::ZPRRegClass.contains(SR) ||
115 AArch64::PPRRegClass.contains(SR);
119 return TRI.getCommonSubClass(&AArch64::ZPRRegClass, RC) ||
120 TRI.getCommonSubClass(&AArch64::PPRRegClass, RC);
123bool SMEPeepholeOpt::optimizeStartStopPairs(
126 const TargetRegisterInfo &
TRI =
130 MachineInstr *Prev =
nullptr;
136 unsigned NumSMChanges = 0;
137 unsigned NumSMChangesRemoved = 0;
139 switch (
MI.getOpcode()) {
140 case AArch64::MSRpstatesvcrImm1:
141 case AArch64::MSRpstatePseudo: {
151 MI.eraseFromParent();
154 NumSMChangesRemoved += 2;
169 switch (
MI.getOpcode()) {
173 case AArch64::COALESCER_BARRIER_FPR16:
174 case AArch64::COALESCER_BARRIER_FPR32:
175 case AArch64::COALESCER_BARRIER_FPR64:
176 case AArch64::COALESCER_BARRIER_FPR128:
187 case AArch64::RestoreZAPseudo:
188 case AArch64::InOutZAUsePseudo:
189 case AArch64::CommitZASavePseudo:
190 case AArch64::SMEStateAllocPseudo:
191 case AArch64::RequiresZASavePseudo:
198 case AArch64::ADJCALLSTACKDOWN:
199 case AArch64::ADJCALLSTACKUP:
200 case AArch64::ANDXri:
201 case AArch64::ADDXri:
204 case AArch64::MSRpstatesvcrImm1:
205 case AArch64::MSRpstatePseudo:
210 HasRemovedAllSMChanges =
211 NumSMChanges && (NumSMChanges == NumSMChangesRemoved);
230bool SMEPeepholeOpt::visitRegSequence(MachineInstr &
MI) {
231 assert(
MI.getMF()->getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
235 case AArch64::ZPR2RegClassID:
236 case AArch64::ZPR4RegClassID:
237 case AArch64::ZPR2Mul2RegClassID:
238 case AArch64::ZPR4Mul4RegClassID:
247 if (
MI.getNumOperands() != 5 &&
MI.getNumOperands() != 9)
251 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
252 MachineOperand &MO =
MI.getOperand(
I);
255 if (!Def || !
Def->getParent()->isCopy())
258 const MachineOperand &CopySrc =
Def->getParent()->getOperand(1);
264 if (!CopySrcOp || !CopySrcOp->
isReg() || OpSubReg != SubReg ||
270 if (CopySrcClass != &AArch64::ZPR2StridedOrContiguousRegClass &&
271 CopySrcClass != &AArch64::ZPR4StridedOrContiguousRegClass)
275 unsigned Opc =
MI.getNumOperands() == 5
276 ? AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO
277 : AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO;
279 const TargetInstrInfo *
TII =
280 MI.getMF()->getSubtarget<AArch64Subtarget>().getInstrInfo();
281 MachineInstrBuilder MIB =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
282 TII->get(
Opc),
MI.getOperand(0).getReg());
283 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2)
286 MI.eraseFromParent();
291 "SME Peephole Optimization",
false,
false)
294 if (skipFunction(MF.getFunction()))
300 assert(MF.getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
303 bool FunctionHasAllSMChangesRemoved =
false;
309 bool BlockHasAllSMChangesRemoved;
310 Changed |= optimizeStartStopPairs(
MBB, BlockHasAllSMChangesRemoved);
311 FunctionHasAllSMChangesRemoved |= BlockHasAllSMChangesRemoved;
315 if (
MI.getOpcode() == AArch64::REG_SEQUENCE)
321 if (FunctionHasAllSMChangesRemoved)
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool isSVERegOp(const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, const MachineOperand &MO)
static bool isMatchingStartStopPair(const MachineInstr *MI1, const MachineInstr *MI2)
static bool isConditionalStartStop(const MachineInstr *MI)
static bool ChangesStreamingMode(const MachineInstr *MI)
This file defines the SmallVector class.
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
void setHasStreamingModeChanges(bool HasChanges)
bool isStreaming() const
Returns true if the function has a streaming body.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
unsigned getID() const
getID() - Return the register class ID number.
static constexpr unsigned NoRegister
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
MachineOperand * getOneDef(Register Reg) const
Returns the defining operand if there is exactly one operand defining the specified register,...
const MachineFunction & getMF() const
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
FunctionPass * createSMEPeepholeOptPass()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
MCRegisterClass TargetRegisterClass