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) &&
234 if ((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::MOVZWi) &&
235 (SecondMI.
getOpcode() == AArch64::MOVKWi &&
240 if((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::MOVZXi) &&
241 (SecondMI.
getOpcode() == AArch64::MOVKXi &&
246 if ((FirstMI ==
nullptr ||
247 (FirstMI->
getOpcode() == AArch64::MOVKXi &&
249 (SecondMI.
getOpcode() == AArch64::MOVKXi &&
260 case AArch64::STRBBui:
261 case AArch64::STRBui:
262 case AArch64::STRDui:
263 case AArch64::STRHHui:
264 case AArch64::STRHui:
265 case AArch64::STRQui:
266 case AArch64::STRSui:
267 case AArch64::STRWui:
268 case AArch64::STRXui:
269 case AArch64::LDRBBui:
270 case AArch64::LDRBui:
271 case AArch64::LDRDui:
272 case AArch64::LDRHHui:
273 case AArch64::LDRHui:
274 case AArch64::LDRQui:
275 case AArch64::LDRSui:
276 case AArch64::LDRWui:
277 case AArch64::LDRXui:
278 case AArch64::LDRSBWui:
279 case AArch64::LDRSBXui:
280 case AArch64::LDRSHWui:
281 case AArch64::LDRSHXui:
282 case AArch64::LDRSWui:
284 if (FirstMI ==
nullptr)
302 if (SecondMI.
getOpcode() == AArch64::CSELWr) {
304 if (FirstMI ==
nullptr)
309 case AArch64::SUBSWrs:
310 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
311 case AArch64::SUBSWrx:
312 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
313 case AArch64::SUBSWrr:
314 case AArch64::SUBSWri:
320 if (SecondMI.
getOpcode() == AArch64::CSELXr) {
322 if (FirstMI ==
nullptr)
327 case AArch64::SUBSXrs:
328 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
329 case AArch64::SUBSXrx:
330 case AArch64::SUBSXrx64:
331 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
332 case AArch64::SUBSXrr:
333 case AArch64::SUBSXri:
345 case AArch64::FCSELSrrr:
346 case AArch64::FCSELDrrr:
347 case AArch64::FCSELHrrr:
354 if (FirstMI ==
nullptr)
358 case AArch64::FCMPSrr:
359 case AArch64::FCMPDrr:
360 case AArch64::FCMPESrr:
361 case AArch64::FCMPEDrr:
362 case AArch64::FCMPHrr:
363 case AArch64::FCMPEHrr:
373 if ((SecondMI.
getOpcode() == AArch64::CSINCWr &&
376 (SecondMI.
getOpcode() == AArch64::CSINCXr &&
380 if (FirstMI ==
nullptr)
386 case AArch64::SUBSWrs:
387 case AArch64::SUBSXrs:
388 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
389 case AArch64::SUBSWrx:
390 case AArch64::SUBSXrx:
391 case AArch64::SUBSXrx64:
392 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
393 case AArch64::SUBSWri:
394 case AArch64::SUBSWrr:
395 case AArch64::SUBSXri:
396 case AArch64::SUBSXrr:
407 if (AArch64InstrInfo::hasShiftedReg(SecondMI))
412 case AArch64::ADDWrr:
413 case AArch64::ADDXrr:
414 case AArch64::SUBWrr:
415 case AArch64::SUBXrr:
416 case AArch64::ADDWrs:
417 case AArch64::ADDXrs:
418 case AArch64::SUBWrs:
419 case AArch64::SUBXrs:
421 case AArch64::ANDWrr:
422 case AArch64::ANDXrr:
423 case AArch64::BICWrr:
424 case AArch64::BICXrr:
425 case AArch64::EONWrr:
426 case AArch64::EONXrr:
427 case AArch64::EORWrr:
428 case AArch64::EORXrr:
429 case AArch64::ORNWrr:
430 case AArch64::ORNXrr:
431 case AArch64::ORRWrr:
432 case AArch64::ORRXrr:
433 case AArch64::ANDWrs:
434 case AArch64::ANDXrs:
435 case AArch64::BICWrs:
436 case AArch64::BICXrs:
437 case AArch64::EONWrs:
438 case AArch64::EONXrs:
439 case AArch64::EORWrs:
440 case AArch64::EORXrs:
441 case AArch64::ORNWrs:
442 case AArch64::ORNXrs:
443 case AArch64::ORRWrs:
444 case AArch64::ORRXrs:
446 if (FirstMI ==
nullptr)
451 case AArch64::ADDWrr:
452 case AArch64::ADDXrr:
453 case AArch64::ADDSWrr:
454 case AArch64::ADDSXrr:
455 case AArch64::SUBWrr:
456 case AArch64::SUBXrr:
457 case AArch64::SUBSWrr:
458 case AArch64::SUBSXrr:
460 case AArch64::ADDWrs:
461 case AArch64::ADDXrs:
462 case AArch64::ADDSWrs:
463 case AArch64::ADDSXrs:
464 case AArch64::SUBWrs:
465 case AArch64::SUBXrs:
466 case AArch64::SUBSWrs:
467 case AArch64::SUBSXrs:
468 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
473 case AArch64::ADDSWrr:
474 case AArch64::ADDSXrr:
475 case AArch64::SUBSWrr:
476 case AArch64::SUBSXrr:
477 case AArch64::ADDSWrs:
478 case AArch64::ADDSXrs:
479 case AArch64::SUBSWrs:
480 case AArch64::SUBSXrs:
482 if (FirstMI ==
nullptr)
487 case AArch64::ADDWrr:
488 case AArch64::ADDXrr:
489 case AArch64::SUBWrr:
490 case AArch64::SUBXrr:
492 case AArch64::ADDWrs:
493 case AArch64::ADDXrs:
494 case AArch64::SUBWrs:
495 case AArch64::SUBXrs:
496 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
507 bool NeedsSubtract =
false;
511 case AArch64::SUBWri:
512 case AArch64::SUBXri:
513 NeedsSubtract =
true;
515 case AArch64::ADDWri:
516 case AArch64::ADDXri:
529 if (FirstMI ==
nullptr) {
534 case AArch64::SUBWrs:
535 case AArch64::SUBXrs:
536 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
539 case AArch64::SUBWrr:
540 case AArch64::SUBXrr:
546 case AArch64::ADDWrs:
547 case AArch64::ADDXrs:
548 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
551 case AArch64::ADDWrr:
552 case AArch64::ADDXrr:
553 if (!NeedsSubtract) {
566 return MI.definesRegister(
Reg,
TRI);
580 const bool ReadOrWriteZA =
MI.readsRegister(AArch64::ZA,
TRI) ||
581 MI.definesRegister(AArch64::ZA,
TRI);
588 if (
MI.mayLoad() ||
MI.mayStore())
602 if (
MI.readsRegister(AArch64::NZCV,
TRI) ||
603 MI.definesRegister(AArch64::NZCV,
TRI))
610 if (ReadGPR && !ReadOrWriteZA)
623 if (FirstMI ==
nullptr)
634 case AArch64::FMAXHrr:
635 case AArch64::FMAXSrr:
636 case AArch64::FMAXDrr:
637 case AArch64::FMINHrr:
638 case AArch64::FMINSrr:
639 case AArch64::FMINDrr:
641 case AArch64::FMAXv4f16:
642 case AArch64::FMAXv8f16:
643 case AArch64::FMAXv2f32:
644 case AArch64::FMAXv4f32:
645 case AArch64::FMAXv2f64:
646 case AArch64::FMINv4f16:
647 case AArch64::FMINv8f16:
648 case AArch64::FMINv2f32:
649 case AArch64::FMINv4f32:
650 case AArch64::FMINv2f64:
664 if (FirstMI ==
nullptr)
688 if (ST.hasFuseAppleSMECompute() &&
690 ++NumFusedAppleSMECompute;
698 if (ST.hasCmpBccFusion() || ST.hasArithmeticBccFusion()) {
699 bool CmpOnly = !ST.hasArithmeticBccFusion();
701 ++NumFusedArithmeticBcc;
706 ++NumFusedArithmeticCbz;
709 if (ST.hasFuseAES() &&
isAESPair(FirstMI, SecondMI,
TRI)) {
717 if (ST.hasFuseAdrpAdd() &&
isAdrpAddPair(FirstMI, SecondMI)) {
729 if (ST.hasFuseCmpCSel() &&
isCmpCSelPair(FirstMI, SecondMI)) {
737 if (ST.hasFuseCmpCSet() &&
isCmpCSetPair(FirstMI, SecondMI)) {
742 ++NumFusedArithmeticLogic;
745 if (ST.hasFuseAddSub2RegAndConstOne() &&
747 ++NumFusedAddSub2RegAndConstOne;
758std::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)
static bool isLiteralsPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Literal generation.
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