27#define DEBUG_TYPE "aarch64-post-select-optimize"
36 AArch64PostSelectOptimize();
39 return "AArch64 Post Select Optimizer";
55void AArch64PostSelectOptimize::getAnalysisUsage(
AnalysisUsage &AU)
const {
62AArch64PostSelectOptimize::AArch64PostSelectOptimize()
71 case AArch64::SUBSXrr:
72 return AArch64::SUBXrr;
73 case AArch64::SUBSWrr:
74 return AArch64::SUBWrr;
75 case AArch64::SUBSXrs:
76 return AArch64::SUBXrs;
77 case AArch64::SUBSWrs:
78 return AArch64::SUBWrs;
79 case AArch64::SUBSXri:
80 return AArch64::SUBXri;
81 case AArch64::SUBSWri:
82 return AArch64::SUBWri;
83 case AArch64::ADDSXrr:
84 return AArch64::ADDXrr;
85 case AArch64::ADDSWrr:
86 return AArch64::ADDWrr;
87 case AArch64::ADDSXrs:
88 return AArch64::ADDXrs;
89 case AArch64::ADDSWrs:
90 return AArch64::ADDWrs;
91 case AArch64::ADDSXri:
92 return AArch64::ADDXri;
93 case AArch64::ADDSWri:
94 return AArch64::ADDWri;
96 return AArch64::SBCXr;
98 return AArch64::SBCWr;
100 return AArch64::ADCXr;
101 case AArch64::ADCSWr:
102 return AArch64::ADCWr;
107 bool Changed =
false;
109 bool CurrentIterChanged = foldSimpleCrossClassCopies(
MI);
110 if (!CurrentIterChanged)
111 CurrentIterChanged |= foldCopyDup(
MI);
112 Changed |= CurrentIterChanged;
117bool AArch64PostSelectOptimize::foldSimpleCrossClassCopies(
MachineInstr &
MI) {
118 auto *MF =
MI.getMF();
119 auto &
MRI = MF->getRegInfo();
124 if (
MI.getOperand(1).getSubReg())
130 if (Src.isPhysical() || Dst.isPhysical())
145 if (!
MRI.hasOneNonDBGUse(Src))
150 if (!
MRI.constrainRegClass(Src, DstRC, 25))
160 MRI.replaceRegWith(Dst, Src);
161 MI.eraseFromParent();
169 auto *MF =
MI.getMF();
170 auto &
MRI = MF->getRegInfo();
171 auto *
TII = MF->getSubtarget().getInstrInfo();
178 if (!Dst.isVirtual() || !Src.isVirtual())
184 if (
MRI.getRegClassOrNull(Dst) != GPRRegClass ||
185 MRI.getRegClassOrNull(Src) != FPRRegClass)
192 for (
auto &
Use :
MRI.use_nodbg_instructions(Dst)) {
201 if (
MRI.getRegClassOrNull(UseOp0) == FPRRegClass &&
202 MRI.getRegClassOrNull(UseOp1) == GPRRegClass)
217 MI.eraseFromParent();
221 return TryMatchDUP(&AArch64::GPR32RegClass, &AArch64::FPR32RegClass,
222 AArch64::DUPi32, AArch64::UMOVvi32) ||
223 TryMatchDUP(&AArch64::GPR64RegClass, &AArch64::FPR64RegClass,
224 AArch64::DUPi64, AArch64::UMOVvi64);
255 bool Changed =
false;
258 const auto &
TII = Subtarget.getInstrInfo();
259 auto TRI = Subtarget.getRegisterInfo();
260 auto RBI = Subtarget.getRegBankInfo();
261 auto &
MRI = MF.getRegInfo();
264 LRU.addLiveOuts(
MBB);
267 bool NZCVDead = LRU.available(AArch64::NZCV);
268 if (NZCVDead &&
II.definesRegister(AArch64::NZCV,
nullptr)) {
272 II.findRegisterDefOperandIdx(AArch64::NZCV,
nullptr);
273 if (DeadNZCVIdx != -1) {
276 LLVM_DEBUG(
dbgs() <<
"Post-select optimizer: converting flag-setting "
279 II.setDesc(
TII->get(NewOpc));
280 II.removeOperand(DeadNZCVIdx);
285 II.getOperand(0), 0);
290 II.getOperand(DeadNZCVIdx).setIsDead();
294 LRU.stepBackward(
II);
299bool AArch64PostSelectOptimize::runOnMachineFunction(
MachineFunction &MF) {
301 MachineFunctionProperties::Property::FailedISel))
304 MachineFunctionProperties::Property::Selected) &&
305 "Expected a selected MF");
307 bool Changed =
false;
308 for (
auto &BB : MF) {
309 Changed |= optimizeNZCVDefs(BB);
310 Changed |= doPeepholeOpts(BB);
315char AArch64PostSelectOptimize::ID = 0;
317 "Optimize AArch64 selected instructions",
325 return new AArch64PostSelectOptimize();
unsigned const MachineRegisterInfo * MRI
unsigned getNonFlagSettingVariant(unsigned Opc)
Optimize AArch64 selected instructions
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
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.
A set of register units used to track register liveness.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
reverse_iterator rbegin()
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool hasProperty(Property P) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
Target-Independent Code Generator Pass Configuration Options.
bool hasSubClass(const TargetRegisterClass *RC) const
Return true if the specified TargetRegisterClass is a proper sub-class of this TargetRegisterClass.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
A Use represents the edge between a Value definition and its users.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createAArch64PostSelectOptimize()
Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
void initializeAArch64PostSelectOptimizePass(PassRegistry &)