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::ADJCALLSTACKDOWN:
188 case AArch64::ADJCALLSTACKUP:
189 case AArch64::ANDXri:
190 case AArch64::ADDXri:
193 case AArch64::MSRpstatesvcrImm1:
194 case AArch64::MSRpstatePseudo:
199 HasRemovedAllSMChanges =
200 NumSMChanges && (NumSMChanges == NumSMChangesRemoved);
219bool SMEPeepholeOpt::visitRegSequence(MachineInstr &
MI) {
220 assert(
MI.getMF()->getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
222 MachineRegisterInfo &
MRI =
MI.getMF()->getRegInfo();
223 switch (
MRI.getRegClass(
MI.getOperand(0).getReg())->getID()) {
224 case AArch64::ZPR2RegClassID:
225 case AArch64::ZPR4RegClassID:
226 case AArch64::ZPR2Mul2RegClassID:
227 case AArch64::ZPR4Mul4RegClassID:
236 if (
MI.getNumOperands() != 5 &&
MI.getNumOperands() != 9)
240 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
241 MachineOperand &MO =
MI.getOperand(
I);
244 if (!Def || !
Def->getParent()->isCopy())
247 const MachineOperand &CopySrc =
Def->getParent()->getOperand(1);
252 MachineOperand *CopySrcOp =
MRI.getOneDef(CopySrc.
getReg());
253 if (!CopySrcOp || !CopySrcOp->
isReg() || OpSubReg !=
SubReg ||
257 const TargetRegisterClass *CopySrcClass =
259 if (CopySrcClass != &AArch64::ZPR2StridedOrContiguousRegClass &&
260 CopySrcClass != &AArch64::ZPR4StridedOrContiguousRegClass)
264 unsigned Opc =
MI.getNumOperands() == 5
265 ? AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO
266 : AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO;
268 const TargetInstrInfo *
TII =
269 MI.getMF()->getSubtarget<AArch64Subtarget>().getInstrInfo();
270 MachineInstrBuilder MIB =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
271 TII->get(
Opc),
MI.getOperand(0).getReg());
272 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2)
275 MI.eraseFromParent();
280 "SME Peephole Optimization",
false,
false)
283 if (skipFunction(MF.getFunction()))
289 assert(MF.getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
292 bool FunctionHasAllSMChangesRemoved =
false;
298 bool BlockHasAllSMChangesRemoved;
299 Changed |= optimizeStartStopPairs(
MBB, BlockHasAllSMChangesRemoved);
300 FunctionHasAllSMChangesRemoved |= BlockHasAllSMChangesRemoved;
304 if (
MI.getOpcode() == AArch64::REG_SEQUENCE)
310 if (FunctionHasAllSMChangesRemoved)
unsigned const MachineRegisterInfo * MRI
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.
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, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
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,...
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
StringRef - 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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...