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);
162 return DestFirst == DestSecond;
169 unsigned SecondOpcode = SecondMI.
getOpcode();
170 switch (SecondOpcode) {
172 case AArch64::AESMCrr:
173 case AArch64::AESMCrrTied:
174 if (FirstMI ==
nullptr)
176 if (FirstMI->
getOpcode() != AArch64::AESErr)
178 return SecondOpcode == AArch64::AESMCrrTied ||
181 case AArch64::AESIMCrr:
182 case AArch64::AESIMCrrTied:
183 if (FirstMI ==
nullptr)
185 if (FirstMI->
getOpcode() != AArch64::AESDrr)
187 return SecondOpcode == AArch64::AESIMCrrTied ||
197 if (SecondMI.
getOpcode() != AArch64::EORv16i8)
201 if (FirstMI ==
nullptr)
205 case AArch64::AESErr:
206 case AArch64::AESDrr:
207 case AArch64::PMULLv16i8:
208 case AArch64::PMULLv8i8:
209 case AArch64::PMULLv1i64:
210 case AArch64::PMULLv2i64:
220 if ((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::ADRP) &&
231 if ((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::MOVZWi) &&
232 (SecondMI.
getOpcode() == AArch64::MOVKWi &&
237 if((FirstMI ==
nullptr || FirstMI->
getOpcode() == AArch64::MOVZXi) &&
238 (SecondMI.
getOpcode() == AArch64::MOVKXi &&
243 if ((FirstMI ==
nullptr ||
244 (FirstMI->
getOpcode() == AArch64::MOVKXi &&
246 (SecondMI.
getOpcode() == AArch64::MOVKXi &&
257 case AArch64::STRBBui:
258 case AArch64::STRBui:
259 case AArch64::STRDui:
260 case AArch64::STRHHui:
261 case AArch64::STRHui:
262 case AArch64::STRQui:
263 case AArch64::STRSui:
264 case AArch64::STRWui:
265 case AArch64::STRXui:
266 case AArch64::LDRBBui:
267 case AArch64::LDRBui:
268 case AArch64::LDRDui:
269 case AArch64::LDRHHui:
270 case AArch64::LDRHui:
271 case AArch64::LDRQui:
272 case AArch64::LDRSui:
273 case AArch64::LDRWui:
274 case AArch64::LDRXui:
275 case AArch64::LDRSBWui:
276 case AArch64::LDRSBXui:
277 case AArch64::LDRSHWui:
278 case AArch64::LDRSHXui:
279 case AArch64::LDRSWui:
281 if (FirstMI ==
nullptr)
299 if (SecondMI.
getOpcode() == AArch64::CSELWr) {
301 if (FirstMI ==
nullptr)
306 case AArch64::SUBSWrs:
307 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
308 case AArch64::SUBSWrx:
309 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
310 case AArch64::SUBSWrr:
311 case AArch64::SUBSWri:
317 if (SecondMI.
getOpcode() == AArch64::CSELXr) {
319 if (FirstMI ==
nullptr)
324 case AArch64::SUBSXrs:
325 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
326 case AArch64::SUBSXrx:
327 case AArch64::SUBSXrx64:
328 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
329 case AArch64::SUBSXrr:
330 case AArch64::SUBSXri:
342 case AArch64::FCSELSrrr:
343 case AArch64::FCSELDrrr:
344 case AArch64::FCSELHrrr:
351 if (FirstMI ==
nullptr)
355 case AArch64::FCMPSrr:
356 case AArch64::FCMPDrr:
357 case AArch64::FCMPESrr:
358 case AArch64::FCMPEDrr:
359 case AArch64::FCMPHrr:
360 case AArch64::FCMPEHrr:
370 if ((SecondMI.
getOpcode() == AArch64::CSINCWr &&
373 (SecondMI.
getOpcode() == AArch64::CSINCXr &&
377 if (FirstMI ==
nullptr)
383 case AArch64::SUBSWrs:
384 case AArch64::SUBSXrs:
385 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
386 case AArch64::SUBSWrx:
387 case AArch64::SUBSXrx:
388 case AArch64::SUBSXrx64:
389 return !AArch64InstrInfo::hasExtendedReg(*FirstMI);
390 case AArch64::SUBSWri:
391 case AArch64::SUBSWrr:
392 case AArch64::SUBSXri:
393 case AArch64::SUBSXrr:
404 if (AArch64InstrInfo::hasShiftedReg(SecondMI))
409 case AArch64::ADDWrr:
410 case AArch64::ADDXrr:
411 case AArch64::SUBWrr:
412 case AArch64::SUBXrr:
413 case AArch64::ADDWrs:
414 case AArch64::ADDXrs:
415 case AArch64::SUBWrs:
416 case AArch64::SUBXrs:
418 case AArch64::ANDWrr:
419 case AArch64::ANDXrr:
420 case AArch64::BICWrr:
421 case AArch64::BICXrr:
422 case AArch64::EONWrr:
423 case AArch64::EONXrr:
424 case AArch64::EORWrr:
425 case AArch64::EORXrr:
426 case AArch64::ORNWrr:
427 case AArch64::ORNXrr:
428 case AArch64::ORRWrr:
429 case AArch64::ORRXrr:
430 case AArch64::ANDWrs:
431 case AArch64::ANDXrs:
432 case AArch64::BICWrs:
433 case AArch64::BICXrs:
434 case AArch64::EONWrs:
435 case AArch64::EONXrs:
436 case AArch64::EORWrs:
437 case AArch64::EORXrs:
438 case AArch64::ORNWrs:
439 case AArch64::ORNXrs:
440 case AArch64::ORRWrs:
441 case AArch64::ORRXrs:
443 if (FirstMI ==
nullptr)
448 case AArch64::ADDWrr:
449 case AArch64::ADDXrr:
450 case AArch64::ADDSWrr:
451 case AArch64::ADDSXrr:
452 case AArch64::SUBWrr:
453 case AArch64::SUBXrr:
454 case AArch64::SUBSWrr:
455 case AArch64::SUBSXrr:
457 case AArch64::ADDWrs:
458 case AArch64::ADDXrs:
459 case AArch64::ADDSWrs:
460 case AArch64::ADDSXrs:
461 case AArch64::SUBWrs:
462 case AArch64::SUBXrs:
463 case AArch64::SUBSWrs:
464 case AArch64::SUBSXrs:
465 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
470 case AArch64::ADDSWrr:
471 case AArch64::ADDSXrr:
472 case AArch64::SUBSWrr:
473 case AArch64::SUBSXrr:
474 case AArch64::ADDSWrs:
475 case AArch64::ADDSXrs:
476 case AArch64::SUBSWrs:
477 case AArch64::SUBSXrs:
479 if (FirstMI ==
nullptr)
484 case AArch64::ADDWrr:
485 case AArch64::ADDXrr:
486 case AArch64::SUBWrr:
487 case AArch64::SUBXrr:
489 case AArch64::ADDWrs:
490 case AArch64::ADDXrs:
491 case AArch64::SUBWrs:
492 case AArch64::SUBXrs:
493 return !AArch64InstrInfo::hasShiftedReg(*FirstMI);
504 bool NeedsSubtract =
false;
508 case AArch64::SUBWri:
509 case AArch64::SUBXri:
510 NeedsSubtract =
true;
512 case AArch64::ADDWri:
513 case AArch64::ADDXri:
526 if (FirstMI ==
nullptr) {
531 case AArch64::SUBWrs:
532 case AArch64::SUBXrs:
533 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
536 case AArch64::SUBWrr:
537 case AArch64::SUBXrr:
543 case AArch64::ADDWrs:
544 case AArch64::ADDXrs:
545 if (AArch64InstrInfo::hasShiftedReg(*FirstMI))
548 case AArch64::ADDWrr:
549 case AArch64::ADDXrr:
550 if (!NeedsSubtract) {
563 return MI.definesRegister(
Reg,
TRI);
577 const bool ReadOrWriteZA =
MI.readsRegister(AArch64::ZA,
TRI) ||
578 MI.definesRegister(AArch64::ZA,
TRI);
585 if (
MI.mayLoad() ||
MI.mayStore())
599 if (
MI.readsRegister(AArch64::NZCV,
TRI) ||
600 MI.definesRegister(AArch64::NZCV,
TRI))
607 if (ReadGPR && !ReadOrWriteZA)
620 if (FirstMI ==
nullptr)
631 case AArch64::FMAXHrr:
632 case AArch64::FMAXSrr:
633 case AArch64::FMAXDrr:
634 case AArch64::FMINHrr:
635 case AArch64::FMINSrr:
636 case AArch64::FMINDrr:
638 case AArch64::FMAXv4f16:
639 case AArch64::FMAXv8f16:
640 case AArch64::FMAXv2f32:
641 case AArch64::FMAXv4f32:
642 case AArch64::FMAXv2f64:
643 case AArch64::FMINv4f16:
644 case AArch64::FMINv8f16:
645 case AArch64::FMINv2f32:
646 case AArch64::FMINv4f32:
647 case AArch64::FMINv2f64:
660 if (FirstMI ==
nullptr)
684 if (ST.hasFuseAppleSMECompute() &&
686 ++NumFusedAppleSMECompute;
694 if (ST.hasCmpBccFusion() || ST.hasArithmeticBccFusion()) {
695 bool CmpOnly = !ST.hasArithmeticBccFusion();
697 ++NumFusedArithmeticBcc;
702 ++NumFusedArithmeticCbz;
705 if (ST.hasFuseAES() &&
isAESPair(FirstMI, SecondMI)) {
713 if (ST.hasFuseAdrpAdd() &&
isAdrpAddPair(FirstMI, SecondMI)) {
725 if (ST.hasFuseCmpCSel() &&
isCmpCSelPair(FirstMI, SecondMI)) {
733 if (ST.hasFuseCmpCSet() &&
isCmpCSetPair(FirstMI, SecondMI)) {
738 ++NumFusedArithmeticLogic;
741 if (ST.hasFuseAddSub2RegAndConstOne() &&
743 ++NumFusedAddSub2RegAndConstOne;
754std::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 isFMinFMaxPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
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 isArithmeticCbzPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
ALU operations followed by CBZ/CBNZ.
static bool isAESPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
AES crypto encoding or decoding.
static bool isCmpCSetPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Compare and cset.
static bool isAdrpAddPair(const MachineInstr *FirstMI, const MachineInstr &SecondMI)
static bool readsRegInClass(const MachineInstr &MI, const TargetRegisterInfo *TRI, const TargetRegisterClass &Class)
static bool mayHaveWAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI)
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 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