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 TargetOpcode::BUNDLE:
240 NumBytes = getInstBundleSize(
MI);
276 case AArch64::CBWPri:
277 case AArch64::CBXPri:
278 case AArch64::CBWPrr:
279 case AArch64::CBXPrr:
287 case AArch64::CBBAssertExt:
288 case AArch64::CBHAssertExt:
319 case AArch64::CBWPri:
320 case AArch64::CBXPri:
321 case AArch64::CBBAssertExt:
322 case AArch64::CBHAssertExt:
323 case AArch64::CBWPrr:
324 case AArch64::CBXPrr:
330 int64_t BrOffset)
const {
332 assert(Bits >= 3 &&
"max branch displacement must be enough to jump"
333 "over conditional branch expansion");
334 return isIntN(Bits, BrOffset / 4);
339 switch (
MI.getOpcode()) {
343 return MI.getOperand(0).getMBB();
348 return MI.getOperand(2).getMBB();
354 return MI.getOperand(1).getMBB();
355 case AArch64::CBWPri:
356 case AArch64::CBXPri:
357 case AArch64::CBBAssertExt:
358 case AArch64::CBHAssertExt:
359 case AArch64::CBWPrr:
360 case AArch64::CBXPrr:
361 return MI.getOperand(3).getMBB();
371 assert(RS &&
"RegScavenger required for long branching");
373 "new block should be inserted for expanding unconditional branch");
376 "restore block should be inserted for restoring clobbered registers");
383 "Branch offsets outside of the signed 33-bit range not supported");
394 RS->enterBasicBlockEnd(
MBB);
397 constexpr Register Reg = AArch64::X16;
398 if (!RS->isRegUsed(Reg)) {
399 insertUnconditionalBranch(
MBB, &NewDestBB,
DL);
410 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
411 if (Scavenged != AArch64::NoRegister) {
412 buildIndirectBranch(Scavenged, NewDestBB);
413 RS->setRegUsed(Scavenged);
422 "Unable to insert indirect branch inside function that has red zone");
445 bool AllowModify)
const {
452 if (
I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
453 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
457 if (!isUnpredicatedTerminator(*
I))
464 unsigned LastOpc = LastInst->
getOpcode();
465 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
480 unsigned SecondLastOpc = SecondLastInst->
getOpcode();
487 LastInst = SecondLastInst;
489 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
494 SecondLastInst = &*
I;
495 SecondLastOpc = SecondLastInst->
getOpcode();
506 LastInst = SecondLastInst;
508 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
510 "unreachable unconditional branches removed above");
519 SecondLastInst = &*
I;
520 SecondLastOpc = SecondLastInst->
getOpcode();
524 if (SecondLastInst &&
I !=
MBB.begin() && isUnpredicatedTerminator(*--
I))
540 I->eraseFromParent();
549 I->eraseFromParent();
558 MachineBranchPredicate &MBP,
559 bool AllowModify)
const {
571 assert(MBP.TrueDest &&
"expected!");
572 MBP.FalseDest = FBB ? FBB :
MBB.getNextNode();
574 MBP.ConditionDef =
nullptr;
575 MBP.SingleUseCondition =
false;
585 if (
I ==
MBB.begin())
601 if (
MI.modifiesRegister(AArch64::NZCV,
nullptr)) {
602 MBP.ConditionDef = &
MI;
611 case AArch64::CBNZX: {
615 MBP.Predicate = (
Opc == AArch64::CBNZX ||
Opc == AArch64::CBNZW)
616 ? MachineBranchPredicate::PRED_NE
617 : MachineBranchPredicate::PRED_EQ;
618 Register CondReg = MBP.LHS.getReg();
627 case AArch64::TBNZX: {
648 Cond[1].setImm(AArch64::CBNZW);
651 Cond[1].setImm(AArch64::CBZW);
654 Cond[1].setImm(AArch64::CBNZX);
657 Cond[1].setImm(AArch64::CBZX);
660 Cond[1].setImm(AArch64::TBNZW);
663 Cond[1].setImm(AArch64::TBZW);
666 Cond[1].setImm(AArch64::TBNZX);
669 Cond[1].setImm(AArch64::TBZX);
673 case AArch64::CBWPri:
674 case AArch64::CBXPri:
675 case AArch64::CBBAssertExt:
676 case AArch64::CBHAssertExt:
677 case AArch64::CBWPrr:
678 case AArch64::CBXPrr: {
691 int *BytesRemoved)
const {
701 I->eraseFromParent();
705 if (
I ==
MBB.begin()) {
718 I->eraseFromParent();
725void AArch64InstrInfo::instantiateCondBranch(
750 if (
Cond.size() > 5) {
761 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
788 unsigned Opc =
MI.getOpcode();
795 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
796 MI.getOperand(0).getReg() == AArch64::XZR) {
798 dbgs() <<
"Removing always taken branch: " <<
MI);
801 for (
auto *S : Succs)
803 MBB->removeSuccessor(S);
805 while (
MBB->rbegin() != &
MI)
806 MBB->rbegin()->eraseFromParent();
807 MI.eraseFromParent();
817 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
818 MI.getOperand(0).getReg() == AArch64::XZR) {
820 dbgs() <<
"Removing never taken branch: " <<
MI);
822 MI.getParent()->removeSuccessor(
Target);
823 MI.eraseFromParent();
836 if (!
DefMI->isFullCopy())
838 VReg =
DefMI->getOperand(1).getReg();
847 unsigned *NewReg =
nullptr) {
852 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.
getRegClass(VReg));
856 switch (
DefMI->getOpcode()) {
857 case AArch64::SUBREG_TO_REG:
861 if (!
DefMI->getOperand(1).isReg())
863 if (!
DefMI->getOperand(2).isImm() ||
864 DefMI->getOperand(2).getImm() != AArch64::sub_32)
867 if (
DefMI->getOpcode() != AArch64::MOVi32imm)
869 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
872 SrcReg = AArch64::XZR;
873 Opc = AArch64::CSINCXr;
876 case AArch64::MOVi32imm:
877 case AArch64::MOVi64imm:
878 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
880 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
881 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
884 case AArch64::ADDSXri:
885 case AArch64::ADDSWri:
887 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
892 case AArch64::ADDXri:
893 case AArch64::ADDWri:
895 if (!
DefMI->getOperand(2).isImm() ||
DefMI->getOperand(2).getImm() != 1 ||
896 DefMI->getOperand(3).getImm() != 0)
898 SrcReg =
DefMI->getOperand(1).getReg();
899 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
902 case AArch64::ORNXrr:
903 case AArch64::ORNWrr: {
906 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
908 SrcReg =
DefMI->getOperand(2).getReg();
909 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
913 case AArch64::SUBSXrr:
914 case AArch64::SUBSWrr:
916 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
921 case AArch64::SUBXrr:
922 case AArch64::SUBWrr: {
925 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
927 SrcReg =
DefMI->getOperand(2).getReg();
928 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
934 assert(
Opc && SrcReg &&
"Missing parameters");
946 int &FalseCycles)
const {
957 if (!RI.getCommonSubClass(RC, MRI.
getRegClass(DstReg)))
961 unsigned ExtraCondLat =
Cond.size() != 1;
965 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
966 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
968 CondCycles = 1 + ExtraCondLat;
969 TrueCycles = FalseCycles = 1;
979 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
980 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
981 CondCycles = 5 + ExtraCondLat;
982 TrueCycles = FalseCycles = 2;
999 switch (
Cond.size()) {
1019 case AArch64::CBNZW:
1023 case AArch64::CBNZX:
1054 case AArch64::TBNZW:
1055 case AArch64::TBNZX:
1077 unsigned SubsOpc, SubsDestReg;
1083 case AArch64::CBWPri:
1084 SubsOpc = AArch64::SUBSWri;
1085 SubsDestReg = AArch64::WZR;
1088 case AArch64::CBXPri:
1089 SubsOpc = AArch64::SUBSXri;
1090 SubsDestReg = AArch64::XZR;
1093 case AArch64::CBWPrr:
1094 SubsOpc = AArch64::SUBSWrr;
1095 SubsDestReg = AArch64::WZR;
1098 case AArch64::CBXPrr:
1099 SubsOpc = AArch64::SUBSXrr;
1100 SubsDestReg = AArch64::XZR;
1129 switch (ExtendType) {
1135 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1136 ExtOpc = AArch64::SBFMWri;
1142 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1143 ExtOpc = AArch64::SBFMWri;
1149 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1150 ExtOpc = AArch64::ANDWri;
1156 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1157 ExtOpc = AArch64::ANDWri;
1166 if (ExtOpc != AArch64::ANDWri)
1168 MBBI.addImm(ExtBits);
1196 bool TryFold =
false;
1198 RC = &AArch64::GPR64RegClass;
1199 Opc = AArch64::CSELXr;
1202 RC = &AArch64::GPR32RegClass;
1203 Opc = AArch64::CSELWr;
1206 RC = &AArch64::FPR64RegClass;
1207 Opc = AArch64::FCSELDrrr;
1209 RC = &AArch64::FPR32RegClass;
1210 Opc = AArch64::FCSELSrrr;
1212 assert(RC &&
"Unsupported regclass");
1216 unsigned NewReg = 0;
1239 (FalseReg.
isVirtual() || FalseReg == AArch64::WZR ||
1240 FalseReg == AArch64::XZR) &&
1241 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1258 assert(BitSize == 64 &&
"Only bit sizes of 32 or 64 allowed");
1263 return Is.
size() <= 2;
1268 assert(
MI.isCopy() &&
"Expected COPY instruction");
1274 if (
Reg.isVirtual())
1276 if (
Reg.isPhysical())
1277 return RI.getMinimalPhysRegClass(
Reg);
1282 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1285 return MI.isAsCheapAsAMove();
1291 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1292 if (isExynosCheapAsMove(
MI))
1294 return MI.isAsCheapAsAMove();
1297 switch (
MI.getOpcode()) {
1299 return MI.isAsCheapAsAMove();
1301 case TargetOpcode::COPY:
1304 case AArch64::ADDWrs:
1305 case AArch64::ADDXrs:
1306 case AArch64::SUBWrs:
1307 case AArch64::SUBXrs:
1308 return Subtarget.hasALULSLFast() &&
MI.getOperand(3).getImm() <= 4;
1313 case AArch64::MOVi32imm:
1315 case AArch64::MOVi64imm:
1320bool AArch64InstrInfo::isFalkorShiftExtFast(
const MachineInstr &
MI) {
1321 switch (
MI.getOpcode()) {
1325 case AArch64::ADDWrs:
1326 case AArch64::ADDXrs:
1327 case AArch64::ADDSWrs:
1328 case AArch64::ADDSXrs: {
1329 unsigned Imm =
MI.getOperand(3).getImm();
1336 case AArch64::ADDWrx:
1337 case AArch64::ADDXrx:
1338 case AArch64::ADDXrx64:
1339 case AArch64::ADDSWrx:
1340 case AArch64::ADDSXrx:
1341 case AArch64::ADDSXrx64: {
1342 unsigned Imm =
MI.getOperand(3).getImm();
1354 case AArch64::SUBWrs:
1355 case AArch64::SUBSWrs: {
1356 unsigned Imm =
MI.getOperand(3).getImm();
1358 return ShiftVal == 0 ||
1362 case AArch64::SUBXrs:
1363 case AArch64::SUBSXrs: {
1364 unsigned Imm =
MI.getOperand(3).getImm();
1366 return ShiftVal == 0 ||
1370 case AArch64::SUBWrx:
1371 case AArch64::SUBXrx:
1372 case AArch64::SUBXrx64:
1373 case AArch64::SUBSWrx:
1374 case AArch64::SUBSXrx:
1375 case AArch64::SUBSXrx64: {
1376 unsigned Imm =
MI.getOperand(3).getImm();
1388 case AArch64::LDRBBroW:
1389 case AArch64::LDRBBroX:
1390 case AArch64::LDRBroW:
1391 case AArch64::LDRBroX:
1392 case AArch64::LDRDroW:
1393 case AArch64::LDRDroX:
1394 case AArch64::LDRHHroW:
1395 case AArch64::LDRHHroX:
1396 case AArch64::LDRHroW:
1397 case AArch64::LDRHroX:
1398 case AArch64::LDRQroW:
1399 case AArch64::LDRQroX:
1400 case AArch64::LDRSBWroW:
1401 case AArch64::LDRSBWroX:
1402 case AArch64::LDRSBXroW:
1403 case AArch64::LDRSBXroX:
1404 case AArch64::LDRSHWroW:
1405 case AArch64::LDRSHWroX:
1406 case AArch64::LDRSHXroW:
1407 case AArch64::LDRSHXroX:
1408 case AArch64::LDRSWroW:
1409 case AArch64::LDRSWroX:
1410 case AArch64::LDRSroW:
1411 case AArch64::LDRSroX:
1412 case AArch64::LDRWroW:
1413 case AArch64::LDRWroX:
1414 case AArch64::LDRXroW:
1415 case AArch64::LDRXroX:
1416 case AArch64::PRFMroW:
1417 case AArch64::PRFMroX:
1418 case AArch64::STRBBroW:
1419 case AArch64::STRBBroX:
1420 case AArch64::STRBroW:
1421 case AArch64::STRBroX:
1422 case AArch64::STRDroW:
1423 case AArch64::STRDroX:
1424 case AArch64::STRHHroW:
1425 case AArch64::STRHHroX:
1426 case AArch64::STRHroW:
1427 case AArch64::STRHroX:
1428 case AArch64::STRQroW:
1429 case AArch64::STRQroX:
1430 case AArch64::STRSroW:
1431 case AArch64::STRSroX:
1432 case AArch64::STRWroW:
1433 case AArch64::STRWroX:
1434 case AArch64::STRXroW:
1435 case AArch64::STRXroX: {
1436 unsigned IsSigned =
MI.getOperand(3).getImm();
1443 unsigned Opc =
MI.getOpcode();
1447 case AArch64::SEH_StackAlloc:
1448 case AArch64::SEH_SaveFPLR:
1449 case AArch64::SEH_SaveFPLR_X:
1450 case AArch64::SEH_SaveReg:
1451 case AArch64::SEH_SaveReg_X:
1452 case AArch64::SEH_SaveRegP:
1453 case AArch64::SEH_SaveRegP_X:
1454 case AArch64::SEH_SaveFReg:
1455 case AArch64::SEH_SaveFReg_X:
1456 case AArch64::SEH_SaveFRegP:
1457 case AArch64::SEH_SaveFRegP_X:
1458 case AArch64::SEH_SetFP:
1459 case AArch64::SEH_AddFP:
1460 case AArch64::SEH_Nop:
1461 case AArch64::SEH_PrologEnd:
1462 case AArch64::SEH_EpilogStart:
1463 case AArch64::SEH_EpilogEnd:
1464 case AArch64::SEH_PACSignLR:
1465 case AArch64::SEH_SaveAnyRegI:
1466 case AArch64::SEH_SaveAnyRegIP:
1467 case AArch64::SEH_SaveAnyRegQP:
1468 case AArch64::SEH_SaveAnyRegQPX:
1469 case AArch64::SEH_AllocZ:
1470 case AArch64::SEH_SaveZReg:
1471 case AArch64::SEH_SavePReg:
1478 unsigned &SubIdx)
const {
1479 switch (
MI.getOpcode()) {
1482 case AArch64::SBFMXri:
1483 case AArch64::UBFMXri:
1486 if (
MI.getOperand(2).getImm() != 0 ||
MI.getOperand(3).getImm() != 31)
1489 SrcReg =
MI.getOperand(1).getReg();
1490 DstReg =
MI.getOperand(0).getReg();
1491 SubIdx = AArch64::sub_32;
1500 int64_t OffsetA = 0, OffsetB = 0;
1501 TypeSize WidthA(0,
false), WidthB(0,
false);
1502 bool OffsetAIsScalable =
false, OffsetBIsScalable =
false;
1523 OffsetAIsScalable == OffsetBIsScalable) {
1524 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1525 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1526 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1527 if (LowWidth.
isScalable() == OffsetAIsScalable &&
1545 switch (
MI.getOpcode()) {
1548 if (
MI.getOperand(0).getImm() == 0x14)
1555 case AArch64::MSRpstatesvcrImm1:
1562 auto Next = std::next(
MI.getIterator());
1563 return Next !=
MBB->end() &&
Next->isCFIInstruction();
1570 Register &SrcReg2, int64_t &CmpMask,
1571 int64_t &CmpValue)
const {
1575 assert(
MI.getNumOperands() >= 2 &&
"All AArch64 cmps should have 2 operands");
1576 if (!
MI.getOperand(1).isReg() ||
MI.getOperand(1).getSubReg())
1579 switch (
MI.getOpcode()) {
1582 case AArch64::PTEST_PP:
1583 case AArch64::PTEST_PP_ANY:
1584 case AArch64::PTEST_PP_FIRST:
1585 SrcReg =
MI.getOperand(0).getReg();
1586 SrcReg2 =
MI.getOperand(1).getReg();
1587 if (
MI.getOperand(2).getSubReg())
1594 case AArch64::SUBSWrr:
1595 case AArch64::SUBSWrs:
1596 case AArch64::SUBSWrx:
1597 case AArch64::SUBSXrr:
1598 case AArch64::SUBSXrs:
1599 case AArch64::SUBSXrx:
1600 case AArch64::ADDSWrr:
1601 case AArch64::ADDSWrs:
1602 case AArch64::ADDSWrx:
1603 case AArch64::ADDSXrr:
1604 case AArch64::ADDSXrs:
1605 case AArch64::ADDSXrx:
1607 SrcReg =
MI.getOperand(1).getReg();
1608 SrcReg2 =
MI.getOperand(2).getReg();
1611 if (
MI.getOperand(2).getSubReg())
1617 case AArch64::SUBSWri:
1618 case AArch64::ADDSWri:
1619 case AArch64::SUBSXri:
1620 case AArch64::ADDSXri:
1621 SrcReg =
MI.getOperand(1).getReg();
1624 CmpValue =
MI.getOperand(2).getImm();
1626 case AArch64::ANDSWri:
1627 case AArch64::ANDSXri:
1630 SrcReg =
MI.getOperand(1).getReg();
1634 MI.getOperand(2).getImm(),
1635 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1644 assert(
MBB &&
"Can't get MachineBasicBlock here");
1646 assert(MF &&
"Can't get MachineFunction here");
1651 for (
unsigned OpIdx = 0, EndIdx = Instr.getNumOperands();
OpIdx < EndIdx;
1658 if (!OpRegCstraints)
1666 "Operand has register constraints without being a register!");
1669 if (
Reg.isPhysical()) {
1686 bool MIDefinesZeroReg =
false;
1687 if (
MI.definesRegister(AArch64::WZR,
nullptr) ||
1688 MI.definesRegister(AArch64::XZR,
nullptr))
1689 MIDefinesZeroReg =
true;
1691 switch (
MI.getOpcode()) {
1693 return MI.getOpcode();
1694 case AArch64::ADDSWrr:
1695 return AArch64::ADDWrr;
1696 case AArch64::ADDSWri:
1697 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1698 case AArch64::ADDSWrs:
1699 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1700 case AArch64::ADDSWrx:
1701 return AArch64::ADDWrx;
1702 case AArch64::ADDSXrr:
1703 return AArch64::ADDXrr;
1704 case AArch64::ADDSXri:
1705 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1706 case AArch64::ADDSXrs:
1707 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1708 case AArch64::ADDSXrx:
1709 return AArch64::ADDXrx;
1710 case AArch64::SUBSWrr:
1711 return AArch64::SUBWrr;
1712 case AArch64::SUBSWri:
1713 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1714 case AArch64::SUBSWrs:
1715 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1716 case AArch64::SUBSWrx:
1717 return AArch64::SUBWrx;
1718 case AArch64::SUBSXrr:
1719 return AArch64::SUBXrr;
1720 case AArch64::SUBSXri:
1721 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1722 case AArch64::SUBSXrs:
1723 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1724 case AArch64::SUBSXrx:
1725 return AArch64::SUBXrx;
1740 if (To == To->getParent()->begin())
1745 if (To->getParent() != From->getParent())
1757 Instr.modifiesRegister(AArch64::NZCV,
TRI)) ||
1758 ((AccessToCheck &
AK_Read) && Instr.readsRegister(AArch64::NZCV,
TRI)))
1764std::optional<unsigned>
1768 unsigned MaskOpcode =
Mask->getOpcode();
1769 unsigned PredOpcode = Pred->
getOpcode();
1770 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1771 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1773 if (PredIsWhileLike) {
1777 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1784 getElementSizeForOpcode(MaskOpcode) ==
1785 getElementSizeForOpcode(PredOpcode))
1791 if (PTest->
getOpcode() == AArch64::PTEST_PP_FIRST &&
1798 if (PredIsPTestLike) {
1803 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1811 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1812 PTestLikeMask->getOperand(1).getReg().isVirtual())
1820 getElementSizeForOpcode(MaskOpcode) ==
1821 getElementSizeForOpcode(PredOpcode)) {
1822 if (Mask == PTestLikeMask || PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1848 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1850 PTest->
getOpcode() == AArch64::PTEST_PP_ANY))
1858 switch (PredOpcode) {
1859 case AArch64::AND_PPzPP:
1860 case AArch64::BIC_PPzPP:
1861 case AArch64::EOR_PPzPP:
1862 case AArch64::NAND_PPzPP:
1863 case AArch64::NOR_PPzPP:
1864 case AArch64::ORN_PPzPP:
1865 case AArch64::ORR_PPzPP:
1866 case AArch64::BRKA_PPzP:
1867 case AArch64::BRKPA_PPzPP:
1868 case AArch64::BRKB_PPzP:
1869 case AArch64::BRKPB_PPzPP:
1870 case AArch64::RDFFR_PPz: {
1874 if (Mask != PredMask)
1878 case AArch64::BRKN_PPzP: {
1882 if ((MaskOpcode != AArch64::PTRUE_B) ||
1883 (
Mask->getOperand(1).getImm() != 31))
1887 case AArch64::PTRUE_B:
1900bool AArch64InstrInfo::optimizePTestInstr(
1901 MachineInstr *PTest,
unsigned MaskReg,
unsigned PredReg,
1906 if (Pred->
isCopy() && PTest->
getOpcode() == AArch64::PTEST_PP_FIRST) {
1910 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
1911 Op.getSubReg() == AArch64::psub0)
1915 unsigned PredOpcode = Pred->
getOpcode();
1916 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
1932 if (*NewOp != PredOpcode) {
1943 for (; i !=
e; ++i) {
1974 if (DeadNZCVIdx != -1) {
1993 if (CmpInstr.
getOpcode() == AArch64::PTEST_PP ||
1994 CmpInstr.
getOpcode() == AArch64::PTEST_PP_ANY ||
1995 CmpInstr.
getOpcode() == AArch64::PTEST_PP_FIRST)
1996 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2005 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2007 return (CmpValue == 0 || CmpValue == 1) &&
2008 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2016 switch (Instr.getOpcode()) {
2018 return AArch64::INSTRUCTION_LIST_END;
2020 case AArch64::ADDSWrr:
2021 case AArch64::ADDSWri:
2022 case AArch64::ADDSXrr:
2023 case AArch64::ADDSXri:
2024 case AArch64::ADDSWrx:
2025 case AArch64::ADDSXrx:
2026 case AArch64::SUBSWrr:
2027 case AArch64::SUBSWri:
2028 case AArch64::SUBSWrx:
2029 case AArch64::SUBSXrr:
2030 case AArch64::SUBSXri:
2031 case AArch64::SUBSXrx:
2032 case AArch64::ANDSWri:
2033 case AArch64::ANDSWrr:
2034 case AArch64::ANDSWrs:
2035 case AArch64::ANDSXri:
2036 case AArch64::ANDSXrr:
2037 case AArch64::ANDSXrs:
2038 case AArch64::BICSWrr:
2039 case AArch64::BICSXrr:
2040 case AArch64::BICSWrs:
2041 case AArch64::BICSXrs:
2042 return Instr.getOpcode();
2044 case AArch64::ADDWrr:
2045 return AArch64::ADDSWrr;
2046 case AArch64::ADDWri:
2047 return AArch64::ADDSWri;
2048 case AArch64::ADDXrr:
2049 return AArch64::ADDSXrr;
2050 case AArch64::ADDXri:
2051 return AArch64::ADDSXri;
2052 case AArch64::ADDWrx:
2053 return AArch64::ADDSWrx;
2054 case AArch64::ADDXrx:
2055 return AArch64::ADDSXrx;
2056 case AArch64::ADCWr:
2057 return AArch64::ADCSWr;
2058 case AArch64::ADCXr:
2059 return AArch64::ADCSXr;
2060 case AArch64::SUBWrr:
2061 return AArch64::SUBSWrr;
2062 case AArch64::SUBWri:
2063 return AArch64::SUBSWri;
2064 case AArch64::SUBXrr:
2065 return AArch64::SUBSXrr;
2066 case AArch64::SUBXri:
2067 return AArch64::SUBSXri;
2068 case AArch64::SUBWrx:
2069 return AArch64::SUBSWrx;
2070 case AArch64::SUBXrx:
2071 return AArch64::SUBSXrx;
2072 case AArch64::SBCWr:
2073 return AArch64::SBCSWr;
2074 case AArch64::SBCXr:
2075 return AArch64::SBCSXr;
2076 case AArch64::ANDWri:
2077 return AArch64::ANDSWri;
2078 case AArch64::ANDXri:
2079 return AArch64::ANDSXri;
2080 case AArch64::ANDWrr:
2081 return AArch64::ANDSWrr;
2082 case AArch64::ANDWrs:
2083 return AArch64::ANDSWrs;
2084 case AArch64::ANDXrr:
2085 return AArch64::ANDSXrr;
2086 case AArch64::ANDXrs:
2087 return AArch64::ANDSXrs;
2088 case AArch64::BICWrr:
2089 return AArch64::BICSWrr;
2090 case AArch64::BICXrr:
2091 return AArch64::BICSXrr;
2092 case AArch64::BICWrs:
2093 return AArch64::BICSWrs;
2094 case AArch64::BICXrs:
2095 return AArch64::BICSXrs;
2101 for (
auto *BB :
MBB->successors())
2102 if (BB->isLiveIn(AArch64::NZCV))
2109int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2111 switch (
Instr.getOpcode()) {
2115 case AArch64::Bcc: {
2116 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2121 case AArch64::CSINVWr:
2122 case AArch64::CSINVXr:
2123 case AArch64::CSINCWr:
2124 case AArch64::CSINCXr:
2125 case AArch64::CSELWr:
2126 case AArch64::CSELXr:
2127 case AArch64::CSNEGWr:
2128 case AArch64::CSNEGXr:
2129 case AArch64::FCSELSrrr:
2130 case AArch64::FCSELDrrr: {
2131 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2143 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2145 Instr.getOperand(CCIdx).
getImm())
2198std::optional<UsedNZCV>
2203 if (
MI.getParent() != CmpParent)
2204 return std::nullopt;
2207 return std::nullopt;
2212 if (Instr.readsRegister(AArch64::NZCV, &
TRI)) {
2215 return std::nullopt;
2220 if (Instr.modifiesRegister(AArch64::NZCV, &
TRI))
2223 return NZCVUsedAfterCmp;
2227 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2231 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2237 case AArch64::ANDSWri:
2238 case AArch64::ANDSWrr:
2239 case AArch64::ANDSWrs:
2240 case AArch64::ANDSXri:
2241 case AArch64::ANDSXrr:
2242 case AArch64::ANDSXrs:
2243 case AArch64::BICSWrr:
2244 case AArch64::BICSXrr:
2245 case AArch64::BICSWrs:
2246 case AArch64::BICSXrs:
2272 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2278 "Caller guarantees that CmpInstr compares with constant 0");
2281 if (!NZVCUsed || NZVCUsed->C)
2304bool AArch64InstrInfo::substituteCmpToZero(
2315 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2322 MI->setDesc(
get(NewOpc));
2327 MI->addRegisterDefined(AArch64::NZCV, &
TRI);
2339 assert((CmpValue == 0 || CmpValue == 1) &&
2340 "Only comparisons to 0 or 1 considered for removal!");
2343 unsigned MIOpc =
MI.getOpcode();
2344 if (MIOpc == AArch64::CSINCWr) {
2345 if (
MI.getOperand(1).getReg() != AArch64::WZR ||
2346 MI.getOperand(2).getReg() != AArch64::WZR)
2348 }
else if (MIOpc == AArch64::CSINCXr) {
2349 if (
MI.getOperand(1).getReg() != AArch64::XZR ||
2350 MI.getOperand(2).getReg() != AArch64::XZR)
2360 if (
MI.findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) != -1)
2364 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2366 if (CmpValue && !IsSubsRegImm)
2368 if (!CmpValue && !IsSubsRegImm && !
isADDSRegImm(CmpOpcode))
2373 if (MIUsedNZCV.
C || MIUsedNZCV.
V)
2376 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2380 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2383 if ((MIUsedNZCV.
Z && NZCVUsedAfterCmp->N) ||
2384 (MIUsedNZCV.
N && NZCVUsedAfterCmp->Z))
2387 if (MIUsedNZCV.
N && !CmpValue)
2429bool AArch64InstrInfo::removeCmpToZeroOrOne(
2436 SmallVector<MachineInstr *, 4> CCUseInstrs;
2437 bool IsInvertCC =
false;
2445 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2446 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2447 assert(Idx >= 0 &&
"Unexpected instruction using CC.");
2448 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2457bool AArch64InstrInfo::expandPostRAPseudo(
MachineInstr &
MI)
const {
2458 if (
MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2459 MI.getOpcode() != AArch64::CATCHRET)
2462 MachineBasicBlock &
MBB = *
MI.getParent();
2464 auto TRI = Subtarget.getRegisterInfo();
2467 if (
MI.getOpcode() == AArch64::CATCHRET) {
2469 const TargetInstrInfo *
TII =
2471 MachineBasicBlock *TargetMBB =
MI.getOperand(0).getMBB();
2476 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2478 FirstEpilogSEH = std::next(FirstEpilogSEH);
2493 if (
M.getStackProtectorGuard() ==
"sysreg") {
2494 const AArch64SysReg::SysReg *SrcReg =
2495 AArch64SysReg::lookupSysRegByName(
M.getStackProtectorGuardReg());
2503 int Offset =
M.getStackProtectorGuardOffset();
2554 const GlobalValue *GV =
2557 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2563 if (Subtarget.isTargetILP32()) {
2564 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2578 assert(!Subtarget.isTargetILP32() &&
"how can large exist in ILP32?");
2605 if (Subtarget.isTargetILP32()) {
2606 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2629 switch (
MI.getOpcode()) {
2632 case AArch64::MOVZWi:
2633 case AArch64::MOVZXi:
2634 if (
MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0) {
2635 assert(
MI.getDesc().getNumOperands() == 3 &&
2636 MI.getOperand(2).getImm() == 0 &&
"invalid MOVZi operands");
2640 case AArch64::ANDWri:
2641 return MI.getOperand(1).getReg() == AArch64::WZR;
2642 case AArch64::ANDXri:
2643 return MI.getOperand(1).getReg() == AArch64::XZR;
2644 case TargetOpcode::COPY:
2645 return MI.getOperand(1).getReg() == AArch64::WZR;
2653 switch (
MI.getOpcode()) {
2656 case TargetOpcode::COPY: {
2659 return (AArch64::GPR32RegClass.
contains(DstReg) ||
2660 AArch64::GPR64RegClass.
contains(DstReg));
2662 case AArch64::ORRXrs:
2663 if (
MI.getOperand(1).getReg() == AArch64::XZR) {
2664 assert(
MI.getDesc().getNumOperands() == 4 &&
2665 MI.getOperand(3).getImm() == 0 &&
"invalid ORRrs operands");
2669 case AArch64::ADDXri:
2670 if (
MI.getOperand(2).getImm() == 0) {
2671 assert(
MI.getDesc().getNumOperands() == 4 &&
2672 MI.getOperand(3).getImm() == 0 &&
"invalid ADDXri operands");
2683 switch (
MI.getOpcode()) {
2686 case TargetOpcode::COPY: {
2688 return AArch64::FPR128RegClass.contains(DstReg);
2690 case AArch64::ORRv16i8:
2691 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
2692 assert(
MI.getDesc().getNumOperands() == 3 &&
MI.getOperand(0).isReg() &&
2693 "invalid ORRv16i8 operands");
2705 case AArch64::LDRWui:
2706 case AArch64::LDRXui:
2707 case AArch64::LDRBui:
2708 case AArch64::LDRHui:
2709 case AArch64::LDRSui:
2710 case AArch64::LDRDui:
2711 case AArch64::LDRQui:
2712 case AArch64::LDR_PXI:
2718 int &FrameIndex)
const {
2722 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2723 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2724 FrameIndex =
MI.getOperand(1).getIndex();
2725 return MI.getOperand(0).getReg();
2734 case AArch64::STRWui:
2735 case AArch64::STRXui:
2736 case AArch64::STRBui:
2737 case AArch64::STRHui:
2738 case AArch64::STRSui:
2739 case AArch64::STRDui:
2740 case AArch64::STRQui:
2741 case AArch64::STR_PXI:
2747 int &FrameIndex)
const {
2751 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2752 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2753 FrameIndex =
MI.getOperand(1).getIndex();
2754 return MI.getOperand(0).getReg();
2760 int &FrameIndex)
const {
2775 return MI.getOperand(0).getReg();
2781 int &FrameIndex)
const {
2796 return MI.getOperand(0).getReg();
2804 return MMO->getFlags() & MOSuppressPair;
2810 if (
MI.memoperands_empty())
2818 return MMO->getFlags() & MOStridedAccess;
2826 case AArch64::STURSi:
2827 case AArch64::STRSpre:
2828 case AArch64::STURDi:
2829 case AArch64::STRDpre:
2830 case AArch64::STURQi:
2831 case AArch64::STRQpre:
2832 case AArch64::STURBBi:
2833 case AArch64::STURHHi:
2834 case AArch64::STURWi:
2835 case AArch64::STRWpre:
2836 case AArch64::STURXi:
2837 case AArch64::STRXpre:
2838 case AArch64::LDURSi:
2839 case AArch64::LDRSpre:
2840 case AArch64::LDURDi:
2841 case AArch64::LDRDpre:
2842 case AArch64::LDURQi:
2843 case AArch64::LDRQpre:
2844 case AArch64::LDURWi:
2845 case AArch64::LDRWpre:
2846 case AArch64::LDURXi:
2847 case AArch64::LDRXpre:
2848 case AArch64::LDRSWpre:
2849 case AArch64::LDURSWi:
2850 case AArch64::LDURHHi:
2851 case AArch64::LDURBBi:
2852 case AArch64::LDURSBWi:
2853 case AArch64::LDURSHWi:
2861 case AArch64::PRFMui:
return AArch64::PRFUMi;
2862 case AArch64::LDRXui:
return AArch64::LDURXi;
2863 case AArch64::LDRWui:
return AArch64::LDURWi;
2864 case AArch64::LDRBui:
return AArch64::LDURBi;
2865 case AArch64::LDRHui:
return AArch64::LDURHi;
2866 case AArch64::LDRSui:
return AArch64::LDURSi;
2867 case AArch64::LDRDui:
return AArch64::LDURDi;
2868 case AArch64::LDRQui:
return AArch64::LDURQi;
2869 case AArch64::LDRBBui:
return AArch64::LDURBBi;
2870 case AArch64::LDRHHui:
return AArch64::LDURHHi;
2871 case AArch64::LDRSBXui:
return AArch64::LDURSBXi;
2872 case AArch64::LDRSBWui:
return AArch64::LDURSBWi;
2873 case AArch64::LDRSHXui:
return AArch64::LDURSHXi;
2874 case AArch64::LDRSHWui:
return AArch64::LDURSHWi;
2875 case AArch64::LDRSWui:
return AArch64::LDURSWi;
2876 case AArch64::STRXui:
return AArch64::STURXi;
2877 case AArch64::STRWui:
return AArch64::STURWi;
2878 case AArch64::STRBui:
return AArch64::STURBi;
2879 case AArch64::STRHui:
return AArch64::STURHi;
2880 case AArch64::STRSui:
return AArch64::STURSi;
2881 case AArch64::STRDui:
return AArch64::STURDi;
2882 case AArch64::STRQui:
return AArch64::STURQi;
2883 case AArch64::STRBBui:
return AArch64::STURBBi;
2884 case AArch64::STRHHui:
return AArch64::STURHHi;
2893 case AArch64::LDAPURBi:
2894 case AArch64::LDAPURHi:
2895 case AArch64::LDAPURi:
2896 case AArch64::LDAPURSBWi:
2897 case AArch64::LDAPURSBXi:
2898 case AArch64::LDAPURSHWi:
2899 case AArch64::LDAPURSHXi:
2900 case AArch64::LDAPURSWi:
2901 case AArch64::LDAPURXi:
2902 case AArch64::LDR_PPXI:
2903 case AArch64::LDR_PXI:
2904 case AArch64::LDR_ZXI:
2905 case AArch64::LDR_ZZXI:
2906 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
2907 case AArch64::LDR_ZZZXI:
2908 case AArch64::LDR_ZZZZXI:
2909 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
2910 case AArch64::LDRBBui:
2911 case AArch64::LDRBui:
2912 case AArch64::LDRDui:
2913 case AArch64::LDRHHui:
2914 case AArch64::LDRHui:
2915 case AArch64::LDRQui:
2916 case AArch64::LDRSBWui:
2917 case AArch64::LDRSBXui:
2918 case AArch64::LDRSHWui:
2919 case AArch64::LDRSHXui:
2920 case AArch64::LDRSui:
2921 case AArch64::LDRSWui:
2922 case AArch64::LDRWui:
2923 case AArch64::LDRXui:
2924 case AArch64::LDURBBi:
2925 case AArch64::LDURBi:
2926 case AArch64::LDURDi:
2927 case AArch64::LDURHHi:
2928 case AArch64::LDURHi:
2929 case AArch64::LDURQi:
2930 case AArch64::LDURSBWi:
2931 case AArch64::LDURSBXi:
2932 case AArch64::LDURSHWi:
2933 case AArch64::LDURSHXi:
2934 case AArch64::LDURSi:
2935 case AArch64::LDURSWi:
2936 case AArch64::LDURWi:
2937 case AArch64::LDURXi:
2938 case AArch64::PRFMui:
2939 case AArch64::PRFUMi:
2940 case AArch64::ST2Gi:
2942 case AArch64::STLURBi:
2943 case AArch64::STLURHi:
2944 case AArch64::STLURWi:
2945 case AArch64::STLURXi:
2946 case AArch64::StoreSwiftAsyncContext:
2947 case AArch64::STR_PPXI:
2948 case AArch64::STR_PXI:
2949 case AArch64::STR_ZXI:
2950 case AArch64::STR_ZZXI:
2951 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
2952 case AArch64::STR_ZZZXI:
2953 case AArch64::STR_ZZZZXI:
2954 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
2955 case AArch64::STRBBui:
2956 case AArch64::STRBui:
2957 case AArch64::STRDui:
2958 case AArch64::STRHHui:
2959 case AArch64::STRHui:
2960 case AArch64::STRQui:
2961 case AArch64::STRSui:
2962 case AArch64::STRWui:
2963 case AArch64::STRXui:
2964 case AArch64::STURBBi:
2965 case AArch64::STURBi:
2966 case AArch64::STURDi:
2967 case AArch64::STURHHi:
2968 case AArch64::STURHi:
2969 case AArch64::STURQi:
2970 case AArch64::STURSi:
2971 case AArch64::STURWi:
2972 case AArch64::STURXi:
2973 case AArch64::STZ2Gi:
2974 case AArch64::STZGi:
2975 case AArch64::TAGPstack:
2977 case AArch64::LD1B_D_IMM:
2978 case AArch64::LD1B_H_IMM:
2979 case AArch64::LD1B_IMM:
2980 case AArch64::LD1B_S_IMM:
2981 case AArch64::LD1D_IMM:
2982 case AArch64::LD1H_D_IMM:
2983 case AArch64::LD1H_IMM:
2984 case AArch64::LD1H_S_IMM:
2985 case AArch64::LD1RB_D_IMM:
2986 case AArch64::LD1RB_H_IMM:
2987 case AArch64::LD1RB_IMM:
2988 case AArch64::LD1RB_S_IMM:
2989 case AArch64::LD1RD_IMM:
2990 case AArch64::LD1RH_D_IMM:
2991 case AArch64::LD1RH_IMM:
2992 case AArch64::LD1RH_S_IMM:
2993 case AArch64::LD1RSB_D_IMM:
2994 case AArch64::LD1RSB_H_IMM:
2995 case AArch64::LD1RSB_S_IMM:
2996 case AArch64::LD1RSH_D_IMM:
2997 case AArch64::LD1RSH_S_IMM:
2998 case AArch64::LD1RSW_IMM:
2999 case AArch64::LD1RW_D_IMM:
3000 case AArch64::LD1RW_IMM:
3001 case AArch64::LD1SB_D_IMM:
3002 case AArch64::LD1SB_H_IMM:
3003 case AArch64::LD1SB_S_IMM:
3004 case AArch64::LD1SH_D_IMM:
3005 case AArch64::LD1SH_S_IMM:
3006 case AArch64::LD1SW_D_IMM:
3007 case AArch64::LD1W_D_IMM:
3008 case AArch64::LD1W_IMM:
3009 case AArch64::LD2B_IMM:
3010 case AArch64::LD2D_IMM:
3011 case AArch64::LD2H_IMM:
3012 case AArch64::LD2W_IMM:
3013 case AArch64::LD3B_IMM:
3014 case AArch64::LD3D_IMM:
3015 case AArch64::LD3H_IMM:
3016 case AArch64::LD3W_IMM:
3017 case AArch64::LD4B_IMM:
3018 case AArch64::LD4D_IMM:
3019 case AArch64::LD4H_IMM:
3020 case AArch64::LD4W_IMM:
3022 case AArch64::LDNF1B_D_IMM:
3023 case AArch64::LDNF1B_H_IMM:
3024 case AArch64::LDNF1B_IMM:
3025 case AArch64::LDNF1B_S_IMM:
3026 case AArch64::LDNF1D_IMM:
3027 case AArch64::LDNF1H_D_IMM:
3028 case AArch64::LDNF1H_IMM:
3029 case AArch64::LDNF1H_S_IMM:
3030 case AArch64::LDNF1SB_D_IMM:
3031 case AArch64::LDNF1SB_H_IMM:
3032 case AArch64::LDNF1SB_S_IMM:
3033 case AArch64::LDNF1SH_D_IMM:
3034 case AArch64::LDNF1SH_S_IMM:
3035 case AArch64::LDNF1SW_D_IMM:
3036 case AArch64::LDNF1W_D_IMM:
3037 case AArch64::LDNF1W_IMM:
3038 case AArch64::LDNPDi:
3039 case AArch64::LDNPQi:
3040 case AArch64::LDNPSi:
3041 case AArch64::LDNPWi:
3042 case AArch64::LDNPXi:
3043 case AArch64::LDNT1B_ZRI:
3044 case AArch64::LDNT1D_ZRI:
3045 case AArch64::LDNT1H_ZRI:
3046 case AArch64::LDNT1W_ZRI:
3047 case AArch64::LDPDi:
3048 case AArch64::LDPQi:
3049 case AArch64::LDPSi:
3050 case AArch64::LDPWi:
3051 case AArch64::LDPXi:
3052 case AArch64::LDRBBpost:
3053 case AArch64::LDRBBpre:
3054 case AArch64::LDRBpost:
3055 case AArch64::LDRBpre:
3056 case AArch64::LDRDpost:
3057 case AArch64::LDRDpre:
3058 case AArch64::LDRHHpost:
3059 case AArch64::LDRHHpre:
3060 case AArch64::LDRHpost:
3061 case AArch64::LDRHpre:
3062 case AArch64::LDRQpost:
3063 case AArch64::LDRQpre:
3064 case AArch64::LDRSpost:
3065 case AArch64::LDRSpre:
3066 case AArch64::LDRWpost:
3067 case AArch64::LDRWpre:
3068 case AArch64::LDRXpost:
3069 case AArch64::LDRXpre:
3070 case AArch64::ST1B_D_IMM:
3071 case AArch64::ST1B_H_IMM:
3072 case AArch64::ST1B_IMM:
3073 case AArch64::ST1B_S_IMM:
3074 case AArch64::ST1D_IMM:
3075 case AArch64::ST1H_D_IMM:
3076 case AArch64::ST1H_IMM:
3077 case AArch64::ST1H_S_IMM:
3078 case AArch64::ST1W_D_IMM:
3079 case AArch64::ST1W_IMM:
3080 case AArch64::ST2B_IMM:
3081 case AArch64::ST2D_IMM:
3082 case AArch64::ST2H_IMM:
3083 case AArch64::ST2W_IMM:
3084 case AArch64::ST3B_IMM:
3085 case AArch64::ST3D_IMM:
3086 case AArch64::ST3H_IMM:
3087 case AArch64::ST3W_IMM:
3088 case AArch64::ST4B_IMM:
3089 case AArch64::ST4D_IMM:
3090 case AArch64::ST4H_IMM:
3091 case AArch64::ST4W_IMM:
3092 case AArch64::STGPi:
3093 case AArch64::STGPreIndex:
3094 case AArch64::STZGPreIndex:
3095 case AArch64::ST2GPreIndex:
3096 case AArch64::STZ2GPreIndex:
3097 case AArch64::STGPostIndex:
3098 case AArch64::STZGPostIndex:
3099 case AArch64::ST2GPostIndex:
3100 case AArch64::STZ2GPostIndex:
3101 case AArch64::STNPDi:
3102 case AArch64::STNPQi:
3103 case AArch64::STNPSi:
3104 case AArch64::STNPWi:
3105 case AArch64::STNPXi:
3106 case AArch64::STNT1B_ZRI:
3107 case AArch64::STNT1D_ZRI:
3108 case AArch64::STNT1H_ZRI:
3109 case AArch64::STNT1W_ZRI:
3110 case AArch64::STPDi:
3111 case AArch64::STPQi:
3112 case AArch64::STPSi:
3113 case AArch64::STPWi:
3114 case AArch64::STPXi:
3115 case AArch64::STRBBpost:
3116 case AArch64::STRBBpre:
3117 case AArch64::STRBpost:
3118 case AArch64::STRBpre:
3119 case AArch64::STRDpost:
3120 case AArch64::STRDpre:
3121 case AArch64::STRHHpost:
3122 case AArch64::STRHHpre:
3123 case AArch64::STRHpost:
3124 case AArch64::STRHpre:
3125 case AArch64::STRQpost:
3126 case AArch64::STRQpre:
3127 case AArch64::STRSpost:
3128 case AArch64::STRSpre:
3129 case AArch64::STRWpost:
3130 case AArch64::STRWpre:
3131 case AArch64::STRXpost:
3132 case AArch64::STRXpre:
3134 case AArch64::LDPDpost:
3135 case AArch64::LDPDpre:
3136 case AArch64::LDPQpost:
3137 case AArch64::LDPQpre:
3138 case AArch64::LDPSpost:
3139 case AArch64::LDPSpre:
3140 case AArch64::LDPWpost:
3141 case AArch64::LDPWpre:
3142 case AArch64::LDPXpost:
3143 case AArch64::LDPXpre:
3144 case AArch64::STGPpre:
3145 case AArch64::STGPpost:
3146 case AArch64::STPDpost:
3147 case AArch64::STPDpre:
3148 case AArch64::STPQpost:
3149 case AArch64::STPQpre:
3150 case AArch64::STPSpost:
3151 case AArch64::STPSpre:
3152 case AArch64::STPWpost:
3153 case AArch64::STPWpre:
3154 case AArch64::STPXpost:
3155 case AArch64::STPXpre:
3161 switch (
MI.getOpcode()) {
3165 case AArch64::STRSui:
3166 case AArch64::STRDui:
3167 case AArch64::STRQui:
3168 case AArch64::STRXui:
3169 case AArch64::STRWui:
3170 case AArch64::LDRSui:
3171 case AArch64::LDRDui:
3172 case AArch64::LDRQui:
3173 case AArch64::LDRXui:
3174 case AArch64::LDRWui:
3175 case AArch64::LDRSWui:
3177 case AArch64::STURSi:
3178 case AArch64::STRSpre:
3179 case AArch64::STURDi:
3180 case AArch64::STRDpre:
3181 case AArch64::STURQi:
3182 case AArch64::STRQpre:
3183 case AArch64::STURWi:
3184 case AArch64::STRWpre:
3185 case AArch64::STURXi:
3186 case AArch64::STRXpre:
3187 case AArch64::LDURSi:
3188 case AArch64::LDRSpre:
3189 case AArch64::LDURDi:
3190 case AArch64::LDRDpre:
3191 case AArch64::LDURQi:
3192 case AArch64::LDRQpre:
3193 case AArch64::LDURWi:
3194 case AArch64::LDRWpre:
3195 case AArch64::LDURXi:
3196 case AArch64::LDRXpre:
3197 case AArch64::LDURSWi:
3198 case AArch64::LDRSWpre:
3200 case AArch64::LDR_ZXI:
3201 case AArch64::STR_ZXI:
3207 switch (
MI.getOpcode()) {
3210 "Unexpected instruction - was a new tail call opcode introduced?");
3212 case AArch64::TCRETURNdi:
3213 case AArch64::TCRETURNri:
3214 case AArch64::TCRETURNrix16x17:
3215 case AArch64::TCRETURNrix17:
3216 case AArch64::TCRETURNrinotx16:
3217 case AArch64::TCRETURNriALL:
3218 case AArch64::AUTH_TCRETURN:
3219 case AArch64::AUTH_TCRETURN_BTI:
3229 case AArch64::ADDWri:
3230 return AArch64::ADDSWri;
3231 case AArch64::ADDWrr:
3232 return AArch64::ADDSWrr;
3233 case AArch64::ADDWrs:
3234 return AArch64::ADDSWrs;
3235 case AArch64::ADDWrx:
3236 return AArch64::ADDSWrx;
3237 case AArch64::ANDWri:
3238 return AArch64::ANDSWri;
3239 case AArch64::ANDWrr:
3240 return AArch64::ANDSWrr;
3241 case AArch64::ANDWrs:
3242 return AArch64::ANDSWrs;
3243 case AArch64::BICWrr:
3244 return AArch64::BICSWrr;
3245 case AArch64::BICWrs:
3246 return AArch64::BICSWrs;
3247 case AArch64::SUBWri:
3248 return AArch64::SUBSWri;
3249 case AArch64::SUBWrr:
3250 return AArch64::SUBSWrr;
3251 case AArch64::SUBWrs:
3252 return AArch64::SUBSWrs;
3253 case AArch64::SUBWrx:
3254 return AArch64::SUBSWrx;
3256 case AArch64::ADDXri:
3257 return AArch64::ADDSXri;
3258 case AArch64::ADDXrr:
3259 return AArch64::ADDSXrr;
3260 case AArch64::ADDXrs:
3261 return AArch64::ADDSXrs;
3262 case AArch64::ADDXrx:
3263 return AArch64::ADDSXrx;
3264 case AArch64::ANDXri:
3265 return AArch64::ANDSXri;
3266 case AArch64::ANDXrr:
3267 return AArch64::ANDSXrr;
3268 case AArch64::ANDXrs:
3269 return AArch64::ANDSXrs;
3270 case AArch64::BICXrr:
3271 return AArch64::BICSXrr;
3272 case AArch64::BICXrs:
3273 return AArch64::BICSXrs;
3274 case AArch64::SUBXri:
3275 return AArch64::SUBSXri;
3276 case AArch64::SUBXrr:
3277 return AArch64::SUBSXrr;
3278 case AArch64::SUBXrs:
3279 return AArch64::SUBSXrs;
3280 case AArch64::SUBXrx:
3281 return AArch64::SUBSXrx;
3283 case AArch64::AND_PPzPP:
3284 return AArch64::ANDS_PPzPP;
3285 case AArch64::BIC_PPzPP:
3286 return AArch64::BICS_PPzPP;
3287 case AArch64::EOR_PPzPP:
3288 return AArch64::EORS_PPzPP;
3289 case AArch64::NAND_PPzPP:
3290 return AArch64::NANDS_PPzPP;
3291 case AArch64::NOR_PPzPP:
3292 return AArch64::NORS_PPzPP;
3293 case AArch64::ORN_PPzPP:
3294 return AArch64::ORNS_PPzPP;
3295 case AArch64::ORR_PPzPP:
3296 return AArch64::ORRS_PPzPP;
3297 case AArch64::BRKA_PPzP:
3298 return AArch64::BRKAS_PPzP;
3299 case AArch64::BRKPA_PPzPP:
3300 return AArch64::BRKPAS_PPzPP;
3301 case AArch64::BRKB_PPzP:
3302 return AArch64::BRKBS_PPzP;
3303 case AArch64::BRKPB_PPzPP:
3304 return AArch64::BRKPBS_PPzPP;
3305 case AArch64::BRKN_PPzP:
3306 return AArch64::BRKNS_PPzP;
3307 case AArch64::RDFFR_PPz:
3308 return AArch64::RDFFRS_PPz;
3309 case AArch64::PTRUE_B:
3310 return AArch64::PTRUES_B;
3321 if (
MI.hasOrderedMemoryRef())
3326 assert((
MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3327 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3328 "Expected a reg or frame index operand.");
3332 bool IsImmPreLdSt = IsPreLdSt &&
MI.getOperand(3).isImm();
3334 if (!
MI.getOperand(2).isImm() && !IsImmPreLdSt)
3347 if (
MI.getOperand(1).isReg() && !IsPreLdSt) {
3348 Register BaseReg =
MI.getOperand(1).getReg();
3350 if (
MI.modifiesRegister(BaseReg,
TRI))
3356 switch (
MI.getOpcode()) {
3359 case AArch64::LDR_ZXI:
3360 case AArch64::STR_ZXI:
3361 if (!Subtarget.isLittleEndian() ||
3362 Subtarget.getSVEVectorSizeInBits() != 128)
3375 const MCAsmInfo &MAI =
MI.getMF()->getTarget().getMCAsmInfo();
3383 if (Subtarget.isPaired128Slow()) {
3384 switch (
MI.getOpcode()) {
3387 case AArch64::LDURQi:
3388 case AArch64::STURQi:
3389 case AArch64::LDRQui:
3390 case AArch64::STRQui:
3417std::optional<ExtAddrMode>
3422 bool OffsetIsScalable;
3423 if (!getMemOperandWithOffset(MemI,
Base,
Offset, OffsetIsScalable,
TRI))
3424 return std::nullopt;
3427 return std::nullopt;
3442 int64_t OffsetScale = 1;
3447 case AArch64::LDURQi:
3448 case AArch64::STURQi:
3452 case AArch64::LDURDi:
3453 case AArch64::STURDi:
3454 case AArch64::LDURXi:
3455 case AArch64::STURXi:
3459 case AArch64::LDURWi:
3460 case AArch64::LDURSWi:
3461 case AArch64::STURWi:
3465 case AArch64::LDURHi:
3466 case AArch64::STURHi:
3467 case AArch64::LDURHHi:
3468 case AArch64::STURHHi:
3469 case AArch64::LDURSHXi:
3470 case AArch64::LDURSHWi:
3474 case AArch64::LDRBroX:
3475 case AArch64::LDRBBroX:
3476 case AArch64::LDRSBXroX:
3477 case AArch64::LDRSBWroX:
3478 case AArch64::STRBroX:
3479 case AArch64::STRBBroX:
3480 case AArch64::LDURBi:
3481 case AArch64::LDURBBi:
3482 case AArch64::LDURSBXi:
3483 case AArch64::LDURSBWi:
3484 case AArch64::STURBi:
3485 case AArch64::STURBBi:
3486 case AArch64::LDRBui:
3487 case AArch64::LDRBBui:
3488 case AArch64::LDRSBXui:
3489 case AArch64::LDRSBWui:
3490 case AArch64::STRBui:
3491 case AArch64::STRBBui:
3495 case AArch64::LDRQroX:
3496 case AArch64::STRQroX:
3497 case AArch64::LDRQui:
3498 case AArch64::STRQui:
3503 case AArch64::LDRDroX:
3504 case AArch64::STRDroX:
3505 case AArch64::LDRXroX:
3506 case AArch64::STRXroX:
3507 case AArch64::LDRDui:
3508 case AArch64::STRDui:
3509 case AArch64::LDRXui:
3510 case AArch64::STRXui:
3515 case AArch64::LDRWroX:
3516 case AArch64::LDRSWroX:
3517 case AArch64::STRWroX:
3518 case AArch64::LDRWui:
3519 case AArch64::LDRSWui:
3520 case AArch64::STRWui:
3525 case AArch64::LDRHroX:
3526 case AArch64::STRHroX:
3527 case AArch64::LDRHHroX:
3528 case AArch64::STRHHroX:
3529 case AArch64::LDRSHXroX:
3530 case AArch64::LDRSHWroX:
3531 case AArch64::LDRHui:
3532 case AArch64::STRHui:
3533 case AArch64::LDRHHui:
3534 case AArch64::STRHHui:
3535 case AArch64::LDRSHXui:
3536 case AArch64::LDRSHWui:
3544 if (BaseRegOp.
isReg() && BaseRegOp.
getReg() == Reg)
3568 case AArch64::SBFMXri:
3581 AM.
Scale = OffsetScale;
3586 case TargetOpcode::SUBREG_TO_REG: {
3602 if (
DefMI.getOpcode() != AArch64::ORRWrs ||
3603 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3604 DefMI.getOperand(3).getImm() != 0)
3611 AM.
Scale = OffsetScale;
3622 auto validateOffsetForLDP = [](
unsigned NumBytes, int64_t OldOffset,
3623 int64_t NewOffset) ->
bool {
3624 int64_t MinOffset, MaxOffset;
3641 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3642 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3644 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) ->
bool {
3646 int64_t NewOffset = OldOffset + Disp;
3647 if (!isLegalAddressingMode(NumBytes, NewOffset, 0))
3651 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3661 auto canFoldAddRegIntoAddrMode =
3666 if ((
unsigned)Scale != Scale)
3668 if (!isLegalAddressingMode(NumBytes, 0, Scale))
3680 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3681 Subtarget.isSTRQroSlow();
3690 case AArch64::ADDXri:
3696 return canFoldAddSubImmIntoAddrMode(Disp);
3698 case AArch64::SUBXri:
3704 return canFoldAddSubImmIntoAddrMode(-Disp);
3706 case AArch64::ADDXrs: {
3719 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3721 if (avoidSlowSTRQ(MemI))
3724 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3727 case AArch64::ADDXrr:
3735 if (!OptSize && avoidSlowSTRQ(MemI))
3737 return canFoldAddRegIntoAddrMode(1);
3739 case AArch64::ADDXrx:
3747 if (!OptSize && avoidSlowSTRQ(MemI))
3756 return canFoldAddRegIntoAddrMode(
3771 case AArch64::LDURQi:
3772 case AArch64::LDRQui:
3773 return AArch64::LDRQroX;
3774 case AArch64::STURQi:
3775 case AArch64::STRQui:
3776 return AArch64::STRQroX;
3777 case AArch64::LDURDi:
3778 case AArch64::LDRDui:
3779 return AArch64::LDRDroX;
3780 case AArch64::STURDi:
3781 case AArch64::STRDui:
3782 return AArch64::STRDroX;
3783 case AArch64::LDURXi:
3784 case AArch64::LDRXui:
3785 return AArch64::LDRXroX;
3786 case AArch64::STURXi:
3787 case AArch64::STRXui:
3788 return AArch64::STRXroX;
3789 case AArch64::LDURWi:
3790 case AArch64::LDRWui:
3791 return AArch64::LDRWroX;
3792 case AArch64::LDURSWi:
3793 case AArch64::LDRSWui:
3794 return AArch64::LDRSWroX;
3795 case AArch64::STURWi:
3796 case AArch64::STRWui:
3797 return AArch64::STRWroX;
3798 case AArch64::LDURHi:
3799 case AArch64::LDRHui:
3800 return AArch64::LDRHroX;
3801 case AArch64::STURHi:
3802 case AArch64::STRHui:
3803 return AArch64::STRHroX;
3804 case AArch64::LDURHHi:
3805 case AArch64::LDRHHui:
3806 return AArch64::LDRHHroX;
3807 case AArch64::STURHHi:
3808 case AArch64::STRHHui:
3809 return AArch64::STRHHroX;
3810 case AArch64::LDURSHXi:
3811 case AArch64::LDRSHXui:
3812 return AArch64::LDRSHXroX;
3813 case AArch64::LDURSHWi:
3814 case AArch64::LDRSHWui:
3815 return AArch64::LDRSHWroX;
3816 case AArch64::LDURBi:
3817 case AArch64::LDRBui:
3818 return AArch64::LDRBroX;
3819 case AArch64::LDURBBi:
3820 case AArch64::LDRBBui:
3821 return AArch64::LDRBBroX;
3822 case AArch64::LDURSBXi:
3823 case AArch64::LDRSBXui:
3824 return AArch64::LDRSBXroX;
3825 case AArch64::LDURSBWi:
3826 case AArch64::LDRSBWui:
3827 return AArch64::LDRSBWroX;
3828 case AArch64::STURBi:
3829 case AArch64::STRBui:
3830 return AArch64::STRBroX;
3831 case AArch64::STURBBi:
3832 case AArch64::STRBBui:
3833 return AArch64::STRBBroX;
3845 case AArch64::LDURQi:
3847 return AArch64::LDRQui;
3848 case AArch64::STURQi:
3850 return AArch64::STRQui;
3851 case AArch64::LDURDi:
3853 return AArch64::LDRDui;
3854 case AArch64::STURDi:
3856 return AArch64::STRDui;
3857 case AArch64::LDURXi:
3859 return AArch64::LDRXui;
3860 case AArch64::STURXi:
3862 return AArch64::STRXui;
3863 case AArch64::LDURWi:
3865 return AArch64::LDRWui;
3866 case AArch64::LDURSWi:
3868 return AArch64::LDRSWui;
3869 case AArch64::STURWi:
3871 return AArch64::STRWui;
3872 case AArch64::LDURHi:
3874 return AArch64::LDRHui;
3875 case AArch64::STURHi:
3877 return AArch64::STRHui;
3878 case AArch64::LDURHHi:
3880 return AArch64::LDRHHui;
3881 case AArch64::STURHHi:
3883 return AArch64::STRHHui;
3884 case AArch64::LDURSHXi:
3886 return AArch64::LDRSHXui;
3887 case AArch64::LDURSHWi:
3889 return AArch64::LDRSHWui;
3890 case AArch64::LDURBi:
3892 return AArch64::LDRBui;
3893 case AArch64::LDURBBi:
3895 return AArch64::LDRBBui;
3896 case AArch64::LDURSBXi:
3898 return AArch64::LDRSBXui;
3899 case AArch64::LDURSBWi:
3901 return AArch64::LDRSBWui;
3902 case AArch64::STURBi:
3904 return AArch64::STRBui;
3905 case AArch64::STURBBi:
3907 return AArch64::STRBBui;
3908 case AArch64::LDRQui:
3909 case AArch64::STRQui:
3912 case AArch64::LDRDui:
3913 case AArch64::STRDui:
3914 case AArch64::LDRXui:
3915 case AArch64::STRXui:
3918 case AArch64::LDRWui:
3919 case AArch64::LDRSWui:
3920 case AArch64::STRWui:
3923 case AArch64::LDRHui:
3924 case AArch64::STRHui:
3925 case AArch64::LDRHHui:
3926 case AArch64::STRHHui:
3927 case AArch64::LDRSHXui:
3928 case AArch64::LDRSHWui:
3931 case AArch64::LDRBui:
3932 case AArch64::LDRBBui:
3933 case AArch64::LDRSBXui:
3934 case AArch64::LDRSBWui:
3935 case AArch64::STRBui:
3936 case AArch64::STRBBui:
3950 case AArch64::LDURQi:
3951 case AArch64::STURQi:
3952 case AArch64::LDURDi:
3953 case AArch64::STURDi:
3954 case AArch64::LDURXi:
3955 case AArch64::STURXi:
3956 case AArch64::LDURWi:
3957 case AArch64::LDURSWi:
3958 case AArch64::STURWi:
3959 case AArch64::LDURHi:
3960 case AArch64::STURHi:
3961 case AArch64::LDURHHi:
3962 case AArch64::STURHHi:
3963 case AArch64::LDURSHXi:
3964 case AArch64::LDURSHWi:
3965 case AArch64::LDURBi:
3966 case AArch64::STURBi:
3967 case AArch64::LDURBBi:
3968 case AArch64::STURBBi:
3969 case AArch64::LDURSBWi:
3970 case AArch64::LDURSBXi:
3972 case AArch64::LDRQui:
3973 return AArch64::LDURQi;
3974 case AArch64::STRQui:
3975 return AArch64::STURQi;
3976 case AArch64::LDRDui:
3977 return AArch64::LDURDi;
3978 case AArch64::STRDui:
3979 return AArch64::STURDi;
3980 case AArch64::LDRXui:
3981 return AArch64::LDURXi;
3982 case AArch64::STRXui:
3983 return AArch64::STURXi;
3984 case AArch64::LDRWui:
3985 return AArch64::LDURWi;
3986 case AArch64::LDRSWui:
3987 return AArch64::LDURSWi;
3988 case AArch64::STRWui:
3989 return AArch64::STURWi;
3990 case AArch64::LDRHui:
3991 return AArch64::LDURHi;
3992 case AArch64::STRHui:
3993 return AArch64::STURHi;
3994 case AArch64::LDRHHui:
3995 return AArch64::LDURHHi;
3996 case AArch64::STRHHui:
3997 return AArch64::STURHHi;
3998 case AArch64::LDRSHXui:
3999 return AArch64::LDURSHXi;
4000 case AArch64::LDRSHWui:
4001 return AArch64::LDURSHWi;
4002 case AArch64::LDRBBui:
4003 return AArch64::LDURBBi;
4004 case AArch64::LDRBui:
4005 return AArch64::LDURBi;
4006 case AArch64::STRBBui:
4007 return AArch64::STURBBi;
4008 case AArch64::STRBui:
4009 return AArch64::STURBi;
4010 case AArch64::LDRSBWui:
4011 return AArch64::LDURSBWi;
4012 case AArch64::LDRSBXui:
4013 return AArch64::LDURSBXi;
4026 case AArch64::LDRQroX:
4027 case AArch64::LDURQi:
4028 case AArch64::LDRQui:
4029 return AArch64::LDRQroW;
4030 case AArch64::STRQroX:
4031 case AArch64::STURQi:
4032 case AArch64::STRQui:
4033 return AArch64::STRQroW;
4034 case AArch64::LDRDroX:
4035 case AArch64::LDURDi:
4036 case AArch64::LDRDui:
4037 return AArch64::LDRDroW;
4038 case AArch64::STRDroX:
4039 case AArch64::STURDi:
4040 case AArch64::STRDui:
4041 return AArch64::STRDroW;
4042 case AArch64::LDRXroX:
4043 case AArch64::LDURXi:
4044 case AArch64::LDRXui:
4045 return AArch64::LDRXroW;
4046 case AArch64::STRXroX:
4047 case AArch64::STURXi:
4048 case AArch64::STRXui:
4049 return AArch64::STRXroW;
4050 case AArch64::LDRWroX:
4051 case AArch64::LDURWi:
4052 case AArch64::LDRWui:
4053 return AArch64::LDRWroW;
4054 case AArch64::LDRSWroX:
4055 case AArch64::LDURSWi:
4056 case AArch64::LDRSWui:
4057 return AArch64::LDRSWroW;
4058 case AArch64::STRWroX:
4059 case AArch64::STURWi:
4060 case AArch64::STRWui:
4061 return AArch64::STRWroW;
4062 case AArch64::LDRHroX:
4063 case AArch64::LDURHi:
4064 case AArch64::LDRHui:
4065 return AArch64::LDRHroW;
4066 case AArch64::STRHroX:
4067 case AArch64::STURHi:
4068 case AArch64::STRHui:
4069 return AArch64::STRHroW;
4070 case AArch64::LDRHHroX:
4071 case AArch64::LDURHHi:
4072 case AArch64::LDRHHui:
4073 return AArch64::LDRHHroW;
4074 case AArch64::STRHHroX:
4075 case AArch64::STURHHi:
4076 case AArch64::STRHHui:
4077 return AArch64::STRHHroW;
4078 case AArch64::LDRSHXroX:
4079 case AArch64::LDURSHXi:
4080 case AArch64::LDRSHXui:
4081 return AArch64::LDRSHXroW;
4082 case AArch64::LDRSHWroX:
4083 case AArch64::LDURSHWi:
4084 case AArch64::LDRSHWui:
4085 return AArch64::LDRSHWroW;
4086 case AArch64::LDRBroX:
4087 case AArch64::LDURBi:
4088 case AArch64::LDRBui:
4089 return AArch64::LDRBroW;
4090 case AArch64::LDRBBroX:
4091 case AArch64::LDURBBi:
4092 case AArch64::LDRBBui:
4093 return AArch64::LDRBBroW;
4094 case AArch64::LDRSBXroX:
4095 case AArch64::LDURSBXi:
4096 case AArch64::LDRSBXui:
4097 return AArch64::LDRSBXroW;
4098 case AArch64::LDRSBWroX:
4099 case AArch64::LDURSBWi:
4100 case AArch64::LDRSBWui:
4101 return AArch64::LDRSBWroW;
4102 case AArch64::STRBroX:
4103 case AArch64::STURBi:
4104 case AArch64::STRBui:
4105 return AArch64::STRBroW;
4106 case AArch64::STRBBroX:
4107 case AArch64::STURBBi:
4108 case AArch64::STRBBui:
4109 return AArch64::STRBBroW;
4134 return B.getInstr();
4138 "Addressing mode not supported for folding");
4155 return B.getInstr();
4162 "Address offset can be a register or an immediate, but not both");
4183 return B.getInstr();
4187 "Function must not be called with an addressing mode it can't handle");
4196 case AArch64::LD1Fourv16b_POST:
4197 case AArch64::LD1Fourv1d_POST:
4198 case AArch64::LD1Fourv2d_POST:
4199 case AArch64::LD1Fourv2s_POST:
4200 case AArch64::LD1Fourv4h_POST:
4201 case AArch64::LD1Fourv4s_POST:
4202 case AArch64::LD1Fourv8b_POST:
4203 case AArch64::LD1Fourv8h_POST:
4204 case AArch64::LD1Onev16b_POST:
4205 case AArch64::LD1Onev1d_POST:
4206 case AArch64::LD1Onev2d_POST:
4207 case AArch64::LD1Onev2s_POST:
4208 case AArch64::LD1Onev4h_POST:
4209 case AArch64::LD1Onev4s_POST:
4210 case AArch64::LD1Onev8b_POST:
4211 case AArch64::LD1Onev8h_POST:
4212 case AArch64::LD1Rv16b_POST:
4213 case AArch64::LD1Rv1d_POST:
4214 case AArch64::LD1Rv2d_POST:
4215 case AArch64::LD1Rv2s_POST:
4216 case AArch64::LD1Rv4h_POST:
4217 case AArch64::LD1Rv4s_POST:
4218 case AArch64::LD1Rv8b_POST:
4219 case AArch64::LD1Rv8h_POST:
4220 case AArch64::LD1Threev16b_POST:
4221 case AArch64::LD1Threev1d_POST:
4222 case AArch64::LD1Threev2d_POST:
4223 case AArch64::LD1Threev2s_POST:
4224 case AArch64::LD1Threev4h_POST:
4225 case AArch64::LD1Threev4s_POST:
4226 case AArch64::LD1Threev8b_POST:
4227 case AArch64::LD1Threev8h_POST:
4228 case AArch64::LD1Twov16b_POST:
4229 case AArch64::LD1Twov1d_POST:
4230 case AArch64::LD1Twov2d_POST:
4231 case AArch64::LD1Twov2s_POST:
4232 case AArch64::LD1Twov4h_POST:
4233 case AArch64::LD1Twov4s_POST:
4234 case AArch64::LD1Twov8b_POST:
4235 case AArch64::LD1Twov8h_POST:
4236 case AArch64::LD1i16_POST:
4237 case AArch64::LD1i32_POST:
4238 case AArch64::LD1i64_POST:
4239 case AArch64::LD1i8_POST:
4240 case AArch64::LD2Rv16b_POST:
4241 case AArch64::LD2Rv1d_POST:
4242 case AArch64::LD2Rv2d_POST:
4243 case AArch64::LD2Rv2s_POST:
4244 case AArch64::LD2Rv4h_POST:
4245 case AArch64::LD2Rv4s_POST:
4246 case AArch64::LD2Rv8b_POST:
4247 case AArch64::LD2Rv8h_POST:
4248 case AArch64::LD2Twov16b_POST:
4249 case AArch64::LD2Twov2d_POST:
4250 case AArch64::LD2Twov2s_POST:
4251 case AArch64::LD2Twov4h_POST:
4252 case AArch64::LD2Twov4s_POST:
4253 case AArch64::LD2Twov8b_POST:
4254 case AArch64::LD2Twov8h_POST:
4255 case AArch64::LD2i16_POST:
4256 case AArch64::LD2i32_POST:
4257 case AArch64::LD2i64_POST:
4258 case AArch64::LD2i8_POST:
4259 case AArch64::LD3Rv16b_POST:
4260 case AArch64::LD3Rv1d_POST:
4261 case AArch64::LD3Rv2d_POST:
4262 case AArch64::LD3Rv2s_POST:
4263 case AArch64::LD3Rv4h_POST:
4264 case AArch64::LD3Rv4s_POST:
4265 case AArch64::LD3Rv8b_POST:
4266 case AArch64::LD3Rv8h_POST:
4267 case AArch64::LD3Threev16b_POST:
4268 case AArch64::LD3Threev2d_POST:
4269 case AArch64::LD3Threev2s_POST:
4270 case AArch64::LD3Threev4h_POST:
4271 case AArch64::LD3Threev4s_POST:
4272 case AArch64::LD3Threev8b_POST:
4273 case AArch64::LD3Threev8h_POST:
4274 case AArch64::LD3i16_POST:
4275 case AArch64::LD3i32_POST:
4276 case AArch64::LD3i64_POST:
4277 case AArch64::LD3i8_POST:
4278 case AArch64::LD4Fourv16b_POST:
4279 case AArch64::LD4Fourv2d_POST:
4280 case AArch64::LD4Fourv2s_POST:
4281 case AArch64::LD4Fourv4h_POST:
4282 case AArch64::LD4Fourv4s_POST:
4283 case AArch64::LD4Fourv8b_POST:
4284 case AArch64::LD4Fourv8h_POST:
4285 case AArch64::LD4Rv16b_POST:
4286 case AArch64::LD4Rv1d_POST:
4287 case AArch64::LD4Rv2d_POST:
4288 case AArch64::LD4Rv2s_POST:
4289 case AArch64::LD4Rv4h_POST:
4290 case AArch64::LD4Rv4s_POST:
4291 case AArch64::LD4Rv8b_POST:
4292 case AArch64::LD4Rv8h_POST:
4293 case AArch64::LD4i16_POST:
4294 case AArch64::LD4i32_POST:
4295 case AArch64::LD4i64_POST:
4296 case AArch64::LD4i8_POST:
4297 case AArch64::LDAPRWpost:
4298 case AArch64::LDAPRXpost:
4299 case AArch64::LDIAPPWpost:
4300 case AArch64::LDIAPPXpost:
4301 case AArch64::LDPDpost:
4302 case AArch64::LDPQpost:
4303 case AArch64::LDPSWpost:
4304 case AArch64::LDPSpost:
4305 case AArch64::LDPWpost:
4306 case AArch64::LDPXpost:
4307 case AArch64::LDRBBpost:
4308 case AArch64::LDRBpost:
4309 case AArch64::LDRDpost:
4310 case AArch64::LDRHHpost:
4311 case AArch64::LDRHpost:
4312 case AArch64::LDRQpost:
4313 case AArch64::LDRSBWpost:
4314 case AArch64::LDRSBXpost:
4315 case AArch64::LDRSHWpost:
4316 case AArch64::LDRSHXpost:
4317 case AArch64::LDRSWpost:
4318 case AArch64::LDRSpost:
4319 case AArch64::LDRWpost:
4320 case AArch64::LDRXpost:
4321 case AArch64::ST1Fourv16b_POST:
4322 case AArch64::ST1Fourv1d_POST:
4323 case AArch64::ST1Fourv2d_POST:
4324 case AArch64::ST1Fourv2s_POST:
4325 case AArch64::ST1Fourv4h_POST:
4326 case AArch64::ST1Fourv4s_POST:
4327 case AArch64::ST1Fourv8b_POST:
4328 case AArch64::ST1Fourv8h_POST:
4329 case AArch64::ST1Onev16b_POST:
4330 case AArch64::ST1Onev1d_POST:
4331 case AArch64::ST1Onev2d_POST:
4332 case AArch64::ST1Onev2s_POST:
4333 case AArch64::ST1Onev4h_POST:
4334 case AArch64::ST1Onev4s_POST:
4335 case AArch64::ST1Onev8b_POST:
4336 case AArch64::ST1Onev8h_POST:
4337 case AArch64::ST1Threev16b_POST:
4338 case AArch64::ST1Threev1d_POST:
4339 case AArch64::ST1Threev2d_POST:
4340 case AArch64::ST1Threev2s_POST:
4341 case AArch64::ST1Threev4h_POST:
4342 case AArch64::ST1Threev4s_POST:
4343 case AArch64::ST1Threev8b_POST:
4344 case AArch64::ST1Threev8h_POST:
4345 case AArch64::ST1Twov16b_POST:
4346 case AArch64::ST1Twov1d_POST:
4347 case AArch64::ST1Twov2d_POST:
4348 case AArch64::ST1Twov2s_POST:
4349 case AArch64::ST1Twov4h_POST:
4350 case AArch64::ST1Twov4s_POST:
4351 case AArch64::ST1Twov8b_POST:
4352 case AArch64::ST1Twov8h_POST:
4353 case AArch64::ST1i16_POST:
4354 case AArch64::ST1i32_POST:
4355 case AArch64::ST1i64_POST:
4356 case AArch64::ST1i8_POST:
4357 case AArch64::ST2GPostIndex:
4358 case AArch64::ST2Twov16b_POST:
4359 case AArch64::ST2Twov2d_POST:
4360 case AArch64::ST2Twov2s_POST:
4361 case AArch64::ST2Twov4h_POST:
4362 case AArch64::ST2Twov4s_POST:
4363 case AArch64::ST2Twov8b_POST:
4364 case AArch64::ST2Twov8h_POST:
4365 case AArch64::ST2i16_POST:
4366 case AArch64::ST2i32_POST:
4367 case AArch64::ST2i64_POST:
4368 case AArch64::ST2i8_POST:
4369 case AArch64::ST3Threev16b_POST:
4370 case AArch64::ST3Threev2d_POST:
4371 case AArch64::ST3Threev2s_POST:
4372 case AArch64::ST3Threev4h_POST:
4373 case AArch64::ST3Threev4s_POST:
4374 case AArch64::ST3Threev8b_POST:
4375 case AArch64::ST3Threev8h_POST:
4376 case AArch64::ST3i16_POST:
4377 case AArch64::ST3i32_POST:
4378 case AArch64::ST3i64_POST:
4379 case AArch64::ST3i8_POST:
4380 case AArch64::ST4Fourv16b_POST:
4381 case AArch64::ST4Fourv2d_POST:
4382 case AArch64::ST4Fourv2s_POST:
4383 case AArch64::ST4Fourv4h_POST:
4384 case AArch64::ST4Fourv4s_POST:
4385 case AArch64::ST4Fourv8b_POST:
4386 case AArch64::ST4Fourv8h_POST:
4387 case AArch64::ST4i16_POST:
4388 case AArch64::ST4i32_POST:
4389 case AArch64::ST4i64_POST:
4390 case AArch64::ST4i8_POST:
4391 case AArch64::STGPostIndex:
4392 case AArch64::STGPpost:
4393 case AArch64::STPDpost:
4394 case AArch64::STPQpost:
4395 case AArch64::STPSpost:
4396 case AArch64::STPWpost:
4397 case AArch64::STPXpost:
4398 case AArch64::STRBBpost:
4399 case AArch64::STRBpost:
4400 case AArch64::STRDpost:
4401 case AArch64::STRHHpost:
4402 case AArch64::STRHpost:
4403 case AArch64::STRQpost:
4404 case AArch64::STRSpost:
4405 case AArch64::STRWpost:
4406 case AArch64::STRXpost:
4407 case AArch64::STZ2GPostIndex:
4408 case AArch64::STZGPostIndex:
4415 bool &OffsetIsScalable,
TypeSize &Width,
4436 int64_t Dummy1, Dummy2;
4458 return BaseOp->
isReg() || BaseOp->
isFI();
4465 assert(OfsOp.
isImm() &&
"Offset operand wasn't immediate.");
4470 TypeSize &Width, int64_t &MinOffset,
4471 int64_t &MaxOffset) {
4477 MinOffset = MaxOffset = 0;
4480 case AArch64::LDRQui:
4481 case AArch64::STRQui:
4487 case AArch64::LDRXui:
4488 case AArch64::LDRDui:
4489 case AArch64::STRXui:
4490 case AArch64::STRDui:
4491 case AArch64::PRFMui:
4497 case AArch64::LDRWui:
4498 case AArch64::LDRSui:
4499 case AArch64::LDRSWui:
4500 case AArch64::STRWui:
4501 case AArch64::STRSui:
4507 case AArch64::LDRHui:
4508 case AArch64::LDRHHui:
4509 case AArch64::LDRSHWui:
4510 case AArch64::LDRSHXui:
4511 case AArch64::STRHui:
4512 case AArch64::STRHHui:
4518 case AArch64::LDRBui:
4519 case AArch64::LDRBBui:
4520 case AArch64::LDRSBWui:
4521 case AArch64::LDRSBXui:
4522 case AArch64::STRBui:
4523 case AArch64::STRBBui:
4530 case AArch64::STRQpre:
4531 case AArch64::LDRQpost:
4537 case AArch64::LDRDpost:
4538 case AArch64::LDRDpre:
4539 case AArch64::LDRXpost:
4540 case AArch64::LDRXpre:
4541 case AArch64::STRDpost:
4542 case AArch64::STRDpre:
4543 case AArch64::STRXpost:
4544 case AArch64::STRXpre:
4550 case AArch64::STRWpost:
4551 case AArch64::STRWpre:
4552 case AArch64::LDRWpost:
4553 case AArch64::LDRWpre:
4554 case AArch64::STRSpost:
4555 case AArch64::STRSpre:
4556 case AArch64::LDRSpost:
4557 case AArch64::LDRSpre:
4563 case AArch64::LDRHpost:
4564 case AArch64::LDRHpre:
4565 case AArch64::STRHpost:
4566 case AArch64::STRHpre:
4567 case AArch64::LDRHHpost:
4568 case AArch64::LDRHHpre:
4569 case AArch64::STRHHpost:
4570 case AArch64::STRHHpre:
4576 case AArch64::LDRBpost:
4577 case AArch64::LDRBpre:
4578 case AArch64::STRBpost:
4579 case AArch64::STRBpre:
4580 case AArch64::LDRBBpost:
4581 case AArch64::LDRBBpre:
4582 case AArch64::STRBBpost:
4583 case AArch64::STRBBpre:
4590 case AArch64::LDURQi:
4591 case AArch64::STURQi:
4597 case AArch64::LDURXi:
4598 case AArch64::LDURDi:
4599 case AArch64::LDAPURXi:
4600 case AArch64::STURXi:
4601 case AArch64::STURDi:
4602 case AArch64::STLURXi:
4603 case AArch64::PRFUMi:
4609 case AArch64::LDURWi:
4610 case AArch64::LDURSi:
4611 case AArch64::LDURSWi:
4612 case AArch64::LDAPURi:
4613 case AArch64::LDAPURSWi:
4614 case AArch64::STURWi:
4615 case AArch64::STURSi:
4616 case AArch64::STLURWi:
4622 case AArch64::LDURHi:
4623 case AArch64::LDURHHi:
4624 case AArch64::LDURSHXi:
4625 case AArch64::LDURSHWi:
4626 case AArch64::LDAPURHi:
4627 case AArch64::LDAPURSHWi:
4628 case AArch64::LDAPURSHXi:
4629 case AArch64::STURHi:
4630 case AArch64::STURHHi:
4631 case AArch64::STLURHi:
4637 case AArch64::LDURBi:
4638 case AArch64::LDURBBi:
4639 case AArch64::LDURSBXi:
4640 case AArch64::LDURSBWi:
4641 case AArch64::LDAPURBi:
4642 case AArch64::LDAPURSBWi:
4643 case AArch64::LDAPURSBXi:
4644 case AArch64::STURBi:
4645 case AArch64::STURBBi:
4646 case AArch64::STLURBi:
4653 case AArch64::LDPQi:
4654 case AArch64::LDNPQi:
4655 case AArch64::STPQi:
4656 case AArch64::STNPQi:
4657 case AArch64::LDPQpost:
4658 case AArch64::LDPQpre:
4659 case AArch64::STPQpost:
4660 case AArch64::STPQpre:
4666 case AArch64::LDPXi:
4667 case AArch64::LDPDi:
4668 case AArch64::LDNPXi:
4669 case AArch64::LDNPDi:
4670 case AArch64::STPXi:
4671 case AArch64::STPDi:
4672 case AArch64::STNPXi:
4673 case AArch64::STNPDi:
4674 case AArch64::LDPDpost:
4675 case AArch64::LDPDpre:
4676 case AArch64::LDPXpost:
4677 case AArch64::LDPXpre:
4678 case AArch64::STPDpost:
4679 case AArch64::STPDpre:
4680 case AArch64::STPXpost:
4681 case AArch64::STPXpre:
4687 case AArch64::LDPWi:
4688 case AArch64::LDPSi:
4689 case AArch64::LDNPWi:
4690 case AArch64::LDNPSi:
4691 case AArch64::STPWi:
4692 case AArch64::STPSi:
4693 case AArch64::STNPWi:
4694 case AArch64::STNPSi:
4695 case AArch64::LDPSpost:
4696 case AArch64::LDPSpre:
4697 case AArch64::LDPWpost:
4698 case AArch64::LDPWpre:
4699 case AArch64::STPSpost:
4700 case AArch64::STPSpre:
4701 case AArch64::STPWpost:
4702 case AArch64::STPWpre:
4708 case AArch64::StoreSwiftAsyncContext:
4721 case AArch64::TAGPstack:
4731 case AArch64::STGPreIndex:
4732 case AArch64::STGPostIndex:
4733 case AArch64::STZGi:
4734 case AArch64::STZGPreIndex:
4735 case AArch64::STZGPostIndex:
4742 case AArch64::STR_ZZZZXI:
4743 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4744 case AArch64::LDR_ZZZZXI:
4745 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4751 case AArch64::STR_ZZZXI:
4752 case AArch64::LDR_ZZZXI:
4758 case AArch64::STR_ZZXI:
4759 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4760 case AArch64::LDR_ZZXI:
4761 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4767 case AArch64::LDR_PXI:
4768 case AArch64::STR_PXI:
4774 case AArch64::LDR_PPXI:
4775 case AArch64::STR_PPXI:
4781 case AArch64::LDR_ZXI:
4782 case AArch64::STR_ZXI:
4788 case AArch64::LD1B_IMM:
4789 case AArch64::LD1H_IMM:
4790 case AArch64::LD1W_IMM:
4791 case AArch64::LD1D_IMM:
4792 case AArch64::LDNT1B_ZRI:
4793 case AArch64::LDNT1H_ZRI:
4794 case AArch64::LDNT1W_ZRI:
4795 case AArch64::LDNT1D_ZRI:
4796 case AArch64::ST1B_IMM:
4797 case AArch64::ST1H_IMM:
4798 case AArch64::ST1W_IMM:
4799 case AArch64::ST1D_IMM:
4800 case AArch64::STNT1B_ZRI:
4801 case AArch64::STNT1H_ZRI:
4802 case AArch64::STNT1W_ZRI:
4803 case AArch64::STNT1D_ZRI:
4804 case AArch64::LDNF1B_IMM:
4805 case AArch64::LDNF1H_IMM:
4806 case AArch64::LDNF1W_IMM:
4807 case AArch64::LDNF1D_IMM:
4815 case AArch64::LD2B_IMM:
4816 case AArch64::LD2H_IMM:
4817 case AArch64::LD2W_IMM:
4818 case AArch64::LD2D_IMM:
4819 case AArch64::ST2B_IMM:
4820 case AArch64::ST2H_IMM:
4821 case AArch64::ST2W_IMM:
4822 case AArch64::ST2D_IMM:
4828 case AArch64::LD3B_IMM:
4829 case AArch64::LD3H_IMM:
4830 case AArch64::LD3W_IMM:
4831 case AArch64::LD3D_IMM:
4832 case AArch64::ST3B_IMM:
4833 case AArch64::ST3H_IMM:
4834 case AArch64::ST3W_IMM:
4835 case AArch64::ST3D_IMM:
4841 case AArch64::LD4B_IMM:
4842 case AArch64::LD4H_IMM:
4843 case AArch64::LD4W_IMM:
4844 case AArch64::LD4D_IMM:
4845 case AArch64::ST4B_IMM:
4846 case AArch64::ST4H_IMM:
4847 case AArch64::ST4W_IMM:
4848 case AArch64::ST4D_IMM:
4854 case AArch64::LD1B_H_IMM:
4855 case AArch64::LD1SB_H_IMM:
4856 case AArch64::LD1H_S_IMM:
4857 case AArch64::LD1SH_S_IMM:
4858 case AArch64::LD1W_D_IMM:
4859 case AArch64::LD1SW_D_IMM:
4860 case AArch64::ST1B_H_IMM:
4861 case AArch64::ST1H_S_IMM:
4862 case AArch64::ST1W_D_IMM:
4863 case AArch64::LDNF1B_H_IMM:
4864 case AArch64::LDNF1SB_H_IMM:
4865 case AArch64::LDNF1H_S_IMM:
4866 case AArch64::LDNF1SH_S_IMM:
4867 case AArch64::LDNF1W_D_IMM:
4868 case AArch64::LDNF1SW_D_IMM:
4876 case AArch64::LD1B_S_IMM:
4877 case AArch64::LD1SB_S_IMM:
4878 case AArch64::LD1H_D_IMM:
4879 case AArch64::LD1SH_D_IMM:
4880 case AArch64::ST1B_S_IMM:
4881 case AArch64::ST1H_D_IMM:
4882 case AArch64::LDNF1B_S_IMM:
4883 case AArch64::LDNF1SB_S_IMM:
4884 case AArch64::LDNF1H_D_IMM:
4885 case AArch64::LDNF1SH_D_IMM:
4893 case AArch64::LD1B_D_IMM:
4894 case AArch64::LD1SB_D_IMM:
4895 case AArch64::ST1B_D_IMM:
4896 case AArch64::LDNF1B_D_IMM:
4897 case AArch64::LDNF1SB_D_IMM:
4905 case AArch64::ST2Gi:
4906 case AArch64::ST2GPreIndex:
4907 case AArch64::ST2GPostIndex:
4908 case AArch64::STZ2Gi:
4909 case AArch64::STZ2GPreIndex:
4910 case AArch64::STZ2GPostIndex:
4916 case AArch64::STGPi:
4917 case AArch64::STGPpost:
4918 case AArch64::STGPpre:
4924 case AArch64::LD1RB_IMM:
4925 case AArch64::LD1RB_H_IMM:
4926 case AArch64::LD1RB_S_IMM:
4927 case AArch64::LD1RB_D_IMM:
4928 case AArch64::LD1RSB_H_IMM:
4929 case AArch64::LD1RSB_S_IMM:
4930 case AArch64::LD1RSB_D_IMM:
4936 case AArch64::LD1RH_IMM:
4937 case AArch64::LD1RH_S_IMM:
4938 case AArch64::LD1RH_D_IMM:
4939 case AArch64::LD1RSH_S_IMM:
4940 case AArch64::LD1RSH_D_IMM:
4946 case AArch64::LD1RW_IMM:
4947 case AArch64::LD1RW_D_IMM:
4948 case AArch64::LD1RSW_IMM:
4954 case AArch64::LD1RD_IMM:
4970 case AArch64::LDRBui:
4971 case AArch64::LDRBBui:
4972 case AArch64::LDURBBi:
4973 case AArch64::LDRSBWui:
4974 case AArch64::LDURSBWi:
4975 case AArch64::STRBui:
4976 case AArch64::STRBBui:
4977 case AArch64::STURBBi:
4979 case AArch64::LDRHui:
4980 case AArch64::LDRHHui:
4981 case AArch64::LDURHHi:
4982 case AArch64::LDRSHWui:
4983 case AArch64::LDURSHWi:
4984 case AArch64::STRHui:
4985 case AArch64::STRHHui:
4986 case AArch64::STURHHi:
4988 case AArch64::LDRSui:
4989 case AArch64::LDURSi:
4990 case AArch64::LDRSpre:
4991 case AArch64::LDRSWui:
4992 case AArch64::LDURSWi:
4993 case AArch64::LDRSWpre:
4994 case AArch64::LDRWpre:
4995 case AArch64::LDRWui:
4996 case AArch64::LDURWi:
4997 case AArch64::STRSui:
4998 case AArch64::STURSi:
4999 case AArch64::STRSpre:
5000 case AArch64::STRWui:
5001 case AArch64::STURWi:
5002 case AArch64::STRWpre:
5003 case AArch64::LDPSi:
5004 case AArch64::LDPSWi:
5005 case AArch64::LDPWi:
5006 case AArch64::STPSi:
5007 case AArch64::STPWi:
5009 case AArch64::LDRDui:
5010 case AArch64::LDURDi:
5011 case AArch64::LDRDpre:
5012 case AArch64::LDRXui:
5013 case AArch64::LDURXi:
5014 case AArch64::LDRXpre:
5015 case AArch64::STRDui:
5016 case AArch64::STURDi:
5017 case AArch64::STRDpre:
5018 case AArch64::STRXui:
5019 case AArch64::STURXi:
5020 case AArch64::STRXpre:
5021 case AArch64::LDPDi:
5022 case AArch64::LDPXi:
5023 case AArch64::STPDi:
5024 case AArch64::STPXi:
5026 case AArch64::LDRQui:
5027 case AArch64::LDURQi:
5028 case AArch64::STRQui:
5029 case AArch64::STURQi:
5030 case AArch64::STRQpre:
5031 case AArch64::LDPQi:
5032 case AArch64::LDRQpre:
5033 case AArch64::STPQi:
5035 case AArch64::STZGi:
5036 case AArch64::ST2Gi:
5037 case AArch64::STZ2Gi:
5038 case AArch64::STGPi:
5044 switch (
MI.getOpcode()) {
5047 case AArch64::LDRWpre:
5048 case AArch64::LDRXpre:
5049 case AArch64::LDRSWpre:
5050 case AArch64::LDRSpre:
5051 case AArch64::LDRDpre:
5052 case AArch64::LDRQpre:
5058 switch (
MI.getOpcode()) {
5061 case AArch64::STRWpre:
5062 case AArch64::STRXpre:
5063 case AArch64::STRSpre:
5064 case AArch64::STRDpre:
5065 case AArch64::STRQpre:
5075 switch (
MI.getOpcode()) {
5078 case AArch64::LDURBBi:
5079 case AArch64::LDURHHi:
5080 case AArch64::LDURWi:
5081 case AArch64::LDRBBui:
5082 case AArch64::LDRHHui:
5083 case AArch64::LDRWui:
5084 case AArch64::LDRBBroX:
5085 case AArch64::LDRHHroX:
5086 case AArch64::LDRWroX:
5087 case AArch64::LDRBBroW:
5088 case AArch64::LDRHHroW:
5089 case AArch64::LDRWroW:
5095 switch (
MI.getOpcode()) {
5098 case AArch64::LDURSBWi:
5099 case AArch64::LDURSHWi:
5100 case AArch64::LDURSBXi:
5101 case AArch64::LDURSHXi:
5102 case AArch64::LDURSWi:
5103 case AArch64::LDRSBWui:
5104 case AArch64::LDRSHWui:
5105 case AArch64::LDRSBXui:
5106 case AArch64::LDRSHXui:
5107 case AArch64::LDRSWui:
5108 case AArch64::LDRSBWroX:
5109 case AArch64::LDRSHWroX:
5110 case AArch64::LDRSBXroX:
5111 case AArch64::LDRSHXroX:
5112 case AArch64::LDRSWroX:
5113 case AArch64::LDRSBWroW:
5114 case AArch64::LDRSHWroW:
5115 case AArch64::LDRSBXroW:
5116 case AArch64::LDRSHXroW:
5117 case AArch64::LDRSWroW:
5123 switch (
MI.getOpcode()) {
5126 case AArch64::LDPSi:
5127 case AArch64::LDPSWi:
5128 case AArch64::LDPDi:
5129 case AArch64::LDPQi:
5130 case AArch64::LDPWi:
5131 case AArch64::LDPXi:
5132 case AArch64::STPSi:
5133 case AArch64::STPDi:
5134 case AArch64::STPQi:
5135 case AArch64::STPWi:
5136 case AArch64::STPXi:
5137 case AArch64::STGPi:
5143 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5147 return MI.getOperand(Idx);
5152 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5156 return MI.getOperand(Idx);
5161 switch (
MI.getOpcode()) {
5164 case AArch64::LDRBroX:
5165 case AArch64::LDRBBroX:
5166 case AArch64::LDRSBXroX:
5167 case AArch64::LDRSBWroX:
5168 case AArch64::LDRHroX:
5169 case AArch64::LDRHHroX:
5170 case AArch64::LDRSHXroX:
5171 case AArch64::LDRSHWroX:
5172 case AArch64::LDRWroX:
5173 case AArch64::LDRSroX:
5174 case AArch64::LDRSWroX:
5175 case AArch64::LDRDroX:
5176 case AArch64::LDRXroX:
5177 case AArch64::LDRQroX:
5178 return MI.getOperand(4);
5184 if (
MI.getParent() ==
nullptr)
5194 auto Reg =
Op.getReg();
5195 if (Reg.isPhysical())
5196 return AArch64::FPR16RegClass.contains(Reg);
5198 return TRC == &AArch64::FPR16RegClass ||
5199 TRC == &AArch64::FPR16_loRegClass;
5208 auto Reg =
Op.getReg();
5209 if (Reg.isPhysical())
5210 return AArch64::FPR128RegClass.contains(Reg);
5212 return TRC == &AArch64::FPR128RegClass ||
5213 TRC == &AArch64::FPR128_loRegClass;
5219 switch (
MI.getOpcode()) {
5222 case AArch64::PACIASP:
5223 case AArch64::PACIBSP:
5226 case AArch64::PAUTH_PROLOGUE:
5229 case AArch64::HINT: {
5230 unsigned Imm =
MI.getOperand(0).getImm();
5232 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5235 if (Imm == 25 || Imm == 27)
5247 assert(Reg.isPhysical() &&
"Expected physical register in isFpOrNEON");
5248 return AArch64::FPR128RegClass.contains(Reg) ||
5249 AArch64::FPR64RegClass.contains(Reg) ||
5250 AArch64::FPR32RegClass.contains(Reg) ||
5251 AArch64::FPR16RegClass.contains(Reg) ||
5252 AArch64::FPR8RegClass.contains(Reg);
5259 auto Reg =
Op.getReg();
5260 if (Reg.isPhysical())
5264 return TRC == &AArch64::FPR128RegClass ||
5265 TRC == &AArch64::FPR128_loRegClass ||
5266 TRC == &AArch64::FPR64RegClass ||
5267 TRC == &AArch64::FPR64_loRegClass ||
5268 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5269 TRC == &AArch64::FPR8RegClass;
5291 if (FirstOpc == SecondOpc)
5297 case AArch64::STRSui:
5298 case AArch64::STURSi:
5299 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5300 case AArch64::STRDui:
5301 case AArch64::STURDi:
5302 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5303 case AArch64::STRQui:
5304 case AArch64::STURQi:
5305 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5306 case AArch64::STRWui:
5307 case AArch64::STURWi:
5308 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5309 case AArch64::STRXui:
5310 case AArch64::STURXi:
5311 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5312 case AArch64::LDRSui:
5313 case AArch64::LDURSi:
5314 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5315 case AArch64::LDRDui:
5316 case AArch64::LDURDi:
5317 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5318 case AArch64::LDRQui:
5319 case AArch64::LDURQi:
5320 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5321 case AArch64::LDRWui:
5322 case AArch64::LDURWi:
5323 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5324 case AArch64::LDRSWui:
5325 case AArch64::LDURSWi:
5326 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5327 case AArch64::LDRXui:
5328 case AArch64::LDURXi:
5329 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5336 int64_t Offset1,
unsigned Opcode1,
int FI2,
5337 int64_t Offset2,
unsigned Opcode2) {
5343 assert(ObjectOffset1 <= ObjectOffset2 &&
"Object offsets are not ordered.");
5346 if (ObjectOffset1 % Scale1 != 0)
5348 ObjectOffset1 /= Scale1;
5350 if (ObjectOffset2 % Scale2 != 0)
5352 ObjectOffset2 /= Scale2;
5353 ObjectOffset1 += Offset1;
5354 ObjectOffset2 += Offset2;
5355 return ObjectOffset1 + 1 == ObjectOffset2;
5367 int64_t OpOffset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
5368 unsigned NumBytes)
const {
5378 "Only base registers and frame indices are supported.");
5385 if (ClusterSize > 2)
5392 unsigned FirstOpc = FirstLdSt.
getOpcode();
5393 unsigned SecondOpc = SecondLdSt.
getOpcode();
5413 if (Offset1 > 63 || Offset1 < -64)
5418 if (BaseOp1.
isFI()) {
5420 "Caller should have ordered offsets.");
5425 BaseOp2.
getIndex(), Offset2, SecondOpc);
5428 assert(Offset1 <= Offset2 &&
"Caller should have ordered offsets.");
5430 return Offset1 + 1 == Offset2;
5440 if (
Reg.isPhysical())
5449 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5458 assert(Subtarget.hasNEON() &&
"Unexpected register copy without NEON");
5460 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5461 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5462 unsigned NumRegs = Indices.
size();
5464 int SubReg = 0, End = NumRegs, Incr = 1;
5466 SubReg = NumRegs - 1;
5471 for (; SubReg != End; SubReg += Incr) {
5483 unsigned Opcode,
unsigned ZeroReg,
5486 unsigned NumRegs = Indices.
size();
5489 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5490 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5491 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5492 "GPR reg sequences should not be able to overlap");
5495 for (
unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5516 unsigned Opc =
MI.getOpcode();
5517 if (
Opc == AArch64::MSRpstatesvcrImm1 ||
Opc == AArch64::MSRpstatePseudo) {
5519 int64_t PState =
MI.getOperand(0).getImm();
5520 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5522 return MI.getOperand(1).getImm() == 1;
5541 bool RenamableSrc)
const {
5543 if (AArch64::GPR32spRegClass.
contains(DestReg) &&
5544 AArch64::GPR32spRegClass.
contains(SrcReg)) {
5545 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5547 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5548 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5550 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5551 &AArch64::GPR64spRegClass);
5552 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5553 &AArch64::GPR64spRegClass);
5563 ++NumZCRegMoveInstrsGPR;
5569 if (Subtarget.hasZeroCycleRegMoveGPR32())
5570 ++NumZCRegMoveInstrsGPR;
5572 }
else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5573 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5575 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5576 &AArch64::GPR64spRegClass);
5577 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5578 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5579 &AArch64::GPR64spRegClass);
5589 ++NumZCRegMoveInstrsGPR;
5595 if (Subtarget.hasZeroCycleRegMoveGPR32())
5596 ++NumZCRegMoveInstrsGPR;
5602 if (AArch64::GPR32spRegClass.
contains(DestReg) && SrcReg == AArch64::WZR) {
5603 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5604 !Subtarget.hasZeroCycleZeroingGPR32()) {
5605 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5606 &AArch64::GPR64spRegClass);
5607 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5611 ++NumZCZeroingInstrsGPR;
5612 }
else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5616 ++NumZCZeroingInstrsGPR;
5625 if (AArch64::GPR64spRegClass.
contains(DestReg) &&
5626 AArch64::GPR64spRegClass.
contains(SrcReg)) {
5627 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5633 if (Subtarget.hasZeroCycleRegMoveGPR64())
5634 ++NumZCRegMoveInstrsGPR;
5640 if (Subtarget.hasZeroCycleRegMoveGPR64())
5641 ++NumZCRegMoveInstrsGPR;
5647 if (AArch64::GPR64spRegClass.
contains(DestReg) && SrcReg == AArch64::XZR) {
5648 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5652 ++NumZCZeroingInstrsGPR;
5662 if (AArch64::PPRRegClass.
contains(DestReg) &&
5663 AArch64::PPRRegClass.
contains(SrcReg)) {
5664 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5665 "Unexpected SVE register.");
5675 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5676 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5677 if (DestIsPNR || SrcIsPNR) {
5679 return (R - AArch64::PN0) + AArch64::P0;
5684 if (PPRSrcReg != PPRDestReg) {
5696 if (AArch64::ZPRRegClass.
contains(DestReg) &&
5697 AArch64::ZPRRegClass.
contains(SrcReg)) {
5698 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5699 "Unexpected SVE register.");
5707 if ((AArch64::ZPR2RegClass.
contains(DestReg) ||
5708 AArch64::ZPR2StridedOrContiguousRegClass.
contains(DestReg)) &&
5709 (AArch64::ZPR2RegClass.
contains(SrcReg) ||
5710 AArch64::ZPR2StridedOrContiguousRegClass.
contains(SrcReg))) {
5711 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5712 "Unexpected SVE register.");
5713 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
5720 if (AArch64::ZPR3RegClass.
contains(DestReg) &&
5721 AArch64::ZPR3RegClass.
contains(SrcReg)) {
5722 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5723 "Unexpected SVE register.");
5724 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5732 if ((AArch64::ZPR4RegClass.
contains(DestReg) ||
5733 AArch64::ZPR4StridedOrContiguousRegClass.
contains(DestReg)) &&
5734 (AArch64::ZPR4RegClass.
contains(SrcReg) ||
5735 AArch64::ZPR4StridedOrContiguousRegClass.
contains(SrcReg))) {
5736 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5737 "Unexpected SVE register.");
5738 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5739 AArch64::zsub2, AArch64::zsub3};
5746 if (AArch64::DDDDRegClass.
contains(DestReg) &&
5747 AArch64::DDDDRegClass.
contains(SrcReg)) {
5748 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5749 AArch64::dsub2, AArch64::dsub3};
5756 if (AArch64::DDDRegClass.
contains(DestReg) &&
5757 AArch64::DDDRegClass.
contains(SrcReg)) {
5758 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5766 if (AArch64::DDRegClass.
contains(DestReg) &&
5767 AArch64::DDRegClass.
contains(SrcReg)) {
5768 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
5775 if (AArch64::QQQQRegClass.
contains(DestReg) &&
5776 AArch64::QQQQRegClass.
contains(SrcReg)) {
5777 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5778 AArch64::qsub2, AArch64::qsub3};
5785 if (AArch64::QQQRegClass.
contains(DestReg) &&
5786 AArch64::QQQRegClass.
contains(SrcReg)) {
5787 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5795 if (AArch64::QQRegClass.
contains(DestReg) &&
5796 AArch64::QQRegClass.
contains(SrcReg)) {
5797 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
5803 if (AArch64::XSeqPairsClassRegClass.
contains(DestReg) &&
5804 AArch64::XSeqPairsClassRegClass.
contains(SrcReg)) {
5805 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
5807 AArch64::XZR, Indices);
5811 if (AArch64::WSeqPairsClassRegClass.
contains(DestReg) &&
5812 AArch64::WSeqPairsClassRegClass.
contains(SrcReg)) {
5813 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
5815 AArch64::WZR, Indices);
5819 if (AArch64::FPR128RegClass.
contains(DestReg) &&
5820 AArch64::FPR128RegClass.
contains(SrcReg)) {
5824 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
5825 !Subtarget.isNeonAvailable()) ||
5829 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
5830 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
5831 }
else if (Subtarget.isNeonAvailable()) {
5835 if (Subtarget.hasZeroCycleRegMoveFPR128())
5836 ++NumZCRegMoveInstrsFPR;
5852 if (AArch64::FPR64RegClass.
contains(DestReg) &&
5853 AArch64::FPR64RegClass.
contains(SrcReg)) {
5854 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5855 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5856 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5858 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
5859 &AArch64::FPR128RegClass);
5860 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
5861 &AArch64::FPR128RegClass);
5870 ++NumZCRegMoveInstrsFPR;
5874 if (Subtarget.hasZeroCycleRegMoveFPR64())
5875 ++NumZCRegMoveInstrsFPR;
5880 if (AArch64::FPR32RegClass.
contains(DestReg) &&
5881 AArch64::FPR32RegClass.
contains(SrcReg)) {
5882 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5883 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5884 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5886 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5887 &AArch64::FPR128RegClass);
5888 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5889 &AArch64::FPR128RegClass);
5898 ++NumZCRegMoveInstrsFPR;
5899 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5900 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5901 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5902 &AArch64::FPR64RegClass);
5903 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5904 &AArch64::FPR64RegClass);
5912 ++NumZCRegMoveInstrsFPR;
5916 if (Subtarget.hasZeroCycleRegMoveFPR32())
5917 ++NumZCRegMoveInstrsFPR;
5922 if (AArch64::FPR16RegClass.
contains(DestReg) &&
5923 AArch64::FPR16RegClass.
contains(SrcReg)) {
5924 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5925 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5926 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5928 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5929 &AArch64::FPR128RegClass);
5930 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5931 &AArch64::FPR128RegClass);
5940 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5941 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5942 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5943 &AArch64::FPR64RegClass);
5944 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5945 &AArch64::FPR64RegClass);
5954 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5955 &AArch64::FPR32RegClass);
5956 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5957 &AArch64::FPR32RegClass);
5964 if (AArch64::FPR8RegClass.
contains(DestReg) &&
5965 AArch64::FPR8RegClass.
contains(SrcReg)) {
5966 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5967 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5968 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
5970 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5971 &AArch64::FPR128RegClass);
5972 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5973 &AArch64::FPR128RegClass);
5982 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5983 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5984 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5985 &AArch64::FPR64RegClass);
5986 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5987 &AArch64::FPR64RegClass);
5996 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5997 &AArch64::FPR32RegClass);
5998 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5999 &AArch64::FPR32RegClass);
6007 if (AArch64::FPR64RegClass.
contains(DestReg) &&
6008 AArch64::GPR64RegClass.
contains(SrcReg)) {
6009 if (AArch64::XZR == SrcReg) {
6017 if (AArch64::GPR64RegClass.
contains(DestReg) &&
6018 AArch64::FPR64RegClass.
contains(SrcReg)) {
6024 if (AArch64::FPR32RegClass.
contains(DestReg) &&
6025 AArch64::GPR32RegClass.
contains(SrcReg)) {
6026 if (AArch64::WZR == SrcReg) {
6034 if (AArch64::GPR32RegClass.
contains(DestReg) &&
6035 AArch64::FPR32RegClass.
contains(SrcReg)) {
6041 if (DestReg == AArch64::NZCV) {
6042 assert(AArch64::GPR64RegClass.
contains(SrcReg) &&
"Invalid NZCV copy");
6044 .
addImm(AArch64SysReg::NZCV)
6050 if (SrcReg == AArch64::NZCV) {
6051 assert(AArch64::GPR64RegClass.
contains(DestReg) &&
"Invalid NZCV copy");
6053 .
addImm(AArch64SysReg::NZCV)
6059 errs() << RI.getRegAsmName(DestReg) <<
" = COPY " << RI.getRegAsmName(SrcReg)
6070 unsigned SubIdx0,
unsigned SubIdx1,
int FI,
6075 SrcReg0 =
TRI.getSubReg(SrcReg, SubIdx0);
6077 SrcReg1 =
TRI.getSubReg(SrcReg, SubIdx1);
6090 Register SrcReg,
bool isKill,
int FI,
6105 switch (RI.getSpillSize(*RC)) {
6107 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6108 Opc = AArch64::STRBui;
6111 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6112 Opc = AArch64::STRHui;
6113 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6114 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6115 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6116 "Unexpected register store without SVE store instructions");
6117 Opc = AArch64::STR_PXI;
6123 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6124 Opc = AArch64::STRWui;
6128 assert(SrcReg != AArch64::WSP);
6129 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6130 Opc = AArch64::STRSui;
6131 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6132 Opc = AArch64::STR_PPXI;
6137 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6138 Opc = AArch64::STRXui;
6142 assert(SrcReg != AArch64::SP);
6143 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6144 Opc = AArch64::STRDui;
6145 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6147 get(AArch64::STPWi), SrcReg, isKill,
6148 AArch64::sube32, AArch64::subo32, FI, MMO);
6153 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6154 Opc = AArch64::STRQui;
6155 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6156 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6157 Opc = AArch64::ST1Twov1d;
6159 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6161 get(AArch64::STPXi), SrcReg, isKill,
6162 AArch64::sube64, AArch64::subo64, FI, MMO);
6164 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6165 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6166 "Unexpected register store without SVE store instructions");
6167 Opc = AArch64::STR_ZXI;
6172 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6173 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6174 Opc = AArch64::ST1Threev1d;
6179 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6180 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6181 Opc = AArch64::ST1Fourv1d;
6183 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6184 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6185 Opc = AArch64::ST1Twov2d;
6187 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6188 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6189 "Unexpected register store without SVE store instructions");
6190 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6192 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6193 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6194 "Unexpected register store without SVE store instructions");
6195 Opc = AArch64::STR_ZZXI;
6200 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6201 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6202 Opc = AArch64::ST1Threev2d;
6204 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6205 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6206 "Unexpected register store without SVE store instructions");
6207 Opc = AArch64::STR_ZZZXI;
6212 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6213 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6214 Opc = AArch64::ST1Fourv2d;
6216 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6217 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6218 "Unexpected register store without SVE store instructions");
6219 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6221 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6222 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6223 "Unexpected register store without SVE store instructions");
6224 Opc = AArch64::STR_ZZZZXI;
6229 assert(
Opc &&
"Unknown register class");
6240 MI.addMemOperand(MMO);
6247 Register DestReg,
unsigned SubIdx0,
6248 unsigned SubIdx1,
int FI,
6252 bool IsUndef =
true;
6254 DestReg0 =
TRI.getSubReg(DestReg, SubIdx0);
6256 DestReg1 =
TRI.getSubReg(DestReg, SubIdx1);
6285 switch (
TRI.getSpillSize(*RC)) {
6287 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6288 Opc = AArch64::LDRBui;
6291 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6292 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6293 Opc = AArch64::LDRHui;
6294 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6295 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6296 "Unexpected register load without SVE load instructions");
6299 Opc = AArch64::LDR_PXI;
6305 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6306 Opc = AArch64::LDRWui;
6310 assert(DestReg != AArch64::WSP);
6311 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6312 Opc = AArch64::LDRSui;
6313 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6314 Opc = AArch64::LDR_PPXI;
6319 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6320 Opc = AArch64::LDRXui;
6324 assert(DestReg != AArch64::SP);
6325 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6326 Opc = AArch64::LDRDui;
6327 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6329 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6330 AArch64::subo32, FI, MMO);
6335 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6336 Opc = AArch64::LDRQui;
6337 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6338 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6339 Opc = AArch64::LD1Twov1d;
6341 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6343 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6344 AArch64::subo64, FI, MMO);
6346 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6347 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6348 "Unexpected register load without SVE load instructions");
6349 Opc = AArch64::LDR_ZXI;
6354 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6355 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6356 Opc = AArch64::LD1Threev1d;
6361 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6362 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6363 Opc = AArch64::LD1Fourv1d;
6365 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6366 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6367 Opc = AArch64::LD1Twov2d;
6369 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6370 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6371 "Unexpected register load without SVE load instructions");
6372 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6374 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6375 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6376 "Unexpected register load without SVE load instructions");
6377 Opc = AArch64::LDR_ZZXI;
6382 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6383 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6384 Opc = AArch64::LD1Threev2d;
6386 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6387 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6388 "Unexpected register load without SVE load instructions");
6389 Opc = AArch64::LDR_ZZZXI;
6394 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6395 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6396 Opc = AArch64::LD1Fourv2d;
6398 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6399 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6400 "Unexpected register load without SVE load instructions");
6401 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6403 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6404 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6405 "Unexpected register load without SVE load instructions");
6406 Opc = AArch64::LDR_ZZZZXI;
6412 assert(
Opc &&
"Unknown register class");
6422 MI.addMemOperand(MMO);
6429 UseMI.getIterator()),
6431 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6432 I.readsRegister(AArch64::NZCV, TRI);
6436void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6441 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6448 ByteSized =
Offset.getFixed();
6449 VGSized =
Offset.getScalable() / 2;
6455void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6457 int64_t &NumDataVectors) {
6461 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6463 NumBytes =
Offset.getFixed();
6465 NumPredicateVectors =
Offset.getScalable() / 2;
6470 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6471 NumPredicateVectors > 62) {
6472 NumDataVectors = NumPredicateVectors / 8;
6473 NumPredicateVectors -= NumDataVectors * 8;
6499 Expr.
push_back((
char)dwarf::DW_OP_bregx);
6507 int64_t OffsetFromDefCFA) {
6521 Comment << (NumBytes < 0 ?
" - " :
" + ") << std::abs(NumBytes);
6522 if (!RegScale.empty())
6532 int64_t NumBytes, NumVGScaledBytes;
6533 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
Offset, NumBytes,
6535 std::string CommentBuffer;
6538 if (
Reg == AArch64::SP)
6540 else if (
Reg == AArch64::FP)
6547 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
6548 assert(DwarfReg <= 31 &&
"DwarfReg out of bounds (0..31)");
6550 Expr.
push_back(dwarf::DW_OP_breg0 + DwarfReg);
6553 if (NumVGScaledBytes) {
6563 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
6571 unsigned FrameReg,
unsigned Reg,
6573 bool LastAdjustmentWasScalable) {
6574 if (
Offset.getScalable())
6577 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6580 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6587 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6588 int64_t NumBytes, NumVGScaledBytes;
6589 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6590 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6592 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6595 if (!NumVGScaledBytes)
6598 std::string CommentBuffer;
6603 assert(NumVGScaledBytes &&
"Expected scalable offset");
6607 if (IncomingVGOffsetFromDefCFA) {
6609 VGRegScale =
"* IncomingVG";
6612 VGRegScale =
"* VG";
6616 OffsetExpr.
push_back(dwarf::DW_OP_plus);
6625 CfaExpr.
push_back(dwarf::DW_CFA_expression);
6640 unsigned SrcReg, int64_t
Offset,
unsigned Opc,
6643 bool *HasWinCFI,
bool EmitCFAOffset,
6646 unsigned MaxEncoding, ShiftSize;
6648 case AArch64::ADDXri:
6649 case AArch64::ADDSXri:
6650 case AArch64::SUBXri:
6651 case AArch64::SUBSXri:
6652 MaxEncoding = 0xfff;
6655 case AArch64::ADDVL_XXI:
6656 case AArch64::ADDPL_XXI:
6657 case AArch64::ADDSVL_XXI:
6658 case AArch64::ADDSPL_XXI:
6673 if (
Opc == AArch64::ADDVL_XXI ||
Opc == AArch64::ADDSVL_XXI)
6675 else if (
Opc == AArch64::ADDPL_XXI ||
Opc == AArch64::ADDSPL_XXI)
6689 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6691 if (TmpReg == AArch64::XZR)
6692 TmpReg =
MBB.getParent()->getRegInfo().createVirtualRegister(
6693 &AArch64::GPR64RegClass);
6695 uint64_t ThisVal = std::min<uint64_t>(
Offset, MaxEncodableValue);
6696 unsigned LocalShiftSize = 0;
6697 if (ThisVal > MaxEncoding) {
6698 ThisVal = ThisVal >> ShiftSize;
6699 LocalShiftSize = ShiftSize;
6701 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
6702 "Encoding cannot handle value that big");
6704 Offset -= ThisVal << LocalShiftSize;
6709 .
addImm(Sign * (
int)ThisVal);
6719 if (Sign == -1 ||
Opc == AArch64::SUBXri ||
Opc == AArch64::SUBSXri)
6720 CFAOffset += Change;
6722 CFAOffset -= Change;
6723 if (EmitCFAOffset && DestReg == TmpReg) {
6736 int Imm = (int)(ThisVal << LocalShiftSize);
6737 if (VScale != 1 && DestReg == AArch64::SP) {
6743 }
else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
6744 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
6745 assert(VScale == 1 &&
"Expected non-scalable operation");
6754 assert(
Offset == 0 &&
"Expected remaining offset to be zero to "
6755 "emit a single SEH directive");
6756 }
else if (DestReg == AArch64::SP) {
6757 assert(VScale == 1 &&
"Expected non-scalable operation");
6760 assert(SrcReg == AArch64::SP &&
"Unexpected SrcReg for SEH_StackAlloc");
6773 unsigned DestReg,
unsigned SrcReg,
6776 bool NeedsWinCFI,
bool *HasWinCFI,
6778 unsigned FrameReg) {
6785 bool UseSVL =
F.hasFnAttribute(
"aarch64_pstate_sm_body");
6787 int64_t Bytes, NumPredicateVectors, NumDataVectors;
6788 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6789 Offset, Bytes, NumPredicateVectors, NumDataVectors);
6792 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
6793 if (NeedsFinalDefNZCV)
6797 if (Bytes || (!
Offset && SrcReg != DestReg)) {
6798 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
6799 "SP increment/decrement not 8-byte aligned");
6800 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
6803 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
6806 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6808 CFAOffset += (
Opc == AArch64::ADDXri ||
Opc == AArch64::ADDSXri)
6815 assert(!(NeedsWinCFI && NumPredicateVectors) &&
6816 "WinCFI can't allocate fractions of an SVE data vector");
6818 if (NumDataVectors) {
6820 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI,
TII,
6821 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6827 if (NumPredicateVectors) {
6828 assert(DestReg != AArch64::SP &&
"Unaligned access to SP");
6830 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI,
TII,
6831 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6835 if (NeedsFinalDefNZCV)
6857 if (
MI.isFullCopy()) {
6860 if (SrcReg == AArch64::SP && DstReg.
isVirtual()) {
6864 if (DstReg == AArch64::SP && SrcReg.
isVirtual()) {
6869 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
6897 if (
MI.isCopy() &&
Ops.size() == 1 &&
6899 (
Ops[0] == 0 ||
Ops[0] == 1)) {
6900 bool IsSpill =
Ops[0] == 0;
6901 bool IsFill = !IsSpill;
6913 :
TRI.getMinimalPhysRegClass(Reg);
6919 "Mismatched register size in non subreg COPY");
6926 return &*--InsertPt;
6938 if (IsSpill && DstMO.
isUndef() && SrcReg == AArch64::WZR &&
6941 "Unexpected subreg on physical register");
6943 FrameIndex, &AArch64::GPR64RegClass,
Register());
6944 return &*--InsertPt;
6961 case AArch64::sub_32:
6962 if (AArch64::GPR64RegClass.hasSubClassEq(
getRegClass(DstReg)))
6963 FillRC = &AArch64::GPR32RegClass;
6966 FillRC = &AArch64::FPR32RegClass;
6969 FillRC = &AArch64::FPR64RegClass;
6975 TRI.getRegSizeInBits(*FillRC) &&
6976 "Mismatched regclass size on folded subreg COPY");
6995 bool *OutUseUnscaledOp,
6996 unsigned *OutUnscaledOp,
6997 int64_t *EmittableOffset) {
6999 if (EmittableOffset)
7000 *EmittableOffset = 0;
7001 if (OutUseUnscaledOp)
7002 *OutUseUnscaledOp =
false;
7008 switch (
MI.getOpcode()) {
7011 case AArch64::LD1Rv1d:
7012 case AArch64::LD1Rv2s:
7013 case AArch64::LD1Rv2d:
7014 case AArch64::LD1Rv4h:
7015 case AArch64::LD1Rv4s:
7016 case AArch64::LD1Rv8b:
7017 case AArch64::LD1Rv8h:
7018 case AArch64::LD1Rv16b:
7019 case AArch64::LD1Twov2d:
7020 case AArch64::LD1Threev2d:
7021 case AArch64::LD1Fourv2d:
7022 case AArch64::LD1Twov1d:
7023 case AArch64::LD1Threev1d:
7024 case AArch64::LD1Fourv1d:
7025 case AArch64::ST1Twov2d:
7026 case AArch64::ST1Threev2d:
7027 case AArch64::ST1Fourv2d:
7028 case AArch64::ST1Twov1d:
7029 case AArch64::ST1Threev1d:
7030 case AArch64::ST1Fourv1d:
7031 case AArch64::ST1i8:
7032 case AArch64::ST1i16:
7033 case AArch64::ST1i32:
7034 case AArch64::ST1i64:
7036 case AArch64::IRGstack:
7037 case AArch64::STGloop:
7038 case AArch64::STZGloop:
7043 TypeSize ScaleValue(0U,
false), Width(0U,
false);
7044 int64_t MinOff, MaxOff;
7050 bool IsMulVL = ScaleValue.isScalable();
7051 unsigned Scale = ScaleValue.getKnownMinValue();
7061 std::optional<unsigned> UnscaledOp =
7063 bool useUnscaledOp = UnscaledOp && (
Offset % Scale ||
Offset < 0);
7064 if (useUnscaledOp &&
7069 Scale = ScaleValue.getKnownMinValue();
7070 assert(IsMulVL == ScaleValue.isScalable() &&
7071 "Unscaled opcode has different value for scalable");
7073 int64_t Remainder =
Offset % Scale;
7074 assert(!(Remainder && useUnscaledOp) &&
7075 "Cannot have remainder when using unscaled op");
7077 assert(MinOff < MaxOff &&
"Unexpected Min/Max offsets");
7078 int64_t NewOffset =
Offset / Scale;
7079 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7082 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7086 if (EmittableOffset)
7087 *EmittableOffset = NewOffset;
7088 if (OutUseUnscaledOp)
7089 *OutUseUnscaledOp = useUnscaledOp;
7090 if (OutUnscaledOp && UnscaledOp)
7091 *OutUnscaledOp = *UnscaledOp;
7104 unsigned Opcode =
MI.getOpcode();
7105 unsigned ImmIdx = FrameRegIdx + 1;
7107 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7112 MI.eraseFromParent();
7118 unsigned UnscaledOp;
7121 &UnscaledOp, &NewOffset);
7125 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
7127 MI.setDesc(
TII->get(UnscaledOp));
7129 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7145bool AArch64InstrInfo::useMachineCombiner()
const {
return true; }
7150 case AArch64::ADDSWrr:
7151 case AArch64::ADDSWri:
7152 case AArch64::ADDSXrr:
7153 case AArch64::ADDSXri:
7154 case AArch64::SUBSWrr:
7155 case AArch64::SUBSXrr:
7157 case AArch64::SUBSWri:
7158 case AArch64::SUBSXri:
7169 case AArch64::ADDWrr:
7170 case AArch64::ADDWri:
7171 case AArch64::SUBWrr:
7172 case AArch64::ADDSWrr:
7173 case AArch64::ADDSWri:
7174 case AArch64::SUBSWrr:
7176 case AArch64::SUBWri:
7177 case AArch64::SUBSWri:
7188 case AArch64::ADDXrr:
7189 case AArch64::ADDXri:
7190 case AArch64::SUBXrr:
7191 case AArch64::ADDSXrr:
7192 case AArch64::ADDSXri:
7193 case AArch64::SUBSXrr:
7195 case AArch64::SUBXri:
7196 case AArch64::SUBSXri:
7197 case AArch64::ADDv8i8:
7198 case AArch64::ADDv16i8:
7199 case AArch64::ADDv4i16:
7200 case AArch64::ADDv8i16:
7201 case AArch64::ADDv2i32:
7202 case AArch64::ADDv4i32:
7203 case AArch64::SUBv8i8:
7204 case AArch64::SUBv16i8:
7205 case AArch64::SUBv4i16:
7206 case AArch64::SUBv8i16:
7207 case AArch64::SUBv2i32:
7208 case AArch64::SUBv4i32:
7221 case AArch64::FADDHrr:
7222 case AArch64::FADDSrr:
7223 case AArch64::FADDDrr:
7224 case AArch64::FADDv4f16:
7225 case AArch64::FADDv8f16:
7226 case AArch64::FADDv2f32:
7227 case AArch64::FADDv2f64:
7228 case AArch64::FADDv4f32:
7229 case AArch64::FSUBHrr:
7230 case AArch64::FSUBSrr:
7231 case AArch64::FSUBDrr:
7232 case AArch64::FSUBv4f16:
7233 case AArch64::FSUBv8f16:
7234 case AArch64::FSUBv2f32:
7235 case AArch64::FSUBv2f64:
7236 case AArch64::FSUBv4f32:
7255 unsigned CombineOpc,
unsigned ZeroReg = 0,
7256 bool CheckZeroReg =
false) {
7263 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
7270 assert(
MI->getNumOperands() >= 4 &&
MI->getOperand(0).isReg() &&
7271 MI->getOperand(1).isReg() &&
MI->getOperand(2).isReg() &&
7272 MI->getOperand(3).isReg() &&
"MAdd/MSub must have a least 4 regs");
7274 if (
MI->getOperand(3).getReg() != ZeroReg)
7279 MI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) == -1)
7288 unsigned MulOpc,
unsigned ZeroReg) {
7303bool AArch64InstrInfo::isAssociativeAndCommutative(
const MachineInstr &Inst,
7304 bool Invert)
const {
7310 case AArch64::FADDHrr:
7311 case AArch64::FADDSrr:
7312 case AArch64::FADDDrr:
7313 case AArch64::FMULHrr:
7314 case AArch64::FMULSrr:
7315 case AArch64::FMULDrr:
7316 case AArch64::FMULX16:
7317 case AArch64::FMULX32:
7318 case AArch64::FMULX64:
7320 case AArch64::FADDv4f16:
7321 case AArch64::FADDv8f16:
7322 case AArch64::FADDv2f32:
7323 case AArch64::FADDv4f32:
7324 case AArch64::FADDv2f64:
7325 case AArch64::FMULv4f16:
7326 case AArch64::FMULv8f16:
7327 case AArch64::FMULv2f32:
7328 case AArch64::FMULv4f32:
7329 case AArch64::FMULv2f64:
7330 case AArch64::FMULXv4f16:
7331 case AArch64::FMULXv8f16:
7332 case AArch64::FMULXv2f32:
7333 case AArch64::FMULXv4f32:
7334 case AArch64::FMULXv2f64:
7338 case AArch64::FADD_ZZZ_H:
7339 case AArch64::FADD_ZZZ_S:
7340 case AArch64::FADD_ZZZ_D:
7341 case AArch64::FMUL_ZZZ_H:
7342 case AArch64::FMUL_ZZZ_S:
7343 case AArch64::FMUL_ZZZ_D:
7354 case AArch64::ADDWrr:
7355 case AArch64::ADDXrr:
7356 case AArch64::ANDWrr:
7357 case AArch64::ANDXrr:
7358 case AArch64::ORRWrr:
7359 case AArch64::ORRXrr:
7360 case AArch64::EORWrr:
7361 case AArch64::EORXrr:
7362 case AArch64::EONWrr:
7363 case AArch64::EONXrr:
7367 case AArch64::ADDv8i8:
7368 case AArch64::ADDv16i8:
7369 case AArch64::ADDv4i16:
7370 case AArch64::ADDv8i16:
7371 case AArch64::ADDv2i32:
7372 case AArch64::ADDv4i32:
7373 case AArch64::ADDv1i64:
7374 case AArch64::ADDv2i64:
7375 case AArch64::MULv8i8:
7376 case AArch64::MULv16i8:
7377 case AArch64::MULv4i16:
7378 case AArch64::MULv8i16:
7379 case AArch64::MULv2i32:
7380 case AArch64::MULv4i32:
7381 case AArch64::ANDv8i8:
7382 case AArch64::ANDv16i8:
7383 case AArch64::ORRv8i8:
7384 case AArch64::ORRv16i8:
7385 case AArch64::EORv8i8:
7386 case AArch64::EORv16i8:
7388 case AArch64::ADD_ZZZ_B:
7389 case AArch64::ADD_ZZZ_H:
7390 case AArch64::ADD_ZZZ_S:
7391 case AArch64::ADD_ZZZ_D:
7392 case AArch64::MUL_ZZZ_B:
7393 case AArch64::MUL_ZZZ_H:
7394 case AArch64::MUL_ZZZ_S:
7395 case AArch64::MUL_ZZZ_D:
7396 case AArch64::AND_ZZZ:
7397 case AArch64::ORR_ZZZ:
7398 case AArch64::EOR_ZZZ:
7429 auto setFound = [&](
int Opcode,
int Operand,
unsigned ZeroReg,
7437 auto setVFound = [&](
int Opcode,
int Operand,
unsigned Pattern) {
7449 case AArch64::ADDWrr:
7451 "ADDWrr does not have register operands");
7452 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7453 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7455 case AArch64::ADDXrr:
7456 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7457 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7459 case AArch64::SUBWrr:
7460 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7461 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7463 case AArch64::SUBXrr:
7464 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7465 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7467 case AArch64::ADDWri:
7468 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7470 case AArch64::ADDXri:
7471 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7473 case AArch64::SUBWri:
7474 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7476 case AArch64::SUBXri:
7477 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7479 case AArch64::ADDv8i8:
7480 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7481 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7483 case AArch64::ADDv16i8:
7484 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7485 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7487 case AArch64::ADDv4i16:
7488 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7489 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7490 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7491 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7493 case AArch64::ADDv8i16:
7494 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7495 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7496 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7497 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7499 case AArch64::ADDv2i32:
7500 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7501 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7502 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7503 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7505 case AArch64::ADDv4i32:
7506 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7507 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7508 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7509 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7511 case AArch64::SUBv8i8:
7512 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7513 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7515 case AArch64::SUBv16i8:
7516 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7517 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7519 case AArch64::SUBv4i16:
7520 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7521 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7522 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7523 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7525 case AArch64::SUBv8i16:
7526 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7527 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7528 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7529 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7531 case AArch64::SUBv2i32:
7532 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7533 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7534 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7535 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7537 case AArch64::SUBv4i32:
7538 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7539 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7540 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7541 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7547bool AArch64InstrInfo::isAccumulationOpcode(
unsigned Opcode)
const {
7551 case AArch64::UABALB_ZZZ_D:
7552 case AArch64::UABALB_ZZZ_H:
7553 case AArch64::UABALB_ZZZ_S:
7554 case AArch64::UABALT_ZZZ_D:
7555 case AArch64::UABALT_ZZZ_H:
7556 case AArch64::UABALT_ZZZ_S:
7557 case AArch64::SABALB_ZZZ_D:
7558 case AArch64::SABALB_ZZZ_S:
7559 case AArch64::SABALB_ZZZ_H:
7560 case AArch64::SABALT_ZZZ_D:
7561 case AArch64::SABALT_ZZZ_S:
7562 case AArch64::SABALT_ZZZ_H:
7563 case AArch64::UABALv16i8_v8i16:
7564 case AArch64::UABALv2i32_v2i64:
7565 case AArch64::UABALv4i16_v4i32:
7566 case AArch64::UABALv4i32_v2i64:
7567 case AArch64::UABALv8i16_v4i32:
7568 case AArch64::UABALv8i8_v8i16:
7569 case AArch64::UABAv16i8:
7570 case AArch64::UABAv2i32:
7571 case AArch64::UABAv4i16:
7572 case AArch64::UABAv4i32:
7573 case AArch64::UABAv8i16:
7574 case AArch64::UABAv8i8:
7575 case AArch64::SABALv16i8_v8i16:
7576 case AArch64::SABALv2i32_v2i64:
7577 case AArch64::SABALv4i16_v4i32:
7578 case AArch64::SABALv4i32_v2i64:
7579 case AArch64::SABALv8i16_v4i32:
7580 case AArch64::SABALv8i8_v8i16:
7581 case AArch64::SABAv16i8:
7582 case AArch64::SABAv2i32:
7583 case AArch64::SABAv4i16:
7584 case AArch64::SABAv4i32:
7585 case AArch64::SABAv8i16:
7586 case AArch64::SABAv8i8:
7593unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7594 unsigned AccumulationOpcode)
const {
7595 switch (AccumulationOpcode) {
7598 case AArch64::UABALB_ZZZ_D:
7599 return AArch64::UABDLB_ZZZ_D;
7600 case AArch64::UABALB_ZZZ_H:
7601 return AArch64::UABDLB_ZZZ_H;
7602 case AArch64::UABALB_ZZZ_S:
7603 return AArch64::UABDLB_ZZZ_S;
7604 case AArch64::UABALT_ZZZ_D:
7605 return AArch64::UABDLT_ZZZ_D;
7606 case AArch64::UABALT_ZZZ_H:
7607 return AArch64::UABDLT_ZZZ_H;
7608 case AArch64::UABALT_ZZZ_S:
7609 return AArch64::UABDLT_ZZZ_S;
7610 case AArch64::UABALv16i8_v8i16:
7611 return AArch64::UABDLv16i8_v8i16;
7612 case AArch64::UABALv2i32_v2i64:
7613 return AArch64::UABDLv2i32_v2i64;
7614 case AArch64::UABALv4i16_v4i32:
7615 return AArch64::UABDLv4i16_v4i32;
7616 case AArch64::UABALv4i32_v2i64:
7617 return AArch64::UABDLv4i32_v2i64;
7618 case AArch64::UABALv8i16_v4i32:
7619 return AArch64::UABDLv8i16_v4i32;
7620 case AArch64::UABALv8i8_v8i16:
7621 return AArch64::UABDLv8i8_v8i16;
7622 case AArch64::UABAv16i8:
7623 return AArch64::UABDv16i8;
7624 case AArch64::UABAv2i32:
7625 return AArch64::UABDv2i32;
7626 case AArch64::UABAv4i16:
7627 return AArch64::UABDv4i16;
7628 case AArch64::UABAv4i32:
7629 return AArch64::UABDv4i32;
7630 case AArch64::UABAv8i16:
7631 return AArch64::UABDv8i16;
7632 case AArch64::UABAv8i8:
7633 return AArch64::UABDv8i8;
7634 case AArch64::SABALB_ZZZ_D:
7635 return AArch64::SABDLB_ZZZ_D;
7636 case AArch64::SABALB_ZZZ_S:
7637 return AArch64::SABDLB_ZZZ_S;
7638 case AArch64::SABALB_ZZZ_H:
7639 return AArch64::SABDLB_ZZZ_H;
7640 case AArch64::SABALT_ZZZ_D:
7641 return AArch64::SABDLT_ZZZ_D;
7642 case AArch64::SABALT_ZZZ_S:
7643 return AArch64::SABDLT_ZZZ_S;
7644 case AArch64::SABALT_ZZZ_H:
7645 return AArch64::SABDLT_ZZZ_H;
7646 case AArch64::SABALv16i8_v8i16:
7647 return AArch64::SABDLv16i8_v8i16;
7648 case AArch64::SABALv2i32_v2i64:
7649 return AArch64::SABDLv2i32_v2i64;
7650 case AArch64::SABALv4i16_v4i32:
7651 return AArch64::SABDLv4i16_v4i32;
7652 case AArch64::SABALv4i32_v2i64:
7653 return AArch64::SABDLv4i32_v2i64;
7654 case AArch64::SABALv8i16_v4i32:
7655 return AArch64::SABDLv8i16_v4i32;
7656 case AArch64::SABALv8i8_v8i16:
7657 return AArch64::SABDLv8i8_v8i16;
7658 case AArch64::SABAv16i8:
7659 return AArch64::SABDv16i8;
7660 case AArch64::SABAv2i32:
7661 return AArch64::SABAv2i32;
7662 case AArch64::SABAv4i16:
7663 return AArch64::SABDv4i16;
7664 case AArch64::SABAv4i32:
7665 return AArch64::SABDv4i32;
7666 case AArch64::SABAv8i16:
7667 return AArch64::SABDv8i16;
7668 case AArch64::SABAv8i8:
7669 return AArch64::SABDv8i8;
7685 auto Match = [&](
int Opcode,
int Operand,
unsigned Pattern) ->
bool {
7697 assert(
false &&
"Unsupported FP instruction in combiner\n");
7699 case AArch64::FADDHrr:
7701 "FADDHrr does not have register operands");
7703 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
7704 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
7706 case AArch64::FADDSrr:
7708 "FADDSrr does not have register operands");
7710 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
7711 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
7713 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
7714 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
7716 case AArch64::FADDDrr:
7717 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
7718 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
7720 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
7721 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
7723 case AArch64::FADDv4f16:
7724 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
7725 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
7727 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
7728 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
7730 case AArch64::FADDv8f16:
7731 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
7732 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
7734 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
7735 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
7737 case AArch64::FADDv2f32:
7738 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
7739 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
7741 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
7742 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
7744 case AArch64::FADDv2f64:
7745 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
7746 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
7748 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
7749 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
7751 case AArch64::FADDv4f32:
7752 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
7753 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
7755 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
7756 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
7758 case AArch64::FSUBHrr:
7759 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
7760 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
7761 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
7763 case AArch64::FSUBSrr:
7764 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
7766 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
7767 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
7769 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
7771 case AArch64::FSUBDrr:
7772 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
7774 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
7775 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
7777 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
7779 case AArch64::FSUBv4f16:
7780 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
7781 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
7783 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
7784 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
7786 case AArch64::FSUBv8f16:
7787 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
7788 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
7790 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
7791 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
7793 case AArch64::FSUBv2f32:
7794 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
7795 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
7797 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
7798 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
7800 case AArch64::FSUBv2f64:
7801 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
7802 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
7804 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
7805 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
7807 case AArch64::FSUBv4f32:
7808 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
7809 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
7811 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
7812 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
7823 auto Match = [&](
unsigned Opcode,
int Operand,
unsigned Pattern) ->
bool {
7830 if (
MI &&
MI->getOpcode() == TargetOpcode::COPY &&
7831 MI->getOperand(1).getReg().isVirtual())
7833 if (
MI &&
MI->getOpcode() == Opcode) {
7845 case AArch64::FMULv2f32:
7846 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
7847 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
7849 case AArch64::FMULv2f64:
7850 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
7851 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
7853 case AArch64::FMULv4f16:
7854 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
7855 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
7857 case AArch64::FMULv4f32:
7858 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
7859 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
7861 case AArch64::FMULv8f16:
7862 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
7863 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
7876 auto Match = [&](
unsigned Opcode,
unsigned Pattern) ->
bool {
7879 if (
MI !=
nullptr && (
MI->getOpcode() == Opcode) &&
7894 case AArch64::FNEGDr:
7896 case AArch64::FNEGSr:
8028 case AArch64::SUBWrr:
8029 case AArch64::SUBSWrr:
8030 case AArch64::SUBXrr:
8031 case AArch64::SUBSXrr:
8076 unsigned LoadLaneOpCode,
unsigned NumLanes) {
8099 while (!RemainingLanes.
empty() && CurrInstr &&
8100 CurrInstr->getOpcode() == LoadLaneOpCode &&
8102 CurrInstr->getNumOperands() == 4) {
8103 RemainingLanes.
erase(CurrInstr->getOperand(2).getImm());
8109 if (!RemainingLanes.
empty())
8113 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8117 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8118 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8119 if (
TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8135 RemainingLoadInstrs.
insert(LoadInstrs.
begin(), LoadInstrs.
end());
8138 for (; MBBItr !=
MBB->begin() && RemainingSteps > 0 &&
8139 !RemainingLoadInstrs.
empty();
8140 --MBBItr, --RemainingSteps) {
8144 RemainingLoadInstrs.
erase(&CurrInstr);
8154 if (RemainingSteps == 0 && !RemainingLoadInstrs.
empty())
8180 case AArch64::LD1i32:
8182 case AArch64::LD1i16:
8184 case AArch64::LD1i8:
8200 unsigned Pattern,
unsigned NumLanes) {
8208 for (
unsigned i = 0; i < NumLanes - 1; ++i) {
8216 return A->getOperand(2).getImm() >
B->getOperand(2).getImm();
8222 auto LoadToLaneInstrsAscending =
llvm::reverse(LoadToLaneInstrs);
8228 auto CreateLD1Instruction = [&](
MachineInstr *OriginalInstr,
8229 Register SrcRegister,
unsigned Lane,
8231 bool OffsetRegisterKillState) {
8239 InstrIdxForVirtReg.
insert(std::make_pair(NewRegister, InsInstrs.
size()));
8240 InsInstrs.
push_back(LoadIndexIntoRegister);
8246 auto CreateLDRInstruction = [&](
unsigned NumLanes,
Register DestReg,
8252 Opcode = AArch64::LDRSui;
8255 Opcode = AArch64::LDRHui;
8258 Opcode = AArch64::LDRBui;
8262 "Got unsupported number of lanes in machine-combiner gather pattern");
8271 auto LanesToLoadToReg0 =
8273 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8274 Register PrevReg = SubregToReg->getOperand(0).getReg();
8276 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8277 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8278 OffsetRegOperand.
getReg(),
8279 OffsetRegOperand.
isKill());
8286 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8288 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8295 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8296 OriginalSplitToLoadOffsetOperand.
getReg(),
8297 OriginalSplitToLoadOffsetOperand.
isKill());
8299 InstrIdxForVirtReg.
insert(
8300 std::make_pair(DestRegForMiddleIndex, InsInstrs.
size()));
8301 InsInstrs.
push_back(MiddleIndexLoadInstr);
8306 unsigned SubregType;
8309 SubregType = AArch64::ssub;
8312 SubregType = AArch64::hsub;
8315 SubregType = AArch64::bsub;
8319 "Got invalid NumLanes for machine-combiner gather pattern");
8322 auto SubRegToRegInstr =
8324 DestRegForSubregToReg)
8327 InstrIdxForVirtReg.
insert(
8328 std::make_pair(DestRegForSubregToReg, InsInstrs.
size()));
8332 auto LanesToLoadToReg1 =
8334 LoadToLaneInstrsAscending.end());
8335 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8337 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8338 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8339 OffsetRegOperand.
getReg(),
8340 OffsetRegOperand.
isKill());
8343 if (Index == NumLanes / 2 - 2) {
8378bool AArch64InstrInfo::getMachineCombinerPatterns(
8380 bool DoRegPressureReduce)
const {
8401 DoRegPressureReduce);
8430 const Register *ReplacedAddend =
nullptr) {
8431 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8433 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8436 Register SrcReg0 = MUL->getOperand(1).getReg();
8437 bool Src0IsKill = MUL->getOperand(1).isKill();
8438 Register SrcReg1 = MUL->getOperand(2).getReg();
8439 bool Src1IsKill = MUL->getOperand(2).isKill();
8443 if (ReplacedAddend) {
8445 SrcReg2 = *ReplacedAddend;
8472 .
addImm(MUL->getOperand(3).getImm());
8479 assert(
false &&
"Invalid FMA instruction kind \n");
8493 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8494 Opc = AArch64::FNMADDSrrr;
8495 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8496 Opc = AArch64::FNMADDDrrr;
8530 unsigned IdxDupOp,
unsigned MulOpc,
8532 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8533 "Invalid index of FMUL operand");
8541 if (Dup->
getOpcode() == TargetOpcode::COPY)
8550 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8591 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8606 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8633 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8661 unsigned IdxMulOpd,
unsigned MaddOpc,
unsigned VR,
8663 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8667 Register SrcReg0 = MUL->getOperand(1).getReg();
8668 bool Src0IsKill = MUL->getOperand(1).isKill();
8669 Register SrcReg1 = MUL->getOperand(2).getReg();
8670 bool Src1IsKill = MUL->getOperand(2).isKill();
8700 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
8701 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
8715 if (Opcode == AArch64::SUBSWrr)
8716 Opcode = AArch64::SUBWrr;
8717 else if (Opcode == AArch64::SUBSXrr)
8718 Opcode = AArch64::SUBXrr;
8720 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
8721 "Unexpected instruction opcode.");
8738 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8745unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
8746 unsigned int AccumulatorOpCode)
const {
8747 switch (AccumulatorOpCode) {
8748 case AArch64::UABALB_ZZZ_D:
8749 case AArch64::SABALB_ZZZ_D:
8750 case AArch64::UABALT_ZZZ_D:
8751 case AArch64::SABALT_ZZZ_D:
8752 return AArch64::ADD_ZZZ_D;
8753 case AArch64::UABALB_ZZZ_H:
8754 case AArch64::SABALB_ZZZ_H:
8755 case AArch64::UABALT_ZZZ_H:
8756 case AArch64::SABALT_ZZZ_H:
8757 return AArch64::ADD_ZZZ_H;
8758 case AArch64::UABALB_ZZZ_S:
8759 case AArch64::SABALB_ZZZ_S:
8760 case AArch64::UABALT_ZZZ_S:
8761 case AArch64::SABALT_ZZZ_S:
8762 return AArch64::ADD_ZZZ_S;
8763 case AArch64::UABALv16i8_v8i16:
8764 case AArch64::SABALv8i8_v8i16:
8765 case AArch64::SABAv8i16:
8766 case AArch64::UABAv8i16:
8767 return AArch64::ADDv8i16;
8768 case AArch64::SABALv2i32_v2i64:
8769 case AArch64::UABALv2i32_v2i64:
8770 case AArch64::SABALv4i32_v2i64:
8771 return AArch64::ADDv2i64;
8772 case AArch64::UABALv4i16_v4i32:
8773 case AArch64::SABALv4i16_v4i32:
8774 case AArch64::SABALv8i16_v4i32:
8775 case AArch64::SABAv4i32:
8776 case AArch64::UABAv4i32:
8777 return AArch64::ADDv4i32;
8778 case AArch64::UABALv4i32_v2i64:
8779 return AArch64::ADDv2i64;
8780 case AArch64::UABALv8i16_v4i32:
8781 return AArch64::ADDv4i32;
8782 case AArch64::UABALv8i8_v8i16:
8783 case AArch64::SABALv16i8_v8i16:
8784 return AArch64::ADDv8i16;
8785 case AArch64::UABAv16i8:
8786 case AArch64::SABAv16i8:
8787 return AArch64::ADDv16i8;
8788 case AArch64::UABAv4i16:
8789 case AArch64::SABAv4i16:
8790 return AArch64::ADDv4i16;
8791 case AArch64::UABAv2i32:
8792 case AArch64::SABAv2i32:
8793 return AArch64::ADDv2i32;
8794 case AArch64::UABAv8i8:
8795 case AArch64::SABAv8i8:
8796 return AArch64::ADDv8i8;
8805void AArch64InstrInfo::genAlternativeCodeSequence(
8815 MachineInstr *
MUL =
nullptr;
8816 const TargetRegisterClass *RC;
8822 DelInstrs, InstrIdxForVirtReg);
8828 InstrIdxForVirtReg);
8834 InstrIdxForVirtReg);
8843 Opc = AArch64::MADDWrrr;
8844 RC = &AArch64::GPR32RegClass;
8846 Opc = AArch64::MADDXrrr;
8847 RC = &AArch64::GPR64RegClass;
8858 Opc = AArch64::MADDWrrr;
8859 RC = &AArch64::GPR32RegClass;
8861 Opc = AArch64::MADDXrrr;
8862 RC = &AArch64::GPR64RegClass;
8875 const TargetRegisterClass *RC;
8876 unsigned BitSize, MovImm;
8879 MovImm = AArch64::MOVi32imm;
8880 RC = &AArch64::GPR32spRegClass;
8882 Opc = AArch64::MADDWrrr;
8883 RC = &AArch64::GPR32RegClass;
8885 MovImm = AArch64::MOVi64imm;
8886 RC = &AArch64::GPR64spRegClass;
8888 Opc = AArch64::MADDXrrr;
8889 RC = &AArch64::GPR64RegClass;
8900 uint64_t UImm =
SignExtend64(IsSub ? -Imm : Imm, BitSize);
8904 if (Insn.
size() != 1)
8906 MachineInstrBuilder MIB1 =
8907 BuildMI(MF, MIMetadata(Root),
TII->get(MovImm), NewVR)
8908 .
addImm(IsSub ? -Imm : Imm);
8910 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8921 const TargetRegisterClass *SubRC;
8922 unsigned SubOpc, ZeroReg;
8924 SubOpc = AArch64::SUBWrr;
8925 SubRC = &AArch64::GPR32spRegClass;
8926 ZeroReg = AArch64::WZR;
8927 Opc = AArch64::MADDWrrr;
8928 RC = &AArch64::GPR32RegClass;
8930 SubOpc = AArch64::SUBXrr;
8931 SubRC = &AArch64::GPR64spRegClass;
8932 ZeroReg = AArch64::XZR;
8933 Opc = AArch64::MADDXrrr;
8934 RC = &AArch64::GPR64RegClass;
8938 MachineInstrBuilder MIB1 =
8939 BuildMI(MF, MIMetadata(Root),
TII->get(SubOpc), NewVR)
8943 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8954 Opc = AArch64::MSUBWrrr;
8955 RC = &AArch64::GPR32RegClass;
8957 Opc = AArch64::MSUBXrrr;
8958 RC = &AArch64::GPR64RegClass;
8963 Opc = AArch64::MLAv8i8;
8964 RC = &AArch64::FPR64RegClass;
8968 Opc = AArch64::MLAv8i8;
8969 RC = &AArch64::FPR64RegClass;
8973 Opc = AArch64::MLAv16i8;
8974 RC = &AArch64::FPR128RegClass;
8978 Opc = AArch64::MLAv16i8;
8979 RC = &AArch64::FPR128RegClass;
8983 Opc = AArch64::MLAv4i16;
8984 RC = &AArch64::FPR64RegClass;
8988 Opc = AArch64::MLAv4i16;
8989 RC = &AArch64::FPR64RegClass;
8993 Opc = AArch64::MLAv8i16;
8994 RC = &AArch64::FPR128RegClass;
8998 Opc = AArch64::MLAv8i16;
8999 RC = &AArch64::FPR128RegClass;
9003 Opc = AArch64::MLAv2i32;
9004 RC = &AArch64::FPR64RegClass;
9008 Opc = AArch64::MLAv2i32;
9009 RC = &AArch64::FPR64RegClass;
9013 Opc = AArch64::MLAv4i32;
9014 RC = &AArch64::FPR128RegClass;
9018 Opc = AArch64::MLAv4i32;
9019 RC = &AArch64::FPR128RegClass;
9024 Opc = AArch64::MLAv8i8;
9025 RC = &AArch64::FPR64RegClass;
9027 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i8,
9031 Opc = AArch64::MLSv8i8;
9032 RC = &AArch64::FPR64RegClass;
9036 Opc = AArch64::MLAv16i8;
9037 RC = &AArch64::FPR128RegClass;
9039 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv16i8,
9043 Opc = AArch64::MLSv16i8;
9044 RC = &AArch64::FPR128RegClass;
9048 Opc = AArch64::MLAv4i16;
9049 RC = &AArch64::FPR64RegClass;
9051 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9055 Opc = AArch64::MLSv4i16;
9056 RC = &AArch64::FPR64RegClass;
9060 Opc = AArch64::MLAv8i16;
9061 RC = &AArch64::FPR128RegClass;
9063 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9067 Opc = AArch64::MLSv8i16;
9068 RC = &AArch64::FPR128RegClass;
9072 Opc = AArch64::MLAv2i32;
9073 RC = &AArch64::FPR64RegClass;
9075 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9079 Opc = AArch64::MLSv2i32;
9080 RC = &AArch64::FPR64RegClass;
9084 Opc = AArch64::MLAv4i32;
9085 RC = &AArch64::FPR128RegClass;
9087 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9091 Opc = AArch64::MLSv4i32;
9092 RC = &AArch64::FPR128RegClass;
9097 Opc = AArch64::MLAv4i16_indexed;
9098 RC = &AArch64::FPR64RegClass;
9102 Opc = AArch64::MLAv4i16_indexed;
9103 RC = &AArch64::FPR64RegClass;
9107 Opc = AArch64::MLAv8i16_indexed;
9108 RC = &AArch64::FPR128RegClass;
9112 Opc = AArch64::MLAv8i16_indexed;
9113 RC = &AArch64::FPR128RegClass;
9117 Opc = AArch64::MLAv2i32_indexed;
9118 RC = &AArch64::FPR64RegClass;
9122 Opc = AArch64::MLAv2i32_indexed;
9123 RC = &AArch64::FPR64RegClass;
9127 Opc = AArch64::MLAv4i32_indexed;
9128 RC = &AArch64::FPR128RegClass;
9132 Opc = AArch64::MLAv4i32_indexed;
9133 RC = &AArch64::FPR128RegClass;
9138 Opc = AArch64::MLAv4i16_indexed;
9139 RC = &AArch64::FPR64RegClass;
9141 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9145 Opc = AArch64::MLSv4i16_indexed;
9146 RC = &AArch64::FPR64RegClass;
9150 Opc = AArch64::MLAv8i16_indexed;
9151 RC = &AArch64::FPR128RegClass;
9153 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9157 Opc = AArch64::MLSv8i16_indexed;
9158 RC = &AArch64::FPR128RegClass;
9162 Opc = AArch64::MLAv2i32_indexed;
9163 RC = &AArch64::FPR64RegClass;
9165 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9169 Opc = AArch64::MLSv2i32_indexed;
9170 RC = &AArch64::FPR64RegClass;
9174 Opc = AArch64::MLAv4i32_indexed;
9175 RC = &AArch64::FPR128RegClass;
9177 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9181 Opc = AArch64::MLSv4i32_indexed;
9182 RC = &AArch64::FPR128RegClass;
9188 Opc = AArch64::FMADDHrrr;
9189 RC = &AArch64::FPR16RegClass;
9193 Opc = AArch64::FMADDSrrr;
9194 RC = &AArch64::FPR32RegClass;
9198 Opc = AArch64::FMADDDrrr;
9199 RC = &AArch64::FPR64RegClass;
9204 Opc = AArch64::FMADDHrrr;
9205 RC = &AArch64::FPR16RegClass;
9209 Opc = AArch64::FMADDSrrr;
9210 RC = &AArch64::FPR32RegClass;
9214 Opc = AArch64::FMADDDrrr;
9215 RC = &AArch64::FPR64RegClass;
9220 Opc = AArch64::FMLAv1i32_indexed;
9221 RC = &AArch64::FPR32RegClass;
9226 Opc = AArch64::FMLAv1i32_indexed;
9227 RC = &AArch64::FPR32RegClass;
9233 Opc = AArch64::FMLAv1i64_indexed;
9234 RC = &AArch64::FPR64RegClass;
9239 Opc = AArch64::FMLAv1i64_indexed;
9240 RC = &AArch64::FPR64RegClass;
9246 RC = &AArch64::FPR64RegClass;
9247 Opc = AArch64::FMLAv4i16_indexed;
9252 RC = &AArch64::FPR64RegClass;
9253 Opc = AArch64::FMLAv4f16;
9258 RC = &AArch64::FPR64RegClass;
9259 Opc = AArch64::FMLAv4i16_indexed;
9264 RC = &AArch64::FPR64RegClass;
9265 Opc = AArch64::FMLAv4f16;
9272 RC = &AArch64::FPR64RegClass;
9274 Opc = AArch64::FMLAv2i32_indexed;
9278 Opc = AArch64::FMLAv2f32;
9285 RC = &AArch64::FPR64RegClass;
9287 Opc = AArch64::FMLAv2i32_indexed;
9291 Opc = AArch64::FMLAv2f32;
9298 RC = &AArch64::FPR128RegClass;
9299 Opc = AArch64::FMLAv8i16_indexed;
9304 RC = &AArch64::FPR128RegClass;
9305 Opc = AArch64::FMLAv8f16;
9310 RC = &AArch64::FPR128RegClass;
9311 Opc = AArch64::FMLAv8i16_indexed;
9316 RC = &AArch64::FPR128RegClass;
9317 Opc = AArch64::FMLAv8f16;
9324 RC = &AArch64::FPR128RegClass;
9326 Opc = AArch64::FMLAv2i64_indexed;
9330 Opc = AArch64::FMLAv2f64;
9337 RC = &AArch64::FPR128RegClass;
9339 Opc = AArch64::FMLAv2i64_indexed;
9343 Opc = AArch64::FMLAv2f64;
9351 RC = &AArch64::FPR128RegClass;
9353 Opc = AArch64::FMLAv4i32_indexed;
9357 Opc = AArch64::FMLAv4f32;
9365 RC = &AArch64::FPR128RegClass;
9367 Opc = AArch64::FMLAv4i32_indexed;
9371 Opc = AArch64::FMLAv4f32;
9378 Opc = AArch64::FNMSUBHrrr;
9379 RC = &AArch64::FPR16RegClass;
9383 Opc = AArch64::FNMSUBSrrr;
9384 RC = &AArch64::FPR32RegClass;
9388 Opc = AArch64::FNMSUBDrrr;
9389 RC = &AArch64::FPR64RegClass;
9394 Opc = AArch64::FNMADDHrrr;
9395 RC = &AArch64::FPR16RegClass;
9399 Opc = AArch64::FNMADDSrrr;
9400 RC = &AArch64::FPR32RegClass;
9404 Opc = AArch64::FNMADDDrrr;
9405 RC = &AArch64::FPR64RegClass;
9410 Opc = AArch64::FMSUBHrrr;
9411 RC = &AArch64::FPR16RegClass;
9415 Opc = AArch64::FMSUBSrrr;
9416 RC = &AArch64::FPR32RegClass;
9420 Opc = AArch64::FMSUBDrrr;
9421 RC = &AArch64::FPR64RegClass;
9426 Opc = AArch64::FMLSv1i32_indexed;
9427 RC = &AArch64::FPR32RegClass;
9433 Opc = AArch64::FMLSv1i64_indexed;
9434 RC = &AArch64::FPR64RegClass;
9441 RC = &AArch64::FPR64RegClass;
9443 MachineInstrBuilder MIB1 =
9444 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f16), NewVR)
9447 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9449 Opc = AArch64::FMLAv4f16;
9453 Opc = AArch64::FMLAv4i16_indexed;
9460 RC = &AArch64::FPR64RegClass;
9461 Opc = AArch64::FMLSv4f16;
9466 RC = &AArch64::FPR64RegClass;
9467 Opc = AArch64::FMLSv4i16_indexed;
9474 RC = &AArch64::FPR64RegClass;
9476 Opc = AArch64::FMLSv2i32_indexed;
9480 Opc = AArch64::FMLSv2f32;
9488 RC = &AArch64::FPR128RegClass;
9490 MachineInstrBuilder MIB1 =
9491 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv8f16), NewVR)
9494 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9496 Opc = AArch64::FMLAv8f16;
9500 Opc = AArch64::FMLAv8i16_indexed;
9507 RC = &AArch64::FPR128RegClass;
9508 Opc = AArch64::FMLSv8f16;
9513 RC = &AArch64::FPR128RegClass;
9514 Opc = AArch64::FMLSv8i16_indexed;
9521 RC = &AArch64::FPR128RegClass;
9523 Opc = AArch64::FMLSv2i64_indexed;
9527 Opc = AArch64::FMLSv2f64;
9535 RC = &AArch64::FPR128RegClass;
9537 Opc = AArch64::FMLSv4i32_indexed;
9541 Opc = AArch64::FMLSv4f32;
9548 RC = &AArch64::FPR64RegClass;
9550 MachineInstrBuilder MIB1 =
9551 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f32), NewVR)
9554 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9556 Opc = AArch64::FMLAv2i32_indexed;
9560 Opc = AArch64::FMLAv2f32;
9568 RC = &AArch64::FPR128RegClass;
9570 MachineInstrBuilder MIB1 =
9571 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f32), NewVR)
9574 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9576 Opc = AArch64::FMLAv4i32_indexed;
9580 Opc = AArch64::FMLAv4f32;
9588 RC = &AArch64::FPR128RegClass;
9590 MachineInstrBuilder MIB1 =
9591 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f64), NewVR)
9594 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9596 Opc = AArch64::FMLAv2i64_indexed;
9600 Opc = AArch64::FMLAv2f64;
9612 &AArch64::FPR128RegClass, MRI);
9621 &AArch64::FPR128RegClass, MRI);
9630 &AArch64::FPR128_loRegClass, MRI);
9639 &AArch64::FPR128RegClass, MRI);
9648 &AArch64::FPR128_loRegClass, MRI);
9682 for (
auto *
MI : InsInstrs)
9683 MI->setFlags(Flags);
9724 bool IsNegativeBranch =
false;
9725 bool IsTestAndBranch =
false;
9726 unsigned TargetBBInMI = 0;
9727 switch (
MI.getOpcode()) {
9731 case AArch64::CBWPri:
9732 case AArch64::CBXPri:
9733 case AArch64::CBBAssertExt:
9734 case AArch64::CBHAssertExt:
9735 case AArch64::CBWPrr:
9736 case AArch64::CBXPrr:
9742 case AArch64::CBNZW:
9743 case AArch64::CBNZX:
9745 IsNegativeBranch =
true;
9750 IsTestAndBranch =
true;
9752 case AArch64::TBNZW:
9753 case AArch64::TBNZX:
9755 IsNegativeBranch =
true;
9756 IsTestAndBranch =
true;
9762 if (IsTestAndBranch &&
MI.getOperand(1).getImm())
9766 assert(
MI.getParent() &&
"Incomplete machine instruction\n");
9777 while (
DefMI->isCopy()) {
9786 switch (
DefMI->getOpcode()) {
9790 case AArch64::ANDWri:
9791 case AArch64::ANDXri: {
9792 if (IsTestAndBranch)
9799 bool Is32Bit = (
DefMI->getOpcode() == AArch64::ANDWri);
9801 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
9816 unsigned Opc = (Imm < 32)
9817 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
9818 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
9831 if (!Is32Bit && Imm < 32)
9833 MI.eraseFromParent();
9837 case AArch64::CSINCWr:
9838 case AArch64::CSINCXr: {
9839 if (!(
DefMI->getOperand(1).getReg() == AArch64::WZR &&
9840 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
9841 !(
DefMI->getOperand(1).getReg() == AArch64::XZR &&
9842 DefMI->getOperand(2).getReg() == AArch64::XZR))
9845 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
9858 if (IsNegativeBranch)
9861 MI.eraseFromParent();
9867std::pair<unsigned, unsigned>
9868AArch64InstrInfo::decomposeMachineOperandsTargetFlags(
unsigned TF)
const {
9870 return std::make_pair(TF & Mask, TF & ~Mask);
9874AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags()
const {
9877 static const std::pair<unsigned, const char *> TargetFlags[] = {
9878 {MO_PAGE,
"aarch64-page"}, {
MO_PAGEOFF,
"aarch64-pageoff"},
9879 {
MO_G3,
"aarch64-g3"}, {
MO_G2,
"aarch64-g2"},
9880 {
MO_G1,
"aarch64-g1"}, {
MO_G0,
"aarch64-g0"},
9886AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags()
const {
9887 using namespace AArch64II;
9889 static const std::pair<unsigned, const char *> TargetFlags[] = {
9892 {
MO_NC,
"aarch64-nc"},
9893 {
MO_S,
"aarch64-s"},
9904AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags()
const {
9905 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10007 MachineFunction *MF =
C.getMF();
10009 const AArch64RegisterInfo *ARI =
10010 static_cast<const AArch64RegisterInfo *
>(&
TRI);
10013 for (
unsigned Reg : AArch64::GPR64RegClass) {
10015 Reg != AArch64::LR &&
10016 Reg != AArch64::X16 &&
10017 Reg != AArch64::X17 &&
10018 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
10019 C.isAvailableInsideSeq(
Reg,
TRI))
10050 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10053std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10054AArch64InstrInfo::getOutliningCandidateInfo(
10056 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10057 unsigned MinRepeats)
const {
10058 unsigned SequenceSize = 0;
10059 for (
auto &
MI : RepeatedSequenceLocs[0])
10062 unsigned NumBytesToCreateFrame = 0;
10068 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10069 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10070 if (LastMI.
getOpcode() == AArch64::ADRP &&
10073 return std::nullopt;
10078 if ((FirstMI.
getOpcode() == AArch64::ADDXri ||
10079 FirstMI.
getOpcode() == AArch64::LDRXui) &&
10082 return std::nullopt;
10093 if (std::adjacent_find(
10094 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10095 [](
const outliner::Candidate &a,
const outliner::Candidate &b) {
10098 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10099 outliningCandidatesSigningKeyConsensus(a, b) &&
10100 outliningCandidatesV8_3OpsConsensus(a, b)) {
10104 }) != RepeatedSequenceLocs.end()) {
10105 return std::nullopt;
10122 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10123 const auto RASignCondition = RepeatedSequenceLocs[0]
10126 ->getSignReturnAddressCondition();
10129 NumBytesToCreateFrame += 8;
10132 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10133 *RepeatedSequenceLocs[0].getMF());
10134 NumBytesToCheckLRInTCEpilogue =
10138 if (isTailCallReturnInst(RepeatedSequenceLocs[0].
back()))
10139 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10147 for (
auto &
MI :
C) {
10148 if (
MI.modifiesRegister(AArch64::SP, &
TRI)) {
10149 switch (
MI.getOpcode()) {
10150 case AArch64::ADDXri:
10151 case AArch64::ADDWri:
10152 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10153 assert(
MI.getOperand(2).isImm() &&
10154 "Expected operand to be immediate");
10155 assert(
MI.getOperand(1).isReg() &&
10156 "Expected operand to be a register");
10160 if (
MI.getOperand(1).getReg() == AArch64::SP)
10161 SPValue +=
MI.getOperand(2).getImm();
10165 case AArch64::SUBXri:
10166 case AArch64::SUBWri:
10167 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10168 assert(
MI.getOperand(2).isImm() &&
10169 "Expected operand to be immediate");
10170 assert(
MI.getOperand(1).isReg() &&
10171 "Expected operand to be a register");
10175 if (
MI.getOperand(1).getReg() == AArch64::SP)
10176 SPValue -=
MI.getOperand(2).getImm();
10193 if (RepeatedSequenceLocs.size() < MinRepeats)
10194 return std::nullopt;
10198 unsigned FlagsSetInAll = 0xF;
10202 FlagsSetInAll &=
C.Flags;
10204 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10207 auto SetCandidateCallInfo =
10208 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
10210 C.setCallInfo(CallID, NumBytesForCall);
10214 NumBytesToCreateFrame += 4;
10222 unsigned CFICount = 0;
10223 for (
auto &
I : RepeatedSequenceLocs[0]) {
10224 if (
I.isCFIInstruction())
10234 std::vector<MCCFIInstruction> CFIInstructions =
10235 C.getMF()->getFrameInstructions();
10237 if (CFICount > 0 && CFICount != CFIInstructions.size())
10238 return std::nullopt;
10246 if (!
MI.modifiesRegister(AArch64::SP, &
TRI) &&
10247 !
MI.readsRegister(AArch64::SP, &
TRI))
10253 if (
MI.modifiesRegister(AArch64::SP, &
TRI))
10258 if (
MI.mayLoadOrStore()) {
10261 bool OffsetIsScalable;
10265 if (!getMemOperandWithOffset(
MI,
Base,
Offset, OffsetIsScalable, &
TRI) ||
10266 !
Base->isReg() ||
Base->getReg() != AArch64::SP)
10270 if (OffsetIsScalable)
10278 TypeSize Scale(0U,
false), DummyWidth(0U,
false);
10279 getMemOpInfo(
MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10282 if (
Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10283 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10298 bool AllStackInstrsSafe =
10303 if (RepeatedSequenceLocs[0].
back().isTerminator()) {
10305 NumBytesToCreateFrame = 0;
10306 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10310 else if (LastInstrOpcode == AArch64::BL ||
10311 ((LastInstrOpcode == AArch64::BLR ||
10312 LastInstrOpcode == AArch64::BLRNoIP) &&
10316 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10324 unsigned NumBytesNoStackCalls = 0;
10325 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10331 ?
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI)
10340 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10343 if (LRAvailable && !IsNoReturn) {
10344 NumBytesNoStackCalls += 4;
10346 CandidatesWithoutStackFixups.push_back(
C);
10351 else if (findRegisterToSaveLRTo(
C)) {
10352 NumBytesNoStackCalls += 12;
10354 CandidatesWithoutStackFixups.push_back(
C);
10359 else if (
C.isAvailableInsideSeq(AArch64::SP,
TRI)) {
10360 NumBytesNoStackCalls += 12;
10362 CandidatesWithoutStackFixups.push_back(
C);
10368 NumBytesNoStackCalls += SequenceSize;
10375 if (!AllStackInstrsSafe ||
10376 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10377 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10379 if (RepeatedSequenceLocs.size() < MinRepeats)
10380 return std::nullopt;
10433 (!
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI) ||
10434 !findRegisterToSaveLRTo(
C));
10440 if (RepeatedSequenceLocs.size() < MinRepeats)
10441 return std::nullopt;
10450 bool ModStackToSaveLR =
false;
10453 ModStackToSaveLR =
true;
10462 ModStackToSaveLR =
true;
10464 if (ModStackToSaveLR) {
10466 if (!AllStackInstrsSafe)
10467 return std::nullopt;
10470 NumBytesToCreateFrame += 8;
10477 return std::nullopt;
10479 return std::make_unique<outliner::OutlinedFunction>(
10480 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10483void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10484 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
10488 const auto &CFn = Candidates.front().getMF()->getFunction();
10490 if (CFn.hasFnAttribute(
"ptrauth-returns"))
10491 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-returns"));
10492 if (CFn.hasFnAttribute(
"ptrauth-auth-traps"))
10493 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-auth-traps"));
10496 if (CFn.hasFnAttribute(
"sign-return-address"))
10497 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address"));
10498 if (CFn.hasFnAttribute(
"sign-return-address-key"))
10499 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address-key"));
10501 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
10504bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10509 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
10516 if (
F.hasSection())
10522 AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
10523 if (!AFI || AFI->
hasRedZone().value_or(
true))
10543 unsigned &Flags)
const {
10545 "Must track liveness!");
10547 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10562 auto AreAllUnsafeRegsDead = [&LRU]() {
10563 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10564 LRU.available(AArch64::NZCV);
10579 bool LRAvailableEverywhere =
true;
10581 LRU.addLiveOuts(
MBB);
10583 auto UpdateWholeMBBFlags = [&
Flags](
const MachineInstr &
MI) {
10584 if (
MI.isCall() && !
MI.isTerminator())
10590 auto CreateNewRangeStartingAt =
10591 [&RangeBegin, &RangeEnd,
10593 RangeBegin = NewBegin;
10594 RangeEnd = std::next(RangeBegin);
10597 auto SaveRangeIfNonEmpty = [&RangeLen, &
Ranges, &RangeBegin, &RangeEnd]() {
10603 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10605 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10607 Ranges.emplace_back(RangeBegin, RangeEnd);
10615 for (; FirstPossibleEndPt !=
MBB.
instr_rend(); ++FirstPossibleEndPt) {
10616 LRU.stepBackward(*FirstPossibleEndPt);
10619 UpdateWholeMBBFlags(*FirstPossibleEndPt);
10620 if (AreAllUnsafeRegsDead())
10627 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
10632 LRU.stepBackward(
MI);
10633 UpdateWholeMBBFlags(
MI);
10634 if (!AreAllUnsafeRegsDead()) {
10635 SaveRangeIfNonEmpty();
10636 CreateNewRangeStartingAt(
MI.getIterator());
10639 LRAvailableEverywhere &= LRU.available(AArch64::LR);
10640 RangeBegin =
MI.getIterator();
10645 if (AreAllUnsafeRegsDead())
10646 SaveRangeIfNonEmpty();
10654 if (!LRAvailableEverywhere)
10662 unsigned Flags)
const {
10663 MachineInstr &
MI = *MIT;
10667 switch (
MI.getOpcode()) {
10668 case AArch64::PACM:
10669 case AArch64::PACIASP:
10670 case AArch64::PACIBSP:
10671 case AArch64::PACIASPPC:
10672 case AArch64::PACIBSPPC:
10673 case AArch64::AUTIASP:
10674 case AArch64::AUTIBSP:
10675 case AArch64::AUTIASPPCi:
10676 case AArch64::AUTIASPPCr:
10677 case AArch64::AUTIBSPPCi:
10678 case AArch64::AUTIBSPPCr:
10679 case AArch64::RETAA:
10680 case AArch64::RETAB:
10681 case AArch64::RETAASPPCi:
10682 case AArch64::RETAASPPCr:
10683 case AArch64::RETABSPPCi:
10684 case AArch64::RETABSPPCr:
10685 case AArch64::EMITBKEY:
10686 case AArch64::PAUTH_PROLOGUE:
10687 case AArch64::PAUTH_EPILOGUE:
10697 if (
MI.isCFIInstruction())
10701 if (
MI.isTerminator())
10707 for (
const MachineOperand &MOP :
MI.operands()) {
10710 assert(!MOP.isCFIIndex());
10713 if (MOP.isReg() && !MOP.isImplicit() &&
10714 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
10721 if (
MI.getOpcode() == AArch64::ADRP)
10741 for (
const MachineOperand &MOP :
MI.operands()) {
10742 if (MOP.isGlobal()) {
10750 if (Callee &&
Callee->getName() ==
"\01_mcount")
10758 if (
MI.getOpcode() == AArch64::BLR ||
10759 MI.getOpcode() == AArch64::BLRNoIP ||
MI.getOpcode() == AArch64::BL)
10763 return UnknownCallOutlineType;
10771 return UnknownCallOutlineType;
10779 return UnknownCallOutlineType;
10800 for (MachineInstr &
MI :
MBB) {
10801 const MachineOperand *
Base;
10802 TypeSize Width(0,
false);
10804 bool OffsetIsScalable;
10807 if (!
MI.mayLoadOrStore() ||
10810 (
Base->isReg() &&
Base->getReg() != AArch64::SP))
10814 TypeSize Scale(0U,
false);
10815 int64_t Dummy1, Dummy2;
10818 assert(StackOffsetOperand.
isImm() &&
"Stack offset wasn't immediate!");
10820 assert(Scale != 0 &&
"Unexpected opcode!");
10821 assert(!OffsetIsScalable &&
"Expected offset to be a byte offset");
10826 int64_t NewImm = (
Offset + 16) / (int64_t)Scale.getFixedValue();
10827 StackOffsetOperand.
setImm(NewImm);
10833 bool ShouldSignReturnAddr) {
10834 if (!ShouldSignReturnAddr)
10842void AArch64InstrInfo::buildOutlinedFrame(
10846 AArch64FunctionInfo *FI = MF.
getInfo<AArch64FunctionInfo>();
10854 unsigned TailOpcode;
10856 TailOpcode = AArch64::TCRETURNdi;
10860 TailOpcode = AArch64::TCRETURNriALL;
10871 bool IsLeafFunction =
true;
10874 auto IsNonTailCall = [](
const MachineInstr &
MI) {
10875 return MI.isCall() && !
MI.isReturn();
10885 "Can only fix up stack references once");
10886 fixupPostOutline(
MBB);
10888 IsLeafFunction =
false;
10899 Et = std::prev(
MBB.
end());
10909 if (MF.
getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
10913 CFIBuilder.buildDefCFAOffset(16);
10917 CFIBuilder.buildOffset(AArch64::LR, -16);
10931 RASignCondition, !IsLeafFunction);
10960 fixupPostOutline(
MBB);
10971 .addGlobalAddress(
M.getNamedValue(MF.
getName()))
10981 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
10990 MachineInstr *Save;
10991 MachineInstr *Restore;
10997 assert(
Reg &&
"No callee-saved register available?");
11031 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
11039bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11047 bool AllowSideEffects)
const {
11049 const AArch64Subtarget &STI = MF.
getSubtarget<AArch64Subtarget>();
11052 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
11065 assert(STI.hasNEON() &&
"Expected to have NEON.");
11071std::optional<DestSourcePair>
11076 if (((
MI.getOpcode() == AArch64::ORRWrs &&
11077 MI.getOperand(1).getReg() == AArch64::WZR &&
11078 MI.getOperand(3).getImm() == 0x0) ||
11079 (
MI.getOpcode() == AArch64::ORRWrr &&
11080 MI.getOperand(1).getReg() == AArch64::WZR)) &&
11082 (!
MI.getOperand(0).getReg().isVirtual() ||
11083 MI.getOperand(0).getSubReg() == 0) &&
11084 (!
MI.getOperand(0).getReg().isPhysical() ||
11089 if (
MI.getOpcode() == AArch64::ORRXrs &&
11090 MI.getOperand(1).getReg() == AArch64::XZR &&
11091 MI.getOperand(3).getImm() == 0x0)
11094 return std::nullopt;
11097std::optional<DestSourcePair>
11099 if ((
MI.getOpcode() == AArch64::ORRWrs &&
11100 MI.getOperand(1).getReg() == AArch64::WZR &&
11101 MI.getOperand(3).getImm() == 0x0) ||
11102 (
MI.getOpcode() == AArch64::ORRWrr &&
11103 MI.getOperand(1).getReg() == AArch64::WZR))
11105 return std::nullopt;
11108std::optional<RegImmPair>
11117 return std::nullopt;
11119 switch (
MI.getOpcode()) {
11121 return std::nullopt;
11122 case AArch64::SUBWri:
11123 case AArch64::SUBXri:
11124 case AArch64::SUBSWri:
11125 case AArch64::SUBSXri:
11128 case AArch64::ADDSWri:
11129 case AArch64::ADDSXri:
11130 case AArch64::ADDWri:
11131 case AArch64::ADDXri: {
11133 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg() ||
11134 !
MI.getOperand(2).isImm())
11135 return std::nullopt;
11136 int Shift =
MI.getOperand(3).getImm();
11137 assert((Shift == 0 || Shift == 12) &&
"Shift can be either 0 or 12");
11141 return RegImmPair{
MI.getOperand(1).getReg(),
Offset};
11147static std::optional<ParamLoadedValue>
11151 auto DestSrc =
TII->isCopyLikeInstr(
MI);
11153 return std::nullopt;
11155 Register DestReg = DestSrc->Destination->getReg();
11156 Register SrcReg = DestSrc->Source->getReg();
11159 return std::nullopt;
11164 if (DestReg == DescribedReg)
11168 if (
MI.getOpcode() == AArch64::ORRWrs &&
11169 TRI->isSuperRegister(DestReg, DescribedReg))
11173 if (
MI.getOpcode() == AArch64::ORRXrs &&
11174 TRI->isSubRegister(DestReg, DescribedReg)) {
11175 Register SrcSubReg =
TRI->getSubReg(SrcReg, AArch64::sub_32);
11179 assert(!
TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11180 "Unhandled ORR[XW]rs copy case");
11182 return std::nullopt;
11185bool AArch64InstrInfo::isFunctionSafeToSplit(
const MachineFunction &MF)
const {
11190 if (MF.
getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(
true))
11196bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11200 auto isAsmGoto = [](
const MachineInstr &
MI) {
11201 return MI.getOpcode() == AArch64::INLINEASM_BR;
11211 auto containsMBB = [&
MBB](
const MachineJumpTableEntry &JTE) {
11218 for (
const MachineInstr &
MI :
MBB) {
11219 switch (
MI.getOpcode()) {
11220 case TargetOpcode::G_BRJT:
11221 case AArch64::JumpTableDest32:
11222 case AArch64::JumpTableDest16:
11223 case AArch64::JumpTableDest8:
11234std::optional<ParamLoadedValue>
11237 const MachineFunction *MF =
MI.getMF();
11239 switch (
MI.getOpcode()) {
11240 case AArch64::MOVZWi:
11241 case AArch64::MOVZXi: {
11244 if (!
TRI->isSuperRegisterEq(
MI.getOperand(0).getReg(),
Reg))
11245 return std::nullopt;
11247 if (!
MI.getOperand(1).isImm())
11248 return std::nullopt;
11249 int64_t Immediate =
MI.getOperand(1).getImm();
11250 int Shift =
MI.getOperand(2).getImm();
11254 case AArch64::ORRWrs:
11255 case AArch64::ORRXrs:
11262bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11265 ExtMI.
getOpcode() == TargetOpcode::G_ZEXT ||
11266 ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT);
11269 if (ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT)
11279 return UserMI->
getOpcode() == TargetOpcode::G_PTR_ADD;
11282uint64_t AArch64InstrInfo::getElementSizeForOpcode(
unsigned Opc)
const {
11286bool AArch64InstrInfo::isPTestLikeOpcode(
unsigned Opc)
const {
11290bool AArch64InstrInfo::isWhileOpcode(
unsigned Opc)
const {
11295AArch64InstrInfo::getTailDuplicateSize(
CodeGenOptLevel OptLevel)
const {
11299bool AArch64InstrInfo::isLegalAddressingMode(
unsigned NumBytes, int64_t
Offset,
11300 unsigned Scale)
const {
11311 unsigned Shift =
Log2_64(NumBytes);
11312 if (NumBytes &&
Offset > 0 && (
Offset / NumBytes) <= (1LL << 12) - 1 &&
11320 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11325 return AArch64::BLRNoIP;
11327 return AArch64::BLR;
11333 auto Builder =
BuildMI(
MBB, InsertPt,
DL,
get(AArch64::PAUTH_EPILOGUE))
11343 Register TargetReg,
bool FrameSetup)
const {
11344 assert(TargetReg != AArch64::SP &&
"New top of stack cannot already be in SP");
11356 MF.
insert(MBBInsertPoint, LoopTestMBB);
11359 MF.
insert(MBBInsertPoint, LoopBodyMBB);
11361 MF.
insert(MBBInsertPoint, ExitMBB);
11371 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::SUBSXrx64),
11379 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::Bcc))
11385 BuildMI(*LoopBodyMBB, LoopBodyMBB->
end(),
DL,
TII->get(AArch64::LDRXui))
11402 BuildMI(*ExitMBB, ExitMBB->
end(),
DL,
TII->get(AArch64::ADDXri), AArch64::SP)
11421 MBB.addSuccessor(LoopTestMBB);
11427 return ExitMBB->
begin();
11432 MachineFunction *MF;
11433 const TargetInstrInfo *
TII;
11434 const TargetRegisterInfo *
TRI;
11435 MachineRegisterInfo &MRI;
11438 MachineBasicBlock *LoopBB;
11440 MachineInstr *CondBranch;
11442 MachineInstr *Comp;
11444 unsigned CompCounterOprNum;
11446 MachineInstr *Update;
11448 unsigned UpdateCounterOprNum;
11452 bool IsUpdatePriorComp;
11458 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11459 MachineInstr *Comp,
unsigned CompCounterOprNum,
11460 MachineInstr *Update,
unsigned UpdateCounterOprNum,
11461 Register Init,
bool IsUpdatePriorComp,
11462 const SmallVectorImpl<MachineOperand> &
Cond)
11464 TII(MF->getSubtarget().getInstrInfo()),
11465 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11466 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11467 CompCounterOprNum(CompCounterOprNum), Update(Update),
11468 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11471 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
11477 std::optional<bool> createTripCountGreaterCondition(
11478 int TC, MachineBasicBlock &
MBB,
11479 SmallVectorImpl<MachineOperand> &CondParam)
override {
11487 void createRemainingIterationsGreaterCondition(
11488 int TC, MachineBasicBlock &
MBB, SmallVectorImpl<MachineOperand> &
Cond,
11489 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts)
override;
11491 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
11493 void adjustTripCount(
int TripCountAdjust)
override {}
11495 bool isMVEExpanderSupported()
override {
return true; }
11514 }
else if (
I == ReplaceOprNum) {
11519 MBB.insert(InsertTo, NewMI);
11523void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11539 assert(CondBranch->getOpcode() == AArch64::Bcc);
11543 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11550 auto AccumulateCond = [&](
Register CurCond,
11561 if (!LastStage0Insts.
empty() && LastStage0Insts[Comp]->getParent() == &
MBB) {
11565 for (
int I = 0;
I <= TC; ++
I) {
11571 AccCond = AccumulateCond(AccCond, CC);
11575 if (Update != Comp && IsUpdatePriorComp) {
11577 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11578 NextCounter =
cloneInstr(Update, UpdateCounterOprNum, Counter,
MBB,
11582 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
11584 }
else if (Update != Comp) {
11589 Counter = NextCounter;
11593 if (LastStage0Insts.
empty()) {
11597 if (IsUpdatePriorComp)
11602 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11605 for (
int I = 0;
I <= TC; ++
I) {
11609 AccCond = AccumulateCond(AccCond, CC);
11610 if (
I != TC && Update != Comp)
11613 Counter = NextCounter;
11629 assert(Phi.getNumOperands() == 5);
11630 if (Phi.getOperand(2).getMBB() ==
MBB) {
11631 RegMBB = Phi.getOperand(1).getReg();
11632 RegOther = Phi.getOperand(3).getReg();
11634 assert(Phi.getOperand(4).getMBB() ==
MBB);
11635 RegMBB = Phi.getOperand(3).getReg();
11636 RegOther = Phi.getOperand(1).getReg();
11641 if (!
Reg.isVirtual())
11650 unsigned &UpdateCounterOprNum,
Register &InitReg,
11651 bool &IsUpdatePriorComp) {
11665 if (!
Reg.isVirtual())
11668 UpdateInst =
nullptr;
11669 UpdateCounterOprNum = 0;
11671 IsUpdatePriorComp =
true;
11675 if (Def->getParent() != LoopBB)
11677 if (Def->isCopy()) {
11679 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
11681 CurReg = Def->getOperand(1).getReg();
11682 }
else if (Def->isPHI()) {
11686 IsUpdatePriorComp =
false;
11691 switch (Def->getOpcode()) {
11692 case AArch64::ADDSXri:
11693 case AArch64::ADDSWri:
11694 case AArch64::SUBSXri:
11695 case AArch64::SUBSWri:
11696 case AArch64::ADDXri:
11697 case AArch64::ADDWri:
11698 case AArch64::SUBXri:
11699 case AArch64::SUBWri:
11701 UpdateCounterOprNum = 1;
11703 case AArch64::ADDSXrr:
11704 case AArch64::ADDSWrr:
11705 case AArch64::SUBSXrr:
11706 case AArch64::SUBSWrr:
11707 case AArch64::ADDXrr:
11708 case AArch64::ADDWrr:
11709 case AArch64::SUBXrr:
11710 case AArch64::SUBWrr:
11713 UpdateCounterOprNum = 1;
11715 UpdateCounterOprNum = 2;
11722 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
11737std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
11748 if (
MI.isCall() ||
MI.hasUnmodeledSideEffects())
11759 if (
TBB == LoopBB && FBB == LoopBB)
11763 if (
TBB != LoopBB && FBB ==
nullptr)
11766 assert((
TBB == LoopBB || FBB == LoopBB) &&
11767 "The Loop must be a single-basic-block loop");
11772 if (CondBranch->
getOpcode() != AArch64::Bcc)
11780 unsigned CompCounterOprNum = 0;
11782 if (
MI.modifiesRegister(AArch64::NZCV, &
TRI)) {
11786 switch (
MI.getOpcode()) {
11787 case AArch64::SUBSXri:
11788 case AArch64::SUBSWri:
11789 case AArch64::ADDSXri:
11790 case AArch64::ADDSWri:
11792 CompCounterOprNum = 1;
11794 case AArch64::ADDSWrr:
11795 case AArch64::ADDSXrr:
11796 case AArch64::SUBSWrr:
11797 case AArch64::SUBSXrr:
11801 if (isWhileOpcode(
MI.getOpcode())) {
11808 if (CompCounterOprNum == 0) {
11810 CompCounterOprNum = 2;
11812 CompCounterOprNum = 1;
11824 bool IsUpdatePriorComp;
11825 unsigned UpdateCounterOprNum;
11827 Update, UpdateCounterOprNum,
Init, IsUpdatePriorComp))
11830 return std::make_unique<AArch64PipelinerLoopInfo>(
11831 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
11841 TypeSize Scale(0U,
false), Width(0U,
false);
11842 int64_t MinOffset, MaxOffset;
11843 if (
getMemOpInfo(
MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
11845 if (
MI.getOperand(ImmIdx).isImm() && !
MI.getOperand(ImmIdx - 1).isFI()) {
11846 int64_t Imm =
MI.getOperand(ImmIdx).getImm();
11847 if (Imm < MinOffset || Imm > MaxOffset) {
11848 ErrInfo =
"Unexpected immediate on load/store instruction";
11854 const MCInstrDesc &MCID =
MI.getDesc();
11856 const MachineOperand &MO =
MI.getOperand(
Op);
11860 ErrInfo =
"OPERAND_IMPLICIT_IMM_0 should be 0";
11869 ErrInfo =
"OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
11880#define GET_INSTRINFO_HELPERS
11881#define GET_INSTRMAP_INFO
11882#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
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,...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - 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.
StringRef - 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 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.