20#define DEBUG_TYPE "aarch64-macro-fusion"
24STATISTIC(NumFusedArithmeticBcc,
"Number of arithmetic-Bcc fusions");
25STATISTIC(NumFusedArithmeticCbz,
"Number of arithmetic-Cbz fusions");
27STATISTIC(NumFusedCryptoEOR,
"Number of crypto-EOR fusions");
28STATISTIC(NumFusedAdrpAdd,
"Number of ADRP-ADD fusions");
29STATISTIC(NumFusedLiterals,
"Number of literal-generation fusions");
30STATISTIC(NumFusedAddress,
"Number of address-generation load/store fusions");
31STATISTIC(NumFusedCmpCSel,
"Number of compare-CSEL fusions");
32STATISTIC(NumFusedFCmpFCSel,
"Number of FP-compare-FCSEL fusions");
33STATISTIC(NumFusedCmpCSet,
"Number of compare-CSET fusions");
34STATISTIC(NumFusedArithmeticLogic,
"Number of arithmetic-logic fusions");
36 "Number of add/sub-two-register-and-constant-one fusions");
37STATISTIC(NumFusedAppleSMECompute,
"Number of Apple SME compute fusions");
38STATISTIC(NumFusedFMinFMax,
"Number of FMIN-FMAX fusions");
47 if (FirstMI ==
nullptr)
59 case AArch64::ADDSWri:
60 case AArch64::ADDSWrr:
61 case AArch64::ADDSXri:
62 case AArch64::ADDSXrr:
63 case AArch64::ANDSWri:
64 case AArch64::ANDSWrr:
65 case AArch64::ANDSXri:
66 case AArch64::ANDSXrr:
67 case AArch64::SUBSWri:
68 case AArch64::SUBSWrr:
69 case AArch64::SUBSXri:
70 case AArch64::SUBSXrr:
71 case AArch64::BICSWrr:
72 case AArch64::BICSXrr:
74 case AArch64::ADDSWrs:
75 case AArch64::ADDSXrs:
76 case AArch64::ANDSWrs:
77 case AArch64::ANDSXrs:
78 case AArch64::SUBSWrs:
79 case AArch64::SUBSXrs:
80 case AArch64::BICSWrs:
81 case AArch64::BICSXrs:
83 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
92 if (SecondMI.
getOpcode() != AArch64::CBZW &&
103 if (FirstMI ==
nullptr)
107 case AArch64::ADDWri:
108 case AArch64::ADDWrr:
109 case AArch64::ADDXri:
110 case AArch64::ADDXrr:
111 case AArch64::ANDWri:
112 case AArch64::ANDWrr:
113 case AArch64::ANDXri:
114 case AArch64::ANDXrr:
115 case AArch64::EORWri:
116 case AArch64::EORWrr:
117 case AArch64::EORXri:
118 case AArch64::EORXrr:
119 case AArch64::ORRWri:
120 case AArch64::ORRWrr:
121 case AArch64::ORRXri:
122 case AArch64::ORRXrr:
123 case AArch64::ORNWrr:
124 case AArch64::ORNXrr:
125 case AArch64::SUBWri:
126 case AArch64::SUBWrr:
127 case AArch64::SUBXri:
128 case AArch64::SUBXrr:
129 case AArch64::BICWrr:
130 case AArch64::BICXrr:
132 case AArch64::ADDWrs:
133 case AArch64::ADDXrs:
134 case AArch64::ANDWrs:
135 case AArch64::ANDXrs:
136 case AArch64::EORWrs:
137 case AArch64::EORXrs:
138 case AArch64::ORNWrs:
139 case AArch64::ORNXrs:
140 case AArch64::ORRWrs:
141 case AArch64::ORRXrs:
142 case AArch64::SUBWrs:
143 case AArch64::SUBXrs:
144 case AArch64::BICWrs:
145 case AArch64::BICXrs:
147 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
165 return TRI->regsOverlap(DestFirst, DestSecond);
172 unsigned SecondOpcode = SecondMI.
getOpcode();
173 switch (SecondOpcode) {
175 case AArch64::AESMCrr:
176 case AArch64::AESMCrrTied:
177 if (FirstMI ==
nullptr)
179 if (FirstMI->
getOpcode() != AArch64::AESErr)
181 return SecondOpcode == AArch64::AESMCrrTied ||
184 case AArch64::AESIMCrr:
185 case AArch64::AESIMCrrTied:
186 if (FirstMI ==
nullptr)
188 if (FirstMI->
getOpcode() != AArch64::AESDrr)
190 return SecondOpcode == AArch64::AESIMCrrTied ||
200 if (SecondMI.
getOpcode() != AArch64::EORv16i8)
204 if (FirstMI ==
nullptr)
208 case AArch64::AESErr:
209 case AArch64::AESDrr:
210 case AArch64::PMULLv16i8:
211 case AArch64::PMULLv8i8:
212 case AArch64::PMULLv1i64:
213 case AArch64::PMULLv2i64:
223 if ((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::ADRP) &&
233 case AArch64::STRBBui:
234 case AArch64::STRBui:
235 case AArch64::STRDui:
236 case AArch64::STRHHui:
237 case AArch64::STRHui:
238 case AArch64::STRQui:
239 case AArch64::STRSui:
240 case AArch64::STRWui:
241 case AArch64::STRXui:
242 case AArch64::LDRBBui:
243 case AArch64::LDRBui:
244 case AArch64::LDRDui:
245 case AArch64::LDRHHui:
246 case AArch64::LDRHui:
247 case AArch64::LDRQui:
248 case AArch64::LDRSui:
249 case AArch64::LDRWui:
250 case AArch64::LDRXui:
251 case AArch64::LDRSBWui:
252 case AArch64::LDRSBXui:
253 case AArch64::LDRSHWui:
254 case AArch64::LDRSHXui:
255 case AArch64::LDRSWui:
257 if (FirstMI ==
nullptr)
275 if (SecondMI.
getOpcode() == AArch64::CSELWr) {
277 if (FirstMI ==
nullptr)
282 case AArch64::SUBSWrs:
283 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
284 case AArch64::SUBSWrx:
285 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
286 case AArch64::SUBSWrr:
287 case AArch64::SUBSWri:
293 if (SecondMI.
getOpcode() == AArch64::CSELXr) {
295 if (FirstMI ==
nullptr)
300 case AArch64::SUBSXrs:
301 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
302 case AArch64::SUBSXrx:
303 case AArch64::SUBSXrx64:
304 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
305 case AArch64::SUBSXrr:
306 case AArch64::SUBSXri:
318 case AArch64::FCSELSrrr:
319 case AArch64::FCSELDrrr:
320 case AArch64::FCSELHrrr:
327 if (FirstMI ==
nullptr)
331 case AArch64::FCMPSrr:
332 case AArch64::FCMPDrr:
333 case AArch64::FCMPESrr:
334 case AArch64::FCMPEDrr:
335 case AArch64::FCMPHrr:
336 case AArch64::FCMPEHrr:
346 if ((SecondMI.
getOpcode() == AArch64::CSINCWr &&
349 (SecondMI.
getOpcode() == AArch64::CSINCXr &&
353 if (FirstMI ==
nullptr)
359 case AArch64::SUBSWrs:
360 case AArch64::SUBSXrs:
361 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
362 case AArch64::SUBSWrx:
363 case AArch64::SUBSXrx:
364 case AArch64::SUBSXrx64:
365 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
366 case AArch64::SUBSWri:
367 case AArch64::SUBSWrr:
368 case AArch64::SUBSXri:
369 case AArch64::SUBSXrr:
380 if (AArch64InstrInfo::hasShiftedReg(SecondMI))
385 case AArch64::ADDWrr:
386 case AArch64::ADDXrr:
387 case AArch64::SUBWrr:
388 case AArch64::SUBXrr:
389 case AArch64::ADDWrs:
390 case AArch64::ADDXrs:
391 case AArch64::SUBWrs:
392 case AArch64::SUBXrs:
394 case AArch64::ANDWrr:
395 case AArch64::ANDXrr:
396 case AArch64::BICWrr:
397 case AArch64::BICXrr:
398 case AArch64::EONWrr:
399 case AArch64::EONXrr:
400 case AArch64::EORWrr:
401 case AArch64::EORXrr:
402 case AArch64::ORNWrr:
403 case AArch64::ORNXrr:
404 case AArch64::ORRWrr:
405 case AArch64::ORRXrr:
406 case AArch64::ANDWrs:
407 case AArch64::ANDXrs:
408 case AArch64::BICWrs:
409 case AArch64::BICXrs:
410 case AArch64::EONWrs:
411 case AArch64::EONXrs:
412 case AArch64::EORWrs:
413 case AArch64::EORXrs:
414 case AArch64::ORNWrs:
415 case AArch64::ORNXrs:
416 case AArch64::ORRWrs:
417 case AArch64::ORRXrs:
419 if (FirstMI ==
nullptr)
424 case AArch64::ADDWrr:
425 case AArch64::ADDXrr:
426 case AArch64::ADDSWrr:
427 case AArch64::ADDSXrr:
428 case AArch64::SUBWrr:
429 case AArch64::SUBXrr:
430 case AArch64::SUBSWrr:
431 case AArch64::SUBSXrr:
433 case AArch64::ADDWrs:
434 case AArch64::ADDXrs:
435 case AArch64::ADDSWrs:
436 case AArch64::ADDSXrs:
437 case AArch64::SUBWrs:
438 case AArch64::SUBXrs:
439 case AArch64::SUBSWrs:
440 case AArch64::SUBSXrs:
441 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
446 case AArch64::ADDSWrr:
447 case AArch64::ADDSXrr:
448 case AArch64::SUBSWrr:
449 case AArch64::SUBSXrr:
450 case AArch64::ADDSWrs:
451 case AArch64::ADDSXrs:
452 case AArch64::SUBSWrs:
453 case AArch64::SUBSXrs:
455 if (FirstMI ==
nullptr)
460 case AArch64::ADDWrr:
461 case AArch64::ADDXrr:
462 case AArch64::SUBWrr:
463 case AArch64::SUBXrr:
465 case AArch64::ADDWrs:
466 case AArch64::ADDXrs:
467 case AArch64::SUBWrs:
468 case AArch64::SUBXrs:
469 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
480 bool NeedsSubtract =
false;
484 case AArch64::SUBWri:
485 case AArch64::SUBXri:
486 NeedsSubtract =
true;
488 case AArch64::ADDWri:
489 case AArch64::ADDXri:
502 if (FirstMI ==
nullptr) {
507 case AArch64::SUBWrs:
508 case AArch64::SUBXrs:
509 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
512 case AArch64::SUBWrr:
513 case AArch64::SUBXrr:
519 case AArch64::ADDWrs:
520 case AArch64::ADDXrs:
521 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
524 case AArch64::ADDWrr:
525 case AArch64::ADDXrr:
526 if (!NeedsSubtract) {
539 return MI.definesRegister(
Reg,
TRI);
553 const bool ReadOrWriteZA =
MI.readsRegister(AArch64::ZA,
TRI) ||
554 MI.definesRegister(AArch64::ZA,
TRI);
561 if (
MI.mayLoad() ||
MI.mayStore())
575 if (
MI.readsRegister(AArch64::NZCV,
TRI) ||
576 MI.definesRegister(AArch64::NZCV,
TRI))
583 if (ReadGPR && !ReadOrWriteZA)
596 if (FirstMI ==
nullptr)
607 case AArch64::FMAXHrr:
608 case AArch64::FMAXSrr:
609 case AArch64::FMAXDrr:
610 case AArch64::FMINHrr:
611 case AArch64::FMINSrr:
612 case AArch64::FMINDrr:
614 case AArch64::FMAXv4f16:
615 case AArch64::FMAXv8f16:
616 case AArch64::FMAXv2f32:
617 case AArch64::FMAXv4f32:
618 case AArch64::FMAXv2f64:
619 case AArch64::FMINv4f16:
620 case AArch64::FMINv8f16:
621 case AArch64::FMINv2f32:
622 case AArch64::FMINv4f32:
623 case AArch64::FMINv2f64:
637 if (FirstMI ==
nullptr)
661 if (ST.hasFuseAppleSMECompute() &&
663 ++NumFusedAppleSMECompute;
671 if (ST.hasCmpBccFusion() || ST.hasArithmeticBccFusion()) {
672 bool CmpOnly = !ST.hasArithmeticBccFusion();
674 ++NumFusedArithmeticBcc;
679 ++NumFusedArithmeticCbz;
682 if (ST.hasFuseAES() &&
isAESPair(FirstMI, SecondMI,
TRI)) {
690 if (ST.hasFuseAdrpAdd() &&
isAdrpAddPair(FirstMI, SecondMI)) {
694 if (ST.hasFuseLiterals() && ST.fusesMOVImmPair(FirstMI, SecondMI)) {
702 if (ST.hasFuseCmpCSel() &&
isCmpCSelPair(FirstMI, SecondMI)) {
710 if (ST.hasFuseCmpCSet() &&
isCmpCSetPair(FirstMI, SecondMI)) {
715 ++NumFusedArithmeticLogic;
718 if (ST.hasFuseAddSub2RegAndConstOne() &&
720 ++NumFusedAddSub2RegAndConstOne;
731std::unique_ptr<ScheduleDAGMutation>
static bool isFusableAppleSMEComputeOp(const MachineInstr &MI, const TargetInstrInfo &TII, const TargetRegisterInfo *TRI)
static bool isFCmpFCSelPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Floating-point compare and floating-point conditional select.
static bool isAddSub2RegAndConstOnePair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
static bool isCmpCSelPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Compare and conditional select.
static bool isArithmeticBccPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI, bool CmpOnly)
CMN, CMP, TST followed by Bcc.
static bool isAddressLdStPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Fuse address generation and loads or stores.
static bool isFMinFMaxPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI, const TargetRegisterInfo *TRI)
static bool isArithmeticCbzPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
ALU operations followed by CBZ/CBNZ.
static bool isCmpCSetPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Compare and cset.
static bool isAdrpAddPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
static bool isAESPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI, const TargetRegisterInfo *TRI)
AES crypto encoding or decoding.
static bool readsRegInClass(const MachineInstr &MI, const TargetRegisterInfo *TRI, const TargetRegisterClass &Class)
static bool definesRegInClass(const MachineInstr &MI, const TargetRegisterInfo *TRI, const TargetRegisterClass &Class)
static bool isArithmeticLogicPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
static bool isFMinFMax(unsigned Opcode)
static bool mayHaveWAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI, const TargetRegisterInfo *TRI)
static bool isCryptoEORPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
AESE/AESD/PMULL + EOR.
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI, const SDep *Dep)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
static bool isAppleSMEComputePair(const MachineInstr *FirstMI, const MachineInstr &SecondMI, const TargetInstrInfo &TII, const TargetRegisterInfo *TRI)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
const MachineOperand & getOperand(unsigned i) const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createMacroFusionDAGMutation(ArrayRef< MacroFusionPredTy > Predicates, bool BranchOnly=false)
Create a DAG scheduling mutation to pair instructions back to back for instructions that benefit acco...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
std::unique_ptr< ScheduleDAGMutation > createAArch64MacroFusionDAGMutation()
Note that you have to add: DAG.addMutation(createAArch64MacroFusionDAGMutation()); to AArch64TargetMa...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI, const SDep *Dep)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
LLVM_ABI bool isNonDataDep(const SDep *Dep)
Returns true if Dep is a non-null non-data dependency.
MCRegisterClass TargetRegisterClass