66#define GET_INSTRINFO_CTOR_DTOR
67#include "AArch64GenInstrInfo.inc"
69#define DEBUG_TYPE "AArch64InstrInfo"
71STATISTIC(NumCopyInstrs,
"Number of COPY instructions expanded");
72STATISTIC(NumZCRegMoveInstrsGPR,
"Number of zero-cycle GPR register move "
73 "instructions expanded from canonical COPY");
74STATISTIC(NumZCRegMoveInstrsFPR,
"Number of zero-cycle FPR register move "
75 "instructions expanded from canonical COPY");
76STATISTIC(NumZCZeroingInstrsGPR,
"Number of zero-cycle GPR zeroing "
77 "instructions expanded from canonical COPY");
82 cl::desc(
"Restrict range of CB instructions (DEBUG)"));
86 cl::desc(
"Restrict range of TB[N]Z instructions (DEBUG)"));
90 cl::desc(
"Restrict range of CB[N]Z instructions (DEBUG)"));
94 cl::desc(
"Restrict range of Bcc instructions (DEBUG)"));
98 cl::desc(
"Restrict range of B instructions (DEBUG)"));
102 cl::desc(
"Restrict range of instructions to search for the "
103 "machine-combiner gather pattern optimization"));
108 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
118 switch (
MI.getOpcode()) {
129 if (
MI.getOperand(0).getReg() != AArch64::LR)
138 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::LR)
156 auto Op =
MI.getOpcode();
157 if (
Op == AArch64::INLINEASM ||
Op == AArch64::INLINEASM_BR)
158 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(), MAI);
162 if (
MI.isMetaInstruction())
167 unsigned NumBytes = 0;
177 NumBytes =
Desc.getSize() ?
Desc.getSize() : 4;
180 if (!MFI->shouldSignReturnAddress(*MF))
183 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
191 switch (
Desc.getOpcode()) {
194 return Desc.getSize();
201 case TargetOpcode::STACKMAP:
204 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
206 case TargetOpcode::PATCHPOINT:
209 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
211 case TargetOpcode::STATEPOINT:
213 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
218 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
223 F.getFnAttributeAsParsedInteger(
"patchable-function-entry", 9) * 4;
225 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
226 case TargetOpcode::PATCHABLE_TAIL_CALL:
227 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
231 case TargetOpcode::PATCHABLE_EVENT_CALL:
237 NumBytes =
MI.getOperand(1).getImm();
239 case AArch64::MOVaddr:
240 case AArch64::MOVaddrJT:
241 case AArch64::MOVaddrCP:
242 case AArch64::MOVaddrBA:
243 case AArch64::MOVaddrTLS:
244 case AArch64::MOVaddrEXT: {
248 MI.getOperand(1).getTargetFlags(),
249 Subtarget.isTargetMachO(), Insn);
250 NumBytes = Insn.
size() * 4;
254 case AArch64::MOVi32imm:
255 case AArch64::MOVi64imm: {
257 unsigned BitSize =
Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
260 NumBytes = Insn.
size() * 4;
264 case TargetOpcode::BUNDLE:
265 NumBytes = getInstBundleSize(
MI);
301 case AArch64::CBWPri:
302 case AArch64::CBXPri:
303 case AArch64::CBWPrr:
304 case AArch64::CBXPrr:
312 case AArch64::CBBAssertExt:
313 case AArch64::CBHAssertExt:
344 case AArch64::CBWPri:
345 case AArch64::CBXPri:
346 case AArch64::CBBAssertExt:
347 case AArch64::CBHAssertExt:
348 case AArch64::CBWPrr:
349 case AArch64::CBXPrr:
355 int64_t BrOffset)
const {
357 assert(Bits >= 3 &&
"max branch displacement must be enough to jump"
358 "over conditional branch expansion");
359 return isIntN(Bits, BrOffset / 4);
364 switch (
MI.getOpcode()) {
368 return MI.getOperand(0).getMBB();
373 return MI.getOperand(2).getMBB();
379 return MI.getOperand(1).getMBB();
380 case AArch64::CBWPri:
381 case AArch64::CBXPri:
382 case AArch64::CBBAssertExt:
383 case AArch64::CBHAssertExt:
384 case AArch64::CBWPrr:
385 case AArch64::CBXPrr:
386 return MI.getOperand(3).getMBB();
396 assert(RS &&
"RegScavenger required for long branching");
398 "new block should be inserted for expanding unconditional branch");
401 "restore block should be inserted for restoring clobbered registers");
408 "Branch offsets outside of the signed 33-bit range not supported");
419 RS->enterBasicBlockEnd(
MBB);
422 constexpr Register Reg = AArch64::X16;
423 if (!RS->isRegUsed(Reg)) {
424 insertUnconditionalBranch(
MBB, &NewDestBB,
DL);
435 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
436 if (Scavenged != AArch64::NoRegister) {
437 buildIndirectBranch(Scavenged, NewDestBB);
438 RS->setRegUsed(Scavenged);
447 "Unable to insert indirect branch inside function that has red zone");
470 bool AllowModify)
const {
477 if (
I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
478 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
482 if (!isUnpredicatedTerminator(*
I))
489 unsigned LastOpc = LastInst->
getOpcode();
490 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
505 unsigned SecondLastOpc = SecondLastInst->
getOpcode();
512 LastInst = SecondLastInst;
514 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
519 SecondLastInst = &*
I;
520 SecondLastOpc = SecondLastInst->
getOpcode();
531 LastInst = SecondLastInst;
533 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
535 "unreachable unconditional branches removed above");
544 SecondLastInst = &*
I;
545 SecondLastOpc = SecondLastInst->
getOpcode();
549 if (SecondLastInst &&
I !=
MBB.begin() && isUnpredicatedTerminator(*--
I))
565 I->eraseFromParent();
574 I->eraseFromParent();
583 MachineBranchPredicate &MBP,
584 bool AllowModify)
const {
596 assert(MBP.TrueDest &&
"expected!");
597 MBP.FalseDest = FBB ? FBB :
MBB.getNextNode();
599 MBP.ConditionDef =
nullptr;
600 MBP.SingleUseCondition =
false;
610 if (
I ==
MBB.begin())
626 if (
MI.modifiesRegister(AArch64::NZCV,
nullptr)) {
627 MBP.ConditionDef = &
MI;
636 case AArch64::CBNZX: {
640 MBP.Predicate = (
Opc == AArch64::CBNZX ||
Opc == AArch64::CBNZW)
641 ? MachineBranchPredicate::PRED_NE
642 : MachineBranchPredicate::PRED_EQ;
643 Register CondReg = MBP.LHS.getReg();
652 case AArch64::TBNZX: {
673 Cond[1].setImm(AArch64::CBNZW);
676 Cond[1].setImm(AArch64::CBZW);
679 Cond[1].setImm(AArch64::CBNZX);
682 Cond[1].setImm(AArch64::CBZX);
685 Cond[1].setImm(AArch64::TBNZW);
688 Cond[1].setImm(AArch64::TBZW);
691 Cond[1].setImm(AArch64::TBNZX);
694 Cond[1].setImm(AArch64::TBZX);
698 case AArch64::CBWPri:
699 case AArch64::CBXPri:
700 case AArch64::CBBAssertExt:
701 case AArch64::CBHAssertExt:
702 case AArch64::CBWPrr:
703 case AArch64::CBXPrr: {
716 int *BytesRemoved)
const {
726 I->eraseFromParent();
730 if (
I ==
MBB.begin()) {
743 I->eraseFromParent();
750void AArch64InstrInfo::instantiateCondBranch(
775 if (
Cond.size() > 5) {
786 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
813 unsigned Opc =
MI.getOpcode();
820 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
821 MI.getOperand(0).getReg() == AArch64::XZR) {
823 dbgs() <<
"Removing always taken branch: " <<
MI);
826 for (
auto *S : Succs)
828 MBB->removeSuccessor(S);
830 while (
MBB->rbegin() != &
MI)
831 MBB->rbegin()->eraseFromParent();
832 MI.eraseFromParent();
842 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
843 MI.getOperand(0).getReg() == AArch64::XZR) {
845 dbgs() <<
"Removing never taken branch: " <<
MI);
847 MI.getParent()->removeSuccessor(
Target);
848 MI.eraseFromParent();
861 if (!
DefMI->isFullCopy())
863 VReg =
DefMI->getOperand(1).getReg();
872 unsigned *NewReg =
nullptr) {
877 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.
getRegClass(VReg));
881 switch (
DefMI->getOpcode()) {
882 case AArch64::SUBREG_TO_REG:
886 if (!
DefMI->getOperand(1).isReg())
888 if (!
DefMI->getOperand(2).isImm() ||
889 DefMI->getOperand(2).getImm() != AArch64::sub_32)
892 if (
DefMI->getOpcode() != AArch64::MOVi32imm)
894 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
897 SrcReg = AArch64::XZR;
898 Opc = AArch64::CSINCXr;
901 case AArch64::MOVi32imm:
902 case AArch64::MOVi64imm:
903 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
905 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
906 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
909 case AArch64::ADDSXri:
910 case AArch64::ADDSWri:
912 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
917 case AArch64::ADDXri:
918 case AArch64::ADDWri:
920 if (!
DefMI->getOperand(2).isImm() ||
DefMI->getOperand(2).getImm() != 1 ||
921 DefMI->getOperand(3).getImm() != 0)
923 SrcReg =
DefMI->getOperand(1).getReg();
924 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
927 case AArch64::ORNXrr:
928 case AArch64::ORNWrr: {
931 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
933 SrcReg =
DefMI->getOperand(2).getReg();
934 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
938 case AArch64::SUBSXrr:
939 case AArch64::SUBSWrr:
941 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
946 case AArch64::SUBXrr:
947 case AArch64::SUBWrr: {
950 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
952 SrcReg =
DefMI->getOperand(2).getReg();
953 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
959 assert(
Opc && SrcReg &&
"Missing parameters");
971 int &FalseCycles)
const {
982 if (!RI.getCommonSubClass(RC, MRI.
getRegClass(DstReg)))
986 unsigned ExtraCondLat =
Cond.size() != 1;
990 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
991 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
993 CondCycles = 1 + ExtraCondLat;
994 TrueCycles = FalseCycles = 1;
1004 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1005 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1006 CondCycles = 5 + ExtraCondLat;
1007 TrueCycles = FalseCycles = 2;
1024 switch (
Cond.size()) {
1044 case AArch64::CBNZW:
1048 case AArch64::CBNZX:
1079 case AArch64::TBNZW:
1080 case AArch64::TBNZX:
1102 unsigned SubsOpc, SubsDestReg;
1108 case AArch64::CBWPri:
1109 SubsOpc = AArch64::SUBSWri;
1110 SubsDestReg = AArch64::WZR;
1113 case AArch64::CBXPri:
1114 SubsOpc = AArch64::SUBSXri;
1115 SubsDestReg = AArch64::XZR;
1118 case AArch64::CBWPrr:
1119 SubsOpc = AArch64::SUBSWrr;
1120 SubsDestReg = AArch64::WZR;
1123 case AArch64::CBXPrr:
1124 SubsOpc = AArch64::SUBSXrr;
1125 SubsDestReg = AArch64::XZR;
1154 switch (ExtendType) {
1160 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1161 ExtOpc = AArch64::SBFMWri;
1167 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1168 ExtOpc = AArch64::SBFMWri;
1174 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1175 ExtOpc = AArch64::ANDWri;
1181 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1182 ExtOpc = AArch64::ANDWri;
1191 if (ExtOpc != AArch64::ANDWri)
1193 MBBI.addImm(ExtBits);
1221 bool TryFold =
false;
1223 RC = &AArch64::GPR64RegClass;
1224 Opc = AArch64::CSELXr;
1227 RC = &AArch64::GPR32RegClass;
1228 Opc = AArch64::CSELWr;
1231 RC = &AArch64::FPR64RegClass;
1232 Opc = AArch64::FCSELDrrr;
1234 RC = &AArch64::FPR32RegClass;
1235 Opc = AArch64::FCSELSrrr;
1237 assert(RC &&
"Unsupported regclass");
1241 unsigned NewReg = 0;
1264 (FalseReg.
isVirtual() || FalseReg == AArch64::WZR ||
1265 FalseReg == AArch64::XZR) &&
1266 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1283 assert(BitSize == 64 &&
"Only bit sizes of 32 or 64 allowed");
1288 return Is.
size() <= 2;
1293 assert(
MI.isCopy() &&
"Expected COPY instruction");
1299 if (
Reg.isVirtual())
1301 if (
Reg.isPhysical())
1302 return RI.getMinimalPhysRegClass(
Reg);
1307 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1310 return MI.isAsCheapAsAMove();
1316 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1317 if (isExynosCheapAsMove(
MI))
1319 return MI.isAsCheapAsAMove();
1322 switch (
MI.getOpcode()) {
1324 return MI.isAsCheapAsAMove();
1326 case TargetOpcode::COPY:
1329 case AArch64::ADDWrs:
1330 case AArch64::ADDXrs:
1331 case AArch64::SUBWrs:
1332 case AArch64::SUBXrs:
1333 return Subtarget.hasALULSLFast() &&
MI.getOperand(3).getImm() <= 4;
1338 case AArch64::MOVi32imm:
1340 case AArch64::MOVi64imm:
1345bool AArch64InstrInfo::isFalkorShiftExtFast(
const MachineInstr &
MI) {
1346 switch (
MI.getOpcode()) {
1350 case AArch64::ADDWrs:
1351 case AArch64::ADDXrs:
1352 case AArch64::ADDSWrs:
1353 case AArch64::ADDSXrs: {
1354 unsigned Imm =
MI.getOperand(3).getImm();
1361 case AArch64::ADDWrx:
1362 case AArch64::ADDXrx:
1363 case AArch64::ADDXrx64:
1364 case AArch64::ADDSWrx:
1365 case AArch64::ADDSXrx:
1366 case AArch64::ADDSXrx64: {
1367 unsigned Imm =
MI.getOperand(3).getImm();
1379 case AArch64::SUBWrs:
1380 case AArch64::SUBSWrs: {
1381 unsigned Imm =
MI.getOperand(3).getImm();
1383 return ShiftVal == 0 ||
1387 case AArch64::SUBXrs:
1388 case AArch64::SUBSXrs: {
1389 unsigned Imm =
MI.getOperand(3).getImm();
1391 return ShiftVal == 0 ||
1395 case AArch64::SUBWrx:
1396 case AArch64::SUBXrx:
1397 case AArch64::SUBXrx64:
1398 case AArch64::SUBSWrx:
1399 case AArch64::SUBSXrx:
1400 case AArch64::SUBSXrx64: {
1401 unsigned Imm =
MI.getOperand(3).getImm();
1413 case AArch64::LDRBBroW:
1414 case AArch64::LDRBBroX:
1415 case AArch64::LDRBroW:
1416 case AArch64::LDRBroX:
1417 case AArch64::LDRDroW:
1418 case AArch64::LDRDroX:
1419 case AArch64::LDRHHroW:
1420 case AArch64::LDRHHroX:
1421 case AArch64::LDRHroW:
1422 case AArch64::LDRHroX:
1423 case AArch64::LDRQroW:
1424 case AArch64::LDRQroX:
1425 case AArch64::LDRSBWroW:
1426 case AArch64::LDRSBWroX:
1427 case AArch64::LDRSBXroW:
1428 case AArch64::LDRSBXroX:
1429 case AArch64::LDRSHWroW:
1430 case AArch64::LDRSHWroX:
1431 case AArch64::LDRSHXroW:
1432 case AArch64::LDRSHXroX:
1433 case AArch64::LDRSWroW:
1434 case AArch64::LDRSWroX:
1435 case AArch64::LDRSroW:
1436 case AArch64::LDRSroX:
1437 case AArch64::LDRWroW:
1438 case AArch64::LDRWroX:
1439 case AArch64::LDRXroW:
1440 case AArch64::LDRXroX:
1441 case AArch64::PRFMroW:
1442 case AArch64::PRFMroX:
1443 case AArch64::STRBBroW:
1444 case AArch64::STRBBroX:
1445 case AArch64::STRBroW:
1446 case AArch64::STRBroX:
1447 case AArch64::STRDroW:
1448 case AArch64::STRDroX:
1449 case AArch64::STRHHroW:
1450 case AArch64::STRHHroX:
1451 case AArch64::STRHroW:
1452 case AArch64::STRHroX:
1453 case AArch64::STRQroW:
1454 case AArch64::STRQroX:
1455 case AArch64::STRSroW:
1456 case AArch64::STRSroX:
1457 case AArch64::STRWroW:
1458 case AArch64::STRWroX:
1459 case AArch64::STRXroW:
1460 case AArch64::STRXroX: {
1461 unsigned IsSigned =
MI.getOperand(3).getImm();
1468 unsigned Opc =
MI.getOpcode();
1472 case AArch64::SEH_StackAlloc:
1473 case AArch64::SEH_SaveFPLR:
1474 case AArch64::SEH_SaveFPLR_X:
1475 case AArch64::SEH_SaveReg:
1476 case AArch64::SEH_SaveReg_X:
1477 case AArch64::SEH_SaveRegP:
1478 case AArch64::SEH_SaveRegP_X:
1479 case AArch64::SEH_SaveFReg:
1480 case AArch64::SEH_SaveFReg_X:
1481 case AArch64::SEH_SaveFRegP:
1482 case AArch64::SEH_SaveFRegP_X:
1483 case AArch64::SEH_SetFP:
1484 case AArch64::SEH_AddFP:
1485 case AArch64::SEH_Nop:
1486 case AArch64::SEH_PrologEnd:
1487 case AArch64::SEH_EpilogStart:
1488 case AArch64::SEH_EpilogEnd:
1489 case AArch64::SEH_PACSignLR:
1490 case AArch64::SEH_SaveAnyRegI:
1491 case AArch64::SEH_SaveAnyRegIP:
1492 case AArch64::SEH_SaveAnyRegQP:
1493 case AArch64::SEH_SaveAnyRegQPX:
1494 case AArch64::SEH_AllocZ:
1495 case AArch64::SEH_SaveZReg:
1496 case AArch64::SEH_SavePReg:
1503 unsigned &SubIdx)
const {
1504 switch (
MI.getOpcode()) {
1507 case AArch64::SBFMXri:
1508 case AArch64::UBFMXri:
1511 if (
MI.getOperand(2).getImm() != 0 ||
MI.getOperand(3).getImm() != 31)
1514 SrcReg =
MI.getOperand(1).getReg();
1515 DstReg =
MI.getOperand(0).getReg();
1516 SubIdx = AArch64::sub_32;
1525 int64_t OffsetA = 0, OffsetB = 0;
1526 TypeSize WidthA(0,
false), WidthB(0,
false);
1527 bool OffsetAIsScalable =
false, OffsetBIsScalable =
false;
1548 OffsetAIsScalable == OffsetBIsScalable) {
1549 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1550 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1551 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1552 if (LowWidth.
isScalable() == OffsetAIsScalable &&
1570 switch (
MI.getOpcode()) {
1573 if (
MI.getOperand(0).getImm() == 0x14)
1580 case AArch64::MSRpstatesvcrImm1:
1587 auto Next = std::next(
MI.getIterator());
1588 return Next !=
MBB->end() &&
Next->isCFIInstruction();
1595 Register &SrcReg2, int64_t &CmpMask,
1596 int64_t &CmpValue)
const {
1600 assert(
MI.getNumOperands() >= 2 &&
"All AArch64 cmps should have 2 operands");
1601 if (!
MI.getOperand(1).isReg() ||
MI.getOperand(1).getSubReg())
1604 switch (
MI.getOpcode()) {
1607 case AArch64::PTEST_PP:
1608 case AArch64::PTEST_PP_ANY:
1609 case AArch64::PTEST_PP_FIRST:
1610 SrcReg =
MI.getOperand(0).getReg();
1611 SrcReg2 =
MI.getOperand(1).getReg();
1612 if (
MI.getOperand(2).getSubReg())
1619 case AArch64::SUBSWrr:
1620 case AArch64::SUBSWrs:
1621 case AArch64::SUBSWrx:
1622 case AArch64::SUBSXrr:
1623 case AArch64::SUBSXrs:
1624 case AArch64::SUBSXrx:
1625 case AArch64::ADDSWrr:
1626 case AArch64::ADDSWrs:
1627 case AArch64::ADDSWrx:
1628 case AArch64::ADDSXrr:
1629 case AArch64::ADDSXrs:
1630 case AArch64::ADDSXrx:
1632 SrcReg =
MI.getOperand(1).getReg();
1633 SrcReg2 =
MI.getOperand(2).getReg();
1636 if (
MI.getOperand(2).getSubReg())
1642 case AArch64::SUBSWri:
1643 case AArch64::ADDSWri:
1644 case AArch64::SUBSXri:
1645 case AArch64::ADDSXri:
1646 SrcReg =
MI.getOperand(1).getReg();
1649 CmpValue =
MI.getOperand(2).getImm();
1651 case AArch64::ANDSWri:
1652 case AArch64::ANDSXri:
1655 SrcReg =
MI.getOperand(1).getReg();
1659 MI.getOperand(2).getImm(),
1660 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1669 assert(
MBB &&
"Can't get MachineBasicBlock here");
1671 assert(MF &&
"Can't get MachineFunction here");
1676 for (
unsigned OpIdx = 0, EndIdx = Instr.getNumOperands();
OpIdx < EndIdx;
1683 if (!OpRegCstraints)
1691 "Operand has register constraints without being a register!");
1694 if (
Reg.isPhysical()) {
1711 bool MIDefinesZeroReg =
false;
1712 if (
MI.definesRegister(AArch64::WZR,
nullptr) ||
1713 MI.definesRegister(AArch64::XZR,
nullptr))
1714 MIDefinesZeroReg =
true;
1716 switch (
MI.getOpcode()) {
1718 return MI.getOpcode();
1719 case AArch64::ADDSWrr:
1720 return AArch64::ADDWrr;
1721 case AArch64::ADDSWri:
1722 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1723 case AArch64::ADDSWrs:
1724 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1725 case AArch64::ADDSWrx:
1726 return AArch64::ADDWrx;
1727 case AArch64::ADDSXrr:
1728 return AArch64::ADDXrr;
1729 case AArch64::ADDSXri:
1730 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1731 case AArch64::ADDSXrs:
1732 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1733 case AArch64::ADDSXrx:
1734 return AArch64::ADDXrx;
1735 case AArch64::SUBSWrr:
1736 return AArch64::SUBWrr;
1737 case AArch64::SUBSWri:
1738 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1739 case AArch64::SUBSWrs:
1740 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1741 case AArch64::SUBSWrx:
1742 return AArch64::SUBWrx;
1743 case AArch64::SUBSXrr:
1744 return AArch64::SUBXrr;
1745 case AArch64::SUBSXri:
1746 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1747 case AArch64::SUBSXrs:
1748 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1749 case AArch64::SUBSXrx:
1750 return AArch64::SUBXrx;
1765 if (To == To->getParent()->begin())
1770 if (To->getParent() != From->getParent())
1782 Instr.modifiesRegister(AArch64::NZCV,
TRI)) ||
1783 ((AccessToCheck &
AK_Read) && Instr.readsRegister(AArch64::NZCV,
TRI)))
1789std::optional<unsigned>
1793 unsigned MaskOpcode =
Mask->getOpcode();
1794 unsigned PredOpcode = Pred->
getOpcode();
1795 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1796 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1798 if (PredIsWhileLike) {
1802 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1809 getElementSizeForOpcode(MaskOpcode) ==
1810 getElementSizeForOpcode(PredOpcode))
1816 if (PTest->
getOpcode() == AArch64::PTEST_PP_FIRST &&
1823 if (PredIsPTestLike) {
1828 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1836 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1837 PTestLikeMask->getOperand(1).getReg().isVirtual())
1845 getElementSizeForOpcode(MaskOpcode) ==
1846 getElementSizeForOpcode(PredOpcode)) {
1847 if (Mask == PTestLikeMask || PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1873 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1875 PTest->
getOpcode() == AArch64::PTEST_PP_ANY))
1883 switch (PredOpcode) {
1884 case AArch64::AND_PPzPP:
1885 case AArch64::BIC_PPzPP:
1886 case AArch64::EOR_PPzPP:
1887 case AArch64::NAND_PPzPP:
1888 case AArch64::NOR_PPzPP:
1889 case AArch64::ORN_PPzPP:
1890 case AArch64::ORR_PPzPP:
1891 case AArch64::BRKA_PPzP:
1892 case AArch64::BRKPA_PPzPP:
1893 case AArch64::BRKB_PPzP:
1894 case AArch64::BRKPB_PPzPP:
1895 case AArch64::RDFFR_PPz: {
1899 if (Mask != PredMask)
1903 case AArch64::BRKN_PPzP: {
1907 if ((MaskOpcode != AArch64::PTRUE_B) ||
1908 (
Mask->getOperand(1).getImm() != 31))
1912 case AArch64::PTRUE_B:
1925bool AArch64InstrInfo::optimizePTestInstr(
1926 MachineInstr *PTest,
unsigned MaskReg,
unsigned PredReg,
1931 if (Pred->
isCopy() && PTest->
getOpcode() == AArch64::PTEST_PP_FIRST) {
1935 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
1936 Op.getSubReg() == AArch64::psub0)
1940 unsigned PredOpcode = Pred->
getOpcode();
1941 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
1957 if (*NewOp != PredOpcode) {
1968 for (; i !=
e; ++i) {
1999 if (DeadNZCVIdx != -1) {
2018 if (CmpInstr.
getOpcode() == AArch64::PTEST_PP ||
2019 CmpInstr.
getOpcode() == AArch64::PTEST_PP_ANY ||
2020 CmpInstr.
getOpcode() == AArch64::PTEST_PP_FIRST)
2021 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2030 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2032 return (CmpValue == 0 || CmpValue == 1) &&
2033 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2041 switch (Instr.getOpcode()) {
2043 return AArch64::INSTRUCTION_LIST_END;
2045 case AArch64::ADDSWrr:
2046 case AArch64::ADDSWri:
2047 case AArch64::ADDSXrr:
2048 case AArch64::ADDSXri:
2049 case AArch64::ADDSWrx:
2050 case AArch64::ADDSXrx:
2051 case AArch64::SUBSWrr:
2052 case AArch64::SUBSWri:
2053 case AArch64::SUBSWrx:
2054 case AArch64::SUBSXrr:
2055 case AArch64::SUBSXri:
2056 case AArch64::SUBSXrx:
2057 case AArch64::ANDSWri:
2058 case AArch64::ANDSWrr:
2059 case AArch64::ANDSWrs:
2060 case AArch64::ANDSXri:
2061 case AArch64::ANDSXrr:
2062 case AArch64::ANDSXrs:
2063 case AArch64::BICSWrr:
2064 case AArch64::BICSXrr:
2065 case AArch64::BICSWrs:
2066 case AArch64::BICSXrs:
2067 return Instr.getOpcode();
2069 case AArch64::ADDWrr:
2070 return AArch64::ADDSWrr;
2071 case AArch64::ADDWri:
2072 return AArch64::ADDSWri;
2073 case AArch64::ADDXrr:
2074 return AArch64::ADDSXrr;
2075 case AArch64::ADDXri:
2076 return AArch64::ADDSXri;
2077 case AArch64::ADDWrx:
2078 return AArch64::ADDSWrx;
2079 case AArch64::ADDXrx:
2080 return AArch64::ADDSXrx;
2081 case AArch64::ADCWr:
2082 return AArch64::ADCSWr;
2083 case AArch64::ADCXr:
2084 return AArch64::ADCSXr;
2085 case AArch64::SUBWrr:
2086 return AArch64::SUBSWrr;
2087 case AArch64::SUBWri:
2088 return AArch64::SUBSWri;
2089 case AArch64::SUBXrr:
2090 return AArch64::SUBSXrr;
2091 case AArch64::SUBXri:
2092 return AArch64::SUBSXri;
2093 case AArch64::SUBWrx:
2094 return AArch64::SUBSWrx;
2095 case AArch64::SUBXrx:
2096 return AArch64::SUBSXrx;
2097 case AArch64::SBCWr:
2098 return AArch64::SBCSWr;
2099 case AArch64::SBCXr:
2100 return AArch64::SBCSXr;
2101 case AArch64::ANDWri:
2102 return AArch64::ANDSWri;
2103 case AArch64::ANDXri:
2104 return AArch64::ANDSXri;
2105 case AArch64::ANDWrr:
2106 return AArch64::ANDSWrr;
2107 case AArch64::ANDWrs:
2108 return AArch64::ANDSWrs;
2109 case AArch64::ANDXrr:
2110 return AArch64::ANDSXrr;
2111 case AArch64::ANDXrs:
2112 return AArch64::ANDSXrs;
2113 case AArch64::BICWrr:
2114 return AArch64::BICSWrr;
2115 case AArch64::BICXrr:
2116 return AArch64::BICSXrr;
2117 case AArch64::BICWrs:
2118 return AArch64::BICSWrs;
2119 case AArch64::BICXrs:
2120 return AArch64::BICSXrs;
2126 for (
auto *BB :
MBB->successors())
2127 if (BB->isLiveIn(AArch64::NZCV))
2134int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2136 switch (
Instr.getOpcode()) {
2140 case AArch64::Bcc: {
2141 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2146 case AArch64::CSINVWr:
2147 case AArch64::CSINVXr:
2148 case AArch64::CSINCWr:
2149 case AArch64::CSINCXr:
2150 case AArch64::CSELWr:
2151 case AArch64::CSELXr:
2152 case AArch64::CSNEGWr:
2153 case AArch64::CSNEGXr:
2154 case AArch64::FCSELSrrr:
2155 case AArch64::FCSELDrrr: {
2156 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2168 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2170 Instr.getOperand(CCIdx).
getImm())
2223std::optional<UsedNZCV>
2228 if (
MI.getParent() != CmpParent)
2229 return std::nullopt;
2232 return std::nullopt;
2237 if (Instr.readsRegister(AArch64::NZCV, &
TRI)) {
2240 return std::nullopt;
2245 if (Instr.modifiesRegister(AArch64::NZCV, &
TRI))
2248 return NZCVUsedAfterCmp;
2252 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2256 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2262 case AArch64::ANDSWri:
2263 case AArch64::ANDSWrr:
2264 case AArch64::ANDSWrs:
2265 case AArch64::ANDSXri:
2266 case AArch64::ANDSXrr:
2267 case AArch64::ANDSXrs:
2268 case AArch64::BICSWrr:
2269 case AArch64::BICSXrr:
2270 case AArch64::BICSWrs:
2271 case AArch64::BICSXrs:
2297 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2303 "Caller guarantees that CmpInstr compares with constant 0");
2306 if (!NZVCUsed || NZVCUsed->C)
2329bool AArch64InstrInfo::substituteCmpToZero(
2340 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2347 MI->setDesc(
get(NewOpc));
2352 MI->addRegisterDefined(AArch64::NZCV, &
TRI);
2364 assert((CmpValue == 0 || CmpValue == 1) &&
2365 "Only comparisons to 0 or 1 considered for removal!");
2368 unsigned MIOpc =
MI.getOpcode();
2369 if (MIOpc == AArch64::CSINCWr) {
2370 if (
MI.getOperand(1).getReg() != AArch64::WZR ||
2371 MI.getOperand(2).getReg() != AArch64::WZR)
2373 }
else if (MIOpc == AArch64::CSINCXr) {
2374 if (
MI.getOperand(1).getReg() != AArch64::XZR ||
2375 MI.getOperand(2).getReg() != AArch64::XZR)
2385 if (
MI.findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) != -1)
2389 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2391 if (CmpValue && !IsSubsRegImm)
2393 if (!CmpValue && !IsSubsRegImm && !
isADDSRegImm(CmpOpcode))
2398 if (MIUsedNZCV.
C || MIUsedNZCV.
V)
2401 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2405 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2408 if ((MIUsedNZCV.
Z && NZCVUsedAfterCmp->N) ||
2409 (MIUsedNZCV.
N && NZCVUsedAfterCmp->Z))
2412 if (MIUsedNZCV.
N && !CmpValue)
2454bool AArch64InstrInfo::removeCmpToZeroOrOne(
2461 SmallVector<MachineInstr *, 4> CCUseInstrs;
2462 bool IsInvertCC =
false;
2470 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2471 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2472 assert(Idx >= 0 &&
"Unexpected instruction using CC.");
2473 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2482bool AArch64InstrInfo::expandPostRAPseudo(
MachineInstr &
MI)
const {
2483 if (
MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2484 MI.getOpcode() != AArch64::CATCHRET)
2487 MachineBasicBlock &
MBB = *
MI.getParent();
2489 auto TRI = Subtarget.getRegisterInfo();
2492 if (
MI.getOpcode() == AArch64::CATCHRET) {
2494 const TargetInstrInfo *
TII =
2496 MachineBasicBlock *TargetMBB =
MI.getOperand(0).getMBB();
2501 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2503 FirstEpilogSEH = std::next(FirstEpilogSEH);
2518 if (
M.getStackProtectorGuard() ==
"sysreg") {
2519 const AArch64SysReg::SysReg *SrcReg =
2520 AArch64SysReg::lookupSysRegByName(
M.getStackProtectorGuardReg());
2528 int Offset =
M.getStackProtectorGuardOffset();
2579 const GlobalValue *GV =
2582 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2585 unsigned GuardWidth =
M.getStackProtectorGuardValueWidth().value_or(
2586 Subtarget.isTargetILP32() ? 4 : 8);
2587 if (GuardWidth != 4 && GuardWidth != 8)
2592 if (GuardWidth == 4) {
2593 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2607 if (GuardWidth == 4)
2641 if (GuardWidth == 4) {
2642 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2665 switch (
MI.getOpcode()) {
2668 case AArch64::MOVZWi:
2669 case AArch64::MOVZXi:
2670 if (
MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0) {
2671 assert(
MI.getDesc().getNumOperands() == 3 &&
2672 MI.getOperand(2).getImm() == 0 &&
"invalid MOVZi operands");
2676 case AArch64::ANDWri:
2677 return MI.getOperand(1).getReg() == AArch64::WZR;
2678 case AArch64::ANDXri:
2679 return MI.getOperand(1).getReg() == AArch64::XZR;
2680 case TargetOpcode::COPY:
2681 return MI.getOperand(1).getReg() == AArch64::WZR;
2689 switch (
MI.getOpcode()) {
2692 case TargetOpcode::COPY: {
2695 return (AArch64::GPR32RegClass.
contains(DstReg) ||
2696 AArch64::GPR64RegClass.
contains(DstReg));
2698 case AArch64::ORRXrs:
2699 if (
MI.getOperand(1).getReg() == AArch64::XZR) {
2700 assert(
MI.getDesc().getNumOperands() == 4 &&
2701 MI.getOperand(3).getImm() == 0 &&
"invalid ORRrs operands");
2705 case AArch64::ADDXri:
2706 if (
MI.getOperand(2).getImm() == 0) {
2707 assert(
MI.getDesc().getNumOperands() == 4 &&
2708 MI.getOperand(3).getImm() == 0 &&
"invalid ADDXri operands");
2719 switch (
MI.getOpcode()) {
2722 case TargetOpcode::COPY: {
2724 return AArch64::FPR128RegClass.contains(DstReg);
2726 case AArch64::ORRv16i8:
2727 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
2728 assert(
MI.getDesc().getNumOperands() == 3 &&
MI.getOperand(0).isReg() &&
2729 "invalid ORRv16i8 operands");
2741 case AArch64::LDRWui:
2742 case AArch64::LDRXui:
2743 case AArch64::LDRBui:
2744 case AArch64::LDRHui:
2745 case AArch64::LDRSui:
2746 case AArch64::LDRDui:
2747 case AArch64::LDRQui:
2748 case AArch64::LDR_PXI:
2754 int &FrameIndex)
const {
2758 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2759 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2760 FrameIndex =
MI.getOperand(1).getIndex();
2761 return MI.getOperand(0).getReg();
2770 case AArch64::STRWui:
2771 case AArch64::STRXui:
2772 case AArch64::STRBui:
2773 case AArch64::STRHui:
2774 case AArch64::STRSui:
2775 case AArch64::STRDui:
2776 case AArch64::STRQui:
2777 case AArch64::STR_PXI:
2783 int &FrameIndex)
const {
2787 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2788 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2789 FrameIndex =
MI.getOperand(1).getIndex();
2790 return MI.getOperand(0).getReg();
2796 int &FrameIndex)
const {
2811 return MI.getOperand(0).getReg();
2817 int &FrameIndex)
const {
2832 return MI.getOperand(0).getReg();
2840 return MMO->getFlags() & MOSuppressPair;
2846 if (
MI.memoperands_empty())
2854 return MMO->getFlags() & MOStridedAccess;
2862 case AArch64::STURSi:
2863 case AArch64::STRSpre:
2864 case AArch64::STURDi:
2865 case AArch64::STRDpre:
2866 case AArch64::STURQi:
2867 case AArch64::STRQpre:
2868 case AArch64::STURBBi:
2869 case AArch64::STURHHi:
2870 case AArch64::STURWi:
2871 case AArch64::STRWpre:
2872 case AArch64::STURXi:
2873 case AArch64::STRXpre:
2874 case AArch64::LDURSi:
2875 case AArch64::LDRSpre:
2876 case AArch64::LDURDi:
2877 case AArch64::LDRDpre:
2878 case AArch64::LDURQi:
2879 case AArch64::LDRQpre:
2880 case AArch64::LDURWi:
2881 case AArch64::LDRWpre:
2882 case AArch64::LDURXi:
2883 case AArch64::LDRXpre:
2884 case AArch64::LDRSWpre:
2885 case AArch64::LDURSWi:
2886 case AArch64::LDURHHi:
2887 case AArch64::LDURBBi:
2888 case AArch64::LDURSBWi:
2889 case AArch64::LDURSHWi:
2897 case AArch64::PRFMui:
return AArch64::PRFUMi;
2898 case AArch64::LDRXui:
return AArch64::LDURXi;
2899 case AArch64::LDRWui:
return AArch64::LDURWi;
2900 case AArch64::LDRBui:
return AArch64::LDURBi;
2901 case AArch64::LDRHui:
return AArch64::LDURHi;
2902 case AArch64::LDRSui:
return AArch64::LDURSi;
2903 case AArch64::LDRDui:
return AArch64::LDURDi;
2904 case AArch64::LDRQui:
return AArch64::LDURQi;
2905 case AArch64::LDRBBui:
return AArch64::LDURBBi;
2906 case AArch64::LDRHHui:
return AArch64::LDURHHi;
2907 case AArch64::LDRSBXui:
return AArch64::LDURSBXi;
2908 case AArch64::LDRSBWui:
return AArch64::LDURSBWi;
2909 case AArch64::LDRSHXui:
return AArch64::LDURSHXi;
2910 case AArch64::LDRSHWui:
return AArch64::LDURSHWi;
2911 case AArch64::LDRSWui:
return AArch64::LDURSWi;
2912 case AArch64::STRXui:
return AArch64::STURXi;
2913 case AArch64::STRWui:
return AArch64::STURWi;
2914 case AArch64::STRBui:
return AArch64::STURBi;
2915 case AArch64::STRHui:
return AArch64::STURHi;
2916 case AArch64::STRSui:
return AArch64::STURSi;
2917 case AArch64::STRDui:
return AArch64::STURDi;
2918 case AArch64::STRQui:
return AArch64::STURQi;
2919 case AArch64::STRBBui:
return AArch64::STURBBi;
2920 case AArch64::STRHHui:
return AArch64::STURHHi;
2929 case AArch64::LDAPURBi:
2930 case AArch64::LDAPURHi:
2931 case AArch64::LDAPURi:
2932 case AArch64::LDAPURSBWi:
2933 case AArch64::LDAPURSBXi:
2934 case AArch64::LDAPURSHWi:
2935 case AArch64::LDAPURSHXi:
2936 case AArch64::LDAPURSWi:
2937 case AArch64::LDAPURXi:
2938 case AArch64::LDR_PPXI:
2939 case AArch64::LDR_PXI:
2940 case AArch64::LDR_ZXI:
2941 case AArch64::LDR_ZZXI:
2942 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
2943 case AArch64::LDR_ZZZXI:
2944 case AArch64::LDR_ZZZZXI:
2945 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
2946 case AArch64::LDRBBui:
2947 case AArch64::LDRBui:
2948 case AArch64::LDRDui:
2949 case AArch64::LDRHHui:
2950 case AArch64::LDRHui:
2951 case AArch64::LDRQui:
2952 case AArch64::LDRSBWui:
2953 case AArch64::LDRSBXui:
2954 case AArch64::LDRSHWui:
2955 case AArch64::LDRSHXui:
2956 case AArch64::LDRSui:
2957 case AArch64::LDRSWui:
2958 case AArch64::LDRWui:
2959 case AArch64::LDRXui:
2960 case AArch64::LDURBBi:
2961 case AArch64::LDURBi:
2962 case AArch64::LDURDi:
2963 case AArch64::LDURHHi:
2964 case AArch64::LDURHi:
2965 case AArch64::LDURQi:
2966 case AArch64::LDURSBWi:
2967 case AArch64::LDURSBXi:
2968 case AArch64::LDURSHWi:
2969 case AArch64::LDURSHXi:
2970 case AArch64::LDURSi:
2971 case AArch64::LDURSWi:
2972 case AArch64::LDURWi:
2973 case AArch64::LDURXi:
2974 case AArch64::PRFMui:
2975 case AArch64::PRFUMi:
2976 case AArch64::ST2Gi:
2978 case AArch64::STLURBi:
2979 case AArch64::STLURHi:
2980 case AArch64::STLURWi:
2981 case AArch64::STLURXi:
2982 case AArch64::StoreSwiftAsyncContext:
2983 case AArch64::STR_PPXI:
2984 case AArch64::STR_PXI:
2985 case AArch64::STR_ZXI:
2986 case AArch64::STR_ZZXI:
2987 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
2988 case AArch64::STR_ZZZXI:
2989 case AArch64::STR_ZZZZXI:
2990 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
2991 case AArch64::STRBBui:
2992 case AArch64::STRBui:
2993 case AArch64::STRDui:
2994 case AArch64::STRHHui:
2995 case AArch64::STRHui:
2996 case AArch64::STRQui:
2997 case AArch64::STRSui:
2998 case AArch64::STRWui:
2999 case AArch64::STRXui:
3000 case AArch64::STURBBi:
3001 case AArch64::STURBi:
3002 case AArch64::STURDi:
3003 case AArch64::STURHHi:
3004 case AArch64::STURHi:
3005 case AArch64::STURQi:
3006 case AArch64::STURSi:
3007 case AArch64::STURWi:
3008 case AArch64::STURXi:
3009 case AArch64::STZ2Gi:
3010 case AArch64::STZGi:
3011 case AArch64::TAGPstack:
3013 case AArch64::LD1B_D_IMM:
3014 case AArch64::LD1B_H_IMM:
3015 case AArch64::LD1B_IMM:
3016 case AArch64::LD1B_S_IMM:
3017 case AArch64::LD1D_IMM:
3018 case AArch64::LD1H_D_IMM:
3019 case AArch64::LD1H_IMM:
3020 case AArch64::LD1H_S_IMM:
3021 case AArch64::LD1RB_D_IMM:
3022 case AArch64::LD1RB_H_IMM:
3023 case AArch64::LD1RB_IMM:
3024 case AArch64::LD1RB_S_IMM:
3025 case AArch64::LD1RD_IMM:
3026 case AArch64::LD1RH_D_IMM:
3027 case AArch64::LD1RH_IMM:
3028 case AArch64::LD1RH_S_IMM:
3029 case AArch64::LD1RSB_D_IMM:
3030 case AArch64::LD1RSB_H_IMM:
3031 case AArch64::LD1RSB_S_IMM:
3032 case AArch64::LD1RSH_D_IMM:
3033 case AArch64::LD1RSH_S_IMM:
3034 case AArch64::LD1RSW_IMM:
3035 case AArch64::LD1RW_D_IMM:
3036 case AArch64::LD1RW_IMM:
3037 case AArch64::LD1SB_D_IMM:
3038 case AArch64::LD1SB_H_IMM:
3039 case AArch64::LD1SB_S_IMM:
3040 case AArch64::LD1SH_D_IMM:
3041 case AArch64::LD1SH_S_IMM:
3042 case AArch64::LD1SW_D_IMM:
3043 case AArch64::LD1W_D_IMM:
3044 case AArch64::LD1W_IMM:
3045 case AArch64::LD2B_IMM:
3046 case AArch64::LD2D_IMM:
3047 case AArch64::LD2H_IMM:
3048 case AArch64::LD2W_IMM:
3049 case AArch64::LD3B_IMM:
3050 case AArch64::LD3D_IMM:
3051 case AArch64::LD3H_IMM:
3052 case AArch64::LD3W_IMM:
3053 case AArch64::LD4B_IMM:
3054 case AArch64::LD4D_IMM:
3055 case AArch64::LD4H_IMM:
3056 case AArch64::LD4W_IMM:
3058 case AArch64::LDNF1B_D_IMM:
3059 case AArch64::LDNF1B_H_IMM:
3060 case AArch64::LDNF1B_IMM:
3061 case AArch64::LDNF1B_S_IMM:
3062 case AArch64::LDNF1D_IMM:
3063 case AArch64::LDNF1H_D_IMM:
3064 case AArch64::LDNF1H_IMM:
3065 case AArch64::LDNF1H_S_IMM:
3066 case AArch64::LDNF1SB_D_IMM:
3067 case AArch64::LDNF1SB_H_IMM:
3068 case AArch64::LDNF1SB_S_IMM:
3069 case AArch64::LDNF1SH_D_IMM:
3070 case AArch64::LDNF1SH_S_IMM:
3071 case AArch64::LDNF1SW_D_IMM:
3072 case AArch64::LDNF1W_D_IMM:
3073 case AArch64::LDNF1W_IMM:
3074 case AArch64::LDNPDi:
3075 case AArch64::LDNPQi:
3076 case AArch64::LDNPSi:
3077 case AArch64::LDNPWi:
3078 case AArch64::LDNPXi:
3079 case AArch64::LDNT1B_ZRI:
3080 case AArch64::LDNT1D_ZRI:
3081 case AArch64::LDNT1H_ZRI:
3082 case AArch64::LDNT1W_ZRI:
3083 case AArch64::LDPDi:
3084 case AArch64::LDPQi:
3085 case AArch64::LDPSi:
3086 case AArch64::LDPWi:
3087 case AArch64::LDPXi:
3088 case AArch64::LDRBBpost:
3089 case AArch64::LDRBBpre:
3090 case AArch64::LDRBpost:
3091 case AArch64::LDRBpre:
3092 case AArch64::LDRDpost:
3093 case AArch64::LDRDpre:
3094 case AArch64::LDRHHpost:
3095 case AArch64::LDRHHpre:
3096 case AArch64::LDRHpost:
3097 case AArch64::LDRHpre:
3098 case AArch64::LDRQpost:
3099 case AArch64::LDRQpre:
3100 case AArch64::LDRSpost:
3101 case AArch64::LDRSpre:
3102 case AArch64::LDRWpost:
3103 case AArch64::LDRWpre:
3104 case AArch64::LDRXpost:
3105 case AArch64::LDRXpre:
3106 case AArch64::ST1B_D_IMM:
3107 case AArch64::ST1B_H_IMM:
3108 case AArch64::ST1B_IMM:
3109 case AArch64::ST1B_S_IMM:
3110 case AArch64::ST1D_IMM:
3111 case AArch64::ST1H_D_IMM:
3112 case AArch64::ST1H_IMM:
3113 case AArch64::ST1H_S_IMM:
3114 case AArch64::ST1W_D_IMM:
3115 case AArch64::ST1W_IMM:
3116 case AArch64::ST2B_IMM:
3117 case AArch64::ST2D_IMM:
3118 case AArch64::ST2H_IMM:
3119 case AArch64::ST2W_IMM:
3120 case AArch64::ST3B_IMM:
3121 case AArch64::ST3D_IMM:
3122 case AArch64::ST3H_IMM:
3123 case AArch64::ST3W_IMM:
3124 case AArch64::ST4B_IMM:
3125 case AArch64::ST4D_IMM:
3126 case AArch64::ST4H_IMM:
3127 case AArch64::ST4W_IMM:
3128 case AArch64::STGPi:
3129 case AArch64::STGPreIndex:
3130 case AArch64::STZGPreIndex:
3131 case AArch64::ST2GPreIndex:
3132 case AArch64::STZ2GPreIndex:
3133 case AArch64::STGPostIndex:
3134 case AArch64::STZGPostIndex:
3135 case AArch64::ST2GPostIndex:
3136 case AArch64::STZ2GPostIndex:
3137 case AArch64::STNPDi:
3138 case AArch64::STNPQi:
3139 case AArch64::STNPSi:
3140 case AArch64::STNPWi:
3141 case AArch64::STNPXi:
3142 case AArch64::STNT1B_ZRI:
3143 case AArch64::STNT1D_ZRI:
3144 case AArch64::STNT1H_ZRI:
3145 case AArch64::STNT1W_ZRI:
3146 case AArch64::STPDi:
3147 case AArch64::STPQi:
3148 case AArch64::STPSi:
3149 case AArch64::STPWi:
3150 case AArch64::STPXi:
3151 case AArch64::STRBBpost:
3152 case AArch64::STRBBpre:
3153 case AArch64::STRBpost:
3154 case AArch64::STRBpre:
3155 case AArch64::STRDpost:
3156 case AArch64::STRDpre:
3157 case AArch64::STRHHpost:
3158 case AArch64::STRHHpre:
3159 case AArch64::STRHpost:
3160 case AArch64::STRHpre:
3161 case AArch64::STRQpost:
3162 case AArch64::STRQpre:
3163 case AArch64::STRSpost:
3164 case AArch64::STRSpre:
3165 case AArch64::STRWpost:
3166 case AArch64::STRWpre:
3167 case AArch64::STRXpost:
3168 case AArch64::STRXpre:
3169 case AArch64::LD1B_2Z_IMM:
3170 case AArch64::LD1B_2Z_STRIDED_IMM:
3171 case AArch64::LD1H_2Z_IMM:
3172 case AArch64::LD1H_2Z_STRIDED_IMM:
3173 case AArch64::LD1W_2Z_IMM:
3174 case AArch64::LD1W_2Z_STRIDED_IMM:
3175 case AArch64::LD1D_2Z_IMM:
3176 case AArch64::LD1D_2Z_STRIDED_IMM:
3177 case AArch64::LD1B_4Z_IMM:
3178 case AArch64::LD1B_4Z_STRIDED_IMM:
3179 case AArch64::LD1H_4Z_IMM:
3180 case AArch64::LD1H_4Z_STRIDED_IMM:
3181 case AArch64::LD1W_4Z_IMM:
3182 case AArch64::LD1W_4Z_STRIDED_IMM:
3183 case AArch64::LD1D_4Z_IMM:
3184 case AArch64::LD1D_4Z_STRIDED_IMM:
3185 case AArch64::LD1B_2Z_IMM_PSEUDO:
3186 case AArch64::LD1H_2Z_IMM_PSEUDO:
3187 case AArch64::LD1W_2Z_IMM_PSEUDO:
3188 case AArch64::LD1D_2Z_IMM_PSEUDO:
3189 case AArch64::LD1B_4Z_IMM_PSEUDO:
3190 case AArch64::LD1H_4Z_IMM_PSEUDO:
3191 case AArch64::LD1W_4Z_IMM_PSEUDO:
3192 case AArch64::LD1D_4Z_IMM_PSEUDO:
3194 case AArch64::LDPDpost:
3195 case AArch64::LDPDpre:
3196 case AArch64::LDPQpost:
3197 case AArch64::LDPQpre:
3198 case AArch64::LDPSpost:
3199 case AArch64::LDPSpre:
3200 case AArch64::LDPWpost:
3201 case AArch64::LDPWpre:
3202 case AArch64::LDPXpost:
3203 case AArch64::LDPXpre:
3204 case AArch64::STGPpre:
3205 case AArch64::STGPpost:
3206 case AArch64::STPDpost:
3207 case AArch64::STPDpre:
3208 case AArch64::STPQpost:
3209 case AArch64::STPQpre:
3210 case AArch64::STPSpost:
3211 case AArch64::STPSpre:
3212 case AArch64::STPWpost:
3213 case AArch64::STPWpre:
3214 case AArch64::STPXpost:
3215 case AArch64::STPXpre:
3221 switch (
MI.getOpcode()) {
3225 case AArch64::STRSui:
3226 case AArch64::STRDui:
3227 case AArch64::STRQui:
3228 case AArch64::STRXui:
3229 case AArch64::STRWui:
3230 case AArch64::LDRSui:
3231 case AArch64::LDRDui:
3232 case AArch64::LDRQui:
3233 case AArch64::LDRXui:
3234 case AArch64::LDRWui:
3235 case AArch64::LDRSWui:
3237 case AArch64::STURSi:
3238 case AArch64::STRSpre:
3239 case AArch64::STURDi:
3240 case AArch64::STRDpre:
3241 case AArch64::STURQi:
3242 case AArch64::STRQpre:
3243 case AArch64::STURWi:
3244 case AArch64::STRWpre:
3245 case AArch64::STURXi:
3246 case AArch64::STRXpre:
3247 case AArch64::LDURSi:
3248 case AArch64::LDRSpre:
3249 case AArch64::LDURDi:
3250 case AArch64::LDRDpre:
3251 case AArch64::LDURQi:
3252 case AArch64::LDRQpre:
3253 case AArch64::LDURWi:
3254 case AArch64::LDRWpre:
3255 case AArch64::LDURXi:
3256 case AArch64::LDRXpre:
3257 case AArch64::LDURSWi:
3258 case AArch64::LDRSWpre:
3260 case AArch64::LDR_ZXI:
3261 case AArch64::STR_ZXI:
3267 switch (
MI.getOpcode()) {
3270 "Unexpected instruction - was a new tail call opcode introduced?");
3272 case AArch64::TCRETURNdi:
3273 case AArch64::TCRETURNri:
3274 case AArch64::TCRETURNrix16x17:
3275 case AArch64::TCRETURNrix17:
3276 case AArch64::TCRETURNrinotx16:
3277 case AArch64::TCRETURNriALL:
3278 case AArch64::AUTH_TCRETURN:
3279 case AArch64::AUTH_TCRETURN_BTI:
3289 case AArch64::ADDWri:
3290 return AArch64::ADDSWri;
3291 case AArch64::ADDWrr:
3292 return AArch64::ADDSWrr;
3293 case AArch64::ADDWrs:
3294 return AArch64::ADDSWrs;
3295 case AArch64::ADDWrx:
3296 return AArch64::ADDSWrx;
3297 case AArch64::ANDWri:
3298 return AArch64::ANDSWri;
3299 case AArch64::ANDWrr:
3300 return AArch64::ANDSWrr;
3301 case AArch64::ANDWrs:
3302 return AArch64::ANDSWrs;
3303 case AArch64::BICWrr:
3304 return AArch64::BICSWrr;
3305 case AArch64::BICWrs:
3306 return AArch64::BICSWrs;
3307 case AArch64::SUBWri:
3308 return AArch64::SUBSWri;
3309 case AArch64::SUBWrr:
3310 return AArch64::SUBSWrr;
3311 case AArch64::SUBWrs:
3312 return AArch64::SUBSWrs;
3313 case AArch64::SUBWrx:
3314 return AArch64::SUBSWrx;
3316 case AArch64::ADDXri:
3317 return AArch64::ADDSXri;
3318 case AArch64::ADDXrr:
3319 return AArch64::ADDSXrr;
3320 case AArch64::ADDXrs:
3321 return AArch64::ADDSXrs;
3322 case AArch64::ADDXrx:
3323 return AArch64::ADDSXrx;
3324 case AArch64::ANDXri:
3325 return AArch64::ANDSXri;
3326 case AArch64::ANDXrr:
3327 return AArch64::ANDSXrr;
3328 case AArch64::ANDXrs:
3329 return AArch64::ANDSXrs;
3330 case AArch64::BICXrr:
3331 return AArch64::BICSXrr;
3332 case AArch64::BICXrs:
3333 return AArch64::BICSXrs;
3334 case AArch64::SUBXri:
3335 return AArch64::SUBSXri;
3336 case AArch64::SUBXrr:
3337 return AArch64::SUBSXrr;
3338 case AArch64::SUBXrs:
3339 return AArch64::SUBSXrs;
3340 case AArch64::SUBXrx:
3341 return AArch64::SUBSXrx;
3343 case AArch64::AND_PPzPP:
3344 return AArch64::ANDS_PPzPP;
3345 case AArch64::BIC_PPzPP:
3346 return AArch64::BICS_PPzPP;
3347 case AArch64::EOR_PPzPP:
3348 return AArch64::EORS_PPzPP;
3349 case AArch64::NAND_PPzPP:
3350 return AArch64::NANDS_PPzPP;
3351 case AArch64::NOR_PPzPP:
3352 return AArch64::NORS_PPzPP;
3353 case AArch64::ORN_PPzPP:
3354 return AArch64::ORNS_PPzPP;
3355 case AArch64::ORR_PPzPP:
3356 return AArch64::ORRS_PPzPP;
3357 case AArch64::BRKA_PPzP:
3358 return AArch64::BRKAS_PPzP;
3359 case AArch64::BRKPA_PPzPP:
3360 return AArch64::BRKPAS_PPzPP;
3361 case AArch64::BRKB_PPzP:
3362 return AArch64::BRKBS_PPzP;
3363 case AArch64::BRKPB_PPzPP:
3364 return AArch64::BRKPBS_PPzPP;
3365 case AArch64::BRKN_PPzP:
3366 return AArch64::BRKNS_PPzP;
3367 case AArch64::RDFFR_PPz:
3368 return AArch64::RDFFRS_PPz;
3369 case AArch64::PTRUE_B:
3370 return AArch64::PTRUES_B;
3381 if (
MI.hasOrderedMemoryRef())
3386 assert((
MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3387 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3388 "Expected a reg or frame index operand.");
3392 bool IsImmPreLdSt = IsPreLdSt &&
MI.getOperand(3).isImm();
3394 if (!
MI.getOperand(2).isImm() && !IsImmPreLdSt)
3407 if (
MI.getOperand(1).isReg() && !IsPreLdSt) {
3408 Register BaseReg =
MI.getOperand(1).getReg();
3410 if (
MI.modifiesRegister(BaseReg,
TRI))
3416 switch (
MI.getOpcode()) {
3419 case AArch64::LDR_ZXI:
3420 case AArch64::STR_ZXI:
3421 if (!Subtarget.isLittleEndian() ||
3422 Subtarget.getSVEVectorSizeInBits() != 128)
3435 const MCAsmInfo &MAI =
MI.getMF()->getTarget().getMCAsmInfo();
3443 if (Subtarget.isPaired128Slow()) {
3444 switch (
MI.getOpcode()) {
3447 case AArch64::LDURQi:
3448 case AArch64::STURQi:
3449 case AArch64::LDRQui:
3450 case AArch64::STRQui:
3477std::optional<ExtAddrMode>
3482 bool OffsetIsScalable;
3483 if (!getMemOperandWithOffset(MemI,
Base,
Offset, OffsetIsScalable,
TRI))
3484 return std::nullopt;
3487 return std::nullopt;
3502 int64_t OffsetScale = 1;
3507 case AArch64::LDURQi:
3508 case AArch64::STURQi:
3512 case AArch64::LDURDi:
3513 case AArch64::STURDi:
3514 case AArch64::LDURXi:
3515 case AArch64::STURXi:
3519 case AArch64::LDURWi:
3520 case AArch64::LDURSWi:
3521 case AArch64::STURWi:
3525 case AArch64::LDURHi:
3526 case AArch64::STURHi:
3527 case AArch64::LDURHHi:
3528 case AArch64::STURHHi:
3529 case AArch64::LDURSHXi:
3530 case AArch64::LDURSHWi:
3534 case AArch64::LDRBroX:
3535 case AArch64::LDRBBroX:
3536 case AArch64::LDRSBXroX:
3537 case AArch64::LDRSBWroX:
3538 case AArch64::STRBroX:
3539 case AArch64::STRBBroX:
3540 case AArch64::LDURBi:
3541 case AArch64::LDURBBi:
3542 case AArch64::LDURSBXi:
3543 case AArch64::LDURSBWi:
3544 case AArch64::STURBi:
3545 case AArch64::STURBBi:
3546 case AArch64::LDRBui:
3547 case AArch64::LDRBBui:
3548 case AArch64::LDRSBXui:
3549 case AArch64::LDRSBWui:
3550 case AArch64::STRBui:
3551 case AArch64::STRBBui:
3555 case AArch64::LDRQroX:
3556 case AArch64::STRQroX:
3557 case AArch64::LDRQui:
3558 case AArch64::STRQui:
3563 case AArch64::LDRDroX:
3564 case AArch64::STRDroX:
3565 case AArch64::LDRXroX:
3566 case AArch64::STRXroX:
3567 case AArch64::LDRDui:
3568 case AArch64::STRDui:
3569 case AArch64::LDRXui:
3570 case AArch64::STRXui:
3575 case AArch64::LDRWroX:
3576 case AArch64::LDRSWroX:
3577 case AArch64::STRWroX:
3578 case AArch64::LDRWui:
3579 case AArch64::LDRSWui:
3580 case AArch64::STRWui:
3585 case AArch64::LDRHroX:
3586 case AArch64::STRHroX:
3587 case AArch64::LDRHHroX:
3588 case AArch64::STRHHroX:
3589 case AArch64::LDRSHXroX:
3590 case AArch64::LDRSHWroX:
3591 case AArch64::LDRHui:
3592 case AArch64::STRHui:
3593 case AArch64::LDRHHui:
3594 case AArch64::STRHHui:
3595 case AArch64::LDRSHXui:
3596 case AArch64::LDRSHWui:
3604 if (BaseRegOp.
isReg() && BaseRegOp.
getReg() == Reg)
3628 case AArch64::SBFMXri:
3641 AM.
Scale = OffsetScale;
3646 case TargetOpcode::SUBREG_TO_REG: {
3662 if (
DefMI.getOpcode() != AArch64::ORRWrs ||
3663 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3664 DefMI.getOperand(3).getImm() != 0)
3671 AM.
Scale = OffsetScale;
3682 auto validateOffsetForLDP = [](
unsigned NumBytes, int64_t OldOffset,
3683 int64_t NewOffset) ->
bool {
3684 int64_t MinOffset, MaxOffset;
3701 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3702 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3704 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) ->
bool {
3706 int64_t NewOffset = OldOffset + Disp;
3707 if (!isLegalAddressingMode(NumBytes, NewOffset, 0))
3711 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3721 auto canFoldAddRegIntoAddrMode =
3726 if ((
unsigned)Scale != Scale)
3728 if (!isLegalAddressingMode(NumBytes, 0, Scale))
3740 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3741 Subtarget.isSTRQroSlow();
3750 case AArch64::ADDXri:
3756 return canFoldAddSubImmIntoAddrMode(Disp);
3758 case AArch64::SUBXri:
3764 return canFoldAddSubImmIntoAddrMode(-Disp);
3766 case AArch64::ADDXrs: {
3779 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3781 if (avoidSlowSTRQ(MemI))
3784 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3787 case AArch64::ADDXrr:
3795 if (!OptSize && avoidSlowSTRQ(MemI))
3797 return canFoldAddRegIntoAddrMode(1);
3799 case AArch64::ADDXrx:
3807 if (!OptSize && avoidSlowSTRQ(MemI))
3816 return canFoldAddRegIntoAddrMode(
3831 case AArch64::LDURQi:
3832 case AArch64::LDRQui:
3833 return AArch64::LDRQroX;
3834 case AArch64::STURQi:
3835 case AArch64::STRQui:
3836 return AArch64::STRQroX;
3837 case AArch64::LDURDi:
3838 case AArch64::LDRDui:
3839 return AArch64::LDRDroX;
3840 case AArch64::STURDi:
3841 case AArch64::STRDui:
3842 return AArch64::STRDroX;
3843 case AArch64::LDURXi:
3844 case AArch64::LDRXui:
3845 return AArch64::LDRXroX;
3846 case AArch64::STURXi:
3847 case AArch64::STRXui:
3848 return AArch64::STRXroX;
3849 case AArch64::LDURWi:
3850 case AArch64::LDRWui:
3851 return AArch64::LDRWroX;
3852 case AArch64::LDURSWi:
3853 case AArch64::LDRSWui:
3854 return AArch64::LDRSWroX;
3855 case AArch64::STURWi:
3856 case AArch64::STRWui:
3857 return AArch64::STRWroX;
3858 case AArch64::LDURHi:
3859 case AArch64::LDRHui:
3860 return AArch64::LDRHroX;
3861 case AArch64::STURHi:
3862 case AArch64::STRHui:
3863 return AArch64::STRHroX;
3864 case AArch64::LDURHHi:
3865 case AArch64::LDRHHui:
3866 return AArch64::LDRHHroX;
3867 case AArch64::STURHHi:
3868 case AArch64::STRHHui:
3869 return AArch64::STRHHroX;
3870 case AArch64::LDURSHXi:
3871 case AArch64::LDRSHXui:
3872 return AArch64::LDRSHXroX;
3873 case AArch64::LDURSHWi:
3874 case AArch64::LDRSHWui:
3875 return AArch64::LDRSHWroX;
3876 case AArch64::LDURBi:
3877 case AArch64::LDRBui:
3878 return AArch64::LDRBroX;
3879 case AArch64::LDURBBi:
3880 case AArch64::LDRBBui:
3881 return AArch64::LDRBBroX;
3882 case AArch64::LDURSBXi:
3883 case AArch64::LDRSBXui:
3884 return AArch64::LDRSBXroX;
3885 case AArch64::LDURSBWi:
3886 case AArch64::LDRSBWui:
3887 return AArch64::LDRSBWroX;
3888 case AArch64::STURBi:
3889 case AArch64::STRBui:
3890 return AArch64::STRBroX;
3891 case AArch64::STURBBi:
3892 case AArch64::STRBBui:
3893 return AArch64::STRBBroX;
3905 case AArch64::LDURQi:
3907 return AArch64::LDRQui;
3908 case AArch64::STURQi:
3910 return AArch64::STRQui;
3911 case AArch64::LDURDi:
3913 return AArch64::LDRDui;
3914 case AArch64::STURDi:
3916 return AArch64::STRDui;
3917 case AArch64::LDURXi:
3919 return AArch64::LDRXui;
3920 case AArch64::STURXi:
3922 return AArch64::STRXui;
3923 case AArch64::LDURWi:
3925 return AArch64::LDRWui;
3926 case AArch64::LDURSWi:
3928 return AArch64::LDRSWui;
3929 case AArch64::STURWi:
3931 return AArch64::STRWui;
3932 case AArch64::LDURHi:
3934 return AArch64::LDRHui;
3935 case AArch64::STURHi:
3937 return AArch64::STRHui;
3938 case AArch64::LDURHHi:
3940 return AArch64::LDRHHui;
3941 case AArch64::STURHHi:
3943 return AArch64::STRHHui;
3944 case AArch64::LDURSHXi:
3946 return AArch64::LDRSHXui;
3947 case AArch64::LDURSHWi:
3949 return AArch64::LDRSHWui;
3950 case AArch64::LDURBi:
3952 return AArch64::LDRBui;
3953 case AArch64::LDURBBi:
3955 return AArch64::LDRBBui;
3956 case AArch64::LDURSBXi:
3958 return AArch64::LDRSBXui;
3959 case AArch64::LDURSBWi:
3961 return AArch64::LDRSBWui;
3962 case AArch64::STURBi:
3964 return AArch64::STRBui;
3965 case AArch64::STURBBi:
3967 return AArch64::STRBBui;
3968 case AArch64::LDRQui:
3969 case AArch64::STRQui:
3972 case AArch64::LDRDui:
3973 case AArch64::STRDui:
3974 case AArch64::LDRXui:
3975 case AArch64::STRXui:
3978 case AArch64::LDRWui:
3979 case AArch64::LDRSWui:
3980 case AArch64::STRWui:
3983 case AArch64::LDRHui:
3984 case AArch64::STRHui:
3985 case AArch64::LDRHHui:
3986 case AArch64::STRHHui:
3987 case AArch64::LDRSHXui:
3988 case AArch64::LDRSHWui:
3991 case AArch64::LDRBui:
3992 case AArch64::LDRBBui:
3993 case AArch64::LDRSBXui:
3994 case AArch64::LDRSBWui:
3995 case AArch64::STRBui:
3996 case AArch64::STRBBui:
4010 case AArch64::LDURQi:
4011 case AArch64::STURQi:
4012 case AArch64::LDURDi:
4013 case AArch64::STURDi:
4014 case AArch64::LDURXi:
4015 case AArch64::STURXi:
4016 case AArch64::LDURWi:
4017 case AArch64::LDURSWi:
4018 case AArch64::STURWi:
4019 case AArch64::LDURHi:
4020 case AArch64::STURHi:
4021 case AArch64::LDURHHi:
4022 case AArch64::STURHHi:
4023 case AArch64::LDURSHXi:
4024 case AArch64::LDURSHWi:
4025 case AArch64::LDURBi:
4026 case AArch64::STURBi:
4027 case AArch64::LDURBBi:
4028 case AArch64::STURBBi:
4029 case AArch64::LDURSBWi:
4030 case AArch64::LDURSBXi:
4032 case AArch64::LDRQui:
4033 return AArch64::LDURQi;
4034 case AArch64::STRQui:
4035 return AArch64::STURQi;
4036 case AArch64::LDRDui:
4037 return AArch64::LDURDi;
4038 case AArch64::STRDui:
4039 return AArch64::STURDi;
4040 case AArch64::LDRXui:
4041 return AArch64::LDURXi;
4042 case AArch64::STRXui:
4043 return AArch64::STURXi;
4044 case AArch64::LDRWui:
4045 return AArch64::LDURWi;
4046 case AArch64::LDRSWui:
4047 return AArch64::LDURSWi;
4048 case AArch64::STRWui:
4049 return AArch64::STURWi;
4050 case AArch64::LDRHui:
4051 return AArch64::LDURHi;
4052 case AArch64::STRHui:
4053 return AArch64::STURHi;
4054 case AArch64::LDRHHui:
4055 return AArch64::LDURHHi;
4056 case AArch64::STRHHui:
4057 return AArch64::STURHHi;
4058 case AArch64::LDRSHXui:
4059 return AArch64::LDURSHXi;
4060 case AArch64::LDRSHWui:
4061 return AArch64::LDURSHWi;
4062 case AArch64::LDRBBui:
4063 return AArch64::LDURBBi;
4064 case AArch64::LDRBui:
4065 return AArch64::LDURBi;
4066 case AArch64::STRBBui:
4067 return AArch64::STURBBi;
4068 case AArch64::STRBui:
4069 return AArch64::STURBi;
4070 case AArch64::LDRSBWui:
4071 return AArch64::LDURSBWi;
4072 case AArch64::LDRSBXui:
4073 return AArch64::LDURSBXi;
4086 case AArch64::LDRQroX:
4087 case AArch64::LDURQi:
4088 case AArch64::LDRQui:
4089 return AArch64::LDRQroW;
4090 case AArch64::STRQroX:
4091 case AArch64::STURQi:
4092 case AArch64::STRQui:
4093 return AArch64::STRQroW;
4094 case AArch64::LDRDroX:
4095 case AArch64::LDURDi:
4096 case AArch64::LDRDui:
4097 return AArch64::LDRDroW;
4098 case AArch64::STRDroX:
4099 case AArch64::STURDi:
4100 case AArch64::STRDui:
4101 return AArch64::STRDroW;
4102 case AArch64::LDRXroX:
4103 case AArch64::LDURXi:
4104 case AArch64::LDRXui:
4105 return AArch64::LDRXroW;
4106 case AArch64::STRXroX:
4107 case AArch64::STURXi:
4108 case AArch64::STRXui:
4109 return AArch64::STRXroW;
4110 case AArch64::LDRWroX:
4111 case AArch64::LDURWi:
4112 case AArch64::LDRWui:
4113 return AArch64::LDRWroW;
4114 case AArch64::LDRSWroX:
4115 case AArch64::LDURSWi:
4116 case AArch64::LDRSWui:
4117 return AArch64::LDRSWroW;
4118 case AArch64::STRWroX:
4119 case AArch64::STURWi:
4120 case AArch64::STRWui:
4121 return AArch64::STRWroW;
4122 case AArch64::LDRHroX:
4123 case AArch64::LDURHi:
4124 case AArch64::LDRHui:
4125 return AArch64::LDRHroW;
4126 case AArch64::STRHroX:
4127 case AArch64::STURHi:
4128 case AArch64::STRHui:
4129 return AArch64::STRHroW;
4130 case AArch64::LDRHHroX:
4131 case AArch64::LDURHHi:
4132 case AArch64::LDRHHui:
4133 return AArch64::LDRHHroW;
4134 case AArch64::STRHHroX:
4135 case AArch64::STURHHi:
4136 case AArch64::STRHHui:
4137 return AArch64::STRHHroW;
4138 case AArch64::LDRSHXroX:
4139 case AArch64::LDURSHXi:
4140 case AArch64::LDRSHXui:
4141 return AArch64::LDRSHXroW;
4142 case AArch64::LDRSHWroX:
4143 case AArch64::LDURSHWi:
4144 case AArch64::LDRSHWui:
4145 return AArch64::LDRSHWroW;
4146 case AArch64::LDRBroX:
4147 case AArch64::LDURBi:
4148 case AArch64::LDRBui:
4149 return AArch64::LDRBroW;
4150 case AArch64::LDRBBroX:
4151 case AArch64::LDURBBi:
4152 case AArch64::LDRBBui:
4153 return AArch64::LDRBBroW;
4154 case AArch64::LDRSBXroX:
4155 case AArch64::LDURSBXi:
4156 case AArch64::LDRSBXui:
4157 return AArch64::LDRSBXroW;
4158 case AArch64::LDRSBWroX:
4159 case AArch64::LDURSBWi:
4160 case AArch64::LDRSBWui:
4161 return AArch64::LDRSBWroW;
4162 case AArch64::STRBroX:
4163 case AArch64::STURBi:
4164 case AArch64::STRBui:
4165 return AArch64::STRBroW;
4166 case AArch64::STRBBroX:
4167 case AArch64::STURBBi:
4168 case AArch64::STRBBui:
4169 return AArch64::STRBBroW;
4194 return B.getInstr();
4198 "Addressing mode not supported for folding");
4215 return B.getInstr();
4222 "Address offset can be a register or an immediate, but not both");
4243 return B.getInstr();
4247 "Function must not be called with an addressing mode it can't handle");
4256 case AArch64::LD1Fourv16b_POST:
4257 case AArch64::LD1Fourv1d_POST:
4258 case AArch64::LD1Fourv2d_POST:
4259 case AArch64::LD1Fourv2s_POST:
4260 case AArch64::LD1Fourv4h_POST:
4261 case AArch64::LD1Fourv4s_POST:
4262 case AArch64::LD1Fourv8b_POST:
4263 case AArch64::LD1Fourv8h_POST:
4264 case AArch64::LD1Onev16b_POST:
4265 case AArch64::LD1Onev1d_POST:
4266 case AArch64::LD1Onev2d_POST:
4267 case AArch64::LD1Onev2s_POST:
4268 case AArch64::LD1Onev4h_POST:
4269 case AArch64::LD1Onev4s_POST:
4270 case AArch64::LD1Onev8b_POST:
4271 case AArch64::LD1Onev8h_POST:
4272 case AArch64::LD1Rv16b_POST:
4273 case AArch64::LD1Rv1d_POST:
4274 case AArch64::LD1Rv2d_POST:
4275 case AArch64::LD1Rv2s_POST:
4276 case AArch64::LD1Rv4h_POST:
4277 case AArch64::LD1Rv4s_POST:
4278 case AArch64::LD1Rv8b_POST:
4279 case AArch64::LD1Rv8h_POST:
4280 case AArch64::LD1Threev16b_POST:
4281 case AArch64::LD1Threev1d_POST:
4282 case AArch64::LD1Threev2d_POST:
4283 case AArch64::LD1Threev2s_POST:
4284 case AArch64::LD1Threev4h_POST:
4285 case AArch64::LD1Threev4s_POST:
4286 case AArch64::LD1Threev8b_POST:
4287 case AArch64::LD1Threev8h_POST:
4288 case AArch64::LD1Twov16b_POST:
4289 case AArch64::LD1Twov1d_POST:
4290 case AArch64::LD1Twov2d_POST:
4291 case AArch64::LD1Twov2s_POST:
4292 case AArch64::LD1Twov4h_POST:
4293 case AArch64::LD1Twov4s_POST:
4294 case AArch64::LD1Twov8b_POST:
4295 case AArch64::LD1Twov8h_POST:
4296 case AArch64::LD1i16_POST:
4297 case AArch64::LD1i32_POST:
4298 case AArch64::LD1i64_POST:
4299 case AArch64::LD1i8_POST:
4300 case AArch64::LD2Rv16b_POST:
4301 case AArch64::LD2Rv1d_POST:
4302 case AArch64::LD2Rv2d_POST:
4303 case AArch64::LD2Rv2s_POST:
4304 case AArch64::LD2Rv4h_POST:
4305 case AArch64::LD2Rv4s_POST:
4306 case AArch64::LD2Rv8b_POST:
4307 case AArch64::LD2Rv8h_POST:
4308 case AArch64::LD2Twov16b_POST:
4309 case AArch64::LD2Twov2d_POST:
4310 case AArch64::LD2Twov2s_POST:
4311 case AArch64::LD2Twov4h_POST:
4312 case AArch64::LD2Twov4s_POST:
4313 case AArch64::LD2Twov8b_POST:
4314 case AArch64::LD2Twov8h_POST:
4315 case AArch64::LD2i16_POST:
4316 case AArch64::LD2i32_POST:
4317 case AArch64::LD2i64_POST:
4318 case AArch64::LD2i8_POST:
4319 case AArch64::LD3Rv16b_POST:
4320 case AArch64::LD3Rv1d_POST:
4321 case AArch64::LD3Rv2d_POST:
4322 case AArch64::LD3Rv2s_POST:
4323 case AArch64::LD3Rv4h_POST:
4324 case AArch64::LD3Rv4s_POST:
4325 case AArch64::LD3Rv8b_POST:
4326 case AArch64::LD3Rv8h_POST:
4327 case AArch64::LD3Threev16b_POST:
4328 case AArch64::LD3Threev2d_POST:
4329 case AArch64::LD3Threev2s_POST:
4330 case AArch64::LD3Threev4h_POST:
4331 case AArch64::LD3Threev4s_POST:
4332 case AArch64::LD3Threev8b_POST:
4333 case AArch64::LD3Threev8h_POST:
4334 case AArch64::LD3i16_POST:
4335 case AArch64::LD3i32_POST:
4336 case AArch64::LD3i64_POST:
4337 case AArch64::LD3i8_POST:
4338 case AArch64::LD4Fourv16b_POST:
4339 case AArch64::LD4Fourv2d_POST:
4340 case AArch64::LD4Fourv2s_POST:
4341 case AArch64::LD4Fourv4h_POST:
4342 case AArch64::LD4Fourv4s_POST:
4343 case AArch64::LD4Fourv8b_POST:
4344 case AArch64::LD4Fourv8h_POST:
4345 case AArch64::LD4Rv16b_POST:
4346 case AArch64::LD4Rv1d_POST:
4347 case AArch64::LD4Rv2d_POST:
4348 case AArch64::LD4Rv2s_POST:
4349 case AArch64::LD4Rv4h_POST:
4350 case AArch64::LD4Rv4s_POST:
4351 case AArch64::LD4Rv8b_POST:
4352 case AArch64::LD4Rv8h_POST:
4353 case AArch64::LD4i16_POST:
4354 case AArch64::LD4i32_POST:
4355 case AArch64::LD4i64_POST:
4356 case AArch64::LD4i8_POST:
4357 case AArch64::LDAPRWpost:
4358 case AArch64::LDAPRXpost:
4359 case AArch64::LDIAPPWpost:
4360 case AArch64::LDIAPPXpost:
4361 case AArch64::LDPDpost:
4362 case AArch64::LDPQpost:
4363 case AArch64::LDPSWpost:
4364 case AArch64::LDPSpost:
4365 case AArch64::LDPWpost:
4366 case AArch64::LDPXpost:
4367 case AArch64::LDRBBpost:
4368 case AArch64::LDRBpost:
4369 case AArch64::LDRDpost:
4370 case AArch64::LDRHHpost:
4371 case AArch64::LDRHpost:
4372 case AArch64::LDRQpost:
4373 case AArch64::LDRSBWpost:
4374 case AArch64::LDRSBXpost:
4375 case AArch64::LDRSHWpost:
4376 case AArch64::LDRSHXpost:
4377 case AArch64::LDRSWpost:
4378 case AArch64::LDRSpost:
4379 case AArch64::LDRWpost:
4380 case AArch64::LDRXpost:
4381 case AArch64::ST1Fourv16b_POST:
4382 case AArch64::ST1Fourv1d_POST:
4383 case AArch64::ST1Fourv2d_POST:
4384 case AArch64::ST1Fourv2s_POST:
4385 case AArch64::ST1Fourv4h_POST:
4386 case AArch64::ST1Fourv4s_POST:
4387 case AArch64::ST1Fourv8b_POST:
4388 case AArch64::ST1Fourv8h_POST:
4389 case AArch64::ST1Onev16b_POST:
4390 case AArch64::ST1Onev1d_POST:
4391 case AArch64::ST1Onev2d_POST:
4392 case AArch64::ST1Onev2s_POST:
4393 case AArch64::ST1Onev4h_POST:
4394 case AArch64::ST1Onev4s_POST:
4395 case AArch64::ST1Onev8b_POST:
4396 case AArch64::ST1Onev8h_POST:
4397 case AArch64::ST1Threev16b_POST:
4398 case AArch64::ST1Threev1d_POST:
4399 case AArch64::ST1Threev2d_POST:
4400 case AArch64::ST1Threev2s_POST:
4401 case AArch64::ST1Threev4h_POST:
4402 case AArch64::ST1Threev4s_POST:
4403 case AArch64::ST1Threev8b_POST:
4404 case AArch64::ST1Threev8h_POST:
4405 case AArch64::ST1Twov16b_POST:
4406 case AArch64::ST1Twov1d_POST:
4407 case AArch64::ST1Twov2d_POST:
4408 case AArch64::ST1Twov2s_POST:
4409 case AArch64::ST1Twov4h_POST:
4410 case AArch64::ST1Twov4s_POST:
4411 case AArch64::ST1Twov8b_POST:
4412 case AArch64::ST1Twov8h_POST:
4413 case AArch64::ST1i16_POST:
4414 case AArch64::ST1i32_POST:
4415 case AArch64::ST1i64_POST:
4416 case AArch64::ST1i8_POST:
4417 case AArch64::ST2GPostIndex:
4418 case AArch64::ST2Twov16b_POST:
4419 case AArch64::ST2Twov2d_POST:
4420 case AArch64::ST2Twov2s_POST:
4421 case AArch64::ST2Twov4h_POST:
4422 case AArch64::ST2Twov4s_POST:
4423 case AArch64::ST2Twov8b_POST:
4424 case AArch64::ST2Twov8h_POST:
4425 case AArch64::ST2i16_POST:
4426 case AArch64::ST2i32_POST:
4427 case AArch64::ST2i64_POST:
4428 case AArch64::ST2i8_POST:
4429 case AArch64::ST3Threev16b_POST:
4430 case AArch64::ST3Threev2d_POST:
4431 case AArch64::ST3Threev2s_POST:
4432 case AArch64::ST3Threev4h_POST:
4433 case AArch64::ST3Threev4s_POST:
4434 case AArch64::ST3Threev8b_POST:
4435 case AArch64::ST3Threev8h_POST:
4436 case AArch64::ST3i16_POST:
4437 case AArch64::ST3i32_POST:
4438 case AArch64::ST3i64_POST:
4439 case AArch64::ST3i8_POST:
4440 case AArch64::ST4Fourv16b_POST:
4441 case AArch64::ST4Fourv2d_POST:
4442 case AArch64::ST4Fourv2s_POST:
4443 case AArch64::ST4Fourv4h_POST:
4444 case AArch64::ST4Fourv4s_POST:
4445 case AArch64::ST4Fourv8b_POST:
4446 case AArch64::ST4Fourv8h_POST:
4447 case AArch64::ST4i16_POST:
4448 case AArch64::ST4i32_POST:
4449 case AArch64::ST4i64_POST:
4450 case AArch64::ST4i8_POST:
4451 case AArch64::STGPostIndex:
4452 case AArch64::STGPpost:
4453 case AArch64::STPDpost:
4454 case AArch64::STPQpost:
4455 case AArch64::STPSpost:
4456 case AArch64::STPWpost:
4457 case AArch64::STPXpost:
4458 case AArch64::STRBBpost:
4459 case AArch64::STRBpost:
4460 case AArch64::STRDpost:
4461 case AArch64::STRHHpost:
4462 case AArch64::STRHpost:
4463 case AArch64::STRQpost:
4464 case AArch64::STRSpost:
4465 case AArch64::STRWpost:
4466 case AArch64::STRXpost:
4467 case AArch64::STZ2GPostIndex:
4468 case AArch64::STZGPostIndex:
4475 bool &OffsetIsScalable,
TypeSize &Width,
4496 int64_t Dummy1, Dummy2;
4518 return BaseOp->
isReg() || BaseOp->
isFI();
4525 assert(OfsOp.
isImm() &&
"Offset operand wasn't immediate.");
4530 TypeSize &Width, int64_t &MinOffset,
4531 int64_t &MaxOffset) {
4537 MinOffset = MaxOffset = 0;
4540 case AArch64::LDRQui:
4541 case AArch64::STRQui:
4547 case AArch64::LDRXui:
4548 case AArch64::LDRDui:
4549 case AArch64::STRXui:
4550 case AArch64::STRDui:
4551 case AArch64::PRFMui:
4557 case AArch64::LDRWui:
4558 case AArch64::LDRSui:
4559 case AArch64::LDRSWui:
4560 case AArch64::STRWui:
4561 case AArch64::STRSui:
4567 case AArch64::LDRHui:
4568 case AArch64::LDRHHui:
4569 case AArch64::LDRSHWui:
4570 case AArch64::LDRSHXui:
4571 case AArch64::STRHui:
4572 case AArch64::STRHHui:
4578 case AArch64::LDRBui:
4579 case AArch64::LDRBBui:
4580 case AArch64::LDRSBWui:
4581 case AArch64::LDRSBXui:
4582 case AArch64::STRBui:
4583 case AArch64::STRBBui:
4590 case AArch64::STRQpre:
4591 case AArch64::LDRQpost:
4597 case AArch64::LDRDpost:
4598 case AArch64::LDRDpre:
4599 case AArch64::LDRXpost:
4600 case AArch64::LDRXpre:
4601 case AArch64::STRDpost:
4602 case AArch64::STRDpre:
4603 case AArch64::STRXpost:
4604 case AArch64::STRXpre:
4610 case AArch64::STRWpost:
4611 case AArch64::STRWpre:
4612 case AArch64::LDRWpost:
4613 case AArch64::LDRWpre:
4614 case AArch64::STRSpost:
4615 case AArch64::STRSpre:
4616 case AArch64::LDRSpost:
4617 case AArch64::LDRSpre:
4623 case AArch64::LDRHpost:
4624 case AArch64::LDRHpre:
4625 case AArch64::STRHpost:
4626 case AArch64::STRHpre:
4627 case AArch64::LDRHHpost:
4628 case AArch64::LDRHHpre:
4629 case AArch64::STRHHpost:
4630 case AArch64::STRHHpre:
4636 case AArch64::LDRBpost:
4637 case AArch64::LDRBpre:
4638 case AArch64::STRBpost:
4639 case AArch64::STRBpre:
4640 case AArch64::LDRBBpost:
4641 case AArch64::LDRBBpre:
4642 case AArch64::STRBBpost:
4643 case AArch64::STRBBpre:
4650 case AArch64::LDURQi:
4651 case AArch64::STURQi:
4657 case AArch64::LDURXi:
4658 case AArch64::LDURDi:
4659 case AArch64::LDAPURXi:
4660 case AArch64::STURXi:
4661 case AArch64::STURDi:
4662 case AArch64::STLURXi:
4663 case AArch64::PRFUMi:
4669 case AArch64::LDURWi:
4670 case AArch64::LDURSi:
4671 case AArch64::LDURSWi:
4672 case AArch64::LDAPURi:
4673 case AArch64::LDAPURSWi:
4674 case AArch64::STURWi:
4675 case AArch64::STURSi:
4676 case AArch64::STLURWi:
4682 case AArch64::LDURHi:
4683 case AArch64::LDURHHi:
4684 case AArch64::LDURSHXi:
4685 case AArch64::LDURSHWi:
4686 case AArch64::LDAPURHi:
4687 case AArch64::LDAPURSHWi:
4688 case AArch64::LDAPURSHXi:
4689 case AArch64::STURHi:
4690 case AArch64::STURHHi:
4691 case AArch64::STLURHi:
4697 case AArch64::LDURBi:
4698 case AArch64::LDURBBi:
4699 case AArch64::LDURSBXi:
4700 case AArch64::LDURSBWi:
4701 case AArch64::LDAPURBi:
4702 case AArch64::LDAPURSBWi:
4703 case AArch64::LDAPURSBXi:
4704 case AArch64::STURBi:
4705 case AArch64::STURBBi:
4706 case AArch64::STLURBi:
4713 case AArch64::LDPQi:
4714 case AArch64::LDNPQi:
4715 case AArch64::STPQi:
4716 case AArch64::STNPQi:
4717 case AArch64::LDPQpost:
4718 case AArch64::LDPQpre:
4719 case AArch64::STPQpost:
4720 case AArch64::STPQpre:
4726 case AArch64::LDPXi:
4727 case AArch64::LDPDi:
4728 case AArch64::LDNPXi:
4729 case AArch64::LDNPDi:
4730 case AArch64::STPXi:
4731 case AArch64::STPDi:
4732 case AArch64::STNPXi:
4733 case AArch64::STNPDi:
4734 case AArch64::LDPDpost:
4735 case AArch64::LDPDpre:
4736 case AArch64::LDPXpost:
4737 case AArch64::LDPXpre:
4738 case AArch64::STPDpost:
4739 case AArch64::STPDpre:
4740 case AArch64::STPXpost:
4741 case AArch64::STPXpre:
4747 case AArch64::LDPWi:
4748 case AArch64::LDPSi:
4749 case AArch64::LDNPWi:
4750 case AArch64::LDNPSi:
4751 case AArch64::STPWi:
4752 case AArch64::STPSi:
4753 case AArch64::STNPWi:
4754 case AArch64::STNPSi:
4755 case AArch64::LDPSpost:
4756 case AArch64::LDPSpre:
4757 case AArch64::LDPWpost:
4758 case AArch64::LDPWpre:
4759 case AArch64::STPSpost:
4760 case AArch64::STPSpre:
4761 case AArch64::STPWpost:
4762 case AArch64::STPWpre:
4768 case AArch64::StoreSwiftAsyncContext:
4781 case AArch64::TAGPstack:
4791 case AArch64::STGPreIndex:
4792 case AArch64::STGPostIndex:
4793 case AArch64::STZGi:
4794 case AArch64::STZGPreIndex:
4795 case AArch64::STZGPostIndex:
4802 case AArch64::STR_ZZZZXI:
4803 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4804 case AArch64::LDR_ZZZZXI:
4805 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4811 case AArch64::STR_ZZZXI:
4812 case AArch64::LDR_ZZZXI:
4818 case AArch64::STR_ZZXI:
4819 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4820 case AArch64::LDR_ZZXI:
4821 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4827 case AArch64::LDR_PXI:
4828 case AArch64::STR_PXI:
4834 case AArch64::LDR_PPXI:
4835 case AArch64::STR_PPXI:
4841 case AArch64::LDR_ZXI:
4842 case AArch64::STR_ZXI:
4848 case AArch64::LD1B_IMM:
4849 case AArch64::LD1H_IMM:
4850 case AArch64::LD1W_IMM:
4851 case AArch64::LD1D_IMM:
4852 case AArch64::LDNT1B_ZRI:
4853 case AArch64::LDNT1H_ZRI:
4854 case AArch64::LDNT1W_ZRI:
4855 case AArch64::LDNT1D_ZRI:
4856 case AArch64::ST1B_IMM:
4857 case AArch64::ST1H_IMM:
4858 case AArch64::ST1W_IMM:
4859 case AArch64::ST1D_IMM:
4860 case AArch64::STNT1B_ZRI:
4861 case AArch64::STNT1H_ZRI:
4862 case AArch64::STNT1W_ZRI:
4863 case AArch64::STNT1D_ZRI:
4864 case AArch64::LDNF1B_IMM:
4865 case AArch64::LDNF1H_IMM:
4866 case AArch64::LDNF1W_IMM:
4867 case AArch64::LDNF1D_IMM:
4875 case AArch64::LD2B_IMM:
4876 case AArch64::LD2H_IMM:
4877 case AArch64::LD2W_IMM:
4878 case AArch64::LD2D_IMM:
4879 case AArch64::ST2B_IMM:
4880 case AArch64::ST2H_IMM:
4881 case AArch64::ST2W_IMM:
4882 case AArch64::ST2D_IMM:
4883 case AArch64::LD1B_2Z_IMM:
4884 case AArch64::LD1B_2Z_STRIDED_IMM:
4885 case AArch64::LD1H_2Z_IMM:
4886 case AArch64::LD1H_2Z_STRIDED_IMM:
4887 case AArch64::LD1W_2Z_IMM:
4888 case AArch64::LD1W_2Z_STRIDED_IMM:
4889 case AArch64::LD1D_2Z_IMM:
4890 case AArch64::LD1D_2Z_STRIDED_IMM:
4891 case AArch64::LD1B_2Z_IMM_PSEUDO:
4892 case AArch64::LD1H_2Z_IMM_PSEUDO:
4893 case AArch64::LD1W_2Z_IMM_PSEUDO:
4894 case AArch64::LD1D_2Z_IMM_PSEUDO:
4900 case AArch64::LD3B_IMM:
4901 case AArch64::LD3H_IMM:
4902 case AArch64::LD3W_IMM:
4903 case AArch64::LD3D_IMM:
4904 case AArch64::ST3B_IMM:
4905 case AArch64::ST3H_IMM:
4906 case AArch64::ST3W_IMM:
4907 case AArch64::ST3D_IMM:
4913 case AArch64::LD4B_IMM:
4914 case AArch64::LD4H_IMM:
4915 case AArch64::LD4W_IMM:
4916 case AArch64::LD4D_IMM:
4917 case AArch64::ST4B_IMM:
4918 case AArch64::ST4H_IMM:
4919 case AArch64::ST4W_IMM:
4920 case AArch64::ST4D_IMM:
4921 case AArch64::LD1B_4Z_IMM:
4922 case AArch64::LD1B_4Z_STRIDED_IMM:
4923 case AArch64::LD1H_4Z_IMM:
4924 case AArch64::LD1H_4Z_STRIDED_IMM:
4925 case AArch64::LD1W_4Z_IMM:
4926 case AArch64::LD1W_4Z_STRIDED_IMM:
4927 case AArch64::LD1D_4Z_IMM:
4928 case AArch64::LD1D_4Z_STRIDED_IMM:
4929 case AArch64::LD1B_4Z_IMM_PSEUDO:
4930 case AArch64::LD1H_4Z_IMM_PSEUDO:
4931 case AArch64::LD1W_4Z_IMM_PSEUDO:
4932 case AArch64::LD1D_4Z_IMM_PSEUDO:
4938 case AArch64::LD1B_H_IMM:
4939 case AArch64::LD1SB_H_IMM:
4940 case AArch64::LD1H_S_IMM:
4941 case AArch64::LD1SH_S_IMM:
4942 case AArch64::LD1W_D_IMM:
4943 case AArch64::LD1SW_D_IMM:
4944 case AArch64::ST1B_H_IMM:
4945 case AArch64::ST1H_S_IMM:
4946 case AArch64::ST1W_D_IMM:
4947 case AArch64::LDNF1B_H_IMM:
4948 case AArch64::LDNF1SB_H_IMM:
4949 case AArch64::LDNF1H_S_IMM:
4950 case AArch64::LDNF1SH_S_IMM:
4951 case AArch64::LDNF1W_D_IMM:
4952 case AArch64::LDNF1SW_D_IMM:
4960 case AArch64::LD1B_S_IMM:
4961 case AArch64::LD1SB_S_IMM:
4962 case AArch64::LD1H_D_IMM:
4963 case AArch64::LD1SH_D_IMM:
4964 case AArch64::ST1B_S_IMM:
4965 case AArch64::ST1H_D_IMM:
4966 case AArch64::LDNF1B_S_IMM:
4967 case AArch64::LDNF1SB_S_IMM:
4968 case AArch64::LDNF1H_D_IMM:
4969 case AArch64::LDNF1SH_D_IMM:
4977 case AArch64::LD1B_D_IMM:
4978 case AArch64::LD1SB_D_IMM:
4979 case AArch64::ST1B_D_IMM:
4980 case AArch64::LDNF1B_D_IMM:
4981 case AArch64::LDNF1SB_D_IMM:
4989 case AArch64::ST2Gi:
4990 case AArch64::ST2GPreIndex:
4991 case AArch64::ST2GPostIndex:
4992 case AArch64::STZ2Gi:
4993 case AArch64::STZ2GPreIndex:
4994 case AArch64::STZ2GPostIndex:
5000 case AArch64::STGPi:
5001 case AArch64::STGPpost:
5002 case AArch64::STGPpre:
5008 case AArch64::LD1RB_IMM:
5009 case AArch64::LD1RB_H_IMM:
5010 case AArch64::LD1RB_S_IMM:
5011 case AArch64::LD1RB_D_IMM:
5012 case AArch64::LD1RSB_H_IMM:
5013 case AArch64::LD1RSB_S_IMM:
5014 case AArch64::LD1RSB_D_IMM:
5020 case AArch64::LD1RH_IMM:
5021 case AArch64::LD1RH_S_IMM:
5022 case AArch64::LD1RH_D_IMM:
5023 case AArch64::LD1RSH_S_IMM:
5024 case AArch64::LD1RSH_D_IMM:
5030 case AArch64::LD1RW_IMM:
5031 case AArch64::LD1RW_D_IMM:
5032 case AArch64::LD1RSW_IMM:
5038 case AArch64::LD1RD_IMM:
5054 case AArch64::LDRBui:
5055 case AArch64::LDRBBui:
5056 case AArch64::LDURBBi:
5057 case AArch64::LDRSBWui:
5058 case AArch64::LDURSBWi:
5059 case AArch64::STRBui:
5060 case AArch64::STRBBui:
5061 case AArch64::STURBBi:
5063 case AArch64::LDRHui:
5064 case AArch64::LDRHHui:
5065 case AArch64::LDURHHi:
5066 case AArch64::LDRSHWui:
5067 case AArch64::LDURSHWi:
5068 case AArch64::STRHui:
5069 case AArch64::STRHHui:
5070 case AArch64::STURHHi:
5072 case AArch64::LDRSui:
5073 case AArch64::LDURSi:
5074 case AArch64::LDRSpre:
5075 case AArch64::LDRSWui:
5076 case AArch64::LDURSWi:
5077 case AArch64::LDRSWpre:
5078 case AArch64::LDRWpre:
5079 case AArch64::LDRWui:
5080 case AArch64::LDURWi:
5081 case AArch64::STRSui:
5082 case AArch64::STURSi:
5083 case AArch64::STRSpre:
5084 case AArch64::STRWui:
5085 case AArch64::STURWi:
5086 case AArch64::STRWpre:
5087 case AArch64::LDPSi:
5088 case AArch64::LDPSWi:
5089 case AArch64::LDPWi:
5090 case AArch64::STPSi:
5091 case AArch64::STPWi:
5093 case AArch64::LDRDui:
5094 case AArch64::LDURDi:
5095 case AArch64::LDRDpre:
5096 case AArch64::LDRXui:
5097 case AArch64::LDURXi:
5098 case AArch64::LDRXpre:
5099 case AArch64::STRDui:
5100 case AArch64::STURDi:
5101 case AArch64::STRDpre:
5102 case AArch64::STRXui:
5103 case AArch64::STURXi:
5104 case AArch64::STRXpre:
5105 case AArch64::LDPDi:
5106 case AArch64::LDPXi:
5107 case AArch64::STPDi:
5108 case AArch64::STPXi:
5110 case AArch64::LDRQui:
5111 case AArch64::LDURQi:
5112 case AArch64::STRQui:
5113 case AArch64::STURQi:
5114 case AArch64::STRQpre:
5115 case AArch64::LDPQi:
5116 case AArch64::LDRQpre:
5117 case AArch64::STPQi:
5119 case AArch64::STZGi:
5120 case AArch64::ST2Gi:
5121 case AArch64::STZ2Gi:
5122 case AArch64::STGPi:
5128 switch (
MI.getOpcode()) {
5131 case AArch64::LDRWpre:
5132 case AArch64::LDRXpre:
5133 case AArch64::LDRSWpre:
5134 case AArch64::LDRSpre:
5135 case AArch64::LDRDpre:
5136 case AArch64::LDRQpre:
5142 switch (
MI.getOpcode()) {
5145 case AArch64::STRWpre:
5146 case AArch64::STRXpre:
5147 case AArch64::STRSpre:
5148 case AArch64::STRDpre:
5149 case AArch64::STRQpre:
5159 switch (
MI.getOpcode()) {
5162 case AArch64::LDURBBi:
5163 case AArch64::LDURHHi:
5164 case AArch64::LDURWi:
5165 case AArch64::LDRBBui:
5166 case AArch64::LDRHHui:
5167 case AArch64::LDRWui:
5168 case AArch64::LDRBBroX:
5169 case AArch64::LDRHHroX:
5170 case AArch64::LDRWroX:
5171 case AArch64::LDRBBroW:
5172 case AArch64::LDRHHroW:
5173 case AArch64::LDRWroW:
5179 switch (
MI.getOpcode()) {
5182 case AArch64::LDURSBWi:
5183 case AArch64::LDURSHWi:
5184 case AArch64::LDURSBXi:
5185 case AArch64::LDURSHXi:
5186 case AArch64::LDURSWi:
5187 case AArch64::LDRSBWui:
5188 case AArch64::LDRSHWui:
5189 case AArch64::LDRSBXui:
5190 case AArch64::LDRSHXui:
5191 case AArch64::LDRSWui:
5192 case AArch64::LDRSBWroX:
5193 case AArch64::LDRSHWroX:
5194 case AArch64::LDRSBXroX:
5195 case AArch64::LDRSHXroX:
5196 case AArch64::LDRSWroX:
5197 case AArch64::LDRSBWroW:
5198 case AArch64::LDRSHWroW:
5199 case AArch64::LDRSBXroW:
5200 case AArch64::LDRSHXroW:
5201 case AArch64::LDRSWroW:
5207 switch (
MI.getOpcode()) {
5210 case AArch64::LDPSi:
5211 case AArch64::LDPSWi:
5212 case AArch64::LDPDi:
5213 case AArch64::LDPQi:
5214 case AArch64::LDPWi:
5215 case AArch64::LDPXi:
5216 case AArch64::STPSi:
5217 case AArch64::STPDi:
5218 case AArch64::STPQi:
5219 case AArch64::STPWi:
5220 case AArch64::STPXi:
5221 case AArch64::STGPi:
5227 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5231 return MI.getOperand(Idx);
5236 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5240 return MI.getOperand(Idx);
5245 switch (
MI.getOpcode()) {
5248 case AArch64::LDRBroX:
5249 case AArch64::LDRBBroX:
5250 case AArch64::LDRSBXroX:
5251 case AArch64::LDRSBWroX:
5252 case AArch64::LDRHroX:
5253 case AArch64::LDRHHroX:
5254 case AArch64::LDRSHXroX:
5255 case AArch64::LDRSHWroX:
5256 case AArch64::LDRWroX:
5257 case AArch64::LDRSroX:
5258 case AArch64::LDRSWroX:
5259 case AArch64::LDRDroX:
5260 case AArch64::LDRXroX:
5261 case AArch64::LDRQroX:
5262 return MI.getOperand(4);
5268 if (
MI.getParent() ==
nullptr)
5278 auto Reg =
Op.getReg();
5279 if (Reg.isPhysical())
5280 return AArch64::FPR16RegClass.contains(Reg);
5282 return TRC == &AArch64::FPR16RegClass ||
5283 TRC == &AArch64::FPR16_loRegClass;
5292 auto Reg =
Op.getReg();
5293 if (Reg.isPhysical())
5294 return AArch64::FPR128RegClass.contains(Reg);
5296 return TRC == &AArch64::FPR128RegClass ||
5297 TRC == &AArch64::FPR128_loRegClass;
5303 switch (
MI.getOpcode()) {
5306 case AArch64::PACIASP:
5307 case AArch64::PACIBSP:
5310 case AArch64::PAUTH_PROLOGUE:
5313 case AArch64::HINT: {
5314 unsigned Imm =
MI.getOperand(0).getImm();
5316 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5319 if (Imm == 25 || Imm == 27)
5331 assert(Reg.isPhysical() &&
"Expected physical register in isFpOrNEON");
5332 return AArch64::FPR128RegClass.contains(Reg) ||
5333 AArch64::FPR64RegClass.contains(Reg) ||
5334 AArch64::FPR32RegClass.contains(Reg) ||
5335 AArch64::FPR16RegClass.contains(Reg) ||
5336 AArch64::FPR8RegClass.contains(Reg);
5343 auto Reg =
Op.getReg();
5344 if (Reg.isPhysical())
5348 return TRC == &AArch64::FPR128RegClass ||
5349 TRC == &AArch64::FPR128_loRegClass ||
5350 TRC == &AArch64::FPR64RegClass ||
5351 TRC == &AArch64::FPR64_loRegClass ||
5352 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5353 TRC == &AArch64::FPR8RegClass;
5375 if (FirstOpc == SecondOpc)
5381 case AArch64::STRSui:
5382 case AArch64::STURSi:
5383 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5384 case AArch64::STRDui:
5385 case AArch64::STURDi:
5386 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5387 case AArch64::STRQui:
5388 case AArch64::STURQi:
5389 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5390 case AArch64::STRWui:
5391 case AArch64::STURWi:
5392 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5393 case AArch64::STRXui:
5394 case AArch64::STURXi:
5395 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5396 case AArch64::LDRSui:
5397 case AArch64::LDURSi:
5398 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5399 case AArch64::LDRDui:
5400 case AArch64::LDURDi:
5401 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5402 case AArch64::LDRQui:
5403 case AArch64::LDURQi:
5404 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5405 case AArch64::LDRWui:
5406 case AArch64::LDURWi:
5407 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5408 case AArch64::LDRSWui:
5409 case AArch64::LDURSWi:
5410 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5411 case AArch64::LDRXui:
5412 case AArch64::LDURXi:
5413 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5420 int64_t Offset1,
unsigned Opcode1,
int FI2,
5421 int64_t Offset2,
unsigned Opcode2) {
5427 assert(ObjectOffset1 <= ObjectOffset2 &&
"Object offsets are not ordered.");
5430 if (ObjectOffset1 % Scale1 != 0)
5432 ObjectOffset1 /= Scale1;
5434 if (ObjectOffset2 % Scale2 != 0)
5436 ObjectOffset2 /= Scale2;
5437 ObjectOffset1 += Offset1;
5438 ObjectOffset2 += Offset2;
5439 return ObjectOffset1 + 1 == ObjectOffset2;
5451 int64_t OpOffset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
5452 unsigned NumBytes)
const {
5462 "Only base registers and frame indices are supported.");
5469 if (ClusterSize > 2)
5476 unsigned FirstOpc = FirstLdSt.
getOpcode();
5477 unsigned SecondOpc = SecondLdSt.
getOpcode();
5497 if (Offset1 > 63 || Offset1 < -64)
5502 if (BaseOp1.
isFI()) {
5504 "Caller should have ordered offsets.");
5509 BaseOp2.
getIndex(), Offset2, SecondOpc);
5512 assert(Offset1 <= Offset2 &&
"Caller should have ordered offsets.");
5514 return Offset1 + 1 == Offset2;
5524 if (
Reg.isPhysical())
5533 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5542 assert(Subtarget.hasNEON() &&
"Unexpected register copy without NEON");
5544 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5545 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5546 unsigned NumRegs = Indices.
size();
5548 int SubReg = 0, End = NumRegs, Incr = 1;
5550 SubReg = NumRegs - 1;
5555 for (; SubReg != End; SubReg += Incr) {
5567 unsigned Opcode,
unsigned ZeroReg,
5570 unsigned NumRegs = Indices.
size();
5573 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5574 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5575 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5576 "GPR reg sequences should not be able to overlap");
5579 for (
unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5600 unsigned Opc =
MI.getOpcode();
5601 if (
Opc == AArch64::MSRpstatesvcrImm1 ||
Opc == AArch64::MSRpstatePseudo) {
5603 int64_t PState =
MI.getOperand(0).getImm();
5604 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5606 return MI.getOperand(1).getImm() == 1;
5625 bool RenamableSrc)
const {
5627 if (AArch64::GPR32spRegClass.
contains(DestReg) &&
5628 AArch64::GPR32spRegClass.
contains(SrcReg)) {
5629 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5631 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5632 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5634 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5635 &AArch64::GPR64spRegClass);
5636 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5637 &AArch64::GPR64spRegClass);
5647 ++NumZCRegMoveInstrsGPR;
5653 if (Subtarget.hasZeroCycleRegMoveGPR32())
5654 ++NumZCRegMoveInstrsGPR;
5656 }
else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5657 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5659 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5660 &AArch64::GPR64spRegClass);
5661 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5662 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5663 &AArch64::GPR64spRegClass);
5673 ++NumZCRegMoveInstrsGPR;
5679 if (Subtarget.hasZeroCycleRegMoveGPR32())
5680 ++NumZCRegMoveInstrsGPR;
5686 if (AArch64::GPR32spRegClass.
contains(DestReg) && SrcReg == AArch64::WZR) {
5687 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5688 !Subtarget.hasZeroCycleZeroingGPR32()) {
5689 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5690 &AArch64::GPR64spRegClass);
5691 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5695 ++NumZCZeroingInstrsGPR;
5696 }
else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5700 ++NumZCZeroingInstrsGPR;
5709 if (AArch64::GPR64spRegClass.
contains(DestReg) &&
5710 AArch64::GPR64spRegClass.
contains(SrcReg)) {
5711 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5717 if (Subtarget.hasZeroCycleRegMoveGPR64())
5718 ++NumZCRegMoveInstrsGPR;
5724 if (Subtarget.hasZeroCycleRegMoveGPR64())
5725 ++NumZCRegMoveInstrsGPR;
5731 if (AArch64::GPR64spRegClass.
contains(DestReg) && SrcReg == AArch64::XZR) {
5732 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5736 ++NumZCZeroingInstrsGPR;
5746 if (AArch64::PPRRegClass.
contains(DestReg) &&
5747 AArch64::PPRRegClass.
contains(SrcReg)) {
5748 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5749 "Unexpected SVE register.");
5759 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5760 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5761 if (DestIsPNR || SrcIsPNR) {
5763 return (R - AArch64::PN0) + AArch64::P0;
5768 if (PPRSrcReg != PPRDestReg) {
5780 if (AArch64::ZPRRegClass.
contains(DestReg) &&
5781 AArch64::ZPRRegClass.
contains(SrcReg)) {
5782 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5783 "Unexpected SVE register.");
5791 if ((AArch64::ZPR2RegClass.
contains(DestReg) ||
5792 AArch64::ZPR2StridedOrContiguousRegClass.
contains(DestReg)) &&
5793 (AArch64::ZPR2RegClass.
contains(SrcReg) ||
5794 AArch64::ZPR2StridedOrContiguousRegClass.
contains(SrcReg))) {
5795 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5796 "Unexpected SVE register.");
5797 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
5804 if (AArch64::ZPR3RegClass.
contains(DestReg) &&
5805 AArch64::ZPR3RegClass.
contains(SrcReg)) {
5806 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5807 "Unexpected SVE register.");
5808 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5816 if ((AArch64::ZPR4RegClass.
contains(DestReg) ||
5817 AArch64::ZPR4StridedOrContiguousRegClass.
contains(DestReg)) &&
5818 (AArch64::ZPR4RegClass.
contains(SrcReg) ||
5819 AArch64::ZPR4StridedOrContiguousRegClass.
contains(SrcReg))) {
5820 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5821 "Unexpected SVE register.");
5822 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5823 AArch64::zsub2, AArch64::zsub3};
5830 if (AArch64::DDDDRegClass.
contains(DestReg) &&
5831 AArch64::DDDDRegClass.
contains(SrcReg)) {
5832 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5833 AArch64::dsub2, AArch64::dsub3};
5840 if (AArch64::DDDRegClass.
contains(DestReg) &&
5841 AArch64::DDDRegClass.
contains(SrcReg)) {
5842 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5850 if (AArch64::DDRegClass.
contains(DestReg) &&
5851 AArch64::DDRegClass.
contains(SrcReg)) {
5852 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
5859 if (AArch64::QQQQRegClass.
contains(DestReg) &&
5860 AArch64::QQQQRegClass.
contains(SrcReg)) {
5861 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5862 AArch64::qsub2, AArch64::qsub3};
5869 if (AArch64::QQQRegClass.
contains(DestReg) &&
5870 AArch64::QQQRegClass.
contains(SrcReg)) {
5871 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5879 if (AArch64::QQRegClass.
contains(DestReg) &&
5880 AArch64::QQRegClass.
contains(SrcReg)) {
5881 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
5887 if (AArch64::XSeqPairsClassRegClass.
contains(DestReg) &&
5888 AArch64::XSeqPairsClassRegClass.
contains(SrcReg)) {
5889 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
5891 AArch64::XZR, Indices);
5895 if (AArch64::WSeqPairsClassRegClass.
contains(DestReg) &&
5896 AArch64::WSeqPairsClassRegClass.
contains(SrcReg)) {
5897 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
5899 AArch64::WZR, Indices);
5903 if (AArch64::FPR128RegClass.
contains(DestReg) &&
5904 AArch64::FPR128RegClass.
contains(SrcReg)) {
5908 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
5909 !Subtarget.isNeonAvailable()) ||
5913 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
5914 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
5915 }
else if (Subtarget.isNeonAvailable()) {
5919 if (Subtarget.hasZeroCycleRegMoveFPR128())
5920 ++NumZCRegMoveInstrsFPR;
5936 if (AArch64::FPR64RegClass.
contains(DestReg) &&
5937 AArch64::FPR64RegClass.
contains(SrcReg)) {
5938 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5939 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5940 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5942 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
5943 &AArch64::FPR128RegClass);
5944 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
5945 &AArch64::FPR128RegClass);
5954 ++NumZCRegMoveInstrsFPR;
5958 if (Subtarget.hasZeroCycleRegMoveFPR64())
5959 ++NumZCRegMoveInstrsFPR;
5964 if (AArch64::FPR32RegClass.
contains(DestReg) &&
5965 AArch64::FPR32RegClass.
contains(SrcReg)) {
5966 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5967 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5968 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5970 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5971 &AArch64::FPR128RegClass);
5972 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5973 &AArch64::FPR128RegClass);
5982 ++NumZCRegMoveInstrsFPR;
5983 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5984 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5985 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5986 &AArch64::FPR64RegClass);
5987 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5988 &AArch64::FPR64RegClass);
5996 ++NumZCRegMoveInstrsFPR;
6000 if (Subtarget.hasZeroCycleRegMoveFPR32())
6001 ++NumZCRegMoveInstrsFPR;
6006 if (AArch64::FPR16RegClass.
contains(DestReg) &&
6007 AArch64::FPR16RegClass.
contains(SrcReg)) {
6008 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6009 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6010 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6012 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6013 &AArch64::FPR128RegClass);
6014 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6015 &AArch64::FPR128RegClass);
6024 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6025 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6026 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6027 &AArch64::FPR64RegClass);
6028 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6029 &AArch64::FPR64RegClass);
6038 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6039 &AArch64::FPR32RegClass);
6040 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6041 &AArch64::FPR32RegClass);
6048 if (AArch64::FPR8RegClass.
contains(DestReg) &&
6049 AArch64::FPR8RegClass.
contains(SrcReg)) {
6050 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6051 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6052 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6054 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6055 &AArch64::FPR128RegClass);
6056 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6057 &AArch64::FPR128RegClass);
6066 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6067 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6068 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6069 &AArch64::FPR64RegClass);
6070 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6071 &AArch64::FPR64RegClass);
6080 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6081 &AArch64::FPR32RegClass);
6082 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6083 &AArch64::FPR32RegClass);
6091 if (AArch64::FPR64RegClass.
contains(DestReg) &&
6092 AArch64::GPR64RegClass.
contains(SrcReg)) {
6093 if (AArch64::XZR == SrcReg) {
6101 if (AArch64::GPR64RegClass.
contains(DestReg) &&
6102 AArch64::FPR64RegClass.
contains(SrcReg)) {
6108 if (AArch64::FPR32RegClass.
contains(DestReg) &&
6109 AArch64::GPR32RegClass.
contains(SrcReg)) {
6110 if (AArch64::WZR == SrcReg) {
6118 if (AArch64::GPR32RegClass.
contains(DestReg) &&
6119 AArch64::FPR32RegClass.
contains(SrcReg)) {
6125 if (DestReg == AArch64::NZCV) {
6126 assert(AArch64::GPR64RegClass.
contains(SrcReg) &&
"Invalid NZCV copy");
6128 .
addImm(AArch64SysReg::NZCV)
6134 if (SrcReg == AArch64::NZCV) {
6135 assert(AArch64::GPR64RegClass.
contains(DestReg) &&
"Invalid NZCV copy");
6137 .
addImm(AArch64SysReg::NZCV)
6143 errs() << RI.getRegAsmName(DestReg) <<
" = COPY " << RI.getRegAsmName(SrcReg)
6154 unsigned SubIdx0,
unsigned SubIdx1,
int FI,
6159 SrcReg0 =
TRI.getSubReg(SrcReg, SubIdx0);
6161 SrcReg1 =
TRI.getSubReg(SrcReg, SubIdx1);
6174 Register SrcReg,
bool isKill,
int FI,
6189 switch (RI.getSpillSize(*RC)) {
6191 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6192 Opc = AArch64::STRBui;
6195 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6196 Opc = AArch64::STRHui;
6197 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6198 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6199 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6200 "Unexpected register store without SVE store instructions");
6201 Opc = AArch64::STR_PXI;
6207 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6208 Opc = AArch64::STRWui;
6212 assert(SrcReg != AArch64::WSP);
6213 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6214 Opc = AArch64::STRSui;
6215 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6216 Opc = AArch64::STR_PPXI;
6221 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6222 Opc = AArch64::STRXui;
6226 assert(SrcReg != AArch64::SP);
6227 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6228 Opc = AArch64::STRDui;
6229 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6231 get(AArch64::STPWi), SrcReg, isKill,
6232 AArch64::sube32, AArch64::subo32, FI, MMO);
6237 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6238 Opc = AArch64::STRQui;
6239 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6240 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6241 Opc = AArch64::ST1Twov1d;
6243 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6245 get(AArch64::STPXi), SrcReg, isKill,
6246 AArch64::sube64, AArch64::subo64, FI, MMO);
6248 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6249 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6250 "Unexpected register store without SVE store instructions");
6251 Opc = AArch64::STR_ZXI;
6256 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6257 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6258 Opc = AArch64::ST1Threev1d;
6263 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6264 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6265 Opc = AArch64::ST1Fourv1d;
6267 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6268 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6269 Opc = AArch64::ST1Twov2d;
6271 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6272 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6273 "Unexpected register store without SVE store instructions");
6274 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6276 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6277 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6278 "Unexpected register store without SVE store instructions");
6279 Opc = AArch64::STR_ZZXI;
6284 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6285 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6286 Opc = AArch64::ST1Threev2d;
6288 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6289 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6290 "Unexpected register store without SVE store instructions");
6291 Opc = AArch64::STR_ZZZXI;
6296 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6297 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6298 Opc = AArch64::ST1Fourv2d;
6300 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6301 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6302 "Unexpected register store without SVE store instructions");
6303 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6305 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6306 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6307 "Unexpected register store without SVE store instructions");
6308 Opc = AArch64::STR_ZZZZXI;
6313 assert(
Opc &&
"Unknown register class");
6324 MI.addMemOperand(MMO);
6331 Register DestReg,
unsigned SubIdx0,
6332 unsigned SubIdx1,
int FI,
6336 bool IsUndef =
true;
6338 DestReg0 =
TRI.getSubReg(DestReg, SubIdx0);
6340 DestReg1 =
TRI.getSubReg(DestReg, SubIdx1);
6369 switch (
TRI.getSpillSize(*RC)) {
6371 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6372 Opc = AArch64::LDRBui;
6375 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6376 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6377 Opc = AArch64::LDRHui;
6378 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6379 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6380 "Unexpected register load without SVE load instructions");
6383 Opc = AArch64::LDR_PXI;
6389 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6390 Opc = AArch64::LDRWui;
6394 assert(DestReg != AArch64::WSP);
6395 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6396 Opc = AArch64::LDRSui;
6397 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6398 Opc = AArch64::LDR_PPXI;
6403 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6404 Opc = AArch64::LDRXui;
6408 assert(DestReg != AArch64::SP);
6409 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6410 Opc = AArch64::LDRDui;
6411 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6413 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6414 AArch64::subo32, FI, MMO);
6419 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6420 Opc = AArch64::LDRQui;
6421 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6422 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6423 Opc = AArch64::LD1Twov1d;
6425 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6427 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6428 AArch64::subo64, FI, MMO);
6430 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6431 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6432 "Unexpected register load without SVE load instructions");
6433 Opc = AArch64::LDR_ZXI;
6438 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6439 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6440 Opc = AArch64::LD1Threev1d;
6445 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6446 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6447 Opc = AArch64::LD1Fourv1d;
6449 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6450 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6451 Opc = AArch64::LD1Twov2d;
6453 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6454 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6455 "Unexpected register load without SVE load instructions");
6456 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6458 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6459 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6460 "Unexpected register load without SVE load instructions");
6461 Opc = AArch64::LDR_ZZXI;
6466 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6467 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6468 Opc = AArch64::LD1Threev2d;
6470 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6471 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6472 "Unexpected register load without SVE load instructions");
6473 Opc = AArch64::LDR_ZZZXI;
6478 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6479 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6480 Opc = AArch64::LD1Fourv2d;
6482 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6483 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6484 "Unexpected register load without SVE load instructions");
6485 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6487 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6488 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6489 "Unexpected register load without SVE load instructions");
6490 Opc = AArch64::LDR_ZZZZXI;
6496 assert(
Opc &&
"Unknown register class");
6506 MI.addMemOperand(MMO);
6513 UseMI.getIterator()),
6515 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6516 I.readsRegister(AArch64::NZCV, TRI);
6520void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6525 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6532 ByteSized =
Offset.getFixed();
6533 VGSized =
Offset.getScalable() / 2;
6539void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6541 int64_t &NumDataVectors) {
6545 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6547 NumBytes =
Offset.getFixed();
6549 NumPredicateVectors =
Offset.getScalable() / 2;
6554 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6555 NumPredicateVectors > 62) {
6556 NumDataVectors = NumPredicateVectors / 8;
6557 NumPredicateVectors -= NumDataVectors * 8;
6583 Expr.
push_back((
char)dwarf::DW_OP_bregx);
6591 int64_t OffsetFromDefCFA) {
6605 Comment << (NumBytes < 0 ?
" - " :
" + ") << std::abs(NumBytes);
6606 if (!RegScale.empty())
6616 int64_t NumBytes, NumVGScaledBytes;
6617 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
Offset, NumBytes,
6619 std::string CommentBuffer;
6622 if (
Reg == AArch64::SP)
6624 else if (
Reg == AArch64::FP)
6631 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
6632 assert(DwarfReg <= 31 &&
"DwarfReg out of bounds (0..31)");
6634 Expr.
push_back(dwarf::DW_OP_breg0 + DwarfReg);
6637 if (NumVGScaledBytes) {
6647 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
6655 unsigned FrameReg,
unsigned Reg,
6657 bool LastAdjustmentWasScalable) {
6658 if (
Offset.getScalable())
6661 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6664 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6671 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6672 int64_t NumBytes, NumVGScaledBytes;
6673 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6674 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6676 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6679 if (!NumVGScaledBytes)
6682 std::string CommentBuffer;
6687 assert(NumVGScaledBytes &&
"Expected scalable offset");
6691 if (IncomingVGOffsetFromDefCFA) {
6693 VGRegScale =
"* IncomingVG";
6696 VGRegScale =
"* VG";
6700 OffsetExpr.
push_back(dwarf::DW_OP_plus);
6709 CfaExpr.
push_back(dwarf::DW_CFA_expression);
6724 unsigned SrcReg, int64_t
Offset,
unsigned Opc,
6727 bool *HasWinCFI,
bool EmitCFAOffset,
6730 unsigned MaxEncoding, ShiftSize;
6732 case AArch64::ADDXri:
6733 case AArch64::ADDSXri:
6734 case AArch64::SUBXri:
6735 case AArch64::SUBSXri:
6736 MaxEncoding = 0xfff;
6739 case AArch64::ADDVL_XXI:
6740 case AArch64::ADDPL_XXI:
6741 case AArch64::ADDSVL_XXI:
6742 case AArch64::ADDSPL_XXI:
6757 if (
Opc == AArch64::ADDVL_XXI ||
Opc == AArch64::ADDSVL_XXI)
6759 else if (
Opc == AArch64::ADDPL_XXI ||
Opc == AArch64::ADDSPL_XXI)
6773 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6775 if (TmpReg == AArch64::XZR)
6776 TmpReg =
MBB.getParent()->getRegInfo().createVirtualRegister(
6777 &AArch64::GPR64RegClass);
6779 uint64_t ThisVal = std::min<uint64_t>(
Offset, MaxEncodableValue);
6780 unsigned LocalShiftSize = 0;
6781 if (ThisVal > MaxEncoding) {
6782 ThisVal = ThisVal >> ShiftSize;
6783 LocalShiftSize = ShiftSize;
6785 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
6786 "Encoding cannot handle value that big");
6788 Offset -= ThisVal << LocalShiftSize;
6793 .
addImm(Sign * (
int)ThisVal);
6803 if (Sign == -1 ||
Opc == AArch64::SUBXri ||
Opc == AArch64::SUBSXri)
6804 CFAOffset += Change;
6806 CFAOffset -= Change;
6807 if (EmitCFAOffset && DestReg == TmpReg) {
6820 int Imm = (int)(ThisVal << LocalShiftSize);
6821 if (VScale != 1 && DestReg == AArch64::SP) {
6827 }
else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
6828 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
6829 assert(VScale == 1 &&
"Expected non-scalable operation");
6838 assert(
Offset == 0 &&
"Expected remaining offset to be zero to "
6839 "emit a single SEH directive");
6840 }
else if (DestReg == AArch64::SP) {
6841 assert(VScale == 1 &&
"Expected non-scalable operation");
6844 assert(SrcReg == AArch64::SP &&
"Unexpected SrcReg for SEH_StackAlloc");
6857 unsigned DestReg,
unsigned SrcReg,
6860 bool NeedsWinCFI,
bool *HasWinCFI,
6862 unsigned FrameReg) {
6869 bool UseSVL =
F.hasFnAttribute(
"aarch64_pstate_sm_body");
6871 int64_t Bytes, NumPredicateVectors, NumDataVectors;
6872 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6873 Offset, Bytes, NumPredicateVectors, NumDataVectors);
6876 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
6877 if (NeedsFinalDefNZCV)
6881 if (Bytes || (!
Offset && SrcReg != DestReg)) {
6882 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
6883 "SP increment/decrement not 8-byte aligned");
6884 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
6887 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
6890 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6892 CFAOffset += (
Opc == AArch64::ADDXri ||
Opc == AArch64::ADDSXri)
6899 assert(!(NeedsWinCFI && NumPredicateVectors) &&
6900 "WinCFI can't allocate fractions of an SVE data vector");
6902 if (NumDataVectors) {
6904 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI,
TII,
6905 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6911 if (NumPredicateVectors) {
6912 assert(DestReg != AArch64::SP &&
"Unaligned access to SP");
6914 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI,
TII,
6915 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6919 if (NeedsFinalDefNZCV)
6941 if (
MI.isFullCopy()) {
6944 if (SrcReg == AArch64::SP && DstReg.
isVirtual()) {
6948 if (DstReg == AArch64::SP && SrcReg.
isVirtual()) {
6953 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
6981 if (
MI.isCopy() &&
Ops.size() == 1 &&
6983 (
Ops[0] == 0 ||
Ops[0] == 1)) {
6984 bool IsSpill =
Ops[0] == 0;
6985 bool IsFill = !IsSpill;
6997 :
TRI.getMinimalPhysRegClass(Reg);
7003 "Mismatched register size in non subreg COPY");
7010 return &*--InsertPt;
7022 if (IsSpill && DstMO.
isUndef() && SrcReg == AArch64::WZR &&
7025 "Unexpected subreg on physical register");
7027 FrameIndex, &AArch64::GPR64RegClass,
Register());
7028 return &*--InsertPt;
7045 case AArch64::sub_32:
7046 if (AArch64::GPR64RegClass.hasSubClassEq(
getRegClass(DstReg)))
7047 FillRC = &AArch64::GPR32RegClass;
7050 FillRC = &AArch64::FPR32RegClass;
7053 FillRC = &AArch64::FPR64RegClass;
7059 TRI.getRegSizeInBits(*FillRC) &&
7060 "Mismatched regclass size on folded subreg COPY");
7079 bool *OutUseUnscaledOp,
7080 unsigned *OutUnscaledOp,
7081 int64_t *EmittableOffset) {
7083 if (EmittableOffset)
7084 *EmittableOffset = 0;
7085 if (OutUseUnscaledOp)
7086 *OutUseUnscaledOp =
false;
7092 switch (
MI.getOpcode()) {
7095 case AArch64::LD1Rv1d:
7096 case AArch64::LD1Rv2s:
7097 case AArch64::LD1Rv2d:
7098 case AArch64::LD1Rv4h:
7099 case AArch64::LD1Rv4s:
7100 case AArch64::LD1Rv8b:
7101 case AArch64::LD1Rv8h:
7102 case AArch64::LD1Rv16b:
7103 case AArch64::LD1Twov2d:
7104 case AArch64::LD1Threev2d:
7105 case AArch64::LD1Fourv2d:
7106 case AArch64::LD1Twov1d:
7107 case AArch64::LD1Threev1d:
7108 case AArch64::LD1Fourv1d:
7109 case AArch64::ST1Twov2d:
7110 case AArch64::ST1Threev2d:
7111 case AArch64::ST1Fourv2d:
7112 case AArch64::ST1Twov1d:
7113 case AArch64::ST1Threev1d:
7114 case AArch64::ST1Fourv1d:
7115 case AArch64::ST1i8:
7116 case AArch64::ST1i16:
7117 case AArch64::ST1i32:
7118 case AArch64::ST1i64:
7120 case AArch64::IRGstack:
7121 case AArch64::STGloop:
7122 case AArch64::STZGloop:
7127 TypeSize ScaleValue(0U,
false), Width(0U,
false);
7128 int64_t MinOff, MaxOff;
7134 bool IsMulVL = ScaleValue.isScalable();
7135 unsigned Scale = ScaleValue.getKnownMinValue();
7145 std::optional<unsigned> UnscaledOp =
7147 bool useUnscaledOp = UnscaledOp && (
Offset % Scale ||
Offset < 0);
7148 if (useUnscaledOp &&
7153 Scale = ScaleValue.getKnownMinValue();
7154 assert(IsMulVL == ScaleValue.isScalable() &&
7155 "Unscaled opcode has different value for scalable");
7157 int64_t Remainder =
Offset % Scale;
7158 assert(!(Remainder && useUnscaledOp) &&
7159 "Cannot have remainder when using unscaled op");
7161 assert(MinOff < MaxOff &&
"Unexpected Min/Max offsets");
7162 int64_t NewOffset =
Offset / Scale;
7163 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7166 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7170 if (EmittableOffset)
7171 *EmittableOffset = NewOffset;
7172 if (OutUseUnscaledOp)
7173 *OutUseUnscaledOp = useUnscaledOp;
7174 if (OutUnscaledOp && UnscaledOp)
7175 *OutUnscaledOp = *UnscaledOp;
7188 unsigned Opcode =
MI.getOpcode();
7189 unsigned ImmIdx = FrameRegIdx + 1;
7191 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7196 MI.eraseFromParent();
7202 unsigned UnscaledOp;
7205 &UnscaledOp, &NewOffset);
7209 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
7211 MI.setDesc(
TII->get(UnscaledOp));
7213 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7229bool AArch64InstrInfo::useMachineCombiner()
const {
return true; }
7234 case AArch64::ADDSWrr:
7235 case AArch64::ADDSWri:
7236 case AArch64::ADDSXrr:
7237 case AArch64::ADDSXri:
7238 case AArch64::SUBSWrr:
7239 case AArch64::SUBSXrr:
7241 case AArch64::SUBSWri:
7242 case AArch64::SUBSXri:
7253 case AArch64::ADDWrr:
7254 case AArch64::ADDWri:
7255 case AArch64::SUBWrr:
7256 case AArch64::ADDSWrr:
7257 case AArch64::ADDSWri:
7258 case AArch64::SUBSWrr:
7260 case AArch64::SUBWri:
7261 case AArch64::SUBSWri:
7272 case AArch64::ADDXrr:
7273 case AArch64::ADDXri:
7274 case AArch64::SUBXrr:
7275 case AArch64::ADDSXrr:
7276 case AArch64::ADDSXri:
7277 case AArch64::SUBSXrr:
7279 case AArch64::SUBXri:
7280 case AArch64::SUBSXri:
7281 case AArch64::ADDv8i8:
7282 case AArch64::ADDv16i8:
7283 case AArch64::ADDv4i16:
7284 case AArch64::ADDv8i16:
7285 case AArch64::ADDv2i32:
7286 case AArch64::ADDv4i32:
7287 case AArch64::SUBv8i8:
7288 case AArch64::SUBv16i8:
7289 case AArch64::SUBv4i16:
7290 case AArch64::SUBv8i16:
7291 case AArch64::SUBv2i32:
7292 case AArch64::SUBv4i32:
7305 case AArch64::FADDHrr:
7306 case AArch64::FADDSrr:
7307 case AArch64::FADDDrr:
7308 case AArch64::FADDv4f16:
7309 case AArch64::FADDv8f16:
7310 case AArch64::FADDv2f32:
7311 case AArch64::FADDv2f64:
7312 case AArch64::FADDv4f32:
7313 case AArch64::FSUBHrr:
7314 case AArch64::FSUBSrr:
7315 case AArch64::FSUBDrr:
7316 case AArch64::FSUBv4f16:
7317 case AArch64::FSUBv8f16:
7318 case AArch64::FSUBv2f32:
7319 case AArch64::FSUBv2f64:
7320 case AArch64::FSUBv4f32:
7339 unsigned CombineOpc,
unsigned ZeroReg = 0,
7340 bool CheckZeroReg =
false) {
7347 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
7354 assert(
MI->getNumOperands() >= 4 &&
MI->getOperand(0).isReg() &&
7355 MI->getOperand(1).isReg() &&
MI->getOperand(2).isReg() &&
7356 MI->getOperand(3).isReg() &&
"MAdd/MSub must have a least 4 regs");
7358 if (
MI->getOperand(3).getReg() != ZeroReg)
7363 MI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) == -1)
7372 unsigned MulOpc,
unsigned ZeroReg) {
7387bool AArch64InstrInfo::isAssociativeAndCommutative(
const MachineInstr &Inst,
7388 bool Invert)
const {
7394 case AArch64::FADDHrr:
7395 case AArch64::FADDSrr:
7396 case AArch64::FADDDrr:
7397 case AArch64::FMULHrr:
7398 case AArch64::FMULSrr:
7399 case AArch64::FMULDrr:
7400 case AArch64::FMULX16:
7401 case AArch64::FMULX32:
7402 case AArch64::FMULX64:
7404 case AArch64::FADDv4f16:
7405 case AArch64::FADDv8f16:
7406 case AArch64::FADDv2f32:
7407 case AArch64::FADDv4f32:
7408 case AArch64::FADDv2f64:
7409 case AArch64::FMULv4f16:
7410 case AArch64::FMULv8f16:
7411 case AArch64::FMULv2f32:
7412 case AArch64::FMULv4f32:
7413 case AArch64::FMULv2f64:
7414 case AArch64::FMULXv4f16:
7415 case AArch64::FMULXv8f16:
7416 case AArch64::FMULXv2f32:
7417 case AArch64::FMULXv4f32:
7418 case AArch64::FMULXv2f64:
7422 case AArch64::FADD_ZZZ_H:
7423 case AArch64::FADD_ZZZ_S:
7424 case AArch64::FADD_ZZZ_D:
7425 case AArch64::FMUL_ZZZ_H:
7426 case AArch64::FMUL_ZZZ_S:
7427 case AArch64::FMUL_ZZZ_D:
7438 case AArch64::ADDWrr:
7439 case AArch64::ADDXrr:
7440 case AArch64::ANDWrr:
7441 case AArch64::ANDXrr:
7442 case AArch64::ORRWrr:
7443 case AArch64::ORRXrr:
7444 case AArch64::EORWrr:
7445 case AArch64::EORXrr:
7446 case AArch64::EONWrr:
7447 case AArch64::EONXrr:
7451 case AArch64::ADDv8i8:
7452 case AArch64::ADDv16i8:
7453 case AArch64::ADDv4i16:
7454 case AArch64::ADDv8i16:
7455 case AArch64::ADDv2i32:
7456 case AArch64::ADDv4i32:
7457 case AArch64::ADDv1i64:
7458 case AArch64::ADDv2i64:
7459 case AArch64::MULv8i8:
7460 case AArch64::MULv16i8:
7461 case AArch64::MULv4i16:
7462 case AArch64::MULv8i16:
7463 case AArch64::MULv2i32:
7464 case AArch64::MULv4i32:
7465 case AArch64::ANDv8i8:
7466 case AArch64::ANDv16i8:
7467 case AArch64::ORRv8i8:
7468 case AArch64::ORRv16i8:
7469 case AArch64::EORv8i8:
7470 case AArch64::EORv16i8:
7472 case AArch64::ADD_ZZZ_B:
7473 case AArch64::ADD_ZZZ_H:
7474 case AArch64::ADD_ZZZ_S:
7475 case AArch64::ADD_ZZZ_D:
7476 case AArch64::MUL_ZZZ_B:
7477 case AArch64::MUL_ZZZ_H:
7478 case AArch64::MUL_ZZZ_S:
7479 case AArch64::MUL_ZZZ_D:
7480 case AArch64::AND_ZZZ:
7481 case AArch64::ORR_ZZZ:
7482 case AArch64::EOR_ZZZ:
7513 auto setFound = [&](
int Opcode,
int Operand,
unsigned ZeroReg,
7521 auto setVFound = [&](
int Opcode,
int Operand,
unsigned Pattern) {
7533 case AArch64::ADDWrr:
7535 "ADDWrr does not have register operands");
7536 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7537 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7539 case AArch64::ADDXrr:
7540 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7541 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7543 case AArch64::SUBWrr:
7544 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7545 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7547 case AArch64::SUBXrr:
7548 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7549 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7551 case AArch64::ADDWri:
7552 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7554 case AArch64::ADDXri:
7555 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7557 case AArch64::SUBWri:
7558 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7560 case AArch64::SUBXri:
7561 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7563 case AArch64::ADDv8i8:
7564 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7565 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7567 case AArch64::ADDv16i8:
7568 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7569 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7571 case AArch64::ADDv4i16:
7572 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7573 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7574 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7575 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7577 case AArch64::ADDv8i16:
7578 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7579 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7580 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7581 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7583 case AArch64::ADDv2i32:
7584 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7585 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7586 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7587 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7589 case AArch64::ADDv4i32:
7590 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7591 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7592 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7593 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7595 case AArch64::SUBv8i8:
7596 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7597 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7599 case AArch64::SUBv16i8:
7600 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7601 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7603 case AArch64::SUBv4i16:
7604 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7605 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7606 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7607 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7609 case AArch64::SUBv8i16:
7610 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7611 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7612 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7613 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7615 case AArch64::SUBv2i32:
7616 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7617 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7618 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7619 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7621 case AArch64::SUBv4i32:
7622 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7623 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7624 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7625 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7631bool AArch64InstrInfo::isAccumulationOpcode(
unsigned Opcode)
const {
7635 case AArch64::UABALB_ZZZ_D:
7636 case AArch64::UABALB_ZZZ_H:
7637 case AArch64::UABALB_ZZZ_S:
7638 case AArch64::UABALT_ZZZ_D:
7639 case AArch64::UABALT_ZZZ_H:
7640 case AArch64::UABALT_ZZZ_S:
7641 case AArch64::SABALB_ZZZ_D:
7642 case AArch64::SABALB_ZZZ_S:
7643 case AArch64::SABALB_ZZZ_H:
7644 case AArch64::SABALT_ZZZ_D:
7645 case AArch64::SABALT_ZZZ_S:
7646 case AArch64::SABALT_ZZZ_H:
7647 case AArch64::UABALv16i8_v8i16:
7648 case AArch64::UABALv2i32_v2i64:
7649 case AArch64::UABALv4i16_v4i32:
7650 case AArch64::UABALv4i32_v2i64:
7651 case AArch64::UABALv8i16_v4i32:
7652 case AArch64::UABALv8i8_v8i16:
7653 case AArch64::UABAv16i8:
7654 case AArch64::UABAv2i32:
7655 case AArch64::UABAv4i16:
7656 case AArch64::UABAv4i32:
7657 case AArch64::UABAv8i16:
7658 case AArch64::UABAv8i8:
7659 case AArch64::SABALv16i8_v8i16:
7660 case AArch64::SABALv2i32_v2i64:
7661 case AArch64::SABALv4i16_v4i32:
7662 case AArch64::SABALv4i32_v2i64:
7663 case AArch64::SABALv8i16_v4i32:
7664 case AArch64::SABALv8i8_v8i16:
7665 case AArch64::SABAv16i8:
7666 case AArch64::SABAv2i32:
7667 case AArch64::SABAv4i16:
7668 case AArch64::SABAv4i32:
7669 case AArch64::SABAv8i16:
7670 case AArch64::SABAv8i8:
7677unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7678 unsigned AccumulationOpcode)
const {
7679 switch (AccumulationOpcode) {
7682 case AArch64::UABALB_ZZZ_D:
7683 return AArch64::UABDLB_ZZZ_D;
7684 case AArch64::UABALB_ZZZ_H:
7685 return AArch64::UABDLB_ZZZ_H;
7686 case AArch64::UABALB_ZZZ_S:
7687 return AArch64::UABDLB_ZZZ_S;
7688 case AArch64::UABALT_ZZZ_D:
7689 return AArch64::UABDLT_ZZZ_D;
7690 case AArch64::UABALT_ZZZ_H:
7691 return AArch64::UABDLT_ZZZ_H;
7692 case AArch64::UABALT_ZZZ_S:
7693 return AArch64::UABDLT_ZZZ_S;
7694 case AArch64::UABALv16i8_v8i16:
7695 return AArch64::UABDLv16i8_v8i16;
7696 case AArch64::UABALv2i32_v2i64:
7697 return AArch64::UABDLv2i32_v2i64;
7698 case AArch64::UABALv4i16_v4i32:
7699 return AArch64::UABDLv4i16_v4i32;
7700 case AArch64::UABALv4i32_v2i64:
7701 return AArch64::UABDLv4i32_v2i64;
7702 case AArch64::UABALv8i16_v4i32:
7703 return AArch64::UABDLv8i16_v4i32;
7704 case AArch64::UABALv8i8_v8i16:
7705 return AArch64::UABDLv8i8_v8i16;
7706 case AArch64::UABAv16i8:
7707 return AArch64::UABDv16i8;
7708 case AArch64::UABAv2i32:
7709 return AArch64::UABDv2i32;
7710 case AArch64::UABAv4i16:
7711 return AArch64::UABDv4i16;
7712 case AArch64::UABAv4i32:
7713 return AArch64::UABDv4i32;
7714 case AArch64::UABAv8i16:
7715 return AArch64::UABDv8i16;
7716 case AArch64::UABAv8i8:
7717 return AArch64::UABDv8i8;
7718 case AArch64::SABALB_ZZZ_D:
7719 return AArch64::SABDLB_ZZZ_D;
7720 case AArch64::SABALB_ZZZ_S:
7721 return AArch64::SABDLB_ZZZ_S;
7722 case AArch64::SABALB_ZZZ_H:
7723 return AArch64::SABDLB_ZZZ_H;
7724 case AArch64::SABALT_ZZZ_D:
7725 return AArch64::SABDLT_ZZZ_D;
7726 case AArch64::SABALT_ZZZ_S:
7727 return AArch64::SABDLT_ZZZ_S;
7728 case AArch64::SABALT_ZZZ_H:
7729 return AArch64::SABDLT_ZZZ_H;
7730 case AArch64::SABALv16i8_v8i16:
7731 return AArch64::SABDLv16i8_v8i16;
7732 case AArch64::SABALv2i32_v2i64:
7733 return AArch64::SABDLv2i32_v2i64;
7734 case AArch64::SABALv4i16_v4i32:
7735 return AArch64::SABDLv4i16_v4i32;
7736 case AArch64::SABALv4i32_v2i64:
7737 return AArch64::SABDLv4i32_v2i64;
7738 case AArch64::SABALv8i16_v4i32:
7739 return AArch64::SABDLv8i16_v4i32;
7740 case AArch64::SABALv8i8_v8i16:
7741 return AArch64::SABDLv8i8_v8i16;
7742 case AArch64::SABAv16i8:
7743 return AArch64::SABDv16i8;
7744 case AArch64::SABAv2i32:
7745 return AArch64::SABAv2i32;
7746 case AArch64::SABAv4i16:
7747 return AArch64::SABDv4i16;
7748 case AArch64::SABAv4i32:
7749 return AArch64::SABDv4i32;
7750 case AArch64::SABAv8i16:
7751 return AArch64::SABDv8i16;
7752 case AArch64::SABAv8i8:
7753 return AArch64::SABDv8i8;
7769 auto Match = [&](
int Opcode,
int Operand,
unsigned Pattern) ->
bool {
7781 assert(
false &&
"Unsupported FP instruction in combiner\n");
7783 case AArch64::FADDHrr:
7785 "FADDHrr does not have register operands");
7787 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
7788 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
7790 case AArch64::FADDSrr:
7792 "FADDSrr does not have register operands");
7794 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
7795 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
7797 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
7798 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
7800 case AArch64::FADDDrr:
7801 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
7802 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
7804 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
7805 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
7807 case AArch64::FADDv4f16:
7808 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
7809 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
7811 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
7812 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
7814 case AArch64::FADDv8f16:
7815 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
7816 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
7818 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
7819 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
7821 case AArch64::FADDv2f32:
7822 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
7823 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
7825 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
7826 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
7828 case AArch64::FADDv2f64:
7829 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
7830 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
7832 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
7833 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
7835 case AArch64::FADDv4f32:
7836 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
7837 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
7839 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
7840 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
7842 case AArch64::FSUBHrr:
7843 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
7844 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
7845 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
7847 case AArch64::FSUBSrr:
7848 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
7850 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
7851 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
7853 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
7855 case AArch64::FSUBDrr:
7856 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
7858 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
7859 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
7861 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
7863 case AArch64::FSUBv4f16:
7864 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
7865 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
7867 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
7868 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
7870 case AArch64::FSUBv8f16:
7871 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
7872 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
7874 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
7875 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
7877 case AArch64::FSUBv2f32:
7878 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
7879 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
7881 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
7882 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
7884 case AArch64::FSUBv2f64:
7885 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
7886 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
7888 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
7889 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
7891 case AArch64::FSUBv4f32:
7892 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
7893 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
7895 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
7896 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
7907 auto Match = [&](
unsigned Opcode,
int Operand,
unsigned Pattern) ->
bool {
7914 if (
MI &&
MI->getOpcode() == TargetOpcode::COPY &&
7915 MI->getOperand(1).getReg().isVirtual())
7917 if (
MI &&
MI->getOpcode() == Opcode) {
7929 case AArch64::FMULv2f32:
7930 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
7931 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
7933 case AArch64::FMULv2f64:
7934 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
7935 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
7937 case AArch64::FMULv4f16:
7938 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
7939 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
7941 case AArch64::FMULv4f32:
7942 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
7943 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
7945 case AArch64::FMULv8f16:
7946 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
7947 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
7960 auto Match = [&](
unsigned Opcode,
unsigned Pattern) ->
bool {
7963 if (
MI !=
nullptr && (
MI->getOpcode() == Opcode) &&
7978 case AArch64::FNEGDr:
7980 case AArch64::FNEGSr:
8112 case AArch64::SUBWrr:
8113 case AArch64::SUBSWrr:
8114 case AArch64::SUBXrr:
8115 case AArch64::SUBSXrr:
8160 unsigned LoadLaneOpCode,
unsigned NumLanes) {
8183 while (!RemainingLanes.
empty() && CurrInstr &&
8184 CurrInstr->getOpcode() == LoadLaneOpCode &&
8186 CurrInstr->getNumOperands() == 4) {
8187 RemainingLanes.
erase(CurrInstr->getOperand(2).getImm());
8193 if (!RemainingLanes.
empty())
8197 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8201 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8202 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8203 if (
TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8219 RemainingLoadInstrs.
insert(LoadInstrs.
begin(), LoadInstrs.
end());
8222 for (; MBBItr !=
MBB->begin() && RemainingSteps > 0 &&
8223 !RemainingLoadInstrs.
empty();
8224 --MBBItr, --RemainingSteps) {
8228 RemainingLoadInstrs.
erase(&CurrInstr);
8238 if (RemainingSteps == 0 && !RemainingLoadInstrs.
empty())
8264 case AArch64::LD1i32:
8266 case AArch64::LD1i16:
8268 case AArch64::LD1i8:
8284 unsigned Pattern,
unsigned NumLanes) {
8292 for (
unsigned i = 0; i < NumLanes - 1; ++i) {
8300 return A->getOperand(2).getImm() >
B->getOperand(2).getImm();
8306 auto LoadToLaneInstrsAscending =
llvm::reverse(LoadToLaneInstrs);
8312 auto CreateLD1Instruction = [&](
MachineInstr *OriginalInstr,
8313 Register SrcRegister,
unsigned Lane,
8315 bool OffsetRegisterKillState) {
8324 InstrIdxForVirtReg.
insert(std::make_pair(NewRegister, InsInstrs.
size()));
8325 InsInstrs.
push_back(LoadIndexIntoRegister);
8331 auto CreateLDRInstruction =
8337 Opcode = AArch64::LDRSui;
8340 Opcode = AArch64::LDRHui;
8343 Opcode = AArch64::LDRBui;
8347 "Got unsupported number of lanes in machine-combiner gather pattern");
8357 auto LanesToLoadToReg0 =
8359 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8360 Register PrevReg = SubregToReg->getOperand(0).getReg();
8362 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8363 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8364 OffsetRegOperand.
getReg(),
8365 OffsetRegOperand.
isKill());
8372 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8374 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8381 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8382 OriginalSplitToLoadOffsetOperand.
getReg(),
8385 InstrIdxForVirtReg.
insert(
8386 std::make_pair(DestRegForMiddleIndex, InsInstrs.
size()));
8387 InsInstrs.
push_back(MiddleIndexLoadInstr);
8392 unsigned SubregType;
8395 SubregType = AArch64::ssub;
8398 SubregType = AArch64::hsub;
8401 SubregType = AArch64::bsub;
8405 "Got invalid NumLanes for machine-combiner gather pattern");
8408 auto SubRegToRegInstr =
8410 DestRegForSubregToReg)
8413 InstrIdxForVirtReg.
insert(
8414 std::make_pair(DestRegForSubregToReg, InsInstrs.
size()));
8418 auto LanesToLoadToReg1 =
8420 LoadToLaneInstrsAscending.end());
8421 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8423 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8424 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8425 OffsetRegOperand.
getReg(),
8426 OffsetRegOperand.
isKill());
8429 if (Index == NumLanes / 2 - 2) {
8464bool AArch64InstrInfo::getMachineCombinerPatterns(
8466 bool DoRegPressureReduce)
const {
8487 DoRegPressureReduce);
8516 const Register *ReplacedAddend =
nullptr) {
8517 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8519 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8522 Register SrcReg0 = MUL->getOperand(1).getReg();
8523 bool Src0IsKill = MUL->getOperand(1).isKill();
8524 Register SrcReg1 = MUL->getOperand(2).getReg();
8525 bool Src1IsKill = MUL->getOperand(2).isKill();
8529 if (ReplacedAddend) {
8531 SrcReg2 = *ReplacedAddend;
8558 .
addImm(MUL->getOperand(3).getImm());
8565 assert(
false &&
"Invalid FMA instruction kind \n");
8579 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8580 Opc = AArch64::FNMADDSrrr;
8581 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8582 Opc = AArch64::FNMADDDrrr;
8616 unsigned IdxDupOp,
unsigned MulOpc,
8618 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8619 "Invalid index of FMUL operand");
8627 if (Dup->
getOpcode() == TargetOpcode::COPY)
8636 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8677 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8692 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8719 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8747 unsigned IdxMulOpd,
unsigned MaddOpc,
unsigned VR,
8749 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8753 Register SrcReg0 = MUL->getOperand(1).getReg();
8754 bool Src0IsKill = MUL->getOperand(1).isKill();
8755 Register SrcReg1 = MUL->getOperand(2).getReg();
8756 bool Src1IsKill = MUL->getOperand(2).isKill();
8786 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
8787 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
8801 if (Opcode == AArch64::SUBSWrr)
8802 Opcode = AArch64::SUBWrr;
8803 else if (Opcode == AArch64::SUBSXrr)
8804 Opcode = AArch64::SUBXrr;
8806 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
8807 "Unexpected instruction opcode.");
8824 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8831unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
8832 unsigned int AccumulatorOpCode)
const {
8833 switch (AccumulatorOpCode) {
8834 case AArch64::UABALB_ZZZ_D:
8835 case AArch64::SABALB_ZZZ_D:
8836 case AArch64::UABALT_ZZZ_D:
8837 case AArch64::SABALT_ZZZ_D:
8838 return AArch64::ADD_ZZZ_D;
8839 case AArch64::UABALB_ZZZ_H:
8840 case AArch64::SABALB_ZZZ_H:
8841 case AArch64::UABALT_ZZZ_H:
8842 case AArch64::SABALT_ZZZ_H:
8843 return AArch64::ADD_ZZZ_H;
8844 case AArch64::UABALB_ZZZ_S:
8845 case AArch64::SABALB_ZZZ_S:
8846 case AArch64::UABALT_ZZZ_S:
8847 case AArch64::SABALT_ZZZ_S:
8848 return AArch64::ADD_ZZZ_S;
8849 case AArch64::UABALv16i8_v8i16:
8850 case AArch64::SABALv8i8_v8i16:
8851 case AArch64::SABAv8i16:
8852 case AArch64::UABAv8i16:
8853 return AArch64::ADDv8i16;
8854 case AArch64::SABALv2i32_v2i64:
8855 case AArch64::UABALv2i32_v2i64:
8856 case AArch64::SABALv4i32_v2i64:
8857 return AArch64::ADDv2i64;
8858 case AArch64::UABALv4i16_v4i32:
8859 case AArch64::SABALv4i16_v4i32:
8860 case AArch64::SABALv8i16_v4i32:
8861 case AArch64::SABAv4i32:
8862 case AArch64::UABAv4i32:
8863 return AArch64::ADDv4i32;
8864 case AArch64::UABALv4i32_v2i64:
8865 return AArch64::ADDv2i64;
8866 case AArch64::UABALv8i16_v4i32:
8867 return AArch64::ADDv4i32;
8868 case AArch64::UABALv8i8_v8i16:
8869 case AArch64::SABALv16i8_v8i16:
8870 return AArch64::ADDv8i16;
8871 case AArch64::UABAv16i8:
8872 case AArch64::SABAv16i8:
8873 return AArch64::ADDv16i8;
8874 case AArch64::UABAv4i16:
8875 case AArch64::SABAv4i16:
8876 return AArch64::ADDv4i16;
8877 case AArch64::UABAv2i32:
8878 case AArch64::SABAv2i32:
8879 return AArch64::ADDv2i32;
8880 case AArch64::UABAv8i8:
8881 case AArch64::SABAv8i8:
8882 return AArch64::ADDv8i8;
8891void AArch64InstrInfo::genAlternativeCodeSequence(
8901 MachineInstr *
MUL =
nullptr;
8902 const TargetRegisterClass *RC;
8908 DelInstrs, InstrIdxForVirtReg);
8914 InstrIdxForVirtReg);
8920 InstrIdxForVirtReg);
8929 Opc = AArch64::MADDWrrr;
8930 RC = &AArch64::GPR32RegClass;
8932 Opc = AArch64::MADDXrrr;
8933 RC = &AArch64::GPR64RegClass;
8944 Opc = AArch64::MADDWrrr;
8945 RC = &AArch64::GPR32RegClass;
8947 Opc = AArch64::MADDXrrr;
8948 RC = &AArch64::GPR64RegClass;
8961 const TargetRegisterClass *RC;
8962 unsigned BitSize, MovImm;
8965 MovImm = AArch64::MOVi32imm;
8966 RC = &AArch64::GPR32spRegClass;
8968 Opc = AArch64::MADDWrrr;
8969 RC = &AArch64::GPR32RegClass;
8971 MovImm = AArch64::MOVi64imm;
8972 RC = &AArch64::GPR64spRegClass;
8974 Opc = AArch64::MADDXrrr;
8975 RC = &AArch64::GPR64RegClass;
8986 uint64_t UImm =
SignExtend64(IsSub ? -Imm : Imm, BitSize);
8990 if (Insn.
size() != 1)
8992 MachineInstrBuilder MIB1 =
8993 BuildMI(MF, MIMetadata(Root),
TII->get(MovImm), NewVR)
8994 .
addImm(IsSub ? -Imm : Imm);
8996 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9007 const TargetRegisterClass *SubRC;
9008 unsigned SubOpc, ZeroReg;
9010 SubOpc = AArch64::SUBWrr;
9011 SubRC = &AArch64::GPR32spRegClass;
9012 ZeroReg = AArch64::WZR;
9013 Opc = AArch64::MADDWrrr;
9014 RC = &AArch64::GPR32RegClass;
9016 SubOpc = AArch64::SUBXrr;
9017 SubRC = &AArch64::GPR64spRegClass;
9018 ZeroReg = AArch64::XZR;
9019 Opc = AArch64::MADDXrrr;
9020 RC = &AArch64::GPR64RegClass;
9024 MachineInstrBuilder MIB1 =
9025 BuildMI(MF, MIMetadata(Root),
TII->get(SubOpc), NewVR)
9029 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9040 Opc = AArch64::MSUBWrrr;
9041 RC = &AArch64::GPR32RegClass;
9043 Opc = AArch64::MSUBXrrr;
9044 RC = &AArch64::GPR64RegClass;
9049 Opc = AArch64::MLAv8i8;
9050 RC = &AArch64::FPR64RegClass;
9054 Opc = AArch64::MLAv8i8;
9055 RC = &AArch64::FPR64RegClass;
9059 Opc = AArch64::MLAv16i8;
9060 RC = &AArch64::FPR128RegClass;
9064 Opc = AArch64::MLAv16i8;
9065 RC = &AArch64::FPR128RegClass;
9069 Opc = AArch64::MLAv4i16;
9070 RC = &AArch64::FPR64RegClass;
9074 Opc = AArch64::MLAv4i16;
9075 RC = &AArch64::FPR64RegClass;
9079 Opc = AArch64::MLAv8i16;
9080 RC = &AArch64::FPR128RegClass;
9084 Opc = AArch64::MLAv8i16;
9085 RC = &AArch64::FPR128RegClass;
9089 Opc = AArch64::MLAv2i32;
9090 RC = &AArch64::FPR64RegClass;
9094 Opc = AArch64::MLAv2i32;
9095 RC = &AArch64::FPR64RegClass;
9099 Opc = AArch64::MLAv4i32;
9100 RC = &AArch64::FPR128RegClass;
9104 Opc = AArch64::MLAv4i32;
9105 RC = &AArch64::FPR128RegClass;
9110 Opc = AArch64::MLAv8i8;
9111 RC = &AArch64::FPR64RegClass;
9113 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i8,
9117 Opc = AArch64::MLSv8i8;
9118 RC = &AArch64::FPR64RegClass;
9122 Opc = AArch64::MLAv16i8;
9123 RC = &AArch64::FPR128RegClass;
9125 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv16i8,
9129 Opc = AArch64::MLSv16i8;
9130 RC = &AArch64::FPR128RegClass;
9134 Opc = AArch64::MLAv4i16;
9135 RC = &AArch64::FPR64RegClass;
9137 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9141 Opc = AArch64::MLSv4i16;
9142 RC = &AArch64::FPR64RegClass;
9146 Opc = AArch64::MLAv8i16;
9147 RC = &AArch64::FPR128RegClass;
9149 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9153 Opc = AArch64::MLSv8i16;
9154 RC = &AArch64::FPR128RegClass;
9158 Opc = AArch64::MLAv2i32;
9159 RC = &AArch64::FPR64RegClass;
9161 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9165 Opc = AArch64::MLSv2i32;
9166 RC = &AArch64::FPR64RegClass;
9170 Opc = AArch64::MLAv4i32;
9171 RC = &AArch64::FPR128RegClass;
9173 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9177 Opc = AArch64::MLSv4i32;
9178 RC = &AArch64::FPR128RegClass;
9183 Opc = AArch64::MLAv4i16_indexed;
9184 RC = &AArch64::FPR64RegClass;
9188 Opc = AArch64::MLAv4i16_indexed;
9189 RC = &AArch64::FPR64RegClass;
9193 Opc = AArch64::MLAv8i16_indexed;
9194 RC = &AArch64::FPR128RegClass;
9198 Opc = AArch64::MLAv8i16_indexed;
9199 RC = &AArch64::FPR128RegClass;
9203 Opc = AArch64::MLAv2i32_indexed;
9204 RC = &AArch64::FPR64RegClass;
9208 Opc = AArch64::MLAv2i32_indexed;
9209 RC = &AArch64::FPR64RegClass;
9213 Opc = AArch64::MLAv4i32_indexed;
9214 RC = &AArch64::FPR128RegClass;
9218 Opc = AArch64::MLAv4i32_indexed;
9219 RC = &AArch64::FPR128RegClass;
9224 Opc = AArch64::MLAv4i16_indexed;
9225 RC = &AArch64::FPR64RegClass;
9227 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9231 Opc = AArch64::MLSv4i16_indexed;
9232 RC = &AArch64::FPR64RegClass;
9236 Opc = AArch64::MLAv8i16_indexed;
9237 RC = &AArch64::FPR128RegClass;
9239 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9243 Opc = AArch64::MLSv8i16_indexed;
9244 RC = &AArch64::FPR128RegClass;
9248 Opc = AArch64::MLAv2i32_indexed;
9249 RC = &AArch64::FPR64RegClass;
9251 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9255 Opc = AArch64::MLSv2i32_indexed;
9256 RC = &AArch64::FPR64RegClass;
9260 Opc = AArch64::MLAv4i32_indexed;
9261 RC = &AArch64::FPR128RegClass;
9263 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9267 Opc = AArch64::MLSv4i32_indexed;
9268 RC = &AArch64::FPR128RegClass;
9274 Opc = AArch64::FMADDHrrr;
9275 RC = &AArch64::FPR16RegClass;
9279 Opc = AArch64::FMADDSrrr;
9280 RC = &AArch64::FPR32RegClass;
9284 Opc = AArch64::FMADDDrrr;
9285 RC = &AArch64::FPR64RegClass;
9290 Opc = AArch64::FMADDHrrr;
9291 RC = &AArch64::FPR16RegClass;
9295 Opc = AArch64::FMADDSrrr;
9296 RC = &AArch64::FPR32RegClass;
9300 Opc = AArch64::FMADDDrrr;
9301 RC = &AArch64::FPR64RegClass;
9306 Opc = AArch64::FMLAv1i32_indexed;
9307 RC = &AArch64::FPR32RegClass;
9312 Opc = AArch64::FMLAv1i32_indexed;
9313 RC = &AArch64::FPR32RegClass;
9319 Opc = AArch64::FMLAv1i64_indexed;
9320 RC = &AArch64::FPR64RegClass;
9325 Opc = AArch64::FMLAv1i64_indexed;
9326 RC = &AArch64::FPR64RegClass;
9332 RC = &AArch64::FPR64RegClass;
9333 Opc = AArch64::FMLAv4i16_indexed;
9338 RC = &AArch64::FPR64RegClass;
9339 Opc = AArch64::FMLAv4f16;
9344 RC = &AArch64::FPR64RegClass;
9345 Opc = AArch64::FMLAv4i16_indexed;
9350 RC = &AArch64::FPR64RegClass;
9351 Opc = AArch64::FMLAv4f16;
9358 RC = &AArch64::FPR64RegClass;
9360 Opc = AArch64::FMLAv2i32_indexed;
9364 Opc = AArch64::FMLAv2f32;
9371 RC = &AArch64::FPR64RegClass;
9373 Opc = AArch64::FMLAv2i32_indexed;
9377 Opc = AArch64::FMLAv2f32;
9384 RC = &AArch64::FPR128RegClass;
9385 Opc = AArch64::FMLAv8i16_indexed;
9390 RC = &AArch64::FPR128RegClass;
9391 Opc = AArch64::FMLAv8f16;
9396 RC = &AArch64::FPR128RegClass;
9397 Opc = AArch64::FMLAv8i16_indexed;
9402 RC = &AArch64::FPR128RegClass;
9403 Opc = AArch64::FMLAv8f16;
9410 RC = &AArch64::FPR128RegClass;
9412 Opc = AArch64::FMLAv2i64_indexed;
9416 Opc = AArch64::FMLAv2f64;
9423 RC = &AArch64::FPR128RegClass;
9425 Opc = AArch64::FMLAv2i64_indexed;
9429 Opc = AArch64::FMLAv2f64;
9437 RC = &AArch64::FPR128RegClass;
9439 Opc = AArch64::FMLAv4i32_indexed;
9443 Opc = AArch64::FMLAv4f32;
9451 RC = &AArch64::FPR128RegClass;
9453 Opc = AArch64::FMLAv4i32_indexed;
9457 Opc = AArch64::FMLAv4f32;
9464 Opc = AArch64::FNMSUBHrrr;
9465 RC = &AArch64::FPR16RegClass;
9469 Opc = AArch64::FNMSUBSrrr;
9470 RC = &AArch64::FPR32RegClass;
9474 Opc = AArch64::FNMSUBDrrr;
9475 RC = &AArch64::FPR64RegClass;
9480 Opc = AArch64::FNMADDHrrr;
9481 RC = &AArch64::FPR16RegClass;
9485 Opc = AArch64::FNMADDSrrr;
9486 RC = &AArch64::FPR32RegClass;
9490 Opc = AArch64::FNMADDDrrr;
9491 RC = &AArch64::FPR64RegClass;
9496 Opc = AArch64::FMSUBHrrr;
9497 RC = &AArch64::FPR16RegClass;
9501 Opc = AArch64::FMSUBSrrr;
9502 RC = &AArch64::FPR32RegClass;
9506 Opc = AArch64::FMSUBDrrr;
9507 RC = &AArch64::FPR64RegClass;
9512 Opc = AArch64::FMLSv1i32_indexed;
9513 RC = &AArch64::FPR32RegClass;
9519 Opc = AArch64::FMLSv1i64_indexed;
9520 RC = &AArch64::FPR64RegClass;
9527 RC = &AArch64::FPR64RegClass;
9529 MachineInstrBuilder MIB1 =
9530 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f16), NewVR)
9533 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9535 Opc = AArch64::FMLAv4f16;
9539 Opc = AArch64::FMLAv4i16_indexed;
9546 RC = &AArch64::FPR64RegClass;
9547 Opc = AArch64::FMLSv4f16;
9552 RC = &AArch64::FPR64RegClass;
9553 Opc = AArch64::FMLSv4i16_indexed;
9560 RC = &AArch64::FPR64RegClass;
9562 Opc = AArch64::FMLSv2i32_indexed;
9566 Opc = AArch64::FMLSv2f32;
9574 RC = &AArch64::FPR128RegClass;
9576 MachineInstrBuilder MIB1 =
9577 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv8f16), NewVR)
9580 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9582 Opc = AArch64::FMLAv8f16;
9586 Opc = AArch64::FMLAv8i16_indexed;
9593 RC = &AArch64::FPR128RegClass;
9594 Opc = AArch64::FMLSv8f16;
9599 RC = &AArch64::FPR128RegClass;
9600 Opc = AArch64::FMLSv8i16_indexed;
9607 RC = &AArch64::FPR128RegClass;
9609 Opc = AArch64::FMLSv2i64_indexed;
9613 Opc = AArch64::FMLSv2f64;
9621 RC = &AArch64::FPR128RegClass;
9623 Opc = AArch64::FMLSv4i32_indexed;
9627 Opc = AArch64::FMLSv4f32;
9634 RC = &AArch64::FPR64RegClass;
9636 MachineInstrBuilder MIB1 =
9637 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f32), NewVR)
9640 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9642 Opc = AArch64::FMLAv2i32_indexed;
9646 Opc = AArch64::FMLAv2f32;
9654 RC = &AArch64::FPR128RegClass;
9656 MachineInstrBuilder MIB1 =
9657 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f32), NewVR)
9660 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9662 Opc = AArch64::FMLAv4i32_indexed;
9666 Opc = AArch64::FMLAv4f32;
9674 RC = &AArch64::FPR128RegClass;
9676 MachineInstrBuilder MIB1 =
9677 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f64), NewVR)
9680 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9682 Opc = AArch64::FMLAv2i64_indexed;
9686 Opc = AArch64::FMLAv2f64;
9698 &AArch64::FPR128RegClass, MRI);
9707 &AArch64::FPR128RegClass, MRI);
9716 &AArch64::FPR128_loRegClass, MRI);
9725 &AArch64::FPR128RegClass, MRI);
9734 &AArch64::FPR128_loRegClass, MRI);
9768 for (
auto *
MI : InsInstrs)
9769 MI->setFlags(Flags);
9810 bool IsNegativeBranch =
false;
9811 bool IsTestAndBranch =
false;
9812 unsigned TargetBBInMI = 0;
9813 switch (
MI.getOpcode()) {
9817 case AArch64::CBWPri:
9818 case AArch64::CBXPri:
9819 case AArch64::CBBAssertExt:
9820 case AArch64::CBHAssertExt:
9821 case AArch64::CBWPrr:
9822 case AArch64::CBXPrr:
9828 case AArch64::CBNZW:
9829 case AArch64::CBNZX:
9831 IsNegativeBranch =
true;
9836 IsTestAndBranch =
true;
9838 case AArch64::TBNZW:
9839 case AArch64::TBNZX:
9841 IsNegativeBranch =
true;
9842 IsTestAndBranch =
true;
9848 if (IsTestAndBranch &&
MI.getOperand(1).getImm())
9852 assert(
MI.getParent() &&
"Incomplete machine instruction\n");
9863 while (
DefMI->isCopy()) {
9872 switch (
DefMI->getOpcode()) {
9876 case AArch64::ANDWri:
9877 case AArch64::ANDXri: {
9878 if (IsTestAndBranch)
9885 bool Is32Bit = (
DefMI->getOpcode() == AArch64::ANDWri);
9887 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
9902 unsigned Opc = (Imm < 32)
9903 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
9904 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
9917 if (!Is32Bit && Imm < 32)
9919 MI.eraseFromParent();
9923 case AArch64::CSINCWr:
9924 case AArch64::CSINCXr: {
9925 if (!(
DefMI->getOperand(1).getReg() == AArch64::WZR &&
9926 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
9927 !(
DefMI->getOperand(1).getReg() == AArch64::XZR &&
9928 DefMI->getOperand(2).getReg() == AArch64::XZR))
9931 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
9944 if (IsNegativeBranch)
9947 MI.eraseFromParent();
9953std::pair<unsigned, unsigned>
9954AArch64InstrInfo::decomposeMachineOperandsTargetFlags(
unsigned TF)
const {
9956 return std::make_pair(TF & Mask, TF & ~Mask);
9960AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags()
const {
9963 static const std::pair<unsigned, const char *> TargetFlags[] = {
9964 {MO_PAGE,
"aarch64-page"}, {
MO_PAGEOFF,
"aarch64-pageoff"},
9965 {
MO_G3,
"aarch64-g3"}, {
MO_G2,
"aarch64-g2"},
9966 {
MO_G1,
"aarch64-g1"}, {
MO_G0,
"aarch64-g0"},
9972AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags()
const {
9973 using namespace AArch64II;
9975 static const std::pair<unsigned, const char *> TargetFlags[] = {
9978 {
MO_NC,
"aarch64-nc"},
9979 {
MO_S,
"aarch64-s"},
9990AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags()
const {
9991 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10093 MachineFunction *MF =
C.getMF();
10095 const AArch64RegisterInfo *ARI =
10096 static_cast<const AArch64RegisterInfo *
>(&
TRI);
10099 for (
unsigned Reg : AArch64::GPR64RegClass) {
10101 Reg != AArch64::LR &&
10102 Reg != AArch64::X16 &&
10103 Reg != AArch64::X17 &&
10104 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
10105 C.isAvailableInsideSeq(
Reg,
TRI))
10136 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10139std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10140AArch64InstrInfo::getOutliningCandidateInfo(
10142 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10143 unsigned MinRepeats)
const {
10144 unsigned SequenceSize = 0;
10145 for (
auto &
MI : RepeatedSequenceLocs[0])
10148 unsigned NumBytesToCreateFrame = 0;
10154 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10155 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10156 if (LastMI.
getOpcode() == AArch64::ADRP &&
10159 return std::nullopt;
10164 if ((FirstMI.
getOpcode() == AArch64::ADDXri ||
10165 FirstMI.
getOpcode() == AArch64::LDRXui) &&
10168 return std::nullopt;
10179 if (std::adjacent_find(
10180 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10181 [](
const outliner::Candidate &a,
const outliner::Candidate &b) {
10184 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10185 outliningCandidatesSigningKeyConsensus(a, b) &&
10186 outliningCandidatesV8_3OpsConsensus(a, b)) {
10190 }) != RepeatedSequenceLocs.end()) {
10191 return std::nullopt;
10208 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10209 const auto RASignCondition = RepeatedSequenceLocs[0]
10212 ->getSignReturnAddressCondition();
10215 NumBytesToCreateFrame += 8;
10218 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10219 *RepeatedSequenceLocs[0].getMF());
10220 NumBytesToCheckLRInTCEpilogue =
10224 if (isTailCallReturnInst(RepeatedSequenceLocs[0].
back()))
10225 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10233 for (
auto &
MI :
C) {
10234 if (
MI.modifiesRegister(AArch64::SP, &
TRI)) {
10235 switch (
MI.getOpcode()) {
10236 case AArch64::ADDXri:
10237 case AArch64::ADDWri:
10238 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10239 assert(
MI.getOperand(2).isImm() &&
10240 "Expected operand to be immediate");
10241 assert(
MI.getOperand(1).isReg() &&
10242 "Expected operand to be a register");
10246 if (
MI.getOperand(1).getReg() == AArch64::SP)
10247 SPValue +=
MI.getOperand(2).getImm();
10251 case AArch64::SUBXri:
10252 case AArch64::SUBWri:
10253 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10254 assert(
MI.getOperand(2).isImm() &&
10255 "Expected operand to be immediate");
10256 assert(
MI.getOperand(1).isReg() &&
10257 "Expected operand to be a register");
10261 if (
MI.getOperand(1).getReg() == AArch64::SP)
10262 SPValue -=
MI.getOperand(2).getImm();
10279 if (RepeatedSequenceLocs.size() < MinRepeats)
10280 return std::nullopt;
10284 unsigned FlagsSetInAll = 0xF;
10288 FlagsSetInAll &=
C.Flags;
10290 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10293 auto SetCandidateCallInfo =
10294 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
10296 C.setCallInfo(CallID, NumBytesForCall);
10300 NumBytesToCreateFrame += 4;
10308 unsigned CFICount = 0;
10309 for (
auto &
I : RepeatedSequenceLocs[0]) {
10310 if (
I.isCFIInstruction())
10320 std::vector<MCCFIInstruction> CFIInstructions =
10321 C.getMF()->getFrameInstructions();
10323 if (CFICount > 0 && CFICount != CFIInstructions.size())
10324 return std::nullopt;
10332 if (!
MI.modifiesRegister(AArch64::SP, &
TRI) &&
10333 !
MI.readsRegister(AArch64::SP, &
TRI))
10339 if (
MI.modifiesRegister(AArch64::SP, &
TRI))
10344 if (
MI.mayLoadOrStore()) {
10347 bool OffsetIsScalable;
10351 if (!getMemOperandWithOffset(
MI,
Base,
Offset, OffsetIsScalable, &
TRI) ||
10352 !
Base->isReg() ||
Base->getReg() != AArch64::SP)
10356 if (OffsetIsScalable)
10364 TypeSize Scale(0U,
false), DummyWidth(0U,
false);
10365 getMemOpInfo(
MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10368 if (
Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10369 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10384 bool AllStackInstrsSafe =
10389 if (RepeatedSequenceLocs[0].
back().isTerminator()) {
10391 NumBytesToCreateFrame = 0;
10392 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10396 else if (LastInstrOpcode == AArch64::BL ||
10397 ((LastInstrOpcode == AArch64::BLR ||
10398 LastInstrOpcode == AArch64::BLRNoIP) &&
10402 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10410 unsigned NumBytesNoStackCalls = 0;
10411 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10417 ?
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI)
10426 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10429 if (LRAvailable && !IsNoReturn) {
10430 NumBytesNoStackCalls += 4;
10432 CandidatesWithoutStackFixups.push_back(
C);
10437 else if (findRegisterToSaveLRTo(
C)) {
10438 NumBytesNoStackCalls += 12;
10440 CandidatesWithoutStackFixups.push_back(
C);
10445 else if (
C.isAvailableInsideSeq(AArch64::SP,
TRI)) {
10446 NumBytesNoStackCalls += 12;
10448 CandidatesWithoutStackFixups.push_back(
C);
10454 NumBytesNoStackCalls += SequenceSize;
10461 if (!AllStackInstrsSafe ||
10462 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10463 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10465 if (RepeatedSequenceLocs.size() < MinRepeats)
10466 return std::nullopt;
10519 (!
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI) ||
10520 !findRegisterToSaveLRTo(
C));
10526 if (RepeatedSequenceLocs.size() < MinRepeats)
10527 return std::nullopt;
10536 bool ModStackToSaveLR =
false;
10539 ModStackToSaveLR =
true;
10548 ModStackToSaveLR =
true;
10550 if (ModStackToSaveLR) {
10552 if (!AllStackInstrsSafe)
10553 return std::nullopt;
10556 NumBytesToCreateFrame += 8;
10563 return std::nullopt;
10565 return std::make_unique<outliner::OutlinedFunction>(
10566 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10569void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10570 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
10574 const auto &CFn = Candidates.front().getMF()->getFunction();
10576 if (CFn.hasFnAttribute(
"ptrauth-returns"))
10577 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-returns"));
10578 if (CFn.hasFnAttribute(
"ptrauth-auth-traps"))
10579 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-auth-traps"));
10582 if (CFn.hasFnAttribute(
"sign-return-address"))
10583 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address"));
10584 if (CFn.hasFnAttribute(
"sign-return-address-key"))
10585 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address-key"));
10587 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
10590bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10595 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
10602 if (
F.hasSection())
10608 AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
10609 if (!AFI || AFI->
hasRedZone().value_or(
true))
10629 unsigned &Flags)
const {
10631 "Must track liveness!");
10633 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10648 auto AreAllUnsafeRegsDead = [&LRU]() {
10649 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10650 LRU.available(AArch64::NZCV);
10665 bool LRAvailableEverywhere =
true;
10667 LRU.addLiveOuts(
MBB);
10669 auto UpdateWholeMBBFlags = [&
Flags](
const MachineInstr &
MI) {
10670 if (
MI.isCall() && !
MI.isTerminator())
10676 auto CreateNewRangeStartingAt =
10677 [&RangeBegin, &RangeEnd,
10679 RangeBegin = NewBegin;
10680 RangeEnd = std::next(RangeBegin);
10683 auto SaveRangeIfNonEmpty = [&RangeLen, &
Ranges, &RangeBegin, &RangeEnd]() {
10689 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10691 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10693 Ranges.emplace_back(RangeBegin, RangeEnd);
10701 for (; FirstPossibleEndPt !=
MBB.
instr_rend(); ++FirstPossibleEndPt) {
10702 if (!FirstPossibleEndPt->isDebugInstr())
10703 LRU.stepBackward(*FirstPossibleEndPt);
10706 UpdateWholeMBBFlags(*FirstPossibleEndPt);
10707 if (AreAllUnsafeRegsDead())
10714 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
10719 if (!
MI.isDebugInstr())
10720 LRU.stepBackward(
MI);
10721 UpdateWholeMBBFlags(
MI);
10722 if (!AreAllUnsafeRegsDead()) {
10723 SaveRangeIfNonEmpty();
10724 CreateNewRangeStartingAt(
MI.getIterator());
10727 LRAvailableEverywhere &= LRU.available(AArch64::LR);
10728 RangeBegin =
MI.getIterator();
10733 if (AreAllUnsafeRegsDead())
10734 SaveRangeIfNonEmpty();
10742 if (!LRAvailableEverywhere)
10750 unsigned Flags)
const {
10751 MachineInstr &
MI = *MIT;
10755 switch (
MI.getOpcode()) {
10756 case AArch64::PACM:
10757 case AArch64::PACIASP:
10758 case AArch64::PACIBSP:
10759 case AArch64::PACIASPPC:
10760 case AArch64::PACIBSPPC:
10761 case AArch64::AUTIASP:
10762 case AArch64::AUTIBSP:
10763 case AArch64::AUTIASPPCi:
10764 case AArch64::AUTIASPPCr:
10765 case AArch64::AUTIBSPPCi:
10766 case AArch64::AUTIBSPPCr:
10767 case AArch64::RETAA:
10768 case AArch64::RETAB:
10769 case AArch64::RETAASPPCi:
10770 case AArch64::RETAASPPCr:
10771 case AArch64::RETABSPPCi:
10772 case AArch64::RETABSPPCr:
10773 case AArch64::EMITBKEY:
10774 case AArch64::PAUTH_PROLOGUE:
10775 case AArch64::PAUTH_EPILOGUE:
10785 if (
MI.isCFIInstruction())
10789 if (
MI.isTerminator())
10795 for (
const MachineOperand &MOP :
MI.operands()) {
10798 assert(!MOP.isCFIIndex());
10801 if (MOP.isReg() && !MOP.isImplicit() &&
10802 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
10809 if (
MI.getOpcode() == AArch64::ADRP)
10829 for (
const MachineOperand &MOP :
MI.operands()) {
10830 if (MOP.isGlobal()) {
10838 if (Callee &&
Callee->getName() ==
"\01_mcount")
10846 if (
MI.getOpcode() == AArch64::BLR ||
10847 MI.getOpcode() == AArch64::BLRNoIP ||
MI.getOpcode() == AArch64::BL)
10851 return UnknownCallOutlineType;
10859 return UnknownCallOutlineType;
10867 return UnknownCallOutlineType;
10888 for (MachineInstr &
MI :
MBB) {
10889 const MachineOperand *
Base;
10890 TypeSize Width(0,
false);
10892 bool OffsetIsScalable;
10895 if (!
MI.mayLoadOrStore() ||
10898 (
Base->isReg() &&
Base->getReg() != AArch64::SP))
10902 TypeSize Scale(0U,
false);
10903 int64_t Dummy1, Dummy2;
10906 assert(StackOffsetOperand.
isImm() &&
"Stack offset wasn't immediate!");
10908 assert(Scale != 0 &&
"Unexpected opcode!");
10909 assert(!OffsetIsScalable &&
"Expected offset to be a byte offset");
10914 int64_t NewImm = (
Offset + 16) / (int64_t)Scale.getFixedValue();
10915 StackOffsetOperand.
setImm(NewImm);
10921 bool ShouldSignReturnAddr) {
10922 if (!ShouldSignReturnAddr)
10930void AArch64InstrInfo::buildOutlinedFrame(
10934 AArch64FunctionInfo *FI = MF.
getInfo<AArch64FunctionInfo>();
10942 unsigned TailOpcode;
10944 TailOpcode = AArch64::TCRETURNdi;
10948 TailOpcode = AArch64::TCRETURNriALL;
10959 bool IsLeafFunction =
true;
10962 auto IsNonTailCall = [](
const MachineInstr &
MI) {
10963 return MI.isCall() && !
MI.isReturn();
10973 "Can only fix up stack references once");
10974 fixupPostOutline(
MBB);
10976 IsLeafFunction =
false;
10987 Et = std::prev(
MBB.
end());
10997 if (MF.
getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11001 CFIBuilder.buildDefCFAOffset(16);
11005 CFIBuilder.buildOffset(AArch64::LR, -16);
11019 RASignCondition, !IsLeafFunction);
11048 fixupPostOutline(
MBB);
11059 .addGlobalAddress(
M.getNamedValue(MF.
getName()))
11069 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
11078 MachineInstr *Save;
11079 MachineInstr *Restore;
11085 assert(
Reg &&
"No callee-saved register available?");
11119 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
11127bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11135 bool AllowSideEffects)
const {
11137 const AArch64Subtarget &STI = MF.
getSubtarget<AArch64Subtarget>();
11140 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
11153 assert(STI.hasNEON() &&
"Expected to have NEON.");
11159std::optional<DestSourcePair>
11164 if (((
MI.getOpcode() == AArch64::ORRWrs &&
11165 MI.getOperand(1).getReg() == AArch64::WZR &&
11166 MI.getOperand(3).getImm() == 0x0) ||
11167 (
MI.getOpcode() == AArch64::ORRWrr &&
11168 MI.getOperand(1).getReg() == AArch64::WZR)) &&
11170 (!
MI.getOperand(0).getReg().isVirtual() ||
11171 MI.getOperand(0).getSubReg() == 0) &&
11172 (!
MI.getOperand(0).getReg().isPhysical() ||
11177 if (
MI.getOpcode() == AArch64::ORRXrs &&
11178 MI.getOperand(1).getReg() == AArch64::XZR &&
11179 MI.getOperand(3).getImm() == 0x0)
11182 return std::nullopt;
11185std::optional<DestSourcePair>
11187 if ((
MI.getOpcode() == AArch64::ORRWrs &&
11188 MI.getOperand(1).getReg() == AArch64::WZR &&
11189 MI.getOperand(3).getImm() == 0x0) ||
11190 (
MI.getOpcode() == AArch64::ORRWrr &&
11191 MI.getOperand(1).getReg() == AArch64::WZR))
11193 return std::nullopt;
11196std::optional<RegImmPair>
11205 return std::nullopt;
11207 switch (
MI.getOpcode()) {
11209 return std::nullopt;
11210 case AArch64::SUBWri:
11211 case AArch64::SUBXri:
11212 case AArch64::SUBSWri:
11213 case AArch64::SUBSXri:
11216 case AArch64::ADDSWri:
11217 case AArch64::ADDSXri:
11218 case AArch64::ADDWri:
11219 case AArch64::ADDXri: {
11221 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg() ||
11222 !
MI.getOperand(2).isImm())
11223 return std::nullopt;
11224 int Shift =
MI.getOperand(3).getImm();
11225 assert((Shift == 0 || Shift == 12) &&
"Shift can be either 0 or 12");
11229 return RegImmPair{
MI.getOperand(1).getReg(),
Offset};
11235static std::optional<ParamLoadedValue>
11239 auto DestSrc =
TII->isCopyLikeInstr(
MI);
11241 return std::nullopt;
11243 Register DestReg = DestSrc->Destination->getReg();
11244 Register SrcReg = DestSrc->Source->getReg();
11247 return std::nullopt;
11252 if (DestReg == DescribedReg)
11256 if (
MI.getOpcode() == AArch64::ORRWrs &&
11257 TRI->isSuperRegister(DestReg, DescribedReg))
11261 if (
MI.getOpcode() == AArch64::ORRXrs &&
11262 TRI->isSubRegister(DestReg, DescribedReg)) {
11263 Register SrcSubReg =
TRI->getSubReg(SrcReg, AArch64::sub_32);
11267 assert(!
TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11268 "Unhandled ORR[XW]rs copy case");
11270 return std::nullopt;
11273bool AArch64InstrInfo::isFunctionSafeToSplit(
const MachineFunction &MF)
const {
11278 if (MF.
getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(
true))
11284bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11288 auto isAsmGoto = [](
const MachineInstr &
MI) {
11289 return MI.getOpcode() == AArch64::INLINEASM_BR;
11299 auto containsMBB = [&
MBB](
const MachineJumpTableEntry &JTE) {
11306 for (
const MachineInstr &
MI :
MBB) {
11307 switch (
MI.getOpcode()) {
11308 case TargetOpcode::G_BRJT:
11309 case AArch64::JumpTableDest32:
11310 case AArch64::JumpTableDest16:
11311 case AArch64::JumpTableDest8:
11322std::optional<ParamLoadedValue>
11325 const MachineFunction *MF =
MI.getMF();
11327 switch (
MI.getOpcode()) {
11328 case AArch64::MOVZWi:
11329 case AArch64::MOVZXi: {
11332 if (!
TRI->isSuperRegisterEq(
MI.getOperand(0).getReg(),
Reg))
11333 return std::nullopt;
11335 if (!
MI.getOperand(1).isImm())
11336 return std::nullopt;
11337 int64_t Immediate =
MI.getOperand(1).getImm();
11338 int Shift =
MI.getOperand(2).getImm();
11342 case AArch64::ORRWrs:
11343 case AArch64::ORRXrs:
11350bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11353 ExtMI.
getOpcode() == TargetOpcode::G_ZEXT ||
11354 ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT);
11357 if (ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT)
11367 return UserMI->
getOpcode() == TargetOpcode::G_PTR_ADD;
11370uint64_t AArch64InstrInfo::getElementSizeForOpcode(
unsigned Opc)
const {
11374bool AArch64InstrInfo::isPTestLikeOpcode(
unsigned Opc)
const {
11378bool AArch64InstrInfo::isWhileOpcode(
unsigned Opc)
const {
11383AArch64InstrInfo::getTailDuplicateSize(
CodeGenOptLevel OptLevel)
const {
11387bool AArch64InstrInfo::isLegalAddressingMode(
unsigned NumBytes, int64_t
Offset,
11388 unsigned Scale)
const {
11399 unsigned Shift =
Log2_64(NumBytes);
11400 if (NumBytes &&
Offset > 0 && (
Offset / NumBytes) <= (1LL << 12) - 1 &&
11408 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11413 return AArch64::BLRNoIP;
11415 return AArch64::BLR;
11421 auto Builder =
BuildMI(
MBB, InsertPt,
DL,
get(AArch64::PAUTH_EPILOGUE))
11431 if (Subtarget.hasPAuthLR())
11442 Register TargetReg,
bool FrameSetup)
const {
11443 assert(TargetReg != AArch64::SP &&
"New top of stack cannot already be in SP");
11455 MF.
insert(MBBInsertPoint, LoopTestMBB);
11458 MF.
insert(MBBInsertPoint, LoopBodyMBB);
11460 MF.
insert(MBBInsertPoint, ExitMBB);
11470 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::SUBSXrx64),
11478 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::Bcc))
11484 BuildMI(*LoopBodyMBB, LoopBodyMBB->
end(),
DL,
TII->get(AArch64::LDRXui))
11501 BuildMI(*ExitMBB, ExitMBB->
end(),
DL,
TII->get(AArch64::ADDXri), AArch64::SP)
11520 MBB.addSuccessor(LoopTestMBB);
11526 return ExitMBB->
begin();
11531 MachineFunction *MF;
11532 const TargetInstrInfo *
TII;
11533 const TargetRegisterInfo *
TRI;
11534 MachineRegisterInfo &MRI;
11537 MachineBasicBlock *LoopBB;
11539 MachineInstr *CondBranch;
11541 MachineInstr *Comp;
11543 unsigned CompCounterOprNum;
11545 MachineInstr *Update;
11547 unsigned UpdateCounterOprNum;
11551 bool IsUpdatePriorComp;
11557 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11558 MachineInstr *Comp,
unsigned CompCounterOprNum,
11559 MachineInstr *Update,
unsigned UpdateCounterOprNum,
11560 Register Init,
bool IsUpdatePriorComp,
11561 const SmallVectorImpl<MachineOperand> &
Cond)
11563 TII(MF->getSubtarget().getInstrInfo()),
11564 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11565 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11566 CompCounterOprNum(CompCounterOprNum), Update(Update),
11567 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11570 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
11576 std::optional<bool> createTripCountGreaterCondition(
11577 int TC, MachineBasicBlock &
MBB,
11578 SmallVectorImpl<MachineOperand> &CondParam)
override {
11586 void createRemainingIterationsGreaterCondition(
11587 int TC, MachineBasicBlock &
MBB, SmallVectorImpl<MachineOperand> &
Cond,
11588 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts)
override;
11590 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
11592 void adjustTripCount(
int TripCountAdjust)
override {}
11594 bool isMVEExpanderSupported()
override {
return true; }
11613 }
else if (
I == ReplaceOprNum) {
11618 MBB.insert(InsertTo, NewMI);
11622void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11638 assert(CondBranch->getOpcode() == AArch64::Bcc);
11642 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11649 auto AccumulateCond = [&](
Register CurCond,
11660 if (!LastStage0Insts.
empty() && LastStage0Insts[Comp]->getParent() == &
MBB) {
11664 for (
int I = 0;
I <= TC; ++
I) {
11670 AccCond = AccumulateCond(AccCond, CC);
11674 if (Update != Comp && IsUpdatePriorComp) {
11676 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11677 NextCounter =
cloneInstr(Update, UpdateCounterOprNum, Counter,
MBB,
11681 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
11683 }
else if (Update != Comp) {
11688 Counter = NextCounter;
11692 if (LastStage0Insts.
empty()) {
11696 if (IsUpdatePriorComp)
11701 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11704 for (
int I = 0;
I <= TC; ++
I) {
11708 AccCond = AccumulateCond(AccCond, CC);
11709 if (
I != TC && Update != Comp)
11712 Counter = NextCounter;
11728 assert(Phi.getNumOperands() == 5);
11729 if (Phi.getOperand(2).getMBB() ==
MBB) {
11730 RegMBB = Phi.getOperand(1).getReg();
11731 RegOther = Phi.getOperand(3).getReg();
11733 assert(Phi.getOperand(4).getMBB() ==
MBB);
11734 RegMBB = Phi.getOperand(3).getReg();
11735 RegOther = Phi.getOperand(1).getReg();
11740 if (!
Reg.isVirtual())
11749 unsigned &UpdateCounterOprNum,
Register &InitReg,
11750 bool &IsUpdatePriorComp) {
11764 if (!
Reg.isVirtual())
11767 UpdateInst =
nullptr;
11768 UpdateCounterOprNum = 0;
11770 IsUpdatePriorComp =
true;
11774 if (Def->getParent() != LoopBB)
11776 if (Def->isCopy()) {
11778 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
11780 CurReg = Def->getOperand(1).getReg();
11781 }
else if (Def->isPHI()) {
11785 IsUpdatePriorComp =
false;
11790 switch (Def->getOpcode()) {
11791 case AArch64::ADDSXri:
11792 case AArch64::ADDSWri:
11793 case AArch64::SUBSXri:
11794 case AArch64::SUBSWri:
11795 case AArch64::ADDXri:
11796 case AArch64::ADDWri:
11797 case AArch64::SUBXri:
11798 case AArch64::SUBWri:
11800 UpdateCounterOprNum = 1;
11802 case AArch64::ADDSXrr:
11803 case AArch64::ADDSWrr:
11804 case AArch64::SUBSXrr:
11805 case AArch64::SUBSWrr:
11806 case AArch64::ADDXrr:
11807 case AArch64::ADDWrr:
11808 case AArch64::SUBXrr:
11809 case AArch64::SUBWrr:
11812 UpdateCounterOprNum = 1;
11814 UpdateCounterOprNum = 2;
11821 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
11836std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
11847 if (
MI.isCall() ||
MI.hasUnmodeledSideEffects())
11858 if (
TBB == LoopBB && FBB == LoopBB)
11862 if (
TBB != LoopBB && FBB ==
nullptr)
11865 assert((
TBB == LoopBB || FBB == LoopBB) &&
11866 "The Loop must be a single-basic-block loop");
11871 if (CondBranch->
getOpcode() != AArch64::Bcc)
11879 unsigned CompCounterOprNum = 0;
11881 if (
MI.modifiesRegister(AArch64::NZCV, &
TRI)) {
11885 switch (
MI.getOpcode()) {
11886 case AArch64::SUBSXri:
11887 case AArch64::SUBSWri:
11888 case AArch64::ADDSXri:
11889 case AArch64::ADDSWri:
11891 CompCounterOprNum = 1;
11893 case AArch64::ADDSWrr:
11894 case AArch64::ADDSXrr:
11895 case AArch64::SUBSWrr:
11896 case AArch64::SUBSXrr:
11900 if (isWhileOpcode(
MI.getOpcode())) {
11907 if (CompCounterOprNum == 0) {
11909 CompCounterOprNum = 2;
11911 CompCounterOprNum = 1;
11923 bool IsUpdatePriorComp;
11924 unsigned UpdateCounterOprNum;
11926 Update, UpdateCounterOprNum,
Init, IsUpdatePriorComp))
11929 return std::make_unique<AArch64PipelinerLoopInfo>(
11930 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
11940 TypeSize Scale(0U,
false), Width(0U,
false);
11941 int64_t MinOffset, MaxOffset;
11942 if (
getMemOpInfo(
MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
11944 if (
MI.getOperand(ImmIdx).isImm() && !
MI.getOperand(ImmIdx - 1).isFI()) {
11945 int64_t Imm =
MI.getOperand(ImmIdx).getImm();
11946 if (Imm < MinOffset || Imm > MaxOffset) {
11947 ErrInfo =
"Unexpected immediate on load/store instruction";
11953 const MCInstrDesc &MCID =
MI.getDesc();
11955 const MachineOperand &MO =
MI.getOperand(
Op);
11959 ErrInfo =
"OPERAND_IMPLICIT_IMM_0 should be 0";
11968 ErrInfo =
"OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
11979#define GET_INSTRINFO_HELPERS
11980#define GET_INSTRMAP_INFO
11981#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
static Register genNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned MnegOpc, const TargetRegisterClass *RC)
genNeg - Helper to generate an intermediate negation of the second operand of Root
static bool isFrameStoreOpcode(int Opcode)
static cl::opt< unsigned > GatherOptSearchLimit("aarch64-search-limit", cl::Hidden, cl::init(2048), cl::desc("Restrict range of instructions to search for the " "machine-combiner gather pattern optimization"))
static bool getMaddPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find instructions that can be turned into madd.
static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr)
Find a condition code used by the instruction.
static MachineInstr * genFusedMultiplyAcc(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyAcc - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genFusedMultiplyAccNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate64(unsigned Opc)
static bool isFrameLoadOpcode(int Opcode)
static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg)
static bool areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI, const AccessKind AccessToCheck=AK_All)
True when condition flags are accessed (either by writing or reading) on the instruction trace starti...
static bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Floating-Point Support.
static bool isADDSRegImm(unsigned Opcode)
static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI)
static bool isANDOpcode(MachineInstr &MI)
static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment, StringRef RegScale={})
static unsigned sForm(MachineInstr &Instr)
Get opcode of S version of Instr.
static bool isCombineInstrSettingFlag(unsigned Opc)
static bool getFNEGPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB, MachineInstr *&UpdateInst, unsigned &UpdateCounterOprNum, Register &InitReg, bool &IsUpdatePriorComp)
If Reg is an induction variable, return true and set some parameters.
static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc)
static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if in a streaming call site region without SME-FA64.
static bool isPostIndexLdStOpcode(unsigned Opcode)
Return true if the opcode is a post-index ld/st instruction, which really loads from base+0.
static std::optional< unsigned > getLFIInstSizeInBytes(const MachineInstr &MI)
Return the maximum number of bytes of code the specified instruction may be after LFI rewriting.
static unsigned getBranchDisplacementBits(unsigned Opc)
static cl::opt< unsigned > CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9), cl::desc("Restrict range of CB instructions (DEBUG)"))
static std::optional< ParamLoadedValue > describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
If the given ORR instruction is a copy, and DescribedReg overlaps with the destination register then,...
static bool getFMULPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static void appendReadRegExpr(SmallVectorImpl< char > &Expr, unsigned RegNum)
static MachineInstr * genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR, const TargetRegisterClass *RC)
genMaddR - Generate madd instruction and combine mul and add using an extra virtual register Example ...
static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum, Register ReplaceReg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertTo)
Clone an instruction from MI.
static bool scaleOffset(unsigned Opc, int64_t &Offset)
static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc)
unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale)
static MachineInstr * genFusedMultiplyIdx(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyIdx - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genIndexedMultiply(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxDupOp, unsigned MulOpc, const TargetRegisterClass *RC, MachineRegisterInfo &MRI)
Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
static bool isSUBSRegImm(unsigned Opcode)
static bool UpdateOperandRegClass(MachineInstr &Instr)
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool isInStreamingCallSiteRegion(MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if the instruction at I is in a streaming call site region, within a single basic block.
static bool canCmpInstrBeRemoved(MachineInstr &MI, MachineInstr &CmpInstr, int CmpValue, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > &CCUseInstrs, bool &IsInvertCC)
unsigned unscaledOffsetOpcode(unsigned Opcode)
static bool getLoadPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Search for patterns of LD instructions we can optimize.
static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI)
Check if CmpInstr can be substituted by MI.
static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC)
static bool isCombineInstrCandidateFP(const MachineInstr &Inst)
static void appendLoadRegExpr(SmallVectorImpl< char > &Expr, int64_t OffsetFromDefCFA)
static void appendConstantExpr(SmallVectorImpl< char > &Expr, int64_t Constant, dwarf::LocationAtom Operation)
static unsigned convertToNonFlagSettingOpc(const MachineInstr &MI)
Return the opcode that does not set flags when possible - otherwise return the original opcode.
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool isCombineInstrCandidate32(unsigned Opc)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
static unsigned offsetExtendOpcode(unsigned Opcode)
static void loadRegPairFromStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register DestReg, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
static void generateGatherLanePattern(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned Pattern, unsigned NumLanes)
Generate optimized instruction sequence for gather load patterns to improve Memory-Level Parallelism ...
static bool getMiscPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find other MI combine patterns.
static bool outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, RegState State, const TargetRegisterInfo *TRI)
static bool outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, int64_t Offset1, unsigned Opcode1, int FI2, int64_t Offset2, unsigned Opcode2)
static cl::opt< unsigned > TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14), cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"))
static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB, Register &RegMBB, Register &RegOther)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
static bool isDefinedOutside(Register Reg, const MachineBasicBlock *BB)
static MachineInstr * genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC, FMAInstKind kind=FMAInstKind::Default, const Register *ReplacedAddend=nullptr)
genFusedMultiply - Generate fused multiply instructions.
static bool getGatherLanePattern(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, unsigned LoadLaneOpCode, unsigned NumLanes)
Check if the given instruction forms a gather load pattern that can be optimized for better Memory-Le...
static MachineInstr * genFusedMultiplyIdxNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate(unsigned Opc)
static unsigned regOffsetOpcode(unsigned Opcode)
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
static cl::opt< unsigned > BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26), cl::desc("Restrict range of B instructions (DEBUG)"))
static bool areCFlagsAliveInSuccessors(const MachineBasicBlock *MBB)
Check if AArch64::NZCV should be alive in successors of MBB.
static void emitFrameOffsetAdj(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, int64_t Offset, unsigned Opc, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFAOffset, StackOffset CFAOffset, unsigned FrameReg)
static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize)
static cl::opt< unsigned > CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"))
static void genSubAdd2SubSub(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned IdxOpd1, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
Do the following transformation A - (B + C) ==> (A - B) - C A - (B + C) ==> (A - C) - B.
static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg, unsigned *NewReg=nullptr)
static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64InstrInfo *TII, bool ShouldSignReturnAddr)
static MachineInstr * genFNegatedMAD(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs)
static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc, unsigned ZeroReg)
static void storeRegPairToStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register SrcReg, bool IsKill, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool branchTargetEnforcement() const
unsigned getArgumentStackToRestore() const
SignReturnAddress getSignReturnAddressCondition() const
bool hasStreamingModeChanges() const
void setOutliningStyle(const std::string &Style)
bool branchProtectionPAuthLR() const
std::optional< bool > hasRedZone() const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
bool shouldSignWithBKey() const
static bool isHForm(const MachineInstr &MI)
Returns whether the instruction is in H form (16 bit operands)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
static bool hasBTISemantics(const MachineInstr &MI)
Returns whether the instruction can be compatible with non-zero BTYPE.
static bool isQForm(const MachineInstr &MI)
Returns whether the instruction is in Q form (128 bit operands)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static bool isFPRCopy(const MachineInstr &MI)
Does this instruction rename an FPR without modifying bits?
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
static bool isGPRCopy(const MachineInstr &MI)
Does this instruction rename a GPR without modifying bits?
static unsigned convertToFlagSettingOpc(unsigned Opc)
Return the opcode that set flags when possible.
void createPauthEpilogueInstr(MachineBasicBlock &MBB, DebugLoc DL) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
static const MachineOperand & getLdStOffsetOp(const MachineInstr &MI)
Returns the immediate offset operator of a load/store.
bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, Register &DstReg, unsigned &SubIdx) const override
static std::optional< unsigned > getUnscaledLdSt(unsigned Opc)
Returns the unscaled load/store for the scaled load/store opcode, if there is a corresponding unscale...
static bool hasUnscaledLdStOffset(unsigned Opc)
Return true if it has an unscaled load/store offset.
static const MachineOperand & getLdStAmountOp(const MachineInstr &MI)
Returns the shift amount operator of a load/store.
static bool isPreLdSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load/store.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI, const TargetRegisterInfo *TRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
bool analyzeBranchPredicate(MachineBasicBlock &MBB, MachineBranchPredicate &MBP, bool AllowModify) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
const AArch64RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
static bool isPreSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed store.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
AArch64InstrInfo(const AArch64Subtarget &STI)
static bool isPairedLdSt(const MachineInstr &MI)
Returns whether the instruction is a paired load/store.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width, const TargetRegisterInfo *TRI) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isStridedAccess(const MachineInstr &MI)
Return true if the given load or store is a strided memory access.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
Detect opportunities for ldp/stp formation.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isThroughputPattern(unsigned Pattern) const override
Return true when a code sequence can improve throughput.
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
static bool isLdStPairSuppressed(const MachineInstr &MI)
Return true if pairing the given load or store is hinted to be unprofitable.
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction supplying the argument to the comparison into one that...
static unsigned getLoadStoreImmIdx(unsigned Opc)
Returns the index for the immediate for a given instruction.
static bool isGPRZero(const MachineInstr &MI)
Does this instruction set its full destination register to zero?
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, unsigned ZeroReg, llvm::ArrayRef< unsigned > Indices) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2,...
CombinerObjective getCombinerObjective(unsigned Pattern) const override
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
bool isAsCheapAsAMove(const MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyLikeInstrImpl(const MachineInstr &MI) const override
static void suppressLdStPair(MachineInstr &MI)
Hint that pairing the given load or store is unprofitable.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isPreLd(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load.
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef< unsigned > Indices) const
bool optimizeCondBranch(MachineInstr &MI) const override
Replace csincr-branch sequence by simple conditional branch.
static int getMemScale(unsigned Opc)
Scaling factor for (scaled or unscaled) load or store.
bool isCandidateToMergeOrPair(const MachineInstr &MI) const
Return true if this is a load/store that can be potentially paired/merged.
MCInst getNop() const override
static const MachineOperand & getLdStBaseOp(const MachineInstr &MI)
Returns the base register operator of a load/store.
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
bool isSVEorStreamingSVEAvailable() const
Returns true if the target has access to either the full range of SVE instructions,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
This is an important base class in LLVM.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
static LocationSize precise(uint64_t Value)
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool usesWindowsCFI() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
static constexpr unsigned NoRegister
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
bool isInlineAsmBrIndirectTarget() const
Returns true if this is the indirect dest of an INLINEASM_BR.
unsigned pred_size() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
reverse_instr_iterator instr_rbegin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
instr_iterator instr_end()
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
void setStackID(int ObjectIdx, uint8_t ID)
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
bool isCall(QueryType Type=AnyInBundle) const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
LLVM_ABI uint32_t mergeFlagsWith(const MachineInstr &Other) const
Return the MIFlags which represent both MachineInstrs.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool registerDefIsDead(Register Reg, const TargetRegisterInfo *TRI) const
Returns true if the register is dead in this machine instruction.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
LLVM_ABI bool isLoadFoldBarrier() const
Returns true if it is illegal to fold a load across this instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
MI-level patchpoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents a location in source code.
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
int64_t getScalable() const
Returns the scalable component of the stack.
static StackOffset get(int64_t Fixed, int64_t Scalable)
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Value * getOperand(unsigned i) const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
self_iterator getIterator()
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_ARM64EC_CALLMANGLE
MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version of a symbol,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static const uint64_t InstrFlagIsWhile
static const uint64_t InstrFlagIsPTestLike
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ ScalablePredicateVector
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< InstrNode * > Instr
LLVM_ABI Instruction & back() const
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static bool isCondBranchOpcode(int Opc)
MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg, unsigned Reg, const StackOffset &Offset, bool LastAdjustmentWasScalable=true)
static bool isPTrueOpcode(unsigned Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool succeeded(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset, bool *OutUseUnscaledOp=nullptr, unsigned *OutUnscaledOp=nullptr, int64_t *EmittableOffset=nullptr)
Check if the Offset is a valid frame offset for MI.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static bool isIndirectBranchOpcode(int Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
@ AArch64FrameOffsetCannotUpdate
Offset cannot apply.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
static bool isSEHInstruction(const MachineInstr &MI)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
AArch64MachineCombinerPattern
@ MULSUBv2i32_indexed_OP1
@ MULADDv4i16_indexed_OP2
@ MULSUBv8i16_indexed_OP2
@ MULSUBv4i16_indexed_OP2
@ MULSUBv4i32_indexed_OP2
@ MULADDv2i32_indexed_OP1
@ MULADDv4i32_indexed_OP1
@ MULADDv2i32_indexed_OP2
@ MULSUBv4i16_indexed_OP1
@ MULADDv4i32_indexed_OP2
@ MULSUBv8i16_indexed_OP1
@ MULSUBv2i32_indexed_OP2
@ MULADDv8i16_indexed_OP1
@ MULSUBv4i32_indexed_OP1
@ MULADDv8i16_indexed_OP2
@ MULADDv4i16_indexed_OP1
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
static MCRegister getXRegFromWReg(MCRegister Reg)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, StackOffset &Offset, const AArch64InstrInfo *TII)
rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static const MachineMemOperand::Flags MOSuppressPair
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
bool optimizeTerminators(MachineBasicBlock *MBB, const TargetInstrInfo &TII)
std::pair< MachineOperand, DIExpression * > ParamLoadedValue
bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI, const MachineInstr &UseMI, const TargetRegisterInfo *TRI)
Return true if there is an instruction /after/ DefMI and before UseMI which either reads or clobbers ...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
static const MachineMemOperand::Flags MOStridedAccess
constexpr RegState getUndefRegState(bool B)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
LLVM_ABI static const MBBSectionID ColdSectionID
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.