73#define DEBUG_TYPE "arm-instrinfo"
75#define GET_INSTRINFO_CTOR_DTOR
76#include "ARMGenInstrInfo.inc"
90 { ARM::VMLAS, ARM::VMULS, ARM::VADDS,
false,
false },
91 { ARM::VMLSS, ARM::VMULS, ARM::VSUBS,
false,
false },
92 { ARM::VMLAD, ARM::VMULD, ARM::VADDD,
false,
false },
93 { ARM::VMLSD, ARM::VMULD, ARM::VSUBD,
false,
false },
94 { ARM::VNMLAS, ARM::VNMULS, ARM::VSUBS,
true,
false },
95 { ARM::VNMLSS, ARM::VMULS, ARM::VSUBS,
true,
false },
96 { ARM::VNMLAD, ARM::VNMULD, ARM::VSUBD,
true,
false },
97 { ARM::VNMLSD, ARM::VMULD, ARM::VSUBD,
true,
false },
100 { ARM::VMLAfd, ARM::VMULfd, ARM::VADDfd,
false,
false },
101 { ARM::VMLSfd, ARM::VMULfd, ARM::VSUBfd,
false,
false },
102 { ARM::VMLAfq, ARM::VMULfq, ARM::VADDfq,
false,
false },
103 { ARM::VMLSfq, ARM::VMULfq, ARM::VSUBfq,
false,
false },
104 { ARM::VMLAslfd, ARM::VMULslfd, ARM::VADDfd,
false,
true },
105 { ARM::VMLSslfd, ARM::VMULslfd, ARM::VSUBfd,
false,
true },
106 { ARM::VMLAslfq, ARM::VMULslfq, ARM::VADDfq,
false,
true },
107 { ARM::VMLSslfq, ARM::VMULslfq, ARM::VSUBfq,
false,
true },
114 for (
unsigned i = 0, e = std::size(
ARM_MLxTable); i != e; ++i) {
115 if (!MLxEntryMap.insert(std::make_pair(
ARM_MLxTable[i].MLxOpc, i)).second)
127 if (usePreRAHazardRecognizer()) {
129 static_cast<const ARMSubtarget *
>(STI)->getInstrItineraryData();
149 std::make_unique<ARMBankConflictHazardRecognizer>(DAG, 0x4,
true));
165 if (Subtarget.isThumb2() || Subtarget.hasVFP2Base())
186 bool AllowModify)
const {
191 if (
I ==
MBB.instr_begin())
201 bool CantAnalyze =
false;
205 while (
I->isDebugInstr() || !
I->isTerminator() ||
207 I->getOpcode() == ARM::t2DoLoopStartTP){
208 if (
I ==
MBB.instr_begin())
219 TBB =
I->getOperand(0).getMBB();
225 assert(!FBB &&
"FBB should have been null.");
227 TBB =
I->getOperand(0).getMBB();
228 Cond.push_back(
I->getOperand(1));
229 Cond.push_back(
I->getOperand(2));
230 }
else if (
I->isReturn()) {
233 }
else if (
I->getOpcode() == ARM::t2LoopEnd &&
240 TBB =
I->getOperand(1).getMBB();
242 Cond.push_back(
I->getOperand(0));
264 while (DI !=
MBB.instr_end()) {
287 if (
I ==
MBB.instr_begin())
299 int *BytesRemoved)
const {
300 assert(!BytesRemoved &&
"code size not handled");
311 I->eraseFromParent();
315 if (
I ==
MBB.begin())
return 1;
321 I->eraseFromParent();
330 int *BytesAdded)
const {
331 assert(!BytesAdded &&
"code size not handled");
340 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
342 "ARM branch conditions have two or three components!");
352 }
else if (
Cond.size() == 2) {
363 if (
Cond.size() == 2)
368 else if (
Cond.size() == 3)
379 if (
Cond.size() == 2) {
391 while (++
I != E &&
I->isInsideBundle()) {
392 int PIdx =
I->findFirstPredOperandIdx();
393 if (PIdx != -1 &&
I->getOperand(PIdx).getImm() !=
ARMCC::AL)
399 int PIdx =
MI.findFirstPredOperandIdx();
400 return PIdx != -1 &&
MI.getOperand(PIdx).getImm() !=
ARMCC::AL;
408 std::string GenericComment =
410 if (!GenericComment.empty())
411 return GenericComment;
415 return std::string();
419 int FirstPredOp =
MI.findFirstPredOperandIdx();
420 if (FirstPredOp != (
int) OpIdx)
421 return std::string();
423 std::string CC =
"CC::";
430 unsigned Opc =
MI.getOpcode();
439 int PIdx =
MI.findFirstPredOperandIdx();
443 MI.getOperand(PIdx+1).setReg(Pred[1].
getReg());
450 "CPSR def isn't expected operand");
451 assert((
MI.getOperand(1).isDead() ||
452 MI.getOperand(1).getReg() != ARM::CPSR) &&
453 "if conversion tried to stop defining used CPSR");
454 MI.getOperand(1).setReg(ARM::NoRegister);
464 if (Pred1.
size() > 2 || Pred2.
size() > 2)
489 std::vector<MachineOperand> &Pred,
490 bool SkipDead)
const {
493 bool ClobbersCPSR = MO.isRegMask() && MO.clobbersPhysReg(ARM::CPSR);
494 bool IsCPSR = MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR;
495 if (ClobbersCPSR || IsCPSR) {
513 for (
const auto &MO :
MI.operands())
514 if (MO.isReg() && MO.getReg() == ARM::CPSR && MO.isDef() && !MO.isDead())
520 switch (
MI->getOpcode()) {
521 default:
return true;
552 if (!
MI.isPredicable())
590 if (!MO.isReg() || MO.isUndef() || MO.isUse())
592 if (MO.getReg() != ARM::CPSR)
612 switch (
MI.getOpcode()) {
619 return MCID.getSize();
620 case TargetOpcode::BUNDLE:
621 return getInstBundleSize(
MI);
622 case TargetOpcode::COPY:
627 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
628 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
629 case TargetOpcode::PATCHABLE_TAIL_CALL:
632 case ARM::CONSTPOOL_ENTRY:
633 case ARM::JUMPTABLE_INSTS:
634 case ARM::JUMPTABLE_ADDRS:
635 case ARM::JUMPTABLE_TBB:
636 case ARM::JUMPTABLE_TBH:
639 return MI.getOperand(2).getImm();
641 return MI.getOperand(1).getImm();
643 case ARM::INLINEASM_BR: {
645 unsigned Size = getInlineAsmLength(
MI.getOperand(0).getSymbolName(), MAI);
657 unsigned Opc = Subtarget.isThumb()
658 ? (Subtarget.isMClass() ? ARM::t2MRS_M : ARM::t2MRS_AR)
666 if (Subtarget.isMClass())
677 unsigned Opc = Subtarget.isThumb()
678 ? (Subtarget.isMClass() ? ARM::t2MSR_M : ARM::t2MSR_AR)
683 if (Subtarget.isMClass())
712 unsigned Cond,
unsigned Inactive) {
722 bool RenamableSrc)
const {
723 bool GPRDest = ARM::GPRRegClass.contains(DestReg);
724 bool GPRSrc = ARM::GPRRegClass.contains(SrcReg);
726 if (GPRDest && GPRSrc) {
734 bool SPRDest = ARM::SPRRegClass.contains(DestReg);
735 bool SPRSrc = ARM::SPRRegClass.contains(SrcReg);
738 if (SPRDest && SPRSrc)
740 else if (GPRDest && SPRSrc)
742 else if (SPRDest && GPRSrc)
744 else if (ARM::DPRRegClass.
contains(DestReg, SrcReg) && Subtarget.hasFP64())
746 else if (ARM::QPRRegClass.
contains(DestReg, SrcReg))
747 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MQPRCopy;
752 if (
Opc == ARM::VORRq ||
Opc == ARM::MVE_VORR)
754 if (
Opc == ARM::MVE_VORR)
756 else if (
Opc != ARM::MQPRCopy)
762 unsigned BeginIdx = 0;
763 unsigned SubRegs = 0;
767 if (ARM::QQPRRegClass.
contains(DestReg, SrcReg)) {
768 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
769 BeginIdx = ARM::qsub_0;
771 }
else if (ARM::QQQQPRRegClass.
contains(DestReg, SrcReg)) {
772 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
773 BeginIdx = ARM::qsub_0;
776 }
else if (ARM::DPairRegClass.
contains(DestReg, SrcReg)) {
778 BeginIdx = ARM::dsub_0;
780 }
else if (ARM::DTripleRegClass.
contains(DestReg, SrcReg)) {
782 BeginIdx = ARM::dsub_0;
784 }
else if (ARM::DQuadRegClass.
contains(DestReg, SrcReg)) {
786 BeginIdx = ARM::dsub_0;
788 }
else if (ARM::GPRPairRegClass.
contains(DestReg, SrcReg)) {
789 Opc = Subtarget.isThumb2() ? ARM::tMOVr : ARM::MOVr;
790 BeginIdx = ARM::gsub_0;
792 }
else if (ARM::DPairSpcRegClass.
contains(DestReg, SrcReg)) {
794 BeginIdx = ARM::dsub_0;
797 }
else if (ARM::DTripleSpcRegClass.
contains(DestReg, SrcReg)) {
799 BeginIdx = ARM::dsub_0;
802 }
else if (ARM::DQuadSpcRegClass.
contains(DestReg, SrcReg)) {
804 BeginIdx = ARM::dsub_0;
807 }
else if (ARM::DPRRegClass.
contains(DestReg, SrcReg) &&
808 !Subtarget.hasFP64()) {
810 BeginIdx = ARM::ssub_0;
812 }
else if (SrcReg == ARM::CPSR) {
815 }
else if (DestReg == ARM::CPSR) {
818 }
else if (DestReg == ARM::VPR) {
824 }
else if (SrcReg == ARM::VPR) {
830 }
else if (DestReg == ARM::FPSCR_NZCV) {
832 BuildMI(
MBB,
I,
I->getDebugLoc(),
get(ARM::VMSR_FPSCR_NZCVQC), DestReg)
836 }
else if (SrcReg == ARM::FPSCR_NZCV) {
838 BuildMI(
MBB,
I,
I->getDebugLoc(),
get(ARM::VMRS_FPSCR_NZCVQC), DestReg)
844 assert(
Opc &&
"Impossible reg-to-reg copy");
850 if (
TRI->regsOverlap(SrcReg,
TRI->getSubReg(DestReg, BeginIdx))) {
851 BeginIdx = BeginIdx + ((SubRegs - 1) * Spacing);
857 for (
unsigned i = 0; i != SubRegs; ++i) {
858 Register Dst =
TRI->getSubReg(DestReg, BeginIdx + i * Spacing);
859 Register Src =
TRI->getSubReg(SrcReg, BeginIdx + i * Spacing);
860 assert(Dst && Src &&
"Bad sub-register");
862 assert(!DstRegs.
count(Src) &&
"destructive vector copy");
867 if (
Opc == ARM::VORRq ||
Opc == ARM::MVE_VORR) {
871 if (
Opc == ARM::MVE_VORR)
876 if (
Opc == ARM::MOVr)
885std::optional<DestSourcePair>
894 if (!
MI.isMoveReg() ||
895 (
MI.getOpcode() == ARM::VORRq &&
896 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg()))
901std::optional<ParamLoadedValue>
905 Register DstReg = DstSrcPair->Destination->getReg();
936 return MIB.
addReg(Reg, State);
940 return MIB.
addReg(Reg, State, SubIdx);
945 Register SrcReg,
bool isKill,
int FI,
958 switch (
TRI.getSpillSize(*RC)) {
960 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
971 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
978 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
985 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
992 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1003 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1010 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1011 if (Subtarget.hasV5TEOps()) {
1014 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1025 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1031 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1047 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1048 Subtarget.hasMVEIntegerOps()) {
1053 .addMemOperand(MMO);
1059 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1062 Subtarget.hasNEON()) {
1076 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1077 AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1083 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1084 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1085 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1087 Subtarget.hasNEON()) {
1096 }
else if (Subtarget.hasMVEIntegerOps()) {
1108 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1109 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1110 AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1116 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1117 Subtarget.hasMVEIntegerOps()) {
1122 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1128 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1129 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1130 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1131 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_4, {});
1132 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_5, {});
1133 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_6, {});
1134 AddDReg(MIB, SrcReg, ARM::dsub_7, {});
1144 int &FrameIndex)
const {
1145 switch (
MI.getOpcode()) {
1149 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1150 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1151 MI.getOperand(3).getImm() == 0) {
1152 FrameIndex =
MI.getOperand(1).getIndex();
1153 return MI.getOperand(0).getReg();
1162 case ARM::VSTR_P0_off:
1163 case ARM::VSTR_FPSCR_NZCVQC_off:
1164 case ARM::MVE_VSTRWU32:
1165 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1166 MI.getOperand(2).getImm() == 0) {
1167 FrameIndex =
MI.getOperand(1).getIndex();
1168 return MI.getOperand(0).getReg();
1172 case ARM::VST1d64TPseudo:
1173 case ARM::VST1d64QPseudo:
1174 if (
MI.getOperand(0).isFI() &&
MI.getOperand(2).getSubReg() == 0) {
1175 FrameIndex =
MI.getOperand(0).getIndex();
1176 return MI.getOperand(2).getReg();
1180 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1181 FrameIndex =
MI.getOperand(1).getIndex();
1182 return MI.getOperand(0).getReg();
1185 case ARM::MQQPRStore:
1186 case ARM::MQQQQPRStore:
1187 if (
MI.getOperand(1).isFI()) {
1188 FrameIndex =
MI.getOperand(1).getIndex();
1189 return MI.getOperand(0).getReg();
1198 int &FrameIndex)
const {
1200 if (
MI.mayStore() && hasStoreToStackSlot(
MI,
Accesses) &&
1217 if (
I !=
MBB.end())
DL =
I->getDebugLoc();
1226 switch (
TRI.getSpillSize(*RC)) {
1228 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
1238 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
1244 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
1250 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
1256 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1266 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1272 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1275 if (Subtarget.hasV5TEOps()) {
1298 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1311 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1312 Subtarget.hasMVEIntegerOps()) {
1314 MIB.addFrameIndex(FI)
1316 .addMemOperand(MMO);
1322 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1324 Subtarget.hasNEON()) {
1345 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1346 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1347 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1349 Subtarget.hasNEON()) {
1355 }
else if (Subtarget.hasMVEIntegerOps()) {
1375 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1376 Subtarget.hasMVEIntegerOps()) {
1380 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1404 int &FrameIndex)
const {
1405 switch (
MI.getOpcode()) {
1409 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1410 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1411 MI.getOperand(3).getImm() == 0) {
1412 FrameIndex =
MI.getOperand(1).getIndex();
1413 return MI.getOperand(0).getReg();
1422 case ARM::VLDR_P0_off:
1423 case ARM::VLDR_FPSCR_NZCVQC_off:
1424 case ARM::MVE_VLDRWU32:
1425 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1426 MI.getOperand(2).getImm() == 0) {
1427 FrameIndex =
MI.getOperand(1).getIndex();
1428 return MI.getOperand(0).getReg();
1432 case ARM::VLD1d8TPseudo:
1433 case ARM::VLD1d16TPseudo:
1434 case ARM::VLD1d32TPseudo:
1435 case ARM::VLD1d64TPseudo:
1436 case ARM::VLD1d8QPseudo:
1437 case ARM::VLD1d16QPseudo:
1438 case ARM::VLD1d32QPseudo:
1439 case ARM::VLD1d64QPseudo:
1440 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1441 FrameIndex =
MI.getOperand(1).getIndex();
1442 return MI.getOperand(0).getReg();
1446 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1447 FrameIndex =
MI.getOperand(1).getIndex();
1448 return MI.getOperand(0).getReg();
1451 case ARM::MQQPRLoad:
1452 case ARM::MQQQQPRLoad:
1453 if (
MI.getOperand(1).isFI()) {
1454 FrameIndex =
MI.getOperand(1).getIndex();
1455 return MI.getOperand(0).getReg();
1464 int &FrameIndex)
const {
1466 if (
MI.mayLoad() && hasLoadFromStackSlot(
MI,
Accesses) &&
1480 bool isThumb2 = Subtarget.
isThumb2();
1487 if (isThumb1 || !
MI->getOperand(1).isDead()) {
1489 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA_UPD
1490 : isThumb1 ? ARM::tLDMIA_UPD
1494 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
1497 if (isThumb1 || !
MI->getOperand(0).isDead()) {
1498 MachineOperand STWb(
MI->getOperand(0));
1499 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA_UPD
1500 : isThumb1 ? ARM::tSTMIA_UPD
1504 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
1507 MachineOperand LDBase(
MI->getOperand(3));
1510 MachineOperand STBase(
MI->getOperand(2));
1519 [&
TRI](
const unsigned &Reg1,
const unsigned &Reg2) ->
bool {
1520 return TRI.getEncodingValue(Reg1) <
1521 TRI.getEncodingValue(Reg2);
1524 for (
const auto &
Reg : ScratchRegs) {
1533 if (
MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) {
1534 expandLoadStackGuard(
MI);
1535 MI.getParent()->erase(
MI);
1539 if (
MI.getOpcode() == ARM::MEMCPY) {
1548 if (!
MI.isCopy() || Subtarget.dontWidenVMOVS() || !Subtarget.hasFP64())
1553 Register DstRegS =
MI.getOperand(0).getReg();
1554 Register SrcRegS =
MI.getOperand(1).getReg();
1555 if (!ARM::SPRRegClass.
contains(DstRegS, SrcRegS))
1560 TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, &ARM::DPRRegClass);
1562 TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, &ARM::DPRRegClass);
1563 if (!DstRegD || !SrcRegD)
1569 if (!
MI.definesRegister(DstRegD,
TRI) ||
MI.readsRegister(DstRegD,
TRI))
1573 if (
MI.getOperand(0).isDead())
1582 int ImpDefIdx =
MI.findRegisterDefOperandIdx(DstRegD,
nullptr);
1583 if (ImpDefIdx != -1)
1584 MI.removeOperand(ImpDefIdx);
1587 MI.setDesc(
get(ARM::VMOVD));
1588 MI.getOperand(0).setReg(DstRegD);
1589 MI.getOperand(1).setReg(SrcRegD);
1596 MI.getOperand(1).setIsUndef();
1601 if (
MI.getOperand(1).isKill()) {
1602 MI.getOperand(1).setIsKill(
false);
1603 MI.addRegisterKilled(SrcRegS,
TRI,
true);
1617 assert(MCPE.isMachineConstantPoolEntry() &&
1618 "Expecting a machine constantpool entry!");
1668 case ARM::tLDRpci_pic:
1669 case ARM::t2LDRpci_pic: {
1689 switch (
I->getOpcode()) {
1690 case ARM::tLDRpci_pic:
1691 case ARM::t2LDRpci_pic: {
1693 unsigned CPI =
I->getOperand(1).getIndex();
1695 I->getOperand(1).setIndex(CPI);
1696 I->getOperand(2).setImm(PCLabelId);
1700 if (!
I->isBundledWithSucc())
1711 if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic ||
1712 Opcode == ARM::tLDRpci || Opcode == ARM::tLDRpci_pic ||
1713 Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1714 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1715 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1716 Opcode == ARM::t2MOV_ga_pcrel) {
1727 if (Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1728 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1729 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1730 Opcode == ARM::t2MOV_ga_pcrel)
1742 if (isARMCP0 && isARMCP1) {
1748 }
else if (!isARMCP0 && !isARMCP1) {
1752 }
else if (Opcode == ARM::PICLDR) {
1760 if (Addr0 != Addr1) {
1796 int64_t &Offset2)
const {
1798 if (Subtarget.isThumb1Only())
return false;
1803 auto IsLoadOpcode = [&](
unsigned Opcode) {
1818 case ARM::t2LDRSHi8:
1820 case ARM::t2LDRBi12:
1821 case ARM::t2LDRSHi12:
1862 int64_t Offset1, int64_t Offset2,
1863 unsigned NumLoads)
const {
1865 if (Subtarget.isThumb1Only())
return false;
1867 assert(Offset2 > Offset1);
1869 if ((Offset2 - Offset1) / 8 > 64)
1900 if (
MI.isDebugInstr())
1904 if (
MI.isTerminator() ||
MI.isPosition())
1908 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
1922 while (++
I !=
MBB->end() &&
I->isDebugInstr())
1924 if (
I !=
MBB->end() &&
I->getOpcode() == ARM::t2IT)
1935 if (!
MI.isCall() &&
MI.definesRegister(ARM::SP,
nullptr))
1943 unsigned NumCycles,
unsigned ExtraPredCycles,
1951 if (
MBB.getParent()->getFunction().hasOptSize()) {
1953 if (!Pred->empty()) {
1955 if (LastMI->
getOpcode() == ARM::t2Bcc) {
1964 MBB, 0, 0, Probability);
1969 unsigned TCycles,
unsigned TExtra,
1971 unsigned FCycles,
unsigned FExtra,
1980 if (Subtarget.isThumb2() &&
TBB.getParent()->getFunction().hasMinSize()) {
1988 const unsigned ScalingUpFactor = 1024;
1990 unsigned PredCost = (TCycles + FCycles + TExtra + FExtra) * ScalingUpFactor;
1991 unsigned UnpredCost;
1992 if (!Subtarget.hasBranchPredictor()) {
1995 unsigned NotTakenBranchCost = 1;
1996 unsigned TakenBranchCost = Subtarget.getMispredictionPenalty();
1997 unsigned TUnpredCycles, FUnpredCycles;
2000 TUnpredCycles = TCycles + NotTakenBranchCost;
2001 FUnpredCycles = TakenBranchCost;
2004 TUnpredCycles = TCycles + TakenBranchCost;
2005 FUnpredCycles = FCycles + NotTakenBranchCost;
2008 PredCost -= 1 * ScalingUpFactor;
2011 unsigned TUnpredCost = Probability.
scale(TUnpredCycles * ScalingUpFactor);
2012 unsigned FUnpredCost = Probability.
getCompl().
scale(FUnpredCycles * ScalingUpFactor);
2013 UnpredCost = TUnpredCost + FUnpredCost;
2016 if (Subtarget.isThumb2() && TCycles + FCycles > 4) {
2017 PredCost += ((TCycles + FCycles - 4) / 4) * ScalingUpFactor;
2020 unsigned TUnpredCost = Probability.
scale(TCycles * ScalingUpFactor);
2021 unsigned FUnpredCost =
2023 UnpredCost = TUnpredCost + FUnpredCost;
2024 UnpredCost += 1 * ScalingUpFactor;
2025 UnpredCost += Subtarget.getMispredictionPenalty() * ScalingUpFactor / 10;
2028 return PredCost <= UnpredCost;
2033 unsigned NumInsts)
const {
2037 if (!Subtarget.isThumb2())
2041 unsigned MaxInsts = Subtarget.restrictIT() ? 1 : 4;
2050 if (
MI.getOpcode() == ARM::t2Bcc &&
2062 if (Subtarget.isThumb2())
2073 return Subtarget.isProfitableToUnpredicate();
2081 int PIdx =
MI.findFirstPredOperandIdx();
2087 PredReg =
MI.getOperand(PIdx+1).getReg();
2096 if (
Opc == ARM::t2B)
2105 unsigned OpIdx2)
const {
2106 switch (
MI.getOpcode()) {
2108 case ARM::t2MOVCCr: {
2113 if (CC ==
ARMCC::AL || PredReg != ARM::CPSR)
2133 if (!Reg.isVirtual())
2147 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2154 if (MO.getReg().isPhysical())
2156 if (MO.isDef() && !MO.isDead())
2159 bool DontMoveAcrossStores =
true;
2160 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2168 bool PreferFalse)
const {
2169 assert((
MI.getOpcode() == ARM::MOVCCr ||
MI.getOpcode() == ARM::t2MOVCCr) &&
2170 "Unknown select instruction");
2173 bool Invert = !
DefMI;
2175 DefMI = canFoldIntoMOVCC(
MI.getOperand(1).getReg(), MRI,
this);
2182 Register DestReg =
MI.getOperand(0).getReg();
2198 i != e && !DefDesc.
operands()[i].isPredicate(); ++i)
2201 unsigned CondCode =
MI.getOperand(3).getImm();
2206 NewMI.
add(
MI.getOperand(4));
2217 NewMI.
add(FalseReg);
2228 if (
DefMI->getParent() !=
MI.getParent())
2232 DefMI->eraseFromParent();
2248 {ARM::ADDSri, ARM::ADDri},
2249 {ARM::ADDSrr, ARM::ADDrr},
2250 {ARM::ADDSrsi, ARM::ADDrsi},
2251 {ARM::ADDSrsr, ARM::ADDrsr},
2253 {ARM::SUBSri, ARM::SUBri},
2254 {ARM::SUBSrr, ARM::SUBrr},
2255 {ARM::SUBSrsi, ARM::SUBrsi},
2256 {ARM::SUBSrsr, ARM::SUBrsr},
2258 {ARM::RSBSri, ARM::RSBri},
2259 {ARM::RSBSrsi, ARM::RSBrsi},
2260 {ARM::RSBSrsr, ARM::RSBrsr},
2262 {ARM::tADDSi3, ARM::tADDi3},
2263 {ARM::tADDSi8, ARM::tADDi8},
2264 {ARM::tADDSrr, ARM::tADDrr},
2265 {ARM::tADCS, ARM::tADC},
2267 {ARM::tSUBSi3, ARM::tSUBi3},
2268 {ARM::tSUBSi8, ARM::tSUBi8},
2269 {ARM::tSUBSrr, ARM::tSUBrr},
2270 {ARM::tSBCS, ARM::tSBC},
2271 {ARM::tRSBS, ARM::tRSB},
2272 {ARM::tLSLSri, ARM::tLSLri},
2274 {ARM::t2ADDSri, ARM::t2ADDri},
2275 {ARM::t2ADDSrr, ARM::t2ADDrr},
2276 {ARM::t2ADDSrs, ARM::t2ADDrs},
2278 {ARM::t2SUBSri, ARM::t2SUBri},
2279 {ARM::t2SUBSrr, ARM::t2SUBrr},
2280 {ARM::t2SUBSrs, ARM::t2SUBrs},
2282 {ARM::t2RSBSri, ARM::t2RSBri},
2283 {ARM::t2RSBSrs, ARM::t2RSBrs},
2288 if (OldOpc == Entry.PseudoOpc)
2289 return Entry.MachineOpc;
2300 if (NumBytes == 0 && DestReg != BaseReg) {
2309 bool isSub = NumBytes < 0;
2310 if (isSub) NumBytes = -NumBytes;
2315 assert(ThisVal &&
"Didn't extract field correctly");
2318 NumBytes &= ~ThisVal;
2323 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
2336 unsigned NumBytes) {
2347 if (!IsPush && !IsPop)
2350 bool IsVFPPushPop =
MI->getOpcode() == ARM::VSTMDDB_UPD ||
2351 MI->getOpcode() == ARM::VLDMDIA_UPD;
2352 bool IsT1PushPop =
MI->getOpcode() == ARM::tPUSH ||
2353 MI->getOpcode() == ARM::tPOP ||
2354 MI->getOpcode() == ARM::tPOP_RET;
2356 assert((IsT1PushPop || (
MI->getOperand(0).getReg() == ARM::SP &&
2357 MI->getOperand(1).getReg() == ARM::SP)) &&
2358 "trying to fold sp update into non-sp-updating push/pop");
2363 if (NumBytes % (IsVFPPushPop ? 8 : 4) != 0)
2368 int RegListIdx = IsT1PushPop ? 2 : 4;
2371 unsigned RegsNeeded;
2374 RegsNeeded = NumBytes / 8;
2375 RegClass = &ARM::DPRRegClass;
2377 RegsNeeded = NumBytes / 4;
2378 RegClass = &ARM::GPRRegClass;
2388 unsigned FirstRegEnc = -1;
2391 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2396 TRI->getEncodingValue(MO.
getReg()) < FirstRegEnc)
2397 FirstRegEnc =
TRI->getEncodingValue(MO.
getReg());
2400 const MCPhysReg *CSRegs =
TRI->getCalleeSavedRegs(&MF);
2403 for (
int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2406 if (IsT1PushPop && CurRegEnc >
TRI->getEncodingValue(ARM::R7))
2413 false,
false,
true));
2423 MI->getParent()->computeRegisterLiveness(
TRI, CurReg,
MI) !=
2445 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i)
2446 MI->removeOperand(i);
2459 unsigned Opcode =
MI.getOpcode();
2465 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
2468 if (Opcode == ARM::ADDri) {
2469 Offset +=
MI.getOperand(FrameRegIdx+1).getImm();
2472 MI.setDesc(
TII.get(ARM::MOVr));
2473 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2474 MI.removeOperand(FrameRegIdx+1);
2480 MI.setDesc(
TII.get(ARM::SUBri));
2486 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2487 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(
Offset);
2502 "Bit extraction didn't work?");
2503 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
2505 unsigned ImmIdx = 0;
2507 unsigned NumBits = 0;
2511 ImmIdx = FrameRegIdx + 1;
2512 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2516 ImmIdx = FrameRegIdx+2;
2523 ImmIdx = FrameRegIdx+2;
2534 ImmIdx = FrameRegIdx+1;
2542 ImmIdx = FrameRegIdx+1;
2552 ImmIdx = FrameRegIdx+1;
2553 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2562 Offset += InstrOffs * Scale;
2563 assert((
Offset & (Scale-1)) == 0 &&
"Can't encode this offset!");
2573 int ImmedOffset =
Offset / Scale;
2574 unsigned Mask = (1 << NumBits) - 1;
2575 if ((
unsigned)
Offset <= Mask * Scale) {
2577 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2583 ImmedOffset = -ImmedOffset;
2585 ImmedOffset |= 1 << NumBits;
2593 ImmedOffset = ImmedOffset & Mask;
2596 ImmedOffset = -ImmedOffset;
2598 ImmedOffset |= 1 << NumBits;
2614 Register &SrcReg2, int64_t &CmpMask,
2615 int64_t &CmpValue)
const {
2616 switch (
MI.getOpcode()) {
2621 SrcReg =
MI.getOperand(0).getReg();
2624 CmpValue =
MI.getOperand(1).getImm();
2629 SrcReg =
MI.getOperand(0).getReg();
2630 SrcReg2 =
MI.getOperand(1).getReg();
2636 SrcReg =
MI.getOperand(0).getReg();
2638 CmpMask =
MI.getOperand(1).getImm();
2651 int CmpMask,
bool CommonUse) {
2652 switch (
MI->getOpcode()) {
2655 if (CmpMask !=
MI->getOperand(2).getImm())
2657 if (SrcReg ==
MI->getOperand(CommonUse ? 1 : 0).getReg())
2747 switch (
MI->getOpcode()) {
2748 default:
return false;
2844 if (!
MI)
return false;
2847 if (CmpMask != ~0) {
2853 if (UI->getParent() != CmpInstr.
getParent())
2862 if (!
MI)
return false;
2871 if (
I ==
B)
return false;
2882 else if (
MI->getParent() != CmpInstr.
getParent() || CmpValue != 0) {
2887 if (CmpInstr.
getOpcode() == ARM::CMPri ||
2895 bool IsThumb1 =
false;
2912 if (
MI && IsThumb1) {
2914 if (
I != E && !
MI->readsRegister(ARM::CPSR,
TRI)) {
2915 bool CanReorder =
true;
2916 for (;
I != E; --
I) {
2917 if (
I->getOpcode() != ARM::tMOVi8) {
2923 MI =
MI->removeFromParent();
2934 bool SubAddIsThumb1 =
false;
2949 if (Instr.modifiesRegister(ARM::CPSR,
TRI) ||
2950 Instr.readsRegister(ARM::CPSR,
TRI))
2972 IsThumb1 = SubAddIsThumb1;
2987 bool isSafe =
false;
2990 while (!isSafe && ++
I != E) {
2992 for (
unsigned IO = 0, EO = Instr.getNumOperands();
2993 !isSafe && IO != EO; ++IO) {
3007 bool IsInstrVSel =
true;
3008 switch (Instr.getOpcode()) {
3010 IsInstrVSel =
false;
3044 bool IsSub =
Opc == ARM::SUBrr ||
Opc == ARM::t2SUBrr ||
3045 Opc == ARM::SUBri ||
Opc == ARM::t2SUBri ||
3046 Opc == ARM::tSUBrr ||
Opc == ARM::tSUBi3 ||
3048 unsigned OpI =
Opc != ARM::tSUBrr ? 1 : 2;
3060 std::make_pair(&((*I).getOperand(IO - 1)), NewCC));
3094 if (Succ->isLiveIn(ARM::CPSR))
3101 unsigned CPSRRegNum =
MI->getNumExplicitOperands() - 1;
3102 MI->getOperand(CPSRRegNum).setReg(ARM::CPSR);
3103 MI->getOperand(CPSRRegNum).setIsDef(
true);
3111 for (
auto &[MO,
Cond] : OperandsToUpdate)
3114 MI->clearRegisterDeads(ARM::CPSR);
3128 int64_t CmpMask, CmpValue;
3130 if (
Next !=
MI.getParent()->end() &&
3141 unsigned DefOpc =
DefMI.getOpcode();
3142 if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm &&
3143 DefOpc != ARM::tMOVi32imm)
3145 if (!
DefMI.getOperand(1).isImm())
3165 if (
UseMI.getOperand(
NumOps - 1).getReg() == ARM::CPSR)
3171 unsigned UseOpc =
UseMI.getOpcode();
3172 unsigned NewUseOpc = 0;
3174 uint32_t SOImmValV1 = 0, SOImmValV2 = 0;
3175 bool Commute =
false;
3177 default:
return false;
3185 case ARM::t2EORrr: {
3186 Commute =
UseMI.getOperand(2).getReg() != Reg;
3191 if (UseOpc == ARM::SUBrr && Commute)
3197 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::ADDri : ARM::SUBri;
3200 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::SUBri : ARM::ADDri;
3214 case ARM::ORRrr: NewUseOpc = ARM::ORRri;
break;
3215 case ARM::EORrr: NewUseOpc = ARM::EORri;
break;
3219 case ARM::t2SUBrr: {
3220 if (UseOpc == ARM::t2SUBrr && Commute)
3225 const bool ToSP =
DefMI.getOperand(0).getReg() == ARM::SP;
3226 const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
3227 const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
3229 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB;
3232 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD;
3247 case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri;
break;
3248 case ARM::t2EORrr: NewUseOpc = ARM::t2EORri;
break;
3255 unsigned OpIdx = Commute ? 2 : 1;
3257 bool isKill =
UseMI.getOperand(OpIdx).isKill();
3267 UseMI.getOperand(1).setReg(NewReg);
3268 UseMI.getOperand(1).setIsKill();
3269 UseMI.getOperand(2).ChangeToImmediate(SOImmValV2);
3270 DefMI.eraseFromParent();
3277 case ARM::t2ADDspImm:
3278 case ARM::t2SUBspImm:
3288 switch (
MI.getOpcode()) {
3292 assert(UOps >= 0 &&
"bad # UOps");
3300 unsigned ShOpVal =
MI.getOperand(3).getImm();
3305 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3313 if (!
MI.getOperand(2).getReg())
3316 unsigned ShOpVal =
MI.getOperand(3).getImm();
3321 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3331 case ARM::LDRSB_POST:
3332 case ARM::LDRSH_POST: {
3335 return (Rt == Rm) ? 4 : 3;
3338 case ARM::LDR_PRE_REG:
3339 case ARM::LDRB_PRE_REG: {
3344 unsigned ShOpVal =
MI.getOperand(4).getImm();
3349 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3355 case ARM::STR_PRE_REG:
3356 case ARM::STRB_PRE_REG: {
3357 unsigned ShOpVal =
MI.getOperand(4).getImm();
3362 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3369 case ARM::STRH_PRE: {
3379 case ARM::LDR_POST_REG:
3380 case ARM::LDRB_POST_REG:
3381 case ARM::LDRH_POST: {
3384 return (Rt == Rm) ? 3 : 2;
3387 case ARM::LDR_PRE_IMM:
3388 case ARM::LDRB_PRE_IMM:
3389 case ARM::LDR_POST_IMM:
3390 case ARM::LDRB_POST_IMM:
3391 case ARM::STRB_POST_IMM:
3392 case ARM::STRB_POST_REG:
3393 case ARM::STRB_PRE_IMM:
3394 case ARM::STRH_POST:
3395 case ARM::STR_POST_IMM:
3396 case ARM::STR_POST_REG:
3397 case ARM::STR_PRE_IMM:
3400 case ARM::LDRSB_PRE:
3401 case ARM::LDRSH_PRE: {
3408 unsigned ShOpVal =
MI.getOperand(4).getImm();
3413 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3426 return (Rt == Rn) ? 3 : 2;
3437 case ARM::LDRD_POST:
3438 case ARM::t2LDRD_POST:
3441 case ARM::STRD_POST:
3442 case ARM::t2STRD_POST:
3445 case ARM::LDRD_PRE: {
3452 return (Rt == Rn) ? 4 : 3;
3455 case ARM::t2LDRD_PRE: {
3458 return (Rt == Rn) ? 4 : 3;
3461 case ARM::STRD_PRE: {
3469 case ARM::t2STRD_PRE:
3472 case ARM::t2LDR_POST:
3473 case ARM::t2LDRB_POST:
3474 case ARM::t2LDRB_PRE:
3475 case ARM::t2LDRSBi12:
3476 case ARM::t2LDRSBi8:
3477 case ARM::t2LDRSBpci:
3479 case ARM::t2LDRH_POST:
3480 case ARM::t2LDRH_PRE:
3482 case ARM::t2LDRSB_POST:
3483 case ARM::t2LDRSB_PRE:
3484 case ARM::t2LDRSH_POST:
3485 case ARM::t2LDRSH_PRE:
3486 case ARM::t2LDRSHi12:
3487 case ARM::t2LDRSHi8:
3488 case ARM::t2LDRSHpci:
3492 case ARM::t2LDRDi8: {
3495 return (Rt == Rn) ? 3 : 2;
3498 case ARM::t2STRB_POST:
3499 case ARM::t2STRB_PRE:
3502 case ARM::t2STRH_POST:
3503 case ARM::t2STRH_PRE:
3505 case ARM::t2STR_POST:
3506 case ARM::t2STR_PRE:
3537 E =
MI.memoperands_end();
3539 Size += (*I)->getSize().getValue();
3546 return std::min(
Size / 4, 16U);
3551 unsigned UOps = 1 + NumRegs;
3555 case ARM::VLDMDIA_UPD:
3556 case ARM::VLDMDDB_UPD:
3557 case ARM::VLDMSIA_UPD:
3558 case ARM::VLDMSDB_UPD:
3559 case ARM::VSTMDIA_UPD:
3560 case ARM::VSTMDDB_UPD:
3561 case ARM::VSTMSIA_UPD:
3562 case ARM::VSTMSDB_UPD:
3563 case ARM::LDMIA_UPD:
3564 case ARM::LDMDA_UPD:
3565 case ARM::LDMDB_UPD:
3566 case ARM::LDMIB_UPD:
3567 case ARM::STMIA_UPD:
3568 case ARM::STMDA_UPD:
3569 case ARM::STMDB_UPD:
3570 case ARM::STMIB_UPD:
3571 case ARM::tLDMIA_UPD:
3572 case ARM::tSTMIA_UPD:
3573 case ARM::t2LDMIA_UPD:
3574 case ARM::t2LDMDB_UPD:
3575 case ARM::t2STMIA_UPD:
3576 case ARM::t2STMDB_UPD:
3579 case ARM::LDMIA_RET:
3581 case ARM::t2LDMIA_RET:
3590 if (!ItinData || ItinData->
isEmpty())
3594 unsigned Class =
Desc.getSchedClass();
3596 if (ItinUOps >= 0) {
3597 if (Subtarget.isSwift() && (
Desc.mayLoad() ||
Desc.mayStore()))
3603 unsigned Opc =
MI.getOpcode();
3622 case ARM::VLDMDIA_UPD:
3623 case ARM::VLDMDDB_UPD:
3625 case ARM::VLDMSIA_UPD:
3626 case ARM::VLDMSDB_UPD:
3628 case ARM::VSTMDIA_UPD:
3629 case ARM::VSTMDDB_UPD:
3631 case ARM::VSTMSIA_UPD:
3632 case ARM::VSTMSDB_UPD: {
3633 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands();
3634 return (NumRegs / 2) + (NumRegs % 2) + 1;
3637 case ARM::LDMIA_RET:
3642 case ARM::LDMIA_UPD:
3643 case ARM::LDMDA_UPD:
3644 case ARM::LDMDB_UPD:
3645 case ARM::LDMIB_UPD:
3650 case ARM::STMIA_UPD:
3651 case ARM::STMDA_UPD:
3652 case ARM::STMDB_UPD:
3653 case ARM::STMIB_UPD:
3655 case ARM::tLDMIA_UPD:
3656 case ARM::tSTMIA_UPD:
3660 case ARM::t2LDMIA_RET:
3663 case ARM::t2LDMIA_UPD:
3664 case ARM::t2LDMDB_UPD:
3667 case ARM::t2STMIA_UPD:
3668 case ARM::t2STMDB_UPD: {
3669 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands() + 1;
3670 switch (Subtarget.getLdStMultipleTiming()) {
3681 unsigned UOps = (NumRegs / 2);
3687 unsigned UOps = (NumRegs / 2);
3690 if ((NumRegs % 2) || !
MI.hasOneMemOperand() ||
3691 (*
MI.memoperands_begin())->getAlign() <
Align(8))
3701std::optional<unsigned>
3704 unsigned DefIdx,
unsigned DefAlign)
const {
3713 DefCycle = RegNo / 2 + 1;
3718 bool isSLoad =
false;
3723 case ARM::VLDMSIA_UPD:
3724 case ARM::VLDMSDB_UPD:
3731 if ((isSLoad && (RegNo % 2)) || DefAlign < 8)
3735 DefCycle = RegNo + 2;
3741std::optional<unsigned>
3744 unsigned DefIdx,
unsigned DefAlign)
const {
3751 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3754 DefCycle = RegNo / 2;
3759 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3760 DefCycle = (RegNo / 2);
3763 if ((RegNo % 2) || DefAlign < 8)
3769 DefCycle = RegNo + 2;
3775std::optional<unsigned>
3778 unsigned UseIdx,
unsigned UseAlign)
const {
3784 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3786 UseCycle = RegNo / 2 + 1;
3789 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3791 bool isSStore =
false;
3796 case ARM::VSTMSIA_UPD:
3797 case ARM::VSTMSDB_UPD:
3804 if ((isSStore && (RegNo % 2)) || UseAlign < 8)
3808 UseCycle = RegNo + 2;
3814std::optional<unsigned>
3817 unsigned UseIdx,
unsigned UseAlign)
const {
3823 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3824 UseCycle = RegNo / 2;
3829 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3830 UseCycle = (RegNo / 2);
3833 if ((RegNo % 2) || UseAlign < 8)
3844 unsigned DefIdx,
unsigned DefAlign,
const MCInstrDesc &UseMCID,
3845 unsigned UseIdx,
unsigned UseAlign)
const {
3855 std::optional<unsigned> DefCycle;
3856 bool LdmBypass =
false;
3863 case ARM::VLDMDIA_UPD:
3864 case ARM::VLDMDDB_UPD:
3866 case ARM::VLDMSIA_UPD:
3867 case ARM::VLDMSDB_UPD:
3868 DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3871 case ARM::LDMIA_RET:
3876 case ARM::LDMIA_UPD:
3877 case ARM::LDMDA_UPD:
3878 case ARM::LDMDB_UPD:
3879 case ARM::LDMIB_UPD:
3881 case ARM::tLDMIA_UPD:
3883 case ARM::t2LDMIA_RET:
3886 case ARM::t2LDMIA_UPD:
3887 case ARM::t2LDMDB_UPD:
3889 DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3897 std::optional<unsigned> UseCycle;
3904 case ARM::VSTMDIA_UPD:
3905 case ARM::VSTMDDB_UPD:
3907 case ARM::VSTMSIA_UPD:
3908 case ARM::VSTMSDB_UPD:
3909 UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3916 case ARM::STMIA_UPD:
3917 case ARM::STMDA_UPD:
3918 case ARM::STMDB_UPD:
3919 case ARM::STMIB_UPD:
3920 case ARM::tSTMIA_UPD:
3925 case ARM::t2STMIA_UPD:
3926 case ARM::t2STMDB_UPD:
3927 UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3935 if (UseCycle > *DefCycle + 1)
3936 return std::nullopt;
3938 UseCycle = *DefCycle - *UseCycle + 1;
3939 if (UseCycle > 0u) {
3945 UseCycle = *UseCycle - 1;
3947 UseClass, UseIdx)) {
3948 UseCycle = *UseCycle - 1;
3957 unsigned &DefIdx,
unsigned &Dist) {
3962 assert(
II->isInsideBundle() &&
"Empty bundle?");
3965 while (
II->isInsideBundle()) {
3966 Idx =
II->findRegisterDefOperandIdx(
Reg,
TRI,
false,
true);
3973 assert(Idx != -1 &&
"Cannot find bundled definition!");
3980 unsigned &UseIdx,
unsigned &Dist) {
3984 assert(
II->isInsideBundle() &&
"Empty bundle?");
3989 while (
II !=
E &&
II->isInsideBundle()) {
3990 Idx =
II->findRegisterUseOperandIdx(
Reg,
TRI,
false);
3993 if (
II->getOpcode() != ARM::t2IT)
4021 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4031 case ARM::t2LDRSHs: {
4033 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4034 if (ShAmt == 0 || ShAmt == 2)
4039 }
else if (Subtarget.
isSwift()) {
4046 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4051 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4062 case ARM::t2LDRSHs: {
4064 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4065 if (ShAmt == 0 || ShAmt == 1 || ShAmt == 2 || ShAmt == 3)
4072 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment()) {
4079 case ARM::VLD1q8wb_fixed:
4080 case ARM::VLD1q16wb_fixed:
4081 case ARM::VLD1q32wb_fixed:
4082 case ARM::VLD1q64wb_fixed:
4083 case ARM::VLD1q8wb_register:
4084 case ARM::VLD1q16wb_register:
4085 case ARM::VLD1q32wb_register:
4086 case ARM::VLD1q64wb_register:
4093 case ARM::VLD2d8wb_fixed:
4094 case ARM::VLD2d16wb_fixed:
4095 case ARM::VLD2d32wb_fixed:
4096 case ARM::VLD2q8wb_fixed:
4097 case ARM::VLD2q16wb_fixed:
4098 case ARM::VLD2q32wb_fixed:
4099 case ARM::VLD2d8wb_register:
4100 case ARM::VLD2d16wb_register:
4101 case ARM::VLD2d32wb_register:
4102 case ARM::VLD2q8wb_register:
4103 case ARM::VLD2q16wb_register:
4104 case ARM::VLD2q32wb_register:
4109 case ARM::VLD3d8_UPD:
4110 case ARM::VLD3d16_UPD:
4111 case ARM::VLD3d32_UPD:
4112 case ARM::VLD1d64Twb_fixed:
4113 case ARM::VLD1d64Twb_register:
4114 case ARM::VLD3q8_UPD:
4115 case ARM::VLD3q16_UPD:
4116 case ARM::VLD3q32_UPD:
4121 case ARM::VLD4d8_UPD:
4122 case ARM::VLD4d16_UPD:
4123 case ARM::VLD4d32_UPD:
4124 case ARM::VLD1d64Qwb_fixed:
4125 case ARM::VLD1d64Qwb_register:
4126 case ARM::VLD4q8_UPD:
4127 case ARM::VLD4q16_UPD:
4128 case ARM::VLD4q32_UPD:
4129 case ARM::VLD1DUPq8:
4130 case ARM::VLD1DUPq16:
4131 case ARM::VLD1DUPq32:
4132 case ARM::VLD1DUPq8wb_fixed:
4133 case ARM::VLD1DUPq16wb_fixed:
4134 case ARM::VLD1DUPq32wb_fixed:
4135 case ARM::VLD1DUPq8wb_register:
4136 case ARM::VLD1DUPq16wb_register:
4137 case ARM::VLD1DUPq32wb_register:
4138 case ARM::VLD2DUPd8:
4139 case ARM::VLD2DUPd16:
4140 case ARM::VLD2DUPd32:
4141 case ARM::VLD2DUPd8wb_fixed:
4142 case ARM::VLD2DUPd16wb_fixed:
4143 case ARM::VLD2DUPd32wb_fixed:
4144 case ARM::VLD2DUPd8wb_register:
4145 case ARM::VLD2DUPd16wb_register:
4146 case ARM::VLD2DUPd32wb_register:
4147 case ARM::VLD4DUPd8:
4148 case ARM::VLD4DUPd16:
4149 case ARM::VLD4DUPd32:
4150 case ARM::VLD4DUPd8_UPD:
4151 case ARM::VLD4DUPd16_UPD:
4152 case ARM::VLD4DUPd32_UPD:
4154 case ARM::VLD1LNd16:
4155 case ARM::VLD1LNd32:
4156 case ARM::VLD1LNd8_UPD:
4157 case ARM::VLD1LNd16_UPD:
4158 case ARM::VLD1LNd32_UPD:
4160 case ARM::VLD2LNd16:
4161 case ARM::VLD2LNd32:
4162 case ARM::VLD2LNq16:
4163 case ARM::VLD2LNq32:
4164 case ARM::VLD2LNd8_UPD:
4165 case ARM::VLD2LNd16_UPD:
4166 case ARM::VLD2LNd32_UPD:
4167 case ARM::VLD2LNq16_UPD:
4168 case ARM::VLD2LNq32_UPD:
4170 case ARM::VLD4LNd16:
4171 case ARM::VLD4LNd32:
4172 case ARM::VLD4LNq16:
4173 case ARM::VLD4LNq32:
4174 case ARM::VLD4LNd8_UPD:
4175 case ARM::VLD4LNd16_UPD:
4176 case ARM::VLD4LNd32_UPD:
4177 case ARM::VLD4LNq16_UPD:
4178 case ARM::VLD4LNq32_UPD:
4192 if (!ItinData || ItinData->
isEmpty())
4193 return std::nullopt;
4199 unsigned DefAdj = 0;
4200 if (
DefMI.isBundle())
4209 unsigned UseAdj = 0;
4210 if (
UseMI.isBundle()) {
4214 return std::nullopt;
4217 return getOperandLatencyImpl(
4218 ItinData, *ResolvedDefMI, DefIdx, ResolvedDefMI->
getDesc(), DefAdj, DefMO,
4219 Reg, *ResolvedUseMI, UseIdx, ResolvedUseMI->
getDesc(), UseAdj);
4222std::optional<unsigned> ARMBaseInstrInfo::getOperandLatencyImpl(
4224 unsigned DefIdx,
const MCInstrDesc &DefMCID,
unsigned DefAdj,
4226 unsigned UseIdx,
const MCInstrDesc &UseMCID,
unsigned UseAdj)
const {
4227 if (Reg == ARM::CPSR) {
4228 if (
DefMI.getOpcode() == ARM::FMSTAT) {
4230 return Subtarget.
isLikeA9() ? 1 : 20;
4234 if (
UseMI.isBranch())
4253 return std::nullopt;
4255 unsigned DefAlign =
DefMI.hasOneMemOperand()
4256 ? (*
DefMI.memoperands_begin())->getAlign().value()
4258 unsigned UseAlign =
UseMI.hasOneMemOperand()
4259 ? (*
UseMI.memoperands_begin())->getAlign().value()
4264 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4267 return std::nullopt;
4270 int Adj = DefAdj + UseAdj;
4274 if (Adj >= 0 || (
int)*
Latency > -Adj) {
4281std::optional<unsigned>
4283 SDNode *DefNode,
unsigned DefIdx,
4284 SDNode *UseNode,
unsigned UseIdx)
const {
4290 if (isZeroCost(DefMCID.
Opcode))
4293 if (!ItinData || ItinData->
isEmpty())
4294 return DefMCID.
mayLoad() ? 3 : 1;
4297 std::optional<unsigned>
Latency =
4299 int Adj = Subtarget.getPreISelOperandLatencyAdjustment();
4300 int Threshold = 1 + Adj;
4306 unsigned DefAlign = !DefMN->memoperands_empty()
4307 ? (*DefMN->memoperands_begin())->getAlign().value()
4310 unsigned UseAlign = !UseMN->memoperands_empty()
4311 ? (*UseMN->memoperands_begin())->getAlign().value()
4314 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4316 return std::nullopt;
4319 (Subtarget.isCortexA8() || Subtarget.isLikeA9() ||
4320 Subtarget.isCortexA7())) {
4337 case ARM::t2LDRSHs: {
4340 if (ShAmt == 0 || ShAmt == 2)
4345 }
else if (DefIdx == 0 &&
Latency > 2U && Subtarget.isSwift()) {
4355 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4372 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment())
4379 case ARM::VLD1q8wb_register:
4380 case ARM::VLD1q16wb_register:
4381 case ARM::VLD1q32wb_register:
4382 case ARM::VLD1q64wb_register:
4383 case ARM::VLD1q8wb_fixed:
4384 case ARM::VLD1q16wb_fixed:
4385 case ARM::VLD1q32wb_fixed:
4386 case ARM::VLD1q64wb_fixed:
4390 case ARM::VLD2q8Pseudo:
4391 case ARM::VLD2q16Pseudo:
4392 case ARM::VLD2q32Pseudo:
4393 case ARM::VLD2d8wb_fixed:
4394 case ARM::VLD2d16wb_fixed:
4395 case ARM::VLD2d32wb_fixed:
4396 case ARM::VLD2q8PseudoWB_fixed:
4397 case ARM::VLD2q16PseudoWB_fixed:
4398 case ARM::VLD2q32PseudoWB_fixed:
4399 case ARM::VLD2d8wb_register:
4400 case ARM::VLD2d16wb_register:
4401 case ARM::VLD2d32wb_register:
4402 case ARM::VLD2q8PseudoWB_register:
4403 case ARM::VLD2q16PseudoWB_register:
4404 case ARM::VLD2q32PseudoWB_register:
4405 case ARM::VLD3d8Pseudo:
4406 case ARM::VLD3d16Pseudo:
4407 case ARM::VLD3d32Pseudo:
4408 case ARM::VLD1d8TPseudo:
4409 case ARM::VLD1d16TPseudo:
4410 case ARM::VLD1d32TPseudo:
4411 case ARM::VLD1d64TPseudo:
4412 case ARM::VLD1d64TPseudoWB_fixed:
4413 case ARM::VLD1d64TPseudoWB_register:
4414 case ARM::VLD3d8Pseudo_UPD:
4415 case ARM::VLD3d16Pseudo_UPD:
4416 case ARM::VLD3d32Pseudo_UPD:
4417 case ARM::VLD3q8Pseudo_UPD:
4418 case ARM::VLD3q16Pseudo_UPD:
4419 case ARM::VLD3q32Pseudo_UPD:
4420 case ARM::VLD3q8oddPseudo:
4421 case ARM::VLD3q16oddPseudo:
4422 case ARM::VLD3q32oddPseudo:
4423 case ARM::VLD3q8oddPseudo_UPD:
4424 case ARM::VLD3q16oddPseudo_UPD:
4425 case ARM::VLD3q32oddPseudo_UPD:
4426 case ARM::VLD4d8Pseudo:
4427 case ARM::VLD4d16Pseudo:
4428 case ARM::VLD4d32Pseudo:
4429 case ARM::VLD1d8QPseudo:
4430 case ARM::VLD1d16QPseudo:
4431 case ARM::VLD1d32QPseudo:
4432 case ARM::VLD1d64QPseudo:
4433 case ARM::VLD1d64QPseudoWB_fixed:
4434 case ARM::VLD1d64QPseudoWB_register:
4435 case ARM::VLD1q8HighQPseudo:
4436 case ARM::VLD1q8LowQPseudo_UPD:
4437 case ARM::VLD1q8HighTPseudo:
4438 case ARM::VLD1q8LowTPseudo_UPD:
4439 case ARM::VLD1q16HighQPseudo:
4440 case ARM::VLD1q16LowQPseudo_UPD:
4441 case ARM::VLD1q16HighTPseudo:
4442 case ARM::VLD1q16LowTPseudo_UPD:
4443 case ARM::VLD1q32HighQPseudo:
4444 case ARM::VLD1q32LowQPseudo_UPD:
4445 case ARM::VLD1q32HighTPseudo:
4446 case ARM::VLD1q32LowTPseudo_UPD:
4447 case ARM::VLD1q64HighQPseudo:
4448 case ARM::VLD1q64LowQPseudo_UPD:
4449 case ARM::VLD1q64HighTPseudo:
4450 case ARM::VLD1q64LowTPseudo_UPD:
4451 case ARM::VLD4d8Pseudo_UPD:
4452 case ARM::VLD4d16Pseudo_UPD:
4453 case ARM::VLD4d32Pseudo_UPD:
4454 case ARM::VLD4q8Pseudo_UPD:
4455 case ARM::VLD4q16Pseudo_UPD:
4456 case ARM::VLD4q32Pseudo_UPD:
4457 case ARM::VLD4q8oddPseudo:
4458 case ARM::VLD4q16oddPseudo:
4459 case ARM::VLD4q32oddPseudo:
4460 case ARM::VLD4q8oddPseudo_UPD:
4461 case ARM::VLD4q16oddPseudo_UPD:
4462 case ARM::VLD4q32oddPseudo_UPD:
4463 case ARM::VLD1DUPq8:
4464 case ARM::VLD1DUPq16:
4465 case ARM::VLD1DUPq32:
4466 case ARM::VLD1DUPq8wb_fixed:
4467 case ARM::VLD1DUPq16wb_fixed:
4468 case ARM::VLD1DUPq32wb_fixed:
4469 case ARM::VLD1DUPq8wb_register:
4470 case ARM::VLD1DUPq16wb_register:
4471 case ARM::VLD1DUPq32wb_register:
4472 case ARM::VLD2DUPd8:
4473 case ARM::VLD2DUPd16:
4474 case ARM::VLD2DUPd32:
4475 case ARM::VLD2DUPd8wb_fixed:
4476 case ARM::VLD2DUPd16wb_fixed:
4477 case ARM::VLD2DUPd32wb_fixed:
4478 case ARM::VLD2DUPd8wb_register:
4479 case ARM::VLD2DUPd16wb_register:
4480 case ARM::VLD2DUPd32wb_register:
4481 case ARM::VLD2DUPq8EvenPseudo:
4482 case ARM::VLD2DUPq8OddPseudo:
4483 case ARM::VLD2DUPq16EvenPseudo:
4484 case ARM::VLD2DUPq16OddPseudo:
4485 case ARM::VLD2DUPq32EvenPseudo:
4486 case ARM::VLD2DUPq32OddPseudo:
4487 case ARM::VLD3DUPq8EvenPseudo:
4488 case ARM::VLD3DUPq8OddPseudo:
4489 case ARM::VLD3DUPq16EvenPseudo:
4490 case ARM::VLD3DUPq16OddPseudo:
4491 case ARM::VLD3DUPq32EvenPseudo:
4492 case ARM::VLD3DUPq32OddPseudo:
4493 case ARM::VLD4DUPd8Pseudo:
4494 case ARM::VLD4DUPd16Pseudo:
4495 case ARM::VLD4DUPd32Pseudo:
4496 case ARM::VLD4DUPd8Pseudo_UPD:
4497 case ARM::VLD4DUPd16Pseudo_UPD:
4498 case ARM::VLD4DUPd32Pseudo_UPD:
4499 case ARM::VLD4DUPq8EvenPseudo:
4500 case ARM::VLD4DUPq8OddPseudo:
4501 case ARM::VLD4DUPq16EvenPseudo:
4502 case ARM::VLD4DUPq16OddPseudo:
4503 case ARM::VLD4DUPq32EvenPseudo:
4504 case ARM::VLD4DUPq32OddPseudo:
4505 case ARM::VLD1LNq8Pseudo:
4506 case ARM::VLD1LNq16Pseudo:
4507 case ARM::VLD1LNq32Pseudo:
4508 case ARM::VLD1LNq8Pseudo_UPD:
4509 case ARM::VLD1LNq16Pseudo_UPD:
4510 case ARM::VLD1LNq32Pseudo_UPD:
4511 case ARM::VLD2LNd8Pseudo:
4512 case ARM::VLD2LNd16Pseudo:
4513 case ARM::VLD2LNd32Pseudo:
4514 case ARM::VLD2LNq16Pseudo:
4515 case ARM::VLD2LNq32Pseudo:
4516 case ARM::VLD2LNd8Pseudo_UPD:
4517 case ARM::VLD2LNd16Pseudo_UPD:
4518 case ARM::VLD2LNd32Pseudo_UPD:
4519 case ARM::VLD2LNq16Pseudo_UPD:
4520 case ARM::VLD2LNq32Pseudo_UPD:
4521 case ARM::VLD4LNd8Pseudo:
4522 case ARM::VLD4LNd16Pseudo:
4523 case ARM::VLD4LNd32Pseudo:
4524 case ARM::VLD4LNq16Pseudo:
4525 case ARM::VLD4LNq32Pseudo:
4526 case ARM::VLD4LNd8Pseudo_UPD:
4527 case ARM::VLD4LNd16Pseudo_UPD:
4528 case ARM::VLD4LNd32Pseudo_UPD:
4529 case ARM::VLD4LNq16Pseudo_UPD:
4530 case ARM::VLD4LNq32Pseudo_UPD:
4540unsigned ARMBaseInstrInfo::getPredicationCost(
const MachineInstr &
MI)
const {
4541 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4550 if (
MCID.isCall() || (
MCID.hasImplicitDefOfPhysReg(ARM::CPSR) &&
4551 !Subtarget.cheapPredicableCPSRDef())) {
4561 unsigned *PredCost)
const {
4562 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4568 if (
MI.isBundle()) {
4572 while (++
I !=
E &&
I->isInsideBundle()) {
4573 if (
I->getOpcode() != ARM::t2IT)
4574 Latency += getInstrLatency(ItinData, *
I, PredCost);
4579 const MCInstrDesc &MCID =
MI.getDesc();
4581 !Subtarget.cheapPredicableCPSRDef()))) {
4602 MI.hasOneMemOperand() ? (*
MI.memoperands_begin())->getAlign().value() : 0;
4604 if (Adj >= 0 || (
int)
Latency > -Adj) {
4612 if (!
Node->isMachineOpcode())
4615 if (!ItinData || ItinData->
isEmpty())
4618 unsigned Opcode =
Node->getMachineOpcode();
4628bool ARMBaseInstrInfo::hasHighOperandLatency(
const TargetSchedModel &SchedModel,
4633 unsigned UseIdx)
const {
4636 if (Subtarget.nonpipelinedVFP() &&
4651 unsigned DefIdx)
const {
4653 if (!ItinData || ItinData->
isEmpty())
4658 unsigned DefClass =
DefMI.getDesc().getSchedClass();
4659 std::optional<unsigned> DefCycle =
4661 return DefCycle && DefCycle <= 2U;
4669 ErrInfo =
"Pseudo flag setting opcodes only exist in Selection DAG";
4672 if (
MI.getOpcode() == ARM::tMOVr && !Subtarget.hasV6Ops()) {
4674 if (!ARM::hGPRRegClass.
contains(
MI.getOperand(0).getReg()) &&
4675 !ARM::hGPRRegClass.contains(
MI.getOperand(1).getReg())) {
4676 ErrInfo =
"Non-flag-setting Thumb1 mov is v6-only";
4680 if (
MI.getOpcode() == ARM::tPUSH ||
4681 MI.getOpcode() == ARM::tPOP ||
4682 MI.getOpcode() == ARM::tPOP_RET) {
4684 if (MO.isImplicit() || !MO.isReg())
4688 if (!(
MI.getOpcode() == ARM::tPUSH &&
Reg == ARM::LR) &&
4689 !(
MI.getOpcode() == ARM::tPOP_RET &&
Reg == ARM::PC)) {
4690 ErrInfo =
"Unsupported register in Thumb1 push/pop";
4696 if (
MI.getOpcode() == ARM::MVE_VMOV_q_rr) {
4697 assert(
MI.getOperand(4).isImm() &&
MI.getOperand(5).isImm());
4698 if ((
MI.getOperand(4).getImm() != 2 &&
MI.getOperand(4).getImm() != 3) ||
4699 MI.getOperand(4).getImm() !=
MI.getOperand(5).getImm() + 2) {
4700 ErrInfo =
"Incorrect array index for MVE_VMOV_q_rr";
4721 for (
auto Op :
MI.operands()) {
4728 ErrInfo =
"Incorrect AddrMode Imm for instruction";
4738 unsigned LoadImmOpc,
4739 unsigned LoadOpc)
const {
4740 assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&
4741 "ROPI/RWPI not currently supported with stack guard");
4749 if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) {
4750 assert(!Subtarget.isReadTPSoft() &&
4751 "TLS stack protector requires hardware TLS register");
4761 Module &M = *
MBB.getParent()->getFunction().getParent();
4762 Offset = M.getStackProtectorGuardOffset();
4767 unsigned AddOpc = (LoadImmOpc == ARM::MRC) ? ARM::ADDri : ARM::t2ADDri;
4778 bool IsIndirect = Subtarget.isGVIndirectSymbol(GV);
4781 if (Subtarget.isTargetMachO()) {
4783 }
else if (Subtarget.isTargetCOFF()) {
4786 else if (IsIndirect)
4788 }
else if (IsIndirect) {
4792 if (LoadImmOpc == ARM::tMOVi32imm) {
4795 ARMSysReg::lookupMClassSysRegByName(
"apsr_nzcvq")->Encoding;
4831 unsigned &AddSubOpc,
4832 bool &NegAcc,
bool &HasLane)
const {
4833 auto I = MLxEntryMap.find(Opcode);
4834 if (
I == MLxEntryMap.end())
4838 MulOpc = Entry.MulOpc;
4839 AddSubOpc = Entry.AddSubOpc;
4840 NegAcc = Entry.NegAcc;
4841 HasLane = Entry.HasLane;
4865std::pair<uint16_t, uint16_t>
4869 if (Subtarget.hasNEON()) {
4878 (
MI.getOpcode() == ARM::VMOVRS ||
MI.getOpcode() == ARM::VMOVSR ||
4879 MI.getOpcode() == ARM::VMOVS))
4886 return std::make_pair(
ExeNEON, 0);
4891 return std::make_pair(
ExeNEON, 0);
4894 return std::make_pair(
ExeVFP, 0);
4900 unsigned SReg,
unsigned &Lane) {
4902 TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);
4909 DReg =
TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
4911 assert(DReg &&
"S-register with no D super-register?");
4936 if (
MI.definesRegister(DReg,
TRI) ||
MI.readsRegister(DReg,
TRI)) {
4942 ImplicitSReg =
TRI->getSubReg(DReg,
4943 (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
4945 MI.getParent()->computeRegisterLiveness(
TRI, ImplicitSReg,
MI);
4960 unsigned DstReg, SrcReg;
4965 switch (
MI.getOpcode()) {
4977 assert(Subtarget.hasNEON() &&
"VORRd requires NEON");
4980 DstReg =
MI.getOperand(0).getReg();
4981 SrcReg =
MI.getOperand(1).getReg();
4983 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
4984 MI.removeOperand(i - 1);
4987 MI.setDesc(
get(ARM::VORRd));
4999 DstReg =
MI.getOperand(0).getReg();
5000 SrcReg =
MI.getOperand(1).getReg();
5002 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5003 MI.removeOperand(i - 1);
5010 MI.setDesc(
get(ARM::VGETLNi32));
5026 DstReg =
MI.getOperand(0).getReg();
5027 SrcReg =
MI.getOperand(1).getReg();
5035 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5036 MI.removeOperand(i - 1);
5040 MI.setDesc(
get(ARM::VSETLNi32));
5059 DstReg =
MI.getOperand(0).getReg();
5060 SrcReg =
MI.getOperand(1).getReg();
5062 unsigned DstLane = 0, SrcLane = 0;
5071 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5072 MI.removeOperand(i - 1);
5077 MI.setDesc(
get(ARM::VDUPLN32d));
5111 MCRegister CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;
5112 bool CurUndef = !
MI.readsRegister(CurReg,
TRI);
5115 CurReg = SrcLane == 0 && DstLane == 0 ? DSrc : DDst;
5116 CurUndef = !
MI.readsRegister(CurReg,
TRI);
5121 if (SrcLane == DstLane)
5124 MI.setDesc(
get(ARM::VEXTd32));
5129 CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;
5130 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5133 CurReg = SrcLane == 0 && DstLane == 1 ? DSrc : DDst;
5134 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5139 if (SrcLane != DstLane)
5145 if (ImplicitSReg != 0)
5171 auto PartialUpdateClearance = Subtarget.getPartialUpdateClearance();
5172 if (!PartialUpdateClearance)
5183 switch (
MI.getOpcode()) {
5189 case ARM::VMOVv4i16:
5190 case ARM::VMOVv2i32:
5191 case ARM::VMOVv2f32:
5192 case ARM::VMOVv1i64:
5193 UseOp =
MI.findRegisterUseOperandIdx(Reg,
TRI,
false);
5197 case ARM::VLD1LNd32:
5206 if (UseOp != -1 &&
MI.getOperand(UseOp).readsReg())
5210 if (Reg.isVirtual()) {
5212 if (!MO.
getSubReg() ||
MI.readsVirtualRegister(Reg))
5214 }
else if (ARM::SPRRegClass.
contains(Reg)) {
5217 TRI->getMatchingSuperReg(Reg, ARM::ssub_0, &ARM::DPRRegClass);
5218 if (!DReg || !
MI.definesRegister(DReg,
TRI))
5224 return PartialUpdateClearance;
5231 assert(OpNum <
MI.getDesc().getNumDefs() &&
"OpNum is not a def");
5236 assert(Reg.isPhysical() &&
"Can't break virtual register dependencies.");
5237 unsigned DReg = Reg;
5240 if (ARM::SPRRegClass.
contains(Reg)) {
5241 DReg = ARM::D0 + (Reg - ARM::S0) / 2;
5242 assert(
TRI->isSuperRegister(Reg, DReg) &&
"Register enums broken");
5245 assert(ARM::DPRRegClass.
contains(DReg) &&
"Can only break D-reg deps");
5246 assert(
MI.definesRegister(DReg,
TRI) &&
"MI doesn't clobber full D-reg");
5259 MI.addRegisterKilled(DReg,
TRI,
true);
5263 return Subtarget.hasFeature(ARM::HasV6KOps);
5267 if (
MI->getNumOperands() < 4)
5269 unsigned ShOpVal =
MI->getOperand(3).getImm();
5273 ((ShImm == 1 || ShImm == 2) &&
5283 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5284 assert(
MI.isRegSequenceLike() &&
"Invalid kind of instruction");
5286 switch (
MI.getOpcode()) {
5298 MOReg = &
MI.getOperand(2);
5310 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5311 assert(
MI.isExtractSubregLike() &&
"Invalid kind of instruction");
5313 switch (
MI.getOpcode()) {
5324 InputReg.
SubIdx = DefIdx == 0 ? ARM::ssub_0 : ARM::ssub_1;
5333 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5334 assert(
MI.isInsertSubregLike() &&
"Invalid kind of instruction");
5336 switch (
MI.getOpcode()) {
5337 case ARM::VSETLNi32:
5338 case ARM::MVE_VMOV_to_lane_32:
5346 BaseReg.Reg = MOBaseReg.
getReg();
5349 InsertedReg.
Reg = MOInsertedReg.
getReg();
5357std::pair<unsigned, unsigned>
5360 return std::make_pair(TF & Mask, TF & ~Mask);
5365 using namespace ARMII;
5367 static const std::pair<unsigned, const char *> TargetFlags[] = {
5368 {MO_LO16,
"arm-lo16"}, {MO_HI16,
"arm-hi16"},
5369 {MO_LO_0_7,
"arm-lo-0-7"}, {MO_HI_0_7,
"arm-hi-0-7"},
5370 {MO_LO_8_15,
"arm-lo-8-15"}, {MO_HI_8_15,
"arm-hi-8-15"},
5377 using namespace ARMII;
5379 static const std::pair<unsigned, const char *> TargetFlags[] = {
5380 {MO_COFFSTUB,
"arm-coffstub"},
5381 {MO_GOT,
"arm-got"},
5382 {MO_SBREL,
"arm-sbrel"},
5383 {MO_DLLIMPORT,
"arm-dllimport"},
5384 {MO_SECREL,
"arm-secrel"},
5385 {MO_NONLAZY,
"arm-nonlazy"}};
5389std::optional<RegImmPair>
5392 unsigned Opcode =
MI.getOpcode();
5399 return std::nullopt;
5402 if (Opcode == ARM::SUBri)
5404 else if (Opcode != ARM::ADDri)
5405 return std::nullopt;
5410 if (!
MI.getOperand(1).isReg() || !
MI.getOperand(2).isImm())
5411 return std::nullopt;
5413 Offset =
MI.getOperand(2).getImm() * Sign;
5421 for (
auto I = From;
I != To; ++
I)
5422 if (
I->modifiesRegister(Reg,
TRI))
5435 if (CmpMI->modifiesRegister(ARM::CPSR,
TRI))
5437 if (CmpMI->readsRegister(ARM::CPSR,
TRI))
5443 if (CmpMI->getOpcode() != ARM::tCMPi8 && CmpMI->getOpcode() != ARM::t2CMPri)
5445 Register Reg = CmpMI->getOperand(0).getReg();
5448 if (Pred !=
ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)
5461 if (Subtarget->isThumb()) {
5463 return ForCodesize ? 2 : 1;
5464 if (Subtarget->hasV6T2Ops() && (Val <= 0xffff ||
5467 return ForCodesize ? 4 : 1;
5469 return ForCodesize ? 4 : 2;
5471 return ForCodesize ? 4 : 2;
5473 return ForCodesize ? 4 : 2;
5476 return ForCodesize ? 4 : 1;
5478 return ForCodesize ? 4 : 1;
5479 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)
5480 return ForCodesize ? 4 : 1;
5482 return ForCodesize ? 8 : 2;
5484 return ForCodesize ? 8 : 2;
5487 return ForCodesize ? 8 : 2;
5488 return ForCodesize ? 8 : 3;
5654 const ARMBaseRegisterInfo *ARI =
5655 static_cast<const ARMBaseRegisterInfo *
>(&
TRI);
5664 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
5665 C.isAvailableInsideSeq(
Reg,
TRI))
5679 for (;
I !=
E; ++
I) {
5683 if (
MI.modifiesRegister(ARM::LR, &
TRI))
5687 unsigned Opcode =
MI.getOpcode();
5688 if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR ||
5689 Opcode == ARM::SUBS_PC_LR || Opcode == ARM::tBX_RET ||
5690 Opcode == ARM::tBXNS_RET || Opcode == ARM::t2BXAUT_RET) {
5696 if (
MI.readsRegister(ARM::LR, &
TRI))
5705 auto Opcode =
MI.getOpcode();
5706 return (Opcode == ARM::BL || Opcode == ARM::BLX || Opcode == ARM::BLX_noip ||
5707 Opcode == ARM::tBL || Opcode == ARM::tBLXi || Opcode == ARM::tBLXr ||
5708 Opcode == ARM::tBLXr_noip);
5711std::optional<std::unique_ptr<outliner::OutlinedFunction>>
5714 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
5715 unsigned MinRepeats)
const {
5716 unsigned SequenceSize = 0;
5717 for (
auto &
MI : RepeatedSequenceLocs[0])
5721 unsigned FlagsSetInAll = 0xF;
5726 FlagsSetInAll &=
C.Flags;
5745 return C.isAnyUnavailableAcrossOrOutOfSeq({ARM::R12, ARM::CPSR},
TRI);
5753 llvm::erase_if(RepeatedSequenceLocs, CantGuaranteeValueAcrossCall);
5756 if (RepeatedSequenceLocs.size() < MinRepeats)
5757 return std::nullopt;
5776 if (std::distance(RepeatedSequenceLocs.begin(), NoBTI) >
5777 std::distance(NoBTI, RepeatedSequenceLocs.end()))
5778 RepeatedSequenceLocs.erase(NoBTI, RepeatedSequenceLocs.end());
5780 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoBTI);
5782 if (RepeatedSequenceLocs.size() < MinRepeats)
5783 return std::nullopt;
5793 if (std::distance(RepeatedSequenceLocs.begin(), NoPAC) >
5794 std::distance(NoPAC, RepeatedSequenceLocs.end()))
5795 RepeatedSequenceLocs.erase(NoPAC, RepeatedSequenceLocs.end());
5797 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoPAC);
5799 if (RepeatedSequenceLocs.size() < MinRepeats)
5800 return std::nullopt;
5806 auto SetCandidateCallInfo =
5807 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
5809 C.setCallInfo(CallID, NumBytesForCall);
5814 const auto &SomeMFI =
5817 if (SomeMFI.branchTargetEnforcement()) {
5826 if (SomeMFI.shouldSignReturnAddress(
true)) {
5836 if (RepeatedSequenceLocs[0].back().isTerminator()) {
5848 unsigned NumBytesNoStackCalls = 0;
5849 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
5854 const auto Last =
C.getMBB()->rbegin();
5855 const bool LRIsAvailable =
5856 C.getMBB()->isReturnBlock() && !
Last->isCall()
5859 :
C.isAvailableAcrossAndOutOfSeq(ARM::LR,
TRI);
5860 if (LRIsAvailable) {
5864 CandidatesWithoutStackFixups.push_back(
C);
5869 else if (findRegisterToSaveLRTo(
C)) {
5873 CandidatesWithoutStackFixups.push_back(
C);
5878 else if (
C.isAvailableInsideSeq(ARM::SP,
TRI)) {
5881 CandidatesWithoutStackFixups.push_back(
C);
5887 NumBytesNoStackCalls += SequenceSize;
5893 if (NumBytesNoStackCalls <=
5894 RepeatedSequenceLocs.size() * Costs.
CallDefault) {
5895 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
5897 if (RepeatedSequenceLocs.size() < MinRepeats)
5898 return std::nullopt;
5923 return std::make_unique<outliner::OutlinedFunction>(
5924 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
5927bool ARMBaseInstrInfo::checkAndUpdateStackOffset(
MachineInstr *
MI,
5930 int SPIdx =
MI->findRegisterUseOperandIdx(ARM::SP,
nullptr);
5955 unsigned NumOps =
MI->getDesc().getNumOperands();
5956 unsigned ImmIdx =
NumOps - 3;
5960 int64_t OffVal =
Offset.getImm();
5966 unsigned NumBits = 0;
5995 assert((
Fixup & 3) == 0 &&
"Can't encode this offset!");
6015 assert(((OffVal * Scale +
Fixup) & (Scale - 1)) == 0 &&
6016 "Can't encode this offset!");
6017 OffVal +=
Fixup / Scale;
6019 unsigned Mask = (1 << NumBits) - 1;
6021 if (OffVal <= Mask) {
6023 MI->getOperand(ImmIdx).setImm(OffVal);
6031 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
6035 const Function &CFn =
C.getMF()->getFunction();
6042 ARMGenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
6050 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
6069 unsigned &Flags)
const {
6072 assert(
MBB.getParent()->getRegInfo().tracksLiveness() &&
6073 "Suitable Machine Function for outlining must track liveness");
6081 bool R12AvailableInBlock = LRU.
available(ARM::R12);
6082 bool CPSRAvailableInBlock = LRU.
available(ARM::CPSR);
6086 if (R12AvailableInBlock && CPSRAvailableInBlock)
6094 if (R12AvailableInBlock && !LRU.
available(ARM::R12))
6096 if (CPSRAvailableInBlock && !LRU.
available(ARM::CPSR))
6106 bool LRIsAvailable =
6107 MBB.isReturnBlock() && !
MBB.back().isCall()
6119 unsigned Flags)
const {
6125 unsigned Opc =
MI.getOpcode();
6126 if (
Opc == ARM::tPICADD ||
Opc == ARM::PICADD ||
Opc == ARM::PICSTR ||
6127 Opc == ARM::PICSTRB ||
Opc == ARM::PICSTRH ||
Opc == ARM::PICLDR ||
6128 Opc == ARM::PICLDRB ||
Opc == ARM::PICLDRH ||
Opc == ARM::PICLDRSB ||
6129 Opc == ARM::PICLDRSH ||
Opc == ARM::t2LDRpci_pic ||
6130 Opc == ARM::t2MOVi16_ga_pcrel ||
Opc == ARM::t2MOVTi16_ga_pcrel ||
6131 Opc == ARM::t2MOV_ga_pcrel)
6135 if (
Opc == ARM::t2BF_LabelPseudo ||
Opc == ARM::t2DoLoopStart ||
6136 Opc == ARM::t2DoLoopStartTP ||
Opc == ARM::t2WhileLoopStart ||
6137 Opc == ARM::t2WhileLoopStartLR ||
Opc == ARM::t2WhileLoopStartTP ||
6138 Opc == ARM::t2LoopDec ||
Opc == ARM::t2LoopEnd ||
6139 Opc == ARM::t2LoopEndDec)
6143 uint64_t MIFlags =
MCID.TSFlags;
6148 if (
MI.isTerminator())
6154 if (
MI.readsRegister(ARM::LR,
TRI) ||
MI.readsRegister(ARM::PC,
TRI))
6162 if (MOP.isGlobal()) {
6171 (Callee->getName() ==
"\01__gnu_mcount_nc" ||
6172 Callee->getName() ==
"\01mcount" || Callee->getName() ==
"__mcount"))
6184 return UnknownCallOutlineType;
6192 return UnknownCallOutlineType;
6200 return UnknownCallOutlineType;
6208 if (
MI.modifiesRegister(ARM::LR,
TRI) ||
MI.modifiesRegister(ARM::PC,
TRI))
6212 if (
MI.modifiesRegister(ARM::SP,
TRI) ||
MI.readsRegister(ARM::SP,
TRI)) {
6225 bool MightNeedStackFixUp =
6229 if (!MightNeedStackFixUp)
6235 if (
MI.modifiesRegister(ARM::SP,
TRI))
6240 if (checkAndUpdateStackOffset(&
MI, Subtarget.getStackAlignment().value(),
6249 if (
MI.readsRegister(ARM::ITSTATE,
TRI) ||
6250 MI.modifiesRegister(ARM::ITSTATE,
TRI))
6254 if (
MI.isCFIInstruction())
6269 int Align = std::max(Subtarget.getStackAlignment().value(),
uint64_t(8));
6271 assert(Align >= 8 && Align <= 256);
6273 assert(Subtarget.isThumb2());
6285 unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
6299 CFIBuilder.buildDefCFAOffset(Align);
6304 CFIBuilder.buildOffset(ARM::LR, -LROffset);
6307 CFIBuilder.buildOffset(ARM::RA_AUTH_CODE, -Align);
6313 bool CFI,
bool Auth)
const {
6314 int Align = Subtarget.getStackAlignment().value();
6317 assert(Subtarget.isThumb2());
6329 unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
6333 if (!Subtarget.isThumb())
6335 MIB.
addImm(Subtarget.getStackAlignment().value())
6343 CFIBuilder.buildDefCFAOffset(0);
6344 CFIBuilder.buildRestore(ARM::LR);
6346 CFIBuilder.buildUndefined(ARM::RA_AUTH_CODE);
6360 bool isThumb = Subtarget.isThumb();
6361 unsigned FuncOp =
isThumb ? 2 : 0;
6362 unsigned Opc =
Call->getOperand(FuncOp).isReg()
6363 ?
isThumb ? ARM::tTAILJMPr : ARM::TAILJMPr
6364 :
isThumb ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd
6368 .
add(
Call->getOperand(FuncOp));
6371 Call->eraseFromParent();
6376 return MI.isCall() && !
MI.isReturn();
6384 Et = std::prev(
MBB.end());
6389 if (!
MBB.isLiveIn(ARM::LR))
6390 MBB.addLiveIn(ARM::LR);
6394 saveLROnStack(
MBB, It,
true, Auth);
6399 "Can only fix up stack references once");
6400 fixupPostOutline(
MBB);
6403 restoreLRFromStack(
MBB, Et,
true, Auth);
6423 fixupPostOutline(
MBB);
6432 bool isThumb = Subtarget.isThumb();
6438 ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND
6444 It =
MBB.insert(It, MIB);
6458 It =
MBB.insert(It, CallMIB);
6465 Register Reg = findRegisterToSaveLRTo(
C);
6466 assert(Reg != 0 &&
"No callee-saved register available?");
6473 CallPt =
MBB.insert(It, CallMIB);
6481 if (!
MBB.isLiveIn(ARM::LR))
6482 MBB.addLiveIn(ARM::LR);
6485 CallPt =
MBB.insert(It, CallMIB);
6496bool ARMBaseInstrInfo::isReMaterializableImpl(
6530 static int constexpr MAX_STAGES = 30;
6531 static int constexpr LAST_IS_USE = MAX_STAGES;
6532 static int constexpr SEEN_AS_LIVE = MAX_STAGES + 1;
6533 typedef std::bitset<MAX_STAGES + 2> IterNeed;
6534 typedef std::map<Register, IterNeed> IterNeeds;
6537 const IterNeeds &CIN);
6549 : EndLoop(EndLoop), LoopCount(LoopCount),
6551 TII(MF->getSubtarget().getInstrInfo()) {}
6553 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
6555 return MI == EndLoop ||
MI == LoopCount;
6558 bool shouldUseSchedule(SwingSchedulerDAG &SSD, SMSchedule &SMS)
override {
6559 if (tooMuchRegisterPressure(SSD, SMS))
6565 std::optional<bool> createTripCountGreaterCondition(
6566 int TC, MachineBasicBlock &
MBB,
6567 SmallVectorImpl<MachineOperand> &
Cond)
override {
6576 }
else if (EndLoop->
getOpcode() == ARM::t2LoopEnd) {
6579 MachineInstr *LoopDec =
nullptr;
6581 if (
I.getOpcode() == ARM::t2LoopDec)
6583 assert(LoopDec &&
"Unable to find copied LoopDec");
6589 .
addReg(ARM::NoRegister);
6597 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
6599 void adjustTripCount(
int TripCountAdjust)
override {}
6603 const IterNeeds &CIN) {
6605 for (
const auto &
N : CIN) {
6606 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6607 for (
int I = 0;
I < Cnt; ++
I)
6612 for (
const auto &
N : CIN) {
6613 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6614 for (
int I = 0;
I < Cnt; ++
I)
6622 IterNeeds CrossIterationNeeds;
6627 for (
auto &SU : SSD.
SUnits) {
6630 for (
auto &S : SU.Succs)
6634 CrossIterationNeeds[
Reg.
id()].set(0);
6635 }
else if (S.isAssignedRegDep()) {
6637 if (OStg >= 0 && OStg != Stg) {
6640 CrossIterationNeeds[
Reg.
id()] |= ((1 << (OStg - Stg)) - 1);
6649 std::vector<SUnit *> ProposedSchedule;
6653 std::deque<SUnit *> Instrs =
6655 std::sort(Instrs.begin(), Instrs.end(),
6656 [](
SUnit *
A,
SUnit *
B) { return A->NodeNum > B->NodeNum; });
6663 for (
auto *SU : ProposedSchedule)
6667 if (!MO.isReg() || !MO.getReg())
6670 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6671 if (CIter == CrossIterationNeeds.end() || CIter->second[LAST_IS_USE] ||
6672 CIter->second[SEEN_AS_LIVE])
6674 if (MO.isDef() && !MO.isDead())
6675 CIter->second.set(SEEN_AS_LIVE);
6676 else if (MO.isUse())
6677 CIter->second.set(LAST_IS_USE);
6679 for (
auto &CI : CrossIterationNeeds)
6680 CI.second.reset(LAST_IS_USE);
6686 RPTracker.init(MF, &RegClassInfo,
nullptr, EndLoop->
getParent(),
6689 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6691 for (
auto *SU : ProposedSchedule) {
6693 RPTracker.setPos(std::next(CurInstI));
6699 if (!MO.isReg() || !MO.getReg())
6702 if (MO.isDef() && !MO.isDead()) {
6703 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6704 if (CIter != CrossIterationNeeds.end()) {
6705 CIter->second.reset(0);
6706 CIter->second.reset(SEEN_AS_LIVE);
6710 for (
auto &S : SU->Preds) {
6712 if (S.isAssignedRegDep()) {
6714 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6715 if (CIter != CrossIterationNeeds.end()) {
6717 assert(Stg2 <= Stg &&
"Data dependence upon earlier stage");
6718 if (Stg - Stg2 < MAX_STAGES)
6719 CIter->second.set(Stg - Stg2);
6720 CIter->second.set(SEEN_AS_LIVE);
6725 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6728 auto &
P = RPTracker.getPressure().MaxSetPressure;
6729 for (
unsigned I = 0,
E =
P.size();
I <
E; ++
I) {
6731 if (
I == ARM::DQuad_with_ssub_0 ||
I == ARM::DTripleSpc_with_ssub_0 ||
6732 I == ARM::DTriple_with_qsub_0_in_QPR)
6744std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
6748 if (Preheader == LoopBB)
6749 Preheader = *std::next(LoopBB->
pred_begin());
6751 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2Bcc) {
6757 for (
auto &L : LoopBB->
instrs()) {
6764 return std::make_unique<ARMPipelinerLoopInfo>(&*
I, CCSetter);
6778 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2LoopEnd) {
6779 for (
auto &L : LoopBB->
instrs())
6784 Register LoopDecResult =
I->getOperand(0).getReg();
6787 if (!LoopDec || LoopDec->
getOpcode() != ARM::t2LoopDec)
6790 for (
auto &J : Preheader->
instrs())
6791 if (J.getOpcode() == ARM::t2DoLoopStart)
6795 return std::make_unique<ARMPipelinerLoopInfo>(&*
I, LoopDec);
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isThumb(const MCSubtargetInfo &STI)
static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI, MachineInstr &MI, MCRegister DReg, unsigned Lane, MCRegister &ImplicitSReg)
getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane, set ImplicitSReg to a register n...
static const MachineInstr * getBundledUseMI(const TargetRegisterInfo *TRI, const MachineInstr &MI, unsigned Reg, unsigned &UseIdx, unsigned &Dist)
static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI)
Create a copy of a const pool value.
static bool isSuitableForMask(MachineInstr *&MI, Register SrcReg, int CmpMask, bool CommonUse)
isSuitableForMask - Identify a suitable 'and' instruction that operates on the given source register ...
static int adjustDefLatency(const ARMSubtarget &Subtarget, const MachineInstr &DefMI, const MCInstrDesc &DefMCID, unsigned DefAlign)
Return the number of cycles to add to (or subtract from) the static itinerary based on the def opcode...
static unsigned getNumMicroOpsSwiftLdSt(const InstrItineraryData *ItinData, const MachineInstr &MI)
static MCRegister getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI, unsigned SReg, unsigned &Lane)
static bool CanTransformInstrIntoTailCall(const MachineInstr &MI)
Return true if MI is a call instruction that the outliner can rewrite as a tail call.
static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[]
static bool isEligibleForITBlock(const MachineInstr *MI)
static ARMCC::CondCodes getCmpToAddCondition(ARMCC::CondCodes CC)
getCmpToAddCondition - assume the flags are set by CMP(a,b), return the condition code if we modify t...
static bool isOptimizeCompareCandidate(MachineInstr *MI, bool &IsThumb1)
static bool isLRAvailable(const TargetRegisterInfo &TRI, MachineBasicBlock::reverse_iterator I, MachineBasicBlock::reverse_iterator E)
static const ARM_MLxEntry ARM_MLxTable[]
static bool isRedundantFlagInstr(const MachineInstr *CmpI, Register SrcReg, Register SrcReg2, int64_t ImmValue, const MachineInstr *OI, bool &IsThumb1)
isRedundantFlagInstr - check whether the first instruction, whose only purpose is to update flags,...
static unsigned getNumMicroOpsSingleIssuePlusExtras(unsigned Opc, unsigned NumRegs)
static const MachineInstr * getBundledDefMI(const TargetRegisterInfo *TRI, const MachineInstr *MI, unsigned Reg, unsigned &DefIdx, unsigned &Dist)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
This file defines the DenseMap class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
PowerPC TLS Dynamic Call Fixup
TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallSet class.
This file defines the SmallVector class.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static bool isCPSRDefined(const MachineInstr &MI)
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction to set the zero flag so that we can remove a "comparis...
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) 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
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const override
foldImmediate - 'Reg' is known to be defined by a move immediate instruction, try to fold the immedia...
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) 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
void copyFromCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister DestReg, bool KillSrc, const ARMSubtarget &Subtarget) const
unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr &MI) const override
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
unsigned getPartialRegUpdateClearance(const MachineInstr &, unsigned, const TargetRegisterInfo *) const override
unsigned getNumLDMAddresses(const MachineInstr &MI) const
Get the number of addresses by LDM or VLDM or zero for unknown.
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
bool produceSameValue(const MachineInstr &MI0, const MachineInstr &MI1, const MachineRegisterInfo *MRI) const override
void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
Analyze loop L, which must be a single-basic-block loop, and if the conditions can be understood enou...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Returns the size of the specified MachineInstr.
void copyToCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister SrcReg, bool KillSrc, const ARMSubtarget &Subtarget) const
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void mergeOutliningCandidateAttributes(Function &F, std::vector< outliner::Candidate > &Candidates) const override
const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, RegState State) const
bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override
ARM supports the MachineOutliner.
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
Enable outlining by default at -Oz.
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...
MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const override
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
bool isPredicated(const MachineInstr &MI) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const
bool isPredicable(const MachineInstr &MI) const override
isPredicable - Return true if the specified instruction can be predicated.
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const override
Specialization of TargetInstrInfo::describeLoadedValue, used to enhance debug entry value description...
std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
unsigned extraSizeToPredicateInstructions(const MachineFunction &MF, unsigned NumInsts) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
const ARMBaseRegisterInfo & getRegisterInfo() const
bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const override
areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are lo...
std::optional< unsigned > getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr &DefMI, unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const override
bool getRegSequenceLikeInputs(const MachineInstr &MI, unsigned DefIdx, SmallVectorImpl< RegSubRegPairAndIdx > &InputRegs) const override
Build the equivalent inputs of a REG_SEQUENCE for the given MI and DefIdx.
unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const override
bool getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPair &BaseReg, RegSubRegPairAndIdx &InsertedReg) const override
Build the equivalent inputs of a INSERT_SUBREG for the given MI and DefIdx.
bool expandPostRAPseudo(MachineInstr &MI) const override
outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MIT, unsigned Flags) const override
bool SubsumesPredicate(ArrayRef< MachineOperand > Pred1, ArrayRef< MachineOperand > Pred2) const override
bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, int64_t Offset2, unsigned NumLoads) const override
shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to determine (in conjunction w...
bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Pred) const override
std::pair< uint16_t, uint16_t > getExecutionDomain(const MachineInstr &MI) const override
VFP/NEON execution domains.
bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, MachineBasicBlock &FMBB) const override
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
bool isFpMLxInstruction(unsigned Opcode) const
isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS instruction.
bool isSwiftFastImmShift(const MachineInstr *MI) const
Returns true if the instruction has a shift by immediate that can be executed in one cycle less.
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
ARMBaseInstrInfo(const ARMSubtarget &STI, const ARMBaseRegisterInfo &TRI)
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
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 if h...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void breakPartialRegDependency(MachineInstr &, unsigned, const TargetRegisterInfo *TRI) const override
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
const ARMSubtarget & getSubtarget() const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
Commutes the operands in the given instruction.
bool getExtractSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPairAndIdx &InputReg) const override
Build the equivalent inputs of a EXTRACT_SUBREG for the given MI and DefIdx.
bool shouldSink(const MachineInstr &MI) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
bool isMachineBasicBlock() const
bool isGlobalValue() const
ARMCP::ARMCPModifier getModifier() const
bool mustAddCurrentAddress() const
virtual bool hasSameValue(ARMConstantPoolValue *ACPV)
hasSameValue - Return true if this ARM constpool value can share the same constantpool entry as anoth...
bool isBlockAddress() const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool isThumb2Function() const
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
bool isThumb1OnlyFunction() const
bool isThumbFunction() const
bool shouldSignReturnAddress() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
Align getStackAlignment() const
getStackAlignment - Returns the minimum alignment known to hold of the stack frame on entry to the fu...
bool enableMachinePipeliner() const override
Returns true if machine pipeliner should be enabled.
@ DoubleIssueCheckUnalignedAccess
Can load/store 2 registers/cycle, but needs an extra cycle if the access is not 64-bit aligned.
@ SingleIssue
Can load/store 1 register/cycle.
@ DoubleIssue
Can load/store 2 registers/cycle.
@ SingleIssuePlusExtras
Can load/store 1 register/cycle, but needs an extra cycle for address computation and potentially als...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type size() const
Returns the number of bits in this bitvector.
LLVM_ABI uint64_t scale(uint64_t Num) const
Scale a large integer.
BranchProbability getCompl() const
Helper class for creating CFI instructions and inserting them into MIR.
void buildRegister(MCRegister Reg1, MCRegister Reg2) const
void buildRestore(MCRegister Reg) const
ConstMIBundleOperands - Iterate over all operands in a const bundle of machine instructions.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasDLLImportStorageClass() const
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Reverses the branch condition of the specified condition list, returning false on success and true if...
Itinerary data supplied by a subtarget to be used by a target.
int getNumMicroOps(unsigned ItinClassIndx) const
Return the number of micro-ops that the given class decodes to.
std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
unsigned getStageLatency(unsigned ItinClassIndx) const
Return the total stage latency of the given class.
std::optional< unsigned > getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Compute and return the use operand latency of a given itinerary class and operand index if the value ...
bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Return true if there is a pipeline forwarding between instructions of itinerary classes DefClass and ...
bool isEmpty() const
Returns true if there are no itineraries.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Describe properties that are true of each instruction in the target description file.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool isCall() const
Return true if the instruction is a call.
unsigned getOpcode() const
Return the opcode number for this descriptor.
LLVM_ABI bool hasImplicitDefOfPhysReg(MCRegister Reg, const MCRegisterInfo *MRI=nullptr) const
Return true if this instruction implicitly defines the specified physical register.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
Wrapper class representing physical registers. Should be passed by value.
bool isValid() const
isValid - Returns true until all the operands have been visited.
unsigned pred_size() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Instructions::iterator instr_iterator
pred_iterator pred_begin()
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
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.
MachineInstrBundleIterator< MachineInstr > iterator
LivenessQueryResult
Possible outcome of a register liveness query to computeRegisterLiveness()
@ LQR_Dead
Register is known to be fully dead.
@ LQR_Live
Register is known to be (at least partially) live.
@ LQR_Unknown
Register liveness not decidable from local neighborhood.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
const Constant * ConstVal
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
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.
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.
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.
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.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) 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 & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
ArrayRef< MachineMemOperand * >::iterator mmo_iterator
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isImplicitDef() const
const MachineBasicBlock * getParent() const
bool isCopyLike() const
Return true if the instruction behaves like a copy.
bool isCall(QueryType Type=AnyInBundle) const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI int findFirstPredOperandIdx() const
Find the index of the first operand in the operand list that is used to represent the predicate.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool isRegSequence() const
bool isInsertSubreg() const
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI bool isIdenticalTo(const MachineInstr &Other, MICheckType Check=CheckDefs) const
Return true if this instruction is identical to Other.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
bool hasOptionalDef(QueryType Type=IgnoreBundle) const
Set if this instruction has an optional definition, e.g.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ 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.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
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 bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
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)
int64_t getOffset() const
Return the offset from the symbol in this operand.
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.
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
use_instr_iterator use_instr_begin(Register RegNo) const
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static use_instr_iterator use_instr_end()
const TargetRegisterInfo * getTargetRegisterInfo() const
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 LLVM_READONLY 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.
void AddHazardRecognizer(std::unique_ptr< ScheduleHazardRecognizer > &&)
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void increaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
LLVM_ABI void decreaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
unsigned getRegPressureSetLimit(unsigned Idx) const
Get the register unit limit for the given pressure set index.
LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)
runOnFunction - Prepare to answer questions about MF.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
@ Anti
A register anti-dependence (aka WAR).
This class represents the scheduled code.
unsigned getMaxStageCount()
Return the maximum stage count needed for this schedule.
int stageScheduled(SUnit *SU) const
Return the stage for a scheduled instruction.
int getInitiationInterval() const
Return the initiation interval for this schedule.
std::deque< SUnit * > & getInstructions(int cycle)
Return the instructions that are scheduled at the specified cycle.
int getFirstCycle() const
Return the first cycle in the completed schedule.
int getFinalCycle() const
Return the last cycle in the finalized schedule.
Scheduling unit. This is a node in the scheduling DAG.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
std::vector< SUnit > SUnits
The scheduling units.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
Represent a constant reference to a string, i.e.
This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
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 ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const
Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const
Compute operand latency based on the available machine model.
const InstrItineraryData * getInstrItineraries() const
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Wrapper class representing a virtual register or register unit.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static CondCodes getOppositeCondition(CondCodes CC)
ARMII - This namespace holds all of the target specific flags that instruction info tracks.
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
AddrMode
ARM Addressing Modes.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned char getAM5FP16Offset(unsigned AM5Opc)
unsigned getSORegOffset(unsigned Op)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
unsigned getAM2Offset(unsigned AM2Opc)
unsigned getSOImmValRotate(unsigned Imm)
getSOImmValRotate - Try to handle Imm with an immediate shifter operand, computing the rotate amount ...
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
ShiftOpc getSORegShOp(unsigned Op)
AddrOpc getAM5Op(unsigned AM5Opc)
bool isSOImmTwoPartValNeg(unsigned V)
isSOImmTwoPartValNeg - Return true if the specified value can be obtained by two SOImmVal,...
unsigned getSOImmTwoPartSecond(unsigned V)
getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...
bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned getT2SOImmTwoPartSecond(unsigned Imm)
unsigned getT2SOImmTwoPartFirst(unsigned Imm)
bool isT2SOImmTwoPartVal(unsigned Imm)
unsigned char getAM5Offset(unsigned AM5Opc)
unsigned getSOImmTwoPartFirst(unsigned V)
getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...
AddrOpc getAM2Op(unsigned AM2Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
Define some predicates that are used for node matching.
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< NodeBase * > Node
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.
constexpr T rotr(T V, int R)
static bool isIndirectCall(const MachineInstr &MI)
MachineInstr * findCMPToFoldIntoCBZ(MachineInstr *Br, const TargetRegisterInfo *TRI)
Search backwards from a tBcc to find a tCMPi8 against 0, meaning we can convert them to a tCBZ or tCB...
static bool isCondBranchOpcode(int Opc)
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
static bool isPushOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond)
static bool isVCTP(const MachineInstr *MI)
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.
bool IsCPSRDead< MachineInstr >(const MachineInstr *MI)
constexpr RegState getKillRegState(bool B)
unsigned getBLXpredOpcode(const MachineFunction &MF)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
static bool isIndirectBranchOpcode(int Opc)
bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI)
Return true if Reg is defd between From and To.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isSEHInstruction(const MachineInstr &MI)
static bool isCalleeSavedRegister(MCRegister Reg, const MCPhysReg *CSRegs)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
auto reverse(ContainerTy &&C)
static bool isJumpTableBranchOpcode(int Opc)
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)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static bool isPopOpcode(int Opc)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond, unsigned Inactive)
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg)
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII)
rewriteARMFrameIndex / rewriteT2FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
unsigned getMatchingCondBranchOpcode(unsigned Opc)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
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...
static const char * ARMCondCodeToString(ARMCC::CondCodes CC)
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned gettBLXrOpcode(const MachineFunction &MF)
static bool isSpeculationBarrierEndBBOpcode(int Opc)
unsigned getBLXOpcode(const MachineFunction &MF)
void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB)
bool isV8EligibleForIT(const InstrType *Instr)
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
constexpr RegState getUndefRegState(bool B)
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
MCRegisterClass TargetRegisterClass
ARM_MLxEntry - Record information about MLA / MLS instructions.
Map pseudo instructions that imply an 'S' bit onto real opcodes.
OutlinerCosts(const ARMSubtarget &target)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr LaneBitmask getAll()
static constexpr LaneBitmask getNone()
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Used to describe a register and immediate addition.
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
An individual sequence of instructions to be replaced with a call to an outlined function.
The information necessary to create an outlined function for some class of candidate.