72#define DEBUG_TYPE "arm-instrinfo"
74#define GET_INSTRINFO_CTOR_DTOR
75#include "ARMGenInstrInfo.inc"
89 { ARM::VMLAS, ARM::VMULS, ARM::VADDS,
false,
false },
90 { ARM::VMLSS, ARM::VMULS, ARM::VSUBS,
false,
false },
91 { ARM::VMLAD, ARM::VMULD, ARM::VADDD,
false,
false },
92 { ARM::VMLSD, ARM::VMULD, ARM::VSUBD,
false,
false },
93 { ARM::VNMLAS, ARM::VNMULS, ARM::VSUBS,
true,
false },
94 { ARM::VNMLSS, ARM::VMULS, ARM::VSUBS,
true,
false },
95 { ARM::VNMLAD, ARM::VNMULD, ARM::VSUBD,
true,
false },
96 { ARM::VNMLSD, ARM::VMULD, ARM::VSUBD,
true,
false },
99 { ARM::VMLAfd, ARM::VMULfd, ARM::VADDfd,
false,
false },
100 { ARM::VMLSfd, ARM::VMULfd, ARM::VSUBfd,
false,
false },
101 { ARM::VMLAfq, ARM::VMULfq, ARM::VADDfq,
false,
false },
102 { ARM::VMLSfq, ARM::VMULfq, ARM::VSUBfq,
false,
false },
103 { ARM::VMLAslfd, ARM::VMULslfd, ARM::VADDfd,
false,
true },
104 { ARM::VMLSslfd, ARM::VMULslfd, ARM::VSUBfd,
false,
true },
105 { ARM::VMLAslfq, ARM::VMULslfq, ARM::VADDfq,
false,
true },
106 { ARM::VMLSslfq, ARM::VMULslfq, ARM::VSUBfq,
false,
true },
113 for (
unsigned i = 0, e = std::size(
ARM_MLxTable); i != e; ++i) {
114 if (!MLxEntryMap.insert(std::make_pair(
ARM_MLxTable[i].MLxOpc, i)).second)
126 if (usePreRAHazardRecognizer()) {
128 static_cast<const ARMSubtarget *
>(STI)->getInstrItineraryData();
148 std::make_unique<ARMBankConflictHazardRecognizer>(DAG, 0x4,
true));
164 if (Subtarget.isThumb2() || Subtarget.hasVFP2Base())
185 bool AllowModify)
const {
190 if (
I ==
MBB.instr_begin())
200 bool CantAnalyze =
false;
204 while (
I->isDebugInstr() || !
I->isTerminator() ||
206 I->getOpcode() == ARM::t2DoLoopStartTP){
207 if (
I ==
MBB.instr_begin())
218 TBB =
I->getOperand(0).getMBB();
224 assert(!FBB &&
"FBB should have been null.");
226 TBB =
I->getOperand(0).getMBB();
227 Cond.push_back(
I->getOperand(1));
228 Cond.push_back(
I->getOperand(2));
229 }
else if (
I->isReturn()) {
232 }
else if (
I->getOpcode() == ARM::t2LoopEnd &&
239 TBB =
I->getOperand(1).getMBB();
241 Cond.push_back(
I->getOperand(0));
263 while (DI !=
MBB.instr_end()) {
286 if (
I ==
MBB.instr_begin())
298 int *BytesRemoved)
const {
299 assert(!BytesRemoved &&
"code size not handled");
310 I->eraseFromParent();
314 if (
I ==
MBB.begin())
return 1;
320 I->eraseFromParent();
329 int *BytesAdded)
const {
330 assert(!BytesAdded &&
"code size not handled");
339 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
341 "ARM branch conditions have two or three components!");
351 }
else if (
Cond.size() == 2) {
362 if (
Cond.size() == 2)
367 else if (
Cond.size() == 3)
378 if (
Cond.size() == 2) {
390 while (++
I != E &&
I->isInsideBundle()) {
391 int PIdx =
I->findFirstPredOperandIdx();
392 if (PIdx != -1 &&
I->getOperand(PIdx).getImm() !=
ARMCC::AL)
398 int PIdx =
MI.findFirstPredOperandIdx();
399 return PIdx != -1 &&
MI.getOperand(PIdx).getImm() !=
ARMCC::AL;
407 std::string GenericComment =
409 if (!GenericComment.empty())
410 return GenericComment;
414 return std::string();
418 int FirstPredOp =
MI.findFirstPredOperandIdx();
419 if (FirstPredOp != (
int) OpIdx)
420 return std::string();
422 std::string CC =
"CC::";
429 unsigned Opc =
MI.getOpcode();
438 int PIdx =
MI.findFirstPredOperandIdx();
442 MI.getOperand(PIdx+1).setReg(Pred[1].
getReg());
449 "CPSR def isn't expected operand");
450 assert((
MI.getOperand(1).isDead() ||
451 MI.getOperand(1).getReg() != ARM::CPSR) &&
452 "if conversion tried to stop defining used CPSR");
463 if (Pred1.
size() > 2 || Pred2.
size() > 2)
488 std::vector<MachineOperand> &Pred,
489 bool SkipDead)
const {
492 bool ClobbersCPSR = MO.isRegMask() && MO.clobbersPhysReg(ARM::CPSR);
493 bool IsCPSR = MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR;
494 if (ClobbersCPSR || IsCPSR) {
512 for (
const auto &MO :
MI.operands())
513 if (MO.isReg() && MO.getReg() == ARM::CPSR && MO.isDef() && !MO.isDead())
519 switch (
MI->getOpcode()) {
520 default:
return true;
551 if (!
MI.isPredicable())
589 if (!MO.isReg() || MO.isUndef() || MO.isUse())
591 if (MO.getReg() != ARM::CPSR)
611 switch (
MI.getOpcode()) {
618 return MCID.getSize();
619 case TargetOpcode::BUNDLE:
620 return getInstBundleSize(
MI);
621 case TargetOpcode::COPY:
626 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
627 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
628 case TargetOpcode::PATCHABLE_TAIL_CALL:
631 case ARM::CONSTPOOL_ENTRY:
632 case ARM::JUMPTABLE_INSTS:
633 case ARM::JUMPTABLE_ADDRS:
634 case ARM::JUMPTABLE_TBB:
635 case ARM::JUMPTABLE_TBH:
638 return MI.getOperand(2).getImm();
640 return MI.getOperand(1).getImm();
642 case ARM::INLINEASM_BR: {
644 unsigned Size = getInlineAsmLength(
MI.getOperand(0).getSymbolName(), MAI);
649 case ARM::Int_eh_sjlj_longjmp:
650 return Subtarget.isTargetDarwin() || Subtarget.isTargetWindows() ? 16 : 20;
651 case ARM::tInt_eh_sjlj_longjmp:
652 return Subtarget.isTargetDarwin() || Subtarget.isTargetWindows() ? 10 : 12;
660 unsigned Opc = Subtarget.isThumb()
661 ? (Subtarget.isMClass() ? ARM::t2MRS_M : ARM::t2MRS_AR)
669 if (Subtarget.isMClass())
680 unsigned Opc = Subtarget.isThumb()
681 ? (Subtarget.isMClass() ? ARM::t2MSR_M : ARM::t2MSR_AR)
686 if (Subtarget.isMClass())
715 unsigned Cond,
unsigned Inactive) {
725 bool RenamableSrc)
const {
726 bool GPRDest = ARM::GPRRegClass.contains(DestReg);
727 bool GPRSrc = ARM::GPRRegClass.contains(SrcReg);
729 if (GPRDest && GPRSrc) {
737 bool SPRDest = ARM::SPRRegClass.contains(DestReg);
738 bool SPRSrc = ARM::SPRRegClass.contains(SrcReg);
741 if (SPRDest && SPRSrc)
743 else if (GPRDest && SPRSrc)
745 else if (SPRDest && GPRSrc)
747 else if (ARM::DPRRegClass.
contains(DestReg, SrcReg) && Subtarget.hasFP64())
749 else if (ARM::QPRRegClass.
contains(DestReg, SrcReg))
750 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MQPRCopy;
755 if (
Opc == ARM::VORRq ||
Opc == ARM::MVE_VORR)
757 if (
Opc == ARM::MVE_VORR)
759 else if (
Opc != ARM::MQPRCopy)
765 unsigned BeginIdx = 0;
766 unsigned SubRegs = 0;
770 if (ARM::QQPRRegClass.
contains(DestReg, SrcReg)) {
771 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
772 BeginIdx = ARM::qsub_0;
774 }
else if (ARM::QQQQPRRegClass.
contains(DestReg, SrcReg)) {
775 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
776 BeginIdx = ARM::qsub_0;
779 }
else if (ARM::DPairRegClass.
contains(DestReg, SrcReg)) {
781 BeginIdx = ARM::dsub_0;
783 }
else if (ARM::DTripleRegClass.
contains(DestReg, SrcReg)) {
785 BeginIdx = ARM::dsub_0;
787 }
else if (ARM::DQuadRegClass.
contains(DestReg, SrcReg)) {
789 BeginIdx = ARM::dsub_0;
791 }
else if (ARM::GPRPairRegClass.
contains(DestReg, SrcReg)) {
792 Opc = Subtarget.isThumb2() ? ARM::tMOVr : ARM::MOVr;
793 BeginIdx = ARM::gsub_0;
795 }
else if (ARM::DPairSpcRegClass.
contains(DestReg, SrcReg)) {
797 BeginIdx = ARM::dsub_0;
800 }
else if (ARM::DTripleSpcRegClass.
contains(DestReg, SrcReg)) {
802 BeginIdx = ARM::dsub_0;
805 }
else if (ARM::DQuadSpcRegClass.
contains(DestReg, SrcReg)) {
807 BeginIdx = ARM::dsub_0;
810 }
else if (ARM::DPRRegClass.
contains(DestReg, SrcReg) &&
811 !Subtarget.hasFP64()) {
813 BeginIdx = ARM::ssub_0;
815 }
else if (SrcReg == ARM::CPSR) {
818 }
else if (DestReg == ARM::CPSR) {
821 }
else if (DestReg == ARM::VPR) {
827 }
else if (SrcReg == ARM::VPR) {
833 }
else if (DestReg == ARM::FPSCR_NZCV) {
835 BuildMI(
MBB,
I,
I->getDebugLoc(),
get(ARM::VMSR_FPSCR_NZCVQC), DestReg)
839 }
else if (SrcReg == ARM::FPSCR_NZCV) {
841 BuildMI(
MBB,
I,
I->getDebugLoc(),
get(ARM::VMRS_FPSCR_NZCVQC), DestReg)
847 assert(
Opc &&
"Impossible reg-to-reg copy");
853 if (
TRI->regsOverlap(SrcReg,
TRI->getSubReg(DestReg, BeginIdx))) {
854 BeginIdx = BeginIdx + ((SubRegs - 1) * Spacing);
860 for (
unsigned i = 0; i != SubRegs; ++i) {
861 Register Dst =
TRI->getSubReg(DestReg, BeginIdx + i * Spacing);
862 Register Src =
TRI->getSubReg(SrcReg, BeginIdx + i * Spacing);
863 assert(Dst && Src &&
"Bad sub-register");
865 assert(!DstRegs.
count(Src) &&
"destructive vector copy");
870 if (
Opc == ARM::VORRq ||
Opc == ARM::MVE_VORR) {
874 if (
Opc == ARM::MVE_VORR)
879 if (
Opc == ARM::MOVr)
888std::optional<DestSourcePair>
897 if (!
MI.isMoveReg() ||
898 (
MI.getOpcode() == ARM::VORRq &&
899 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg()))
904std::optional<ParamLoadedValue>
908 Register DstReg = DstSrcPair->Destination->getReg();
938 switch (
MI.getOpcode()) {
942 case ARM::tBLXr_noip:
944 return MI.getOperand(2);
955 return MIB.
addReg(Reg, State);
959 return MIB.
addReg(Reg, State, SubIdx);
964 Register SrcReg,
bool isKill,
int FI,
977 switch (
TRI.getSpillSize(*RC)) {
979 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
990 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
997 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
1004 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
1011 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1022 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1029 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1030 if (Subtarget.hasV5TEOps()) {
1033 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1044 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1050 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1066 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1067 Subtarget.hasMVEIntegerOps()) {
1072 .addMemOperand(MMO);
1078 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1081 Subtarget.hasNEON()) {
1095 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1096 AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1102 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1103 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1104 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1106 Subtarget.hasNEON()) {
1115 }
else if (Subtarget.hasMVEIntegerOps()) {
1127 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1128 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1129 AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1135 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1136 Subtarget.hasMVEIntegerOps()) {
1141 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1147 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1148 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1149 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1150 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_4, {});
1151 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_5, {});
1152 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_6, {});
1153 AddDReg(MIB, SrcReg, ARM::dsub_7, {});
1163 int &FrameIndex)
const {
1164 switch (
MI.getOpcode()) {
1168 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1169 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1170 MI.getOperand(3).getImm() == 0) {
1171 FrameIndex =
MI.getOperand(1).getIndex();
1172 return MI.getOperand(0).getReg();
1181 case ARM::VSTR_P0_off:
1182 case ARM::VSTR_FPSCR_NZCVQC_off:
1183 case ARM::MVE_VSTRWU32:
1184 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1185 MI.getOperand(2).getImm() == 0) {
1186 FrameIndex =
MI.getOperand(1).getIndex();
1187 return MI.getOperand(0).getReg();
1191 case ARM::VST1d64TPseudo:
1192 case ARM::VST1d64QPseudo:
1193 if (
MI.getOperand(0).isFI() &&
MI.getOperand(2).getSubReg() == 0) {
1194 FrameIndex =
MI.getOperand(0).getIndex();
1195 return MI.getOperand(2).getReg();
1199 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1200 FrameIndex =
MI.getOperand(1).getIndex();
1201 return MI.getOperand(0).getReg();
1204 case ARM::MQQPRStore:
1205 case ARM::MQQQQPRStore:
1206 if (
MI.getOperand(1).isFI()) {
1207 FrameIndex =
MI.getOperand(1).getIndex();
1208 return MI.getOperand(0).getReg();
1217 int &FrameIndex)
const {
1219 if (
MI.mayStore() && hasStoreToStackSlot(
MI,
Accesses) &&
1236 if (
I !=
MBB.end())
DL =
I->getDebugLoc();
1245 switch (
TRI.getSpillSize(*RC)) {
1247 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
1257 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
1263 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
1269 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
1275 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1285 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1291 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1294 if (Subtarget.hasV5TEOps()) {
1317 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1330 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1331 Subtarget.hasMVEIntegerOps()) {
1333 MIB.addFrameIndex(FI)
1335 .addMemOperand(MMO);
1341 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1343 Subtarget.hasNEON()) {
1364 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1365 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1366 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1368 Subtarget.hasNEON()) {
1374 }
else if (Subtarget.hasMVEIntegerOps()) {
1394 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1395 Subtarget.hasMVEIntegerOps()) {
1399 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1423 int &FrameIndex)
const {
1424 switch (
MI.getOpcode()) {
1428 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1429 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1430 MI.getOperand(3).getImm() == 0) {
1431 FrameIndex =
MI.getOperand(1).getIndex();
1432 return MI.getOperand(0).getReg();
1441 case ARM::VLDR_P0_off:
1442 case ARM::VLDR_FPSCR_NZCVQC_off:
1443 case ARM::MVE_VLDRWU32:
1444 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1445 MI.getOperand(2).getImm() == 0) {
1446 FrameIndex =
MI.getOperand(1).getIndex();
1447 return MI.getOperand(0).getReg();
1451 case ARM::VLD1d8TPseudo:
1452 case ARM::VLD1d16TPseudo:
1453 case ARM::VLD1d32TPseudo:
1454 case ARM::VLD1d64TPseudo:
1455 case ARM::VLD1d8QPseudo:
1456 case ARM::VLD1d16QPseudo:
1457 case ARM::VLD1d32QPseudo:
1458 case ARM::VLD1d64QPseudo:
1459 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1460 FrameIndex =
MI.getOperand(1).getIndex();
1461 return MI.getOperand(0).getReg();
1465 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1466 FrameIndex =
MI.getOperand(1).getIndex();
1467 return MI.getOperand(0).getReg();
1470 case ARM::MQQPRLoad:
1471 case ARM::MQQQQPRLoad:
1472 if (
MI.getOperand(1).isFI()) {
1473 FrameIndex =
MI.getOperand(1).getIndex();
1474 return MI.getOperand(0).getReg();
1483 int &FrameIndex)
const {
1485 if (
MI.mayLoad() && hasLoadFromStackSlot(
MI,
Accesses) &&
1499 bool isThumb2 = Subtarget.
isThumb2();
1506 if (isThumb1 || !
MI->getOperand(1).isDead()) {
1508 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA_UPD
1509 : isThumb1 ? ARM::tLDMIA_UPD
1513 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
1516 if (isThumb1 || !
MI->getOperand(0).isDead()) {
1517 MachineOperand STWb(
MI->getOperand(0));
1518 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA_UPD
1519 : isThumb1 ? ARM::tSTMIA_UPD
1523 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
1526 MachineOperand LDBase(
MI->getOperand(3));
1529 MachineOperand STBase(
MI->getOperand(2));
1538 [&
TRI](
const unsigned &Reg1,
const unsigned &Reg2) ->
bool {
1539 return TRI.getEncodingValue(Reg1) <
1540 TRI.getEncodingValue(Reg2);
1543 for (
const auto &
Reg : ScratchRegs) {
1552 if (
MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) {
1553 expandLoadStackGuard(
MI);
1554 MI.getParent()->erase(
MI);
1558 if (
MI.getOpcode() == ARM::MEMCPY) {
1567 if (!
MI.isCopy() || Subtarget.dontWidenVMOVS() || !Subtarget.hasFP64())
1572 Register DstRegS =
MI.getOperand(0).getReg();
1573 Register SrcRegS =
MI.getOperand(1).getReg();
1574 if (!ARM::SPRRegClass.
contains(DstRegS, SrcRegS))
1579 TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, &ARM::DPRRegClass);
1581 TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, &ARM::DPRRegClass);
1582 if (!DstRegD || !SrcRegD)
1588 if (!
MI.definesRegister(DstRegD,
TRI) ||
MI.readsRegister(DstRegD,
TRI))
1592 if (
MI.getOperand(0).isDead())
1601 int ImpDefIdx =
MI.findRegisterDefOperandIdx(DstRegD,
nullptr);
1602 if (ImpDefIdx != -1)
1603 MI.removeOperand(ImpDefIdx);
1606 MI.setDesc(
get(ARM::VMOVD));
1607 MI.getOperand(0).setReg(DstRegD);
1608 MI.getOperand(1).setReg(SrcRegD);
1615 MI.getOperand(1).setIsUndef();
1620 if (
MI.getOperand(1).isKill()) {
1621 MI.getOperand(1).setIsKill(
false);
1622 MI.addRegisterKilled(SrcRegS,
TRI,
true);
1636 assert(MCPE.isMachineConstantPoolEntry() &&
1637 "Expecting a machine constantpool entry!");
1687 case ARM::tLDRpci_pic:
1688 case ARM::t2LDRpci_pic: {
1708 switch (
I->getOpcode()) {
1709 case ARM::tLDRpci_pic:
1710 case ARM::t2LDRpci_pic: {
1712 unsigned CPI =
I->getOperand(1).getIndex();
1714 I->getOperand(1).setIndex(CPI);
1715 I->getOperand(2).setImm(PCLabelId);
1719 if (!
I->isBundledWithSucc())
1730 if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic ||
1731 Opcode == ARM::tLDRpci || Opcode == ARM::tLDRpci_pic ||
1732 Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1733 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1734 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1735 Opcode == ARM::t2MOV_ga_pcrel) {
1746 if (Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1747 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1748 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1749 Opcode == ARM::t2MOV_ga_pcrel)
1761 if (isARMCP0 && isARMCP1) {
1767 }
else if (!isARMCP0 && !isARMCP1) {
1771 }
else if (Opcode == ARM::PICLDR) {
1779 if (Addr0 != Addr1) {
1815 int64_t &Offset2)
const {
1817 if (Subtarget.isThumb1Only())
return false;
1822 auto IsLoadOpcode = [&](
unsigned Opcode) {
1837 case ARM::t2LDRSHi8:
1839 case ARM::t2LDRBi12:
1840 case ARM::t2LDRSHi12:
1881 int64_t Offset1, int64_t Offset2,
1882 unsigned NumLoads)
const {
1884 if (Subtarget.isThumb1Only())
return false;
1886 assert(Offset2 > Offset1);
1888 if ((Offset2 - Offset1) / 8 > 64)
1919 if (
MI.isDebugInstr())
1923 if (
MI.isTerminator() ||
MI.isPosition())
1927 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
1941 while (++
I !=
MBB->end() &&
I->isDebugInstr())
1943 if (
I !=
MBB->end() &&
I->getOpcode() == ARM::t2IT)
1954 if (!
MI.isCall() &&
MI.definesRegister(ARM::SP,
nullptr))
1962 unsigned NumCycles,
unsigned ExtraPredCycles,
1970 if (
MBB.getParent()->getFunction().hasOptSize()) {
1972 if (!Pred->empty()) {
1974 if (LastMI->
getOpcode() == ARM::t2Bcc) {
1983 MBB, 0, 0, Probability);
1988 unsigned TCycles,
unsigned TExtra,
1990 unsigned FCycles,
unsigned FExtra,
1999 if (Subtarget.isThumb2() &&
TBB.getParent()->getFunction().hasMinSize()) {
2007 const unsigned ScalingUpFactor = 1024;
2009 unsigned PredCost = (TCycles + FCycles + TExtra + FExtra) * ScalingUpFactor;
2010 unsigned UnpredCost;
2011 if (!Subtarget.hasBranchPredictor()) {
2014 unsigned NotTakenBranchCost = 1;
2015 unsigned TakenBranchCost = Subtarget.getMispredictionPenalty();
2016 unsigned TUnpredCycles, FUnpredCycles;
2019 TUnpredCycles = TCycles + NotTakenBranchCost;
2020 FUnpredCycles = TakenBranchCost;
2023 TUnpredCycles = TCycles + TakenBranchCost;
2024 FUnpredCycles = FCycles + NotTakenBranchCost;
2027 PredCost -= 1 * ScalingUpFactor;
2030 unsigned TUnpredCost = Probability.
scale(TUnpredCycles * ScalingUpFactor);
2031 unsigned FUnpredCost = Probability.
getCompl().
scale(FUnpredCycles * ScalingUpFactor);
2032 UnpredCost = TUnpredCost + FUnpredCost;
2035 if (Subtarget.isThumb2() && TCycles + FCycles > 4) {
2036 PredCost += ((TCycles + FCycles - 4) / 4) * ScalingUpFactor;
2039 unsigned TUnpredCost = Probability.
scale(TCycles * ScalingUpFactor);
2040 unsigned FUnpredCost =
2042 UnpredCost = TUnpredCost + FUnpredCost;
2043 UnpredCost += 1 * ScalingUpFactor;
2044 UnpredCost += Subtarget.getMispredictionPenalty() * ScalingUpFactor / 10;
2047 return PredCost <= UnpredCost;
2052 unsigned NumInsts)
const {
2056 if (!Subtarget.isThumb2())
2060 unsigned MaxInsts = Subtarget.restrictIT() ? 1 : 4;
2069 if (
MI.getOpcode() == ARM::t2Bcc &&
2081 if (Subtarget.isThumb2())
2092 return Subtarget.isProfitableToUnpredicate();
2100 int PIdx =
MI.findFirstPredOperandIdx();
2106 PredReg =
MI.getOperand(PIdx+1).getReg();
2115 if (
Opc == ARM::t2B)
2124 unsigned OpIdx2)
const {
2125 switch (
MI.getOpcode()) {
2127 case ARM::t2MOVCCr: {
2132 if (CC ==
ARMCC::AL || PredReg != ARM::CPSR)
2152 if (!Reg.isVirtual())
2166 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2173 if (MO.getReg().isPhysical())
2175 if (MO.isDef() && !MO.isDead())
2178 bool DontMoveAcrossStores =
true;
2179 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2187 bool PreferFalse)
const {
2188 assert((
MI.getOpcode() == ARM::MOVCCr ||
MI.getOpcode() == ARM::t2MOVCCr) &&
2189 "Unknown select instruction");
2192 bool Invert = !
DefMI;
2194 DefMI = canFoldIntoMOVCC(
MI.getOperand(1).getReg(), MRI,
this);
2201 Register DestReg =
MI.getOperand(0).getReg();
2217 i != e && !DefDesc.
operands()[i].isPredicate(); ++i)
2220 unsigned CondCode =
MI.getOperand(3).getImm();
2225 NewMI.
add(
MI.getOperand(4));
2236 NewMI.
add(FalseReg);
2247 if (
DefMI->getParent() !=
MI.getParent())
2251 DefMI->eraseFromParent();
2267 {ARM::ADDSri, ARM::ADDri},
2268 {ARM::ADDSrr, ARM::ADDrr},
2269 {ARM::ADDSrsi, ARM::ADDrsi},
2270 {ARM::ADDSrsr, ARM::ADDrsr},
2272 {ARM::SUBSri, ARM::SUBri},
2273 {ARM::SUBSrr, ARM::SUBrr},
2274 {ARM::SUBSrsi, ARM::SUBrsi},
2275 {ARM::SUBSrsr, ARM::SUBrsr},
2277 {ARM::RSBSri, ARM::RSBri},
2278 {ARM::RSBSrsi, ARM::RSBrsi},
2279 {ARM::RSBSrsr, ARM::RSBrsr},
2281 {ARM::tADDSi3, ARM::tADDi3},
2282 {ARM::tADDSi8, ARM::tADDi8},
2283 {ARM::tADDSrr, ARM::tADDrr},
2284 {ARM::tADCS, ARM::tADC},
2286 {ARM::tSUBSi3, ARM::tSUBi3},
2287 {ARM::tSUBSi8, ARM::tSUBi8},
2288 {ARM::tSUBSrr, ARM::tSUBrr},
2289 {ARM::tSBCS, ARM::tSBC},
2290 {ARM::tRSBS, ARM::tRSB},
2291 {ARM::tLSLSri, ARM::tLSLri},
2293 {ARM::t2ADDSri, ARM::t2ADDri},
2294 {ARM::t2ADDSrr, ARM::t2ADDrr},
2295 {ARM::t2ADDSrs, ARM::t2ADDrs},
2297 {ARM::t2SUBSri, ARM::t2SUBri},
2298 {ARM::t2SUBSrr, ARM::t2SUBrr},
2299 {ARM::t2SUBSrs, ARM::t2SUBrs},
2301 {ARM::t2RSBSri, ARM::t2RSBri},
2302 {ARM::t2RSBSrs, ARM::t2RSBrs},
2307 if (OldOpc == Entry.PseudoOpc)
2308 return Entry.MachineOpc;
2319 if (NumBytes == 0 && DestReg != BaseReg) {
2328 bool isSub = NumBytes < 0;
2329 if (isSub) NumBytes = -NumBytes;
2334 assert(ThisVal &&
"Didn't extract field correctly");
2337 NumBytes &= ~ThisVal;
2342 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
2355 unsigned NumBytes) {
2366 if (!IsPush && !IsPop)
2369 bool IsVFPPushPop =
MI->getOpcode() == ARM::VSTMDDB_UPD ||
2370 MI->getOpcode() == ARM::VLDMDIA_UPD;
2371 bool IsT1PushPop =
MI->getOpcode() == ARM::tPUSH ||
2372 MI->getOpcode() == ARM::tPOP ||
2373 MI->getOpcode() == ARM::tPOP_RET;
2375 assert((IsT1PushPop || (
MI->getOperand(0).getReg() == ARM::SP &&
2376 MI->getOperand(1).getReg() == ARM::SP)) &&
2377 "trying to fold sp update into non-sp-updating push/pop");
2382 if (NumBytes % (IsVFPPushPop ? 8 : 4) != 0)
2387 int RegListIdx = IsT1PushPop ? 2 : 4;
2390 unsigned RegsNeeded;
2393 RegsNeeded = NumBytes / 8;
2394 RegClass = &ARM::DPRRegClass;
2396 RegsNeeded = NumBytes / 4;
2397 RegClass = &ARM::GPRRegClass;
2407 unsigned FirstRegEnc = -1;
2410 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2415 TRI->getEncodingValue(MO.
getReg()) < FirstRegEnc)
2416 FirstRegEnc =
TRI->getEncodingValue(MO.
getReg());
2419 const MCPhysReg *CSRegs =
TRI->getCalleeSavedRegs(&MF);
2422 for (
int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2425 if (IsT1PushPop && CurRegEnc >
TRI->getEncodingValue(ARM::R7))
2432 false,
false,
true));
2442 MI->getParent()->computeRegisterLiveness(
TRI, CurReg,
MI) !=
2464 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i)
2465 MI->removeOperand(i);
2478 unsigned Opcode =
MI.getOpcode();
2484 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
2487 if (Opcode == ARM::ADDri) {
2488 Offset +=
MI.getOperand(FrameRegIdx+1).getImm();
2491 MI.setDesc(
TII.get(ARM::MOVr));
2492 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2493 MI.removeOperand(FrameRegIdx+1);
2499 MI.setDesc(
TII.get(ARM::SUBri));
2505 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2506 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(
Offset);
2521 "Bit extraction didn't work?");
2522 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
2524 unsigned ImmIdx = 0;
2526 unsigned NumBits = 0;
2530 ImmIdx = FrameRegIdx + 1;
2531 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2535 ImmIdx = FrameRegIdx+2;
2542 ImmIdx = FrameRegIdx+2;
2553 ImmIdx = FrameRegIdx+1;
2561 ImmIdx = FrameRegIdx+1;
2571 ImmIdx = FrameRegIdx+1;
2572 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2581 Offset += InstrOffs * Scale;
2582 assert((
Offset & (Scale-1)) == 0 &&
"Can't encode this offset!");
2592 int ImmedOffset =
Offset / Scale;
2593 unsigned Mask = (1 << NumBits) - 1;
2594 if ((
unsigned)
Offset <= Mask * Scale) {
2596 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2602 ImmedOffset = -ImmedOffset;
2604 ImmedOffset |= 1 << NumBits;
2612 ImmedOffset = ImmedOffset & Mask;
2615 ImmedOffset = -ImmedOffset;
2617 ImmedOffset |= 1 << NumBits;
2633 Register &SrcReg2, int64_t &CmpMask,
2634 int64_t &CmpValue)
const {
2635 switch (
MI.getOpcode()) {
2640 SrcReg =
MI.getOperand(0).getReg();
2643 CmpValue =
MI.getOperand(1).getImm();
2648 SrcReg =
MI.getOperand(0).getReg();
2649 SrcReg2 =
MI.getOperand(1).getReg();
2655 SrcReg =
MI.getOperand(0).getReg();
2657 CmpMask =
MI.getOperand(1).getImm();
2670 int CmpMask,
bool CommonUse) {
2671 switch (
MI->getOpcode()) {
2674 if (CmpMask !=
MI->getOperand(2).getImm())
2676 if (SrcReg ==
MI->getOperand(CommonUse ? 1 : 0).getReg())
2766 switch (
MI->getOpcode()) {
2767 default:
return false;
2863 if (!
MI)
return false;
2866 if (CmpMask != ~0) {
2872 if (UI->getParent() != CmpInstr.
getParent())
2881 if (!
MI)
return false;
2890 if (
I ==
B)
return false;
2901 else if (
MI->getParent() != CmpInstr.
getParent() || CmpValue != 0) {
2906 if (CmpInstr.
getOpcode() == ARM::CMPri ||
2914 bool IsThumb1 =
false;
2931 if (
MI && IsThumb1) {
2933 if (
I != E && !
MI->readsRegister(ARM::CPSR,
TRI)) {
2934 bool CanReorder =
true;
2935 for (;
I != E; --
I) {
2936 if (
I->getOpcode() != ARM::tMOVi8) {
2942 MI =
MI->removeFromParent();
2953 bool SubAddIsThumb1 =
false;
2968 if (Instr.modifiesRegister(ARM::CPSR,
TRI) ||
2969 Instr.readsRegister(ARM::CPSR,
TRI))
2991 IsThumb1 = SubAddIsThumb1;
3006 bool isSafe =
false;
3009 while (!isSafe && ++
I != E) {
3011 for (
unsigned IO = 0, EO = Instr.getNumOperands();
3012 !isSafe && IO != EO; ++IO) {
3026 bool IsInstrVSel =
true;
3027 switch (Instr.getOpcode()) {
3029 IsInstrVSel =
false;
3063 bool IsSub =
Opc == ARM::SUBrr ||
Opc == ARM::t2SUBrr ||
3064 Opc == ARM::SUBri ||
Opc == ARM::t2SUBri ||
3065 Opc == ARM::tSUBrr ||
Opc == ARM::tSUBi3 ||
3067 unsigned OpI =
Opc != ARM::tSUBrr ? 1 : 2;
3079 std::make_pair(&((*I).getOperand(IO - 1)), NewCC));
3113 if (Succ->isLiveIn(ARM::CPSR))
3120 unsigned CPSRRegNum =
MI->getNumExplicitOperands() - 1;
3121 MI->getOperand(CPSRRegNum).setReg(ARM::CPSR);
3122 MI->getOperand(CPSRRegNum).setIsDef(
true);
3130 for (
auto &[MO,
Cond] : OperandsToUpdate)
3133 MI->clearRegisterDeads(ARM::CPSR);
3147 int64_t CmpMask, CmpValue;
3149 if (
Next !=
MI.getParent()->end() &&
3160 unsigned DefOpc =
DefMI.getOpcode();
3161 if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm &&
3162 DefOpc != ARM::tMOVi32imm)
3164 if (!
DefMI.getOperand(1).isImm())
3184 if (
UseMI.getOperand(
NumOps - 1).getReg() == ARM::CPSR)
3190 unsigned UseOpc =
UseMI.getOpcode();
3191 unsigned NewUseOpc = 0;
3193 uint32_t SOImmValV1 = 0, SOImmValV2 = 0;
3194 bool Commute =
false;
3196 default:
return false;
3204 case ARM::t2EORrr: {
3205 Commute =
UseMI.getOperand(2).getReg() != Reg;
3210 if (UseOpc == ARM::SUBrr && Commute)
3216 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::ADDri : ARM::SUBri;
3219 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::SUBri : ARM::ADDri;
3233 case ARM::ORRrr: NewUseOpc = ARM::ORRri;
break;
3234 case ARM::EORrr: NewUseOpc = ARM::EORri;
break;
3238 case ARM::t2SUBrr: {
3239 if (UseOpc == ARM::t2SUBrr && Commute)
3244 const bool ToSP =
DefMI.getOperand(0).getReg() == ARM::SP;
3245 const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
3246 const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
3248 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB;
3251 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD;
3266 case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri;
break;
3267 case ARM::t2EORrr: NewUseOpc = ARM::t2EORri;
break;
3274 unsigned OpIdx = Commute ? 2 : 1;
3276 bool isKill =
UseMI.getOperand(OpIdx).isKill();
3286 UseMI.getOperand(1).setReg(NewReg);
3287 UseMI.getOperand(1).setIsKill();
3288 UseMI.getOperand(2).ChangeToImmediate(SOImmValV2);
3289 DefMI.eraseFromParent();
3296 case ARM::t2ADDspImm:
3297 case ARM::t2SUBspImm:
3307 switch (
MI.getOpcode()) {
3311 assert(UOps >= 0 &&
"bad # UOps");
3319 unsigned ShOpVal =
MI.getOperand(3).getImm();
3324 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3332 if (!
MI.getOperand(2).getReg())
3335 unsigned ShOpVal =
MI.getOperand(3).getImm();
3340 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3350 case ARM::LDRSB_POST:
3351 case ARM::LDRSH_POST: {
3354 return (Rt == Rm) ? 4 : 3;
3357 case ARM::LDR_PRE_REG:
3358 case ARM::LDRB_PRE_REG: {
3363 unsigned ShOpVal =
MI.getOperand(4).getImm();
3368 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3374 case ARM::STR_PRE_REG:
3375 case ARM::STRB_PRE_REG: {
3376 unsigned ShOpVal =
MI.getOperand(4).getImm();
3381 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3388 case ARM::STRH_PRE: {
3398 case ARM::LDR_POST_REG:
3399 case ARM::LDRB_POST_REG:
3400 case ARM::LDRH_POST: {
3403 return (Rt == Rm) ? 3 : 2;
3406 case ARM::LDR_PRE_IMM:
3407 case ARM::LDRB_PRE_IMM:
3408 case ARM::LDR_POST_IMM:
3409 case ARM::LDRB_POST_IMM:
3410 case ARM::STRB_POST_IMM:
3411 case ARM::STRB_POST_REG:
3412 case ARM::STRB_PRE_IMM:
3413 case ARM::STRH_POST:
3414 case ARM::STR_POST_IMM:
3415 case ARM::STR_POST_REG:
3416 case ARM::STR_PRE_IMM:
3419 case ARM::LDRSB_PRE:
3420 case ARM::LDRSH_PRE: {
3427 unsigned ShOpVal =
MI.getOperand(4).getImm();
3432 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3445 return (Rt == Rn) ? 3 : 2;
3456 case ARM::LDRD_POST:
3457 case ARM::t2LDRD_POST:
3460 case ARM::STRD_POST:
3461 case ARM::t2STRD_POST:
3464 case ARM::LDRD_PRE: {
3471 return (Rt == Rn) ? 4 : 3;
3474 case ARM::t2LDRD_PRE: {
3477 return (Rt == Rn) ? 4 : 3;
3480 case ARM::STRD_PRE: {
3488 case ARM::t2STRD_PRE:
3491 case ARM::t2LDR_POST:
3492 case ARM::t2LDRB_POST:
3493 case ARM::t2LDRB_PRE:
3494 case ARM::t2LDRSBi12:
3495 case ARM::t2LDRSBi8:
3496 case ARM::t2LDRSBpci:
3498 case ARM::t2LDRH_POST:
3499 case ARM::t2LDRH_PRE:
3501 case ARM::t2LDRSB_POST:
3502 case ARM::t2LDRSB_PRE:
3503 case ARM::t2LDRSH_POST:
3504 case ARM::t2LDRSH_PRE:
3505 case ARM::t2LDRSHi12:
3506 case ARM::t2LDRSHi8:
3507 case ARM::t2LDRSHpci:
3511 case ARM::t2LDRDi8: {
3514 return (Rt == Rn) ? 3 : 2;
3517 case ARM::t2STRB_POST:
3518 case ARM::t2STRB_PRE:
3521 case ARM::t2STRH_POST:
3522 case ARM::t2STRH_PRE:
3524 case ARM::t2STR_POST:
3525 case ARM::t2STR_PRE:
3556 E =
MI.memoperands_end();
3558 Size += (*I)->getSize().getValue();
3565 return std::min(
Size / 4, 16U);
3570 unsigned UOps = 1 + NumRegs;
3574 case ARM::VLDMDIA_UPD:
3575 case ARM::VLDMDDB_UPD:
3576 case ARM::VLDMSIA_UPD:
3577 case ARM::VLDMSDB_UPD:
3578 case ARM::VSTMDIA_UPD:
3579 case ARM::VSTMDDB_UPD:
3580 case ARM::VSTMSIA_UPD:
3581 case ARM::VSTMSDB_UPD:
3582 case ARM::LDMIA_UPD:
3583 case ARM::LDMDA_UPD:
3584 case ARM::LDMDB_UPD:
3585 case ARM::LDMIB_UPD:
3586 case ARM::STMIA_UPD:
3587 case ARM::STMDA_UPD:
3588 case ARM::STMDB_UPD:
3589 case ARM::STMIB_UPD:
3590 case ARM::tLDMIA_UPD:
3591 case ARM::tSTMIA_UPD:
3592 case ARM::t2LDMIA_UPD:
3593 case ARM::t2LDMDB_UPD:
3594 case ARM::t2STMIA_UPD:
3595 case ARM::t2STMDB_UPD:
3598 case ARM::LDMIA_RET:
3600 case ARM::t2LDMIA_RET:
3609 if (!ItinData || ItinData->
isEmpty())
3613 unsigned Class =
Desc.getSchedClass();
3615 if (ItinUOps >= 0) {
3616 if (Subtarget.isSwift() && (
Desc.mayLoad() ||
Desc.mayStore()))
3622 unsigned Opc =
MI.getOpcode();
3641 case ARM::VLDMDIA_UPD:
3642 case ARM::VLDMDDB_UPD:
3644 case ARM::VLDMSIA_UPD:
3645 case ARM::VLDMSDB_UPD:
3647 case ARM::VSTMDIA_UPD:
3648 case ARM::VSTMDDB_UPD:
3650 case ARM::VSTMSIA_UPD:
3651 case ARM::VSTMSDB_UPD: {
3652 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands();
3653 return (NumRegs / 2) + (NumRegs % 2) + 1;
3656 case ARM::LDMIA_RET:
3661 case ARM::LDMIA_UPD:
3662 case ARM::LDMDA_UPD:
3663 case ARM::LDMDB_UPD:
3664 case ARM::LDMIB_UPD:
3669 case ARM::STMIA_UPD:
3670 case ARM::STMDA_UPD:
3671 case ARM::STMDB_UPD:
3672 case ARM::STMIB_UPD:
3674 case ARM::tLDMIA_UPD:
3675 case ARM::tSTMIA_UPD:
3679 case ARM::t2LDMIA_RET:
3682 case ARM::t2LDMIA_UPD:
3683 case ARM::t2LDMDB_UPD:
3686 case ARM::t2STMIA_UPD:
3687 case ARM::t2STMDB_UPD: {
3688 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands() + 1;
3689 switch (Subtarget.getLdStMultipleTiming()) {
3700 unsigned UOps = (NumRegs / 2);
3706 unsigned UOps = (NumRegs / 2);
3709 if ((NumRegs % 2) || !
MI.hasOneMemOperand() ||
3710 (*
MI.memoperands_begin())->getAlign() <
Align(8))
3720std::optional<unsigned>
3723 unsigned DefIdx,
unsigned DefAlign)
const {
3732 DefCycle = RegNo / 2 + 1;
3737 bool isSLoad =
false;
3742 case ARM::VLDMSIA_UPD:
3743 case ARM::VLDMSDB_UPD:
3750 if ((isSLoad && (RegNo % 2)) || DefAlign < 8)
3754 DefCycle = RegNo + 2;
3760std::optional<unsigned>
3763 unsigned DefIdx,
unsigned DefAlign)
const {
3770 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3773 DefCycle = RegNo / 2;
3778 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3779 DefCycle = (RegNo / 2);
3782 if ((RegNo % 2) || DefAlign < 8)
3788 DefCycle = RegNo + 2;
3794std::optional<unsigned>
3797 unsigned UseIdx,
unsigned UseAlign)
const {
3803 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3805 UseCycle = RegNo / 2 + 1;
3808 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3810 bool isSStore =
false;
3815 case ARM::VSTMSIA_UPD:
3816 case ARM::VSTMSDB_UPD:
3823 if ((isSStore && (RegNo % 2)) || UseAlign < 8)
3827 UseCycle = RegNo + 2;
3833std::optional<unsigned>
3836 unsigned UseIdx,
unsigned UseAlign)
const {
3842 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3843 UseCycle = RegNo / 2;
3848 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3849 UseCycle = (RegNo / 2);
3852 if ((RegNo % 2) || UseAlign < 8)
3863 unsigned DefIdx,
unsigned DefAlign,
const MCInstrDesc &UseMCID,
3864 unsigned UseIdx,
unsigned UseAlign)
const {
3874 std::optional<unsigned> DefCycle;
3875 bool LdmBypass =
false;
3882 case ARM::VLDMDIA_UPD:
3883 case ARM::VLDMDDB_UPD:
3885 case ARM::VLDMSIA_UPD:
3886 case ARM::VLDMSDB_UPD:
3887 DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3890 case ARM::LDMIA_RET:
3895 case ARM::LDMIA_UPD:
3896 case ARM::LDMDA_UPD:
3897 case ARM::LDMDB_UPD:
3898 case ARM::LDMIB_UPD:
3900 case ARM::tLDMIA_UPD:
3902 case ARM::t2LDMIA_RET:
3905 case ARM::t2LDMIA_UPD:
3906 case ARM::t2LDMDB_UPD:
3908 DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3916 std::optional<unsigned> UseCycle;
3923 case ARM::VSTMDIA_UPD:
3924 case ARM::VSTMDDB_UPD:
3926 case ARM::VSTMSIA_UPD:
3927 case ARM::VSTMSDB_UPD:
3928 UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3935 case ARM::STMIA_UPD:
3936 case ARM::STMDA_UPD:
3937 case ARM::STMDB_UPD:
3938 case ARM::STMIB_UPD:
3939 case ARM::tSTMIA_UPD:
3944 case ARM::t2STMIA_UPD:
3945 case ARM::t2STMDB_UPD:
3946 UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3954 if (UseCycle > *DefCycle + 1)
3955 return std::nullopt;
3957 UseCycle = *DefCycle - *UseCycle + 1;
3958 if (UseCycle > 0u) {
3964 UseCycle = *UseCycle - 1;
3966 UseClass, UseIdx)) {
3967 UseCycle = *UseCycle - 1;
3976 unsigned &DefIdx,
unsigned &Dist) {
3981 assert(
II->isInsideBundle() &&
"Empty bundle?");
3984 while (
II->isInsideBundle()) {
3985 Idx =
II->findRegisterDefOperandIdx(
Reg,
TRI,
false,
true);
3992 assert(Idx != -1 &&
"Cannot find bundled definition!");
3999 unsigned &UseIdx,
unsigned &Dist) {
4003 assert(
II->isInsideBundle() &&
"Empty bundle?");
4008 while (
II !=
E &&
II->isInsideBundle()) {
4009 Idx =
II->findRegisterUseOperandIdx(
Reg,
TRI,
false);
4012 if (
II->getOpcode() != ARM::t2IT)
4040 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4050 case ARM::t2LDRSHs: {
4052 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4053 if (ShAmt == 0 || ShAmt == 2)
4058 }
else if (Subtarget.
isSwift()) {
4065 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4070 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4081 case ARM::t2LDRSHs: {
4083 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4084 if (ShAmt == 0 || ShAmt == 1 || ShAmt == 2 || ShAmt == 3)
4091 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment()) {
4098 case ARM::VLD1q8wb_fixed:
4099 case ARM::VLD1q16wb_fixed:
4100 case ARM::VLD1q32wb_fixed:
4101 case ARM::VLD1q64wb_fixed:
4102 case ARM::VLD1q8wb_register:
4103 case ARM::VLD1q16wb_register:
4104 case ARM::VLD1q32wb_register:
4105 case ARM::VLD1q64wb_register:
4112 case ARM::VLD2d8wb_fixed:
4113 case ARM::VLD2d16wb_fixed:
4114 case ARM::VLD2d32wb_fixed:
4115 case ARM::VLD2q8wb_fixed:
4116 case ARM::VLD2q16wb_fixed:
4117 case ARM::VLD2q32wb_fixed:
4118 case ARM::VLD2d8wb_register:
4119 case ARM::VLD2d16wb_register:
4120 case ARM::VLD2d32wb_register:
4121 case ARM::VLD2q8wb_register:
4122 case ARM::VLD2q16wb_register:
4123 case ARM::VLD2q32wb_register:
4128 case ARM::VLD3d8_UPD:
4129 case ARM::VLD3d16_UPD:
4130 case ARM::VLD3d32_UPD:
4131 case ARM::VLD1d64Twb_fixed:
4132 case ARM::VLD1d64Twb_register:
4133 case ARM::VLD3q8_UPD:
4134 case ARM::VLD3q16_UPD:
4135 case ARM::VLD3q32_UPD:
4140 case ARM::VLD4d8_UPD:
4141 case ARM::VLD4d16_UPD:
4142 case ARM::VLD4d32_UPD:
4143 case ARM::VLD1d64Qwb_fixed:
4144 case ARM::VLD1d64Qwb_register:
4145 case ARM::VLD4q8_UPD:
4146 case ARM::VLD4q16_UPD:
4147 case ARM::VLD4q32_UPD:
4148 case ARM::VLD1DUPq8:
4149 case ARM::VLD1DUPq16:
4150 case ARM::VLD1DUPq32:
4151 case ARM::VLD1DUPq8wb_fixed:
4152 case ARM::VLD1DUPq16wb_fixed:
4153 case ARM::VLD1DUPq32wb_fixed:
4154 case ARM::VLD1DUPq8wb_register:
4155 case ARM::VLD1DUPq16wb_register:
4156 case ARM::VLD1DUPq32wb_register:
4157 case ARM::VLD2DUPd8:
4158 case ARM::VLD2DUPd16:
4159 case ARM::VLD2DUPd32:
4160 case ARM::VLD2DUPd8wb_fixed:
4161 case ARM::VLD2DUPd16wb_fixed:
4162 case ARM::VLD2DUPd32wb_fixed:
4163 case ARM::VLD2DUPd8wb_register:
4164 case ARM::VLD2DUPd16wb_register:
4165 case ARM::VLD2DUPd32wb_register:
4166 case ARM::VLD4DUPd8:
4167 case ARM::VLD4DUPd16:
4168 case ARM::VLD4DUPd32:
4169 case ARM::VLD4DUPd8_UPD:
4170 case ARM::VLD4DUPd16_UPD:
4171 case ARM::VLD4DUPd32_UPD:
4173 case ARM::VLD1LNd16:
4174 case ARM::VLD1LNd32:
4175 case ARM::VLD1LNd8_UPD:
4176 case ARM::VLD1LNd16_UPD:
4177 case ARM::VLD1LNd32_UPD:
4179 case ARM::VLD2LNd16:
4180 case ARM::VLD2LNd32:
4181 case ARM::VLD2LNq16:
4182 case ARM::VLD2LNq32:
4183 case ARM::VLD2LNd8_UPD:
4184 case ARM::VLD2LNd16_UPD:
4185 case ARM::VLD2LNd32_UPD:
4186 case ARM::VLD2LNq16_UPD:
4187 case ARM::VLD2LNq32_UPD:
4189 case ARM::VLD4LNd16:
4190 case ARM::VLD4LNd32:
4191 case ARM::VLD4LNq16:
4192 case ARM::VLD4LNq32:
4193 case ARM::VLD4LNd8_UPD:
4194 case ARM::VLD4LNd16_UPD:
4195 case ARM::VLD4LNd32_UPD:
4196 case ARM::VLD4LNq16_UPD:
4197 case ARM::VLD4LNq32_UPD:
4211 if (!ItinData || ItinData->
isEmpty())
4212 return std::nullopt;
4218 unsigned DefAdj = 0;
4219 if (
DefMI.isBundle())
4228 unsigned UseAdj = 0;
4229 if (
UseMI.isBundle()) {
4233 return std::nullopt;
4236 return getOperandLatencyImpl(
4237 ItinData, *ResolvedDefMI, DefIdx, ResolvedDefMI->
getDesc(), DefAdj, DefMO,
4238 Reg, *ResolvedUseMI, UseIdx, ResolvedUseMI->
getDesc(), UseAdj);
4241std::optional<unsigned> ARMBaseInstrInfo::getOperandLatencyImpl(
4243 unsigned DefIdx,
const MCInstrDesc &DefMCID,
unsigned DefAdj,
4245 unsigned UseIdx,
const MCInstrDesc &UseMCID,
unsigned UseAdj)
const {
4246 if (Reg == ARM::CPSR) {
4247 if (
DefMI.getOpcode() == ARM::FMSTAT) {
4249 return Subtarget.
isLikeA9() ? 1 : 20;
4253 if (
UseMI.isBranch())
4272 return std::nullopt;
4274 unsigned DefAlign =
DefMI.hasOneMemOperand()
4275 ? (*
DefMI.memoperands_begin())->getAlign().value()
4277 unsigned UseAlign =
UseMI.hasOneMemOperand()
4278 ? (*
UseMI.memoperands_begin())->getAlign().value()
4283 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4286 return std::nullopt;
4289 int Adj = DefAdj + UseAdj;
4293 if (Adj >= 0 || (
int)*
Latency > -Adj) {
4300std::optional<unsigned>
4302 SDNode *DefNode,
unsigned DefIdx,
4303 SDNode *UseNode,
unsigned UseIdx)
const {
4309 if (isZeroCost(DefMCID.
Opcode))
4312 if (!ItinData || ItinData->
isEmpty())
4313 return DefMCID.
mayLoad() ? 3 : 1;
4316 std::optional<unsigned>
Latency =
4318 int Adj = Subtarget.getPreISelOperandLatencyAdjustment();
4319 int Threshold = 1 + Adj;
4325 unsigned DefAlign = !DefMN->memoperands_empty()
4326 ? (*DefMN->memoperands_begin())->getAlign().value()
4329 unsigned UseAlign = !UseMN->memoperands_empty()
4330 ? (*UseMN->memoperands_begin())->getAlign().value()
4333 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4335 return std::nullopt;
4338 (Subtarget.isCortexA8() || Subtarget.isLikeA9() ||
4339 Subtarget.isCortexA7())) {
4356 case ARM::t2LDRSHs: {
4359 if (ShAmt == 0 || ShAmt == 2)
4364 }
else if (DefIdx == 0 &&
Latency > 2U && Subtarget.isSwift()) {
4374 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4391 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment())
4398 case ARM::VLD1q8wb_register:
4399 case ARM::VLD1q16wb_register:
4400 case ARM::VLD1q32wb_register:
4401 case ARM::VLD1q64wb_register:
4402 case ARM::VLD1q8wb_fixed:
4403 case ARM::VLD1q16wb_fixed:
4404 case ARM::VLD1q32wb_fixed:
4405 case ARM::VLD1q64wb_fixed:
4409 case ARM::VLD2q8Pseudo:
4410 case ARM::VLD2q16Pseudo:
4411 case ARM::VLD2q32Pseudo:
4412 case ARM::VLD2d8wb_fixed:
4413 case ARM::VLD2d16wb_fixed:
4414 case ARM::VLD2d32wb_fixed:
4415 case ARM::VLD2q8PseudoWB_fixed:
4416 case ARM::VLD2q16PseudoWB_fixed:
4417 case ARM::VLD2q32PseudoWB_fixed:
4418 case ARM::VLD2d8wb_register:
4419 case ARM::VLD2d16wb_register:
4420 case ARM::VLD2d32wb_register:
4421 case ARM::VLD2q8PseudoWB_register:
4422 case ARM::VLD2q16PseudoWB_register:
4423 case ARM::VLD2q32PseudoWB_register:
4424 case ARM::VLD3d8Pseudo:
4425 case ARM::VLD3d16Pseudo:
4426 case ARM::VLD3d32Pseudo:
4427 case ARM::VLD1d8TPseudo:
4428 case ARM::VLD1d16TPseudo:
4429 case ARM::VLD1d32TPseudo:
4430 case ARM::VLD1d64TPseudo:
4431 case ARM::VLD1d64TPseudoWB_fixed:
4432 case ARM::VLD1d64TPseudoWB_register:
4433 case ARM::VLD3d8Pseudo_UPD:
4434 case ARM::VLD3d16Pseudo_UPD:
4435 case ARM::VLD3d32Pseudo_UPD:
4436 case ARM::VLD3q8Pseudo_UPD:
4437 case ARM::VLD3q16Pseudo_UPD:
4438 case ARM::VLD3q32Pseudo_UPD:
4439 case ARM::VLD3q8oddPseudo:
4440 case ARM::VLD3q16oddPseudo:
4441 case ARM::VLD3q32oddPseudo:
4442 case ARM::VLD3q8oddPseudo_UPD:
4443 case ARM::VLD3q16oddPseudo_UPD:
4444 case ARM::VLD3q32oddPseudo_UPD:
4445 case ARM::VLD4d8Pseudo:
4446 case ARM::VLD4d16Pseudo:
4447 case ARM::VLD4d32Pseudo:
4448 case ARM::VLD1d8QPseudo:
4449 case ARM::VLD1d16QPseudo:
4450 case ARM::VLD1d32QPseudo:
4451 case ARM::VLD1d64QPseudo:
4452 case ARM::VLD1d64QPseudoWB_fixed:
4453 case ARM::VLD1d64QPseudoWB_register:
4454 case ARM::VLD1q8HighQPseudo:
4455 case ARM::VLD1q8LowQPseudo_UPD:
4456 case ARM::VLD1q8HighTPseudo:
4457 case ARM::VLD1q8LowTPseudo_UPD:
4458 case ARM::VLD1q16HighQPseudo:
4459 case ARM::VLD1q16LowQPseudo_UPD:
4460 case ARM::VLD1q16HighTPseudo:
4461 case ARM::VLD1q16LowTPseudo_UPD:
4462 case ARM::VLD1q32HighQPseudo:
4463 case ARM::VLD1q32LowQPseudo_UPD:
4464 case ARM::VLD1q32HighTPseudo:
4465 case ARM::VLD1q32LowTPseudo_UPD:
4466 case ARM::VLD1q64HighQPseudo:
4467 case ARM::VLD1q64LowQPseudo_UPD:
4468 case ARM::VLD1q64HighTPseudo:
4469 case ARM::VLD1q64LowTPseudo_UPD:
4470 case ARM::VLD4d8Pseudo_UPD:
4471 case ARM::VLD4d16Pseudo_UPD:
4472 case ARM::VLD4d32Pseudo_UPD:
4473 case ARM::VLD4q8Pseudo_UPD:
4474 case ARM::VLD4q16Pseudo_UPD:
4475 case ARM::VLD4q32Pseudo_UPD:
4476 case ARM::VLD4q8oddPseudo:
4477 case ARM::VLD4q16oddPseudo:
4478 case ARM::VLD4q32oddPseudo:
4479 case ARM::VLD4q8oddPseudo_UPD:
4480 case ARM::VLD4q16oddPseudo_UPD:
4481 case ARM::VLD4q32oddPseudo_UPD:
4482 case ARM::VLD1DUPq8:
4483 case ARM::VLD1DUPq16:
4484 case ARM::VLD1DUPq32:
4485 case ARM::VLD1DUPq8wb_fixed:
4486 case ARM::VLD1DUPq16wb_fixed:
4487 case ARM::VLD1DUPq32wb_fixed:
4488 case ARM::VLD1DUPq8wb_register:
4489 case ARM::VLD1DUPq16wb_register:
4490 case ARM::VLD1DUPq32wb_register:
4491 case ARM::VLD2DUPd8:
4492 case ARM::VLD2DUPd16:
4493 case ARM::VLD2DUPd32:
4494 case ARM::VLD2DUPd8wb_fixed:
4495 case ARM::VLD2DUPd16wb_fixed:
4496 case ARM::VLD2DUPd32wb_fixed:
4497 case ARM::VLD2DUPd8wb_register:
4498 case ARM::VLD2DUPd16wb_register:
4499 case ARM::VLD2DUPd32wb_register:
4500 case ARM::VLD2DUPq8EvenPseudo:
4501 case ARM::VLD2DUPq8OddPseudo:
4502 case ARM::VLD2DUPq16EvenPseudo:
4503 case ARM::VLD2DUPq16OddPseudo:
4504 case ARM::VLD2DUPq32EvenPseudo:
4505 case ARM::VLD2DUPq32OddPseudo:
4506 case ARM::VLD3DUPq8EvenPseudo:
4507 case ARM::VLD3DUPq8OddPseudo:
4508 case ARM::VLD3DUPq16EvenPseudo:
4509 case ARM::VLD3DUPq16OddPseudo:
4510 case ARM::VLD3DUPq32EvenPseudo:
4511 case ARM::VLD3DUPq32OddPseudo:
4512 case ARM::VLD4DUPd8Pseudo:
4513 case ARM::VLD4DUPd16Pseudo:
4514 case ARM::VLD4DUPd32Pseudo:
4515 case ARM::VLD4DUPd8Pseudo_UPD:
4516 case ARM::VLD4DUPd16Pseudo_UPD:
4517 case ARM::VLD4DUPd32Pseudo_UPD:
4518 case ARM::VLD4DUPq8EvenPseudo:
4519 case ARM::VLD4DUPq8OddPseudo:
4520 case ARM::VLD4DUPq16EvenPseudo:
4521 case ARM::VLD4DUPq16OddPseudo:
4522 case ARM::VLD4DUPq32EvenPseudo:
4523 case ARM::VLD4DUPq32OddPseudo:
4524 case ARM::VLD1LNq8Pseudo:
4525 case ARM::VLD1LNq16Pseudo:
4526 case ARM::VLD1LNq32Pseudo:
4527 case ARM::VLD1LNq8Pseudo_UPD:
4528 case ARM::VLD1LNq16Pseudo_UPD:
4529 case ARM::VLD1LNq32Pseudo_UPD:
4530 case ARM::VLD2LNd8Pseudo:
4531 case ARM::VLD2LNd16Pseudo:
4532 case ARM::VLD2LNd32Pseudo:
4533 case ARM::VLD2LNq16Pseudo:
4534 case ARM::VLD2LNq32Pseudo:
4535 case ARM::VLD2LNd8Pseudo_UPD:
4536 case ARM::VLD2LNd16Pseudo_UPD:
4537 case ARM::VLD2LNd32Pseudo_UPD:
4538 case ARM::VLD2LNq16Pseudo_UPD:
4539 case ARM::VLD2LNq32Pseudo_UPD:
4540 case ARM::VLD4LNd8Pseudo:
4541 case ARM::VLD4LNd16Pseudo:
4542 case ARM::VLD4LNd32Pseudo:
4543 case ARM::VLD4LNq16Pseudo:
4544 case ARM::VLD4LNq32Pseudo:
4545 case ARM::VLD4LNd8Pseudo_UPD:
4546 case ARM::VLD4LNd16Pseudo_UPD:
4547 case ARM::VLD4LNd32Pseudo_UPD:
4548 case ARM::VLD4LNq16Pseudo_UPD:
4549 case ARM::VLD4LNq32Pseudo_UPD:
4559unsigned ARMBaseInstrInfo::getPredicationCost(
const MachineInstr &
MI)
const {
4560 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4569 if (
MCID.isCall() || (
MCID.hasImplicitDefOfPhysReg(ARM::CPSR) &&
4570 !Subtarget.cheapPredicableCPSRDef())) {
4580 unsigned *PredCost)
const {
4581 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4587 if (
MI.isBundle()) {
4591 while (++
I !=
E &&
I->isInsideBundle()) {
4592 if (
I->getOpcode() != ARM::t2IT)
4593 Latency += getInstrLatency(ItinData, *
I, PredCost);
4598 const MCInstrDesc &MCID =
MI.getDesc();
4600 !Subtarget.cheapPredicableCPSRDef()))) {
4621 MI.hasOneMemOperand() ? (*
MI.memoperands_begin())->getAlign().value() : 0;
4623 if (Adj >= 0 || (
int)
Latency > -Adj) {
4631 if (!
Node->isMachineOpcode())
4634 if (!ItinData || ItinData->
isEmpty())
4637 unsigned Opcode =
Node->getMachineOpcode();
4647bool ARMBaseInstrInfo::hasHighOperandLatency(
const TargetSchedModel &SchedModel,
4652 unsigned UseIdx)
const {
4655 if (Subtarget.nonpipelinedVFP() &&
4670 unsigned DefIdx)
const {
4672 if (!ItinData || ItinData->
isEmpty())
4677 unsigned DefClass =
DefMI.getDesc().getSchedClass();
4678 std::optional<unsigned> DefCycle =
4680 return DefCycle && DefCycle <= 2U;
4688 ErrInfo =
"Pseudo flag setting opcodes only exist in Selection DAG";
4691 if (
MI.getOpcode() == ARM::tMOVr && !Subtarget.hasV6Ops()) {
4693 if (!ARM::hGPRRegClass.
contains(
MI.getOperand(0).getReg()) &&
4694 !ARM::hGPRRegClass.contains(
MI.getOperand(1).getReg())) {
4695 ErrInfo =
"Non-flag-setting Thumb1 mov is v6-only";
4699 if (
MI.getOpcode() == ARM::tPUSH ||
4700 MI.getOpcode() == ARM::tPOP ||
4701 MI.getOpcode() == ARM::tPOP_RET) {
4703 if (MO.isImplicit() || !MO.isReg())
4707 if (!(
MI.getOpcode() == ARM::tPUSH &&
Reg == ARM::LR) &&
4708 !(
MI.getOpcode() == ARM::tPOP_RET &&
Reg == ARM::PC)) {
4709 ErrInfo =
"Unsupported register in Thumb1 push/pop";
4715 if (
MI.getOpcode() == ARM::MVE_VMOV_q_rr) {
4716 assert(
MI.getOperand(4).isImm() &&
MI.getOperand(5).isImm());
4717 if ((
MI.getOperand(4).getImm() != 2 &&
MI.getOperand(4).getImm() != 3) ||
4718 MI.getOperand(4).getImm() !=
MI.getOperand(5).getImm() + 2) {
4719 ErrInfo =
"Incorrect array index for MVE_VMOV_q_rr";
4740 for (
auto Op :
MI.operands()) {
4747 ErrInfo =
"Incorrect AddrMode Imm for instruction";
4757 unsigned LoadImmOpc,
4758 unsigned LoadOpc)
const {
4759 assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&
4760 "ROPI/RWPI not currently supported with stack guard");
4768 if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) {
4769 assert(!Subtarget.isReadTPSoft() &&
4770 "TLS stack protector requires hardware TLS register");
4780 Module &M = *
MBB.getParent()->getFunction().getParent();
4781 Offset = M.getStackProtectorGuardOffset();
4786 unsigned AddOpc = (LoadImmOpc == ARM::MRC) ? ARM::ADDri : ARM::t2ADDri;
4797 bool IsIndirect = Subtarget.isGVIndirectSymbol(GV);
4800 if (Subtarget.isTargetMachO()) {
4802 }
else if (Subtarget.isTargetCOFF()) {
4805 else if (IsIndirect)
4807 }
else if (IsIndirect) {
4811 if (LoadImmOpc == ARM::tMOVi32imm) {
4814 ARMSysReg::lookupMClassSysRegByName(
"apsr_nzcvq")->Encoding;
4850 unsigned &AddSubOpc,
4851 bool &NegAcc,
bool &HasLane)
const {
4852 auto I = MLxEntryMap.find(Opcode);
4853 if (
I == MLxEntryMap.end())
4857 MulOpc = Entry.MulOpc;
4858 AddSubOpc = Entry.AddSubOpc;
4859 NegAcc = Entry.NegAcc;
4860 HasLane = Entry.HasLane;
4884std::pair<uint16_t, uint16_t>
4888 if (Subtarget.hasNEON()) {
4897 (
MI.getOpcode() == ARM::VMOVRS ||
MI.getOpcode() == ARM::VMOVSR ||
4898 MI.getOpcode() == ARM::VMOVS))
4905 return std::make_pair(
ExeNEON, 0);
4910 return std::make_pair(
ExeNEON, 0);
4913 return std::make_pair(
ExeVFP, 0);
4919 unsigned SReg,
unsigned &Lane) {
4921 TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);
4928 DReg =
TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
4930 assert(DReg &&
"S-register with no D super-register?");
4955 if (
MI.definesRegister(DReg,
TRI) ||
MI.readsRegister(DReg,
TRI)) {
4961 ImplicitSReg =
TRI->getSubReg(DReg,
4962 (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
4964 MI.getParent()->computeRegisterLiveness(
TRI, ImplicitSReg,
MI);
4979 unsigned DstReg, SrcReg;
4984 switch (
MI.getOpcode()) {
4996 assert(Subtarget.hasNEON() &&
"VORRd requires NEON");
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);
5006 MI.setDesc(
get(ARM::VORRd));
5018 DstReg =
MI.getOperand(0).getReg();
5019 SrcReg =
MI.getOperand(1).getReg();
5021 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5022 MI.removeOperand(i - 1);
5029 MI.setDesc(
get(ARM::VGETLNi32));
5045 DstReg =
MI.getOperand(0).getReg();
5046 SrcReg =
MI.getOperand(1).getReg();
5054 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5055 MI.removeOperand(i - 1);
5059 MI.setDesc(
get(ARM::VSETLNi32));
5078 DstReg =
MI.getOperand(0).getReg();
5079 SrcReg =
MI.getOperand(1).getReg();
5081 unsigned DstLane = 0, SrcLane = 0;
5090 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5091 MI.removeOperand(i - 1);
5096 MI.setDesc(
get(ARM::VDUPLN32d));
5130 MCRegister CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;
5131 bool CurUndef = !
MI.readsRegister(CurReg,
TRI);
5134 CurReg = SrcLane == 0 && DstLane == 0 ? DSrc : DDst;
5135 CurUndef = !
MI.readsRegister(CurReg,
TRI);
5140 if (SrcLane == DstLane)
5143 MI.setDesc(
get(ARM::VEXTd32));
5148 CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;
5149 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5152 CurReg = SrcLane == 0 && DstLane == 1 ? DSrc : DDst;
5153 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5158 if (SrcLane != DstLane)
5164 if (ImplicitSReg != 0)
5190 auto PartialUpdateClearance = Subtarget.getPartialUpdateClearance();
5191 if (!PartialUpdateClearance)
5202 switch (
MI.getOpcode()) {
5208 case ARM::VMOVv4i16:
5209 case ARM::VMOVv2i32:
5210 case ARM::VMOVv2f32:
5211 case ARM::VMOVv1i64:
5212 UseOp =
MI.findRegisterUseOperandIdx(Reg,
TRI,
false);
5216 case ARM::VLD1LNd32:
5225 if (UseOp != -1 &&
MI.getOperand(UseOp).readsReg())
5229 if (Reg.isVirtual()) {
5231 if (!MO.
getSubReg() ||
MI.readsVirtualRegister(Reg))
5233 }
else if (ARM::SPRRegClass.
contains(Reg)) {
5236 TRI->getMatchingSuperReg(Reg, ARM::ssub_0, &ARM::DPRRegClass);
5237 if (!DReg || !
MI.definesRegister(DReg,
TRI))
5243 return PartialUpdateClearance;
5250 assert(OpNum <
MI.getDesc().getNumDefs() &&
"OpNum is not a def");
5255 assert(Reg.isPhysical() &&
"Can't break virtual register dependencies.");
5256 unsigned DReg = Reg;
5259 if (ARM::SPRRegClass.
contains(Reg)) {
5260 DReg = ARM::D0 + (Reg - ARM::S0) / 2;
5261 assert(
TRI->isSuperRegister(Reg, DReg) &&
"Register enums broken");
5264 assert(ARM::DPRRegClass.
contains(DReg) &&
"Can only break D-reg deps");
5265 assert(
MI.definesRegister(DReg,
TRI) &&
"MI doesn't clobber full D-reg");
5278 MI.addRegisterKilled(DReg,
TRI,
true);
5282 return Subtarget.hasFeature(ARM::HasV6KOps);
5286 if (
MI->getNumOperands() < 4)
5288 unsigned ShOpVal =
MI->getOperand(3).getImm();
5292 ((ShImm == 1 || ShImm == 2) &&
5302 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5303 assert(
MI.isRegSequenceLike() &&
"Invalid kind of instruction");
5305 switch (
MI.getOpcode()) {
5317 MOReg = &
MI.getOperand(2);
5329 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5330 assert(
MI.isExtractSubregLike() &&
"Invalid kind of instruction");
5332 switch (
MI.getOpcode()) {
5343 InputReg.
SubIdx = DefIdx == 0 ? ARM::ssub_0 : ARM::ssub_1;
5352 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5353 assert(
MI.isInsertSubregLike() &&
"Invalid kind of instruction");
5355 switch (
MI.getOpcode()) {
5356 case ARM::VSETLNi32:
5357 case ARM::MVE_VMOV_to_lane_32:
5365 BaseReg.Reg = MOBaseReg.
getReg();
5368 InsertedReg.
Reg = MOInsertedReg.
getReg();
5376std::pair<unsigned, unsigned>
5379 return std::make_pair(TF & Mask, TF & ~Mask);
5384 using namespace ARMII;
5386 static const std::pair<unsigned, const char *> TargetFlags[] = {
5387 {MO_LO16,
"arm-lo16"}, {MO_HI16,
"arm-hi16"},
5388 {MO_LO_0_7,
"arm-lo-0-7"}, {MO_HI_0_7,
"arm-hi-0-7"},
5389 {MO_LO_8_15,
"arm-lo-8-15"}, {MO_HI_8_15,
"arm-hi-8-15"},
5396 using namespace ARMII;
5398 static const std::pair<unsigned, const char *> TargetFlags[] = {
5399 {MO_COFFSTUB,
"arm-coffstub"},
5400 {MO_GOT,
"arm-got"},
5401 {MO_SBREL,
"arm-sbrel"},
5402 {MO_DLLIMPORT,
"arm-dllimport"},
5403 {MO_SECREL,
"arm-secrel"},
5404 {MO_NONLAZY,
"arm-nonlazy"}};
5408std::optional<RegImmPair>
5411 unsigned Opcode =
MI.getOpcode();
5418 return std::nullopt;
5421 if (Opcode == ARM::SUBri)
5423 else if (Opcode != ARM::ADDri)
5424 return std::nullopt;
5429 if (!
MI.getOperand(1).isReg() || !
MI.getOperand(2).isImm())
5430 return std::nullopt;
5432 Offset =
MI.getOperand(2).getImm() * Sign;
5440 for (
auto I = From;
I != To; ++
I)
5441 if (
I->modifiesRegister(Reg,
TRI))
5454 if (CmpMI->modifiesRegister(ARM::CPSR,
TRI))
5456 if (CmpMI->readsRegister(ARM::CPSR,
TRI))
5462 if (CmpMI->getOpcode() != ARM::tCMPi8 && CmpMI->getOpcode() != ARM::t2CMPri)
5464 Register Reg = CmpMI->getOperand(0).getReg();
5467 if (Pred !=
ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)
5480 if (Subtarget->isThumb()) {
5482 return ForCodesize ? 2 : 1;
5483 if (Subtarget->hasV6T2Ops() && (Val <= 0xffff ||
5486 return ForCodesize ? 4 : 1;
5488 return ForCodesize ? 4 : 2;
5490 return ForCodesize ? 4 : 2;
5492 return ForCodesize ? 4 : 2;
5495 return ForCodesize ? 4 : 1;
5497 return ForCodesize ? 4 : 1;
5498 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)
5499 return ForCodesize ? 4 : 1;
5501 return ForCodesize ? 8 : 2;
5503 return ForCodesize ? 8 : 2;
5506 return ForCodesize ? 8 : 2;
5507 return ForCodesize ? 8 : 3;
5673 const ARMBaseRegisterInfo *ARI =
5674 static_cast<const ARMBaseRegisterInfo *
>(&
TRI);
5683 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
5684 C.isAvailableInsideSeq(
Reg,
TRI))
5698 for (;
I !=
E; ++
I) {
5702 if (
MI.modifiesRegister(ARM::LR, &
TRI))
5706 unsigned Opcode =
MI.getOpcode();
5707 if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR ||
5708 Opcode == ARM::SUBS_PC_LR || Opcode == ARM::tBX_RET ||
5709 Opcode == ARM::tBXNS_RET || Opcode == ARM::t2BXAUT_RET) {
5715 if (
MI.readsRegister(ARM::LR, &
TRI))
5724 auto Opcode =
MI.getOpcode();
5725 return (Opcode == ARM::BL || Opcode == ARM::BLX || Opcode == ARM::BLX_noip ||
5726 Opcode == ARM::tBL || Opcode == ARM::tBLXi || Opcode == ARM::tBLXr ||
5727 Opcode == ARM::tBLXr_noip);
5730std::optional<std::unique_ptr<outliner::OutlinedFunction>>
5733 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
5734 unsigned MinRepeats)
const {
5735 unsigned SequenceSize = 0;
5736 for (
auto &
MI : RepeatedSequenceLocs[0])
5740 unsigned FlagsSetInAll = 0xF;
5745 FlagsSetInAll &=
C.Flags;
5764 return C.isAnyUnavailableAcrossOrOutOfSeq({ARM::R12, ARM::CPSR},
TRI);
5772 llvm::erase_if(RepeatedSequenceLocs, CantGuaranteeValueAcrossCall);
5775 if (RepeatedSequenceLocs.size() < MinRepeats)
5776 return std::nullopt;
5795 if (std::distance(RepeatedSequenceLocs.begin(), NoBTI) >
5796 std::distance(NoBTI, RepeatedSequenceLocs.end()))
5797 RepeatedSequenceLocs.erase(NoBTI, RepeatedSequenceLocs.end());
5799 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoBTI);
5801 if (RepeatedSequenceLocs.size() < MinRepeats)
5802 return std::nullopt;
5812 if (std::distance(RepeatedSequenceLocs.begin(), NoPAC) >
5813 std::distance(NoPAC, RepeatedSequenceLocs.end()))
5814 RepeatedSequenceLocs.erase(NoPAC, RepeatedSequenceLocs.end());
5816 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoPAC);
5818 if (RepeatedSequenceLocs.size() < MinRepeats)
5819 return std::nullopt;
5825 auto SetCandidateCallInfo =
5826 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
5828 C.setCallInfo(CallID, NumBytesForCall);
5833 const auto &SomeMFI =
5836 if (SomeMFI.branchTargetEnforcement()) {
5845 if (SomeMFI.shouldSignReturnAddress(
true)) {
5855 if (RepeatedSequenceLocs[0].back().isTerminator()) {
5867 unsigned NumBytesNoStackCalls = 0;
5868 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
5873 const auto Last =
C.getMBB()->rbegin();
5874 const bool LRIsAvailable =
5875 C.getMBB()->isReturnBlock() && !
Last->isCall()
5878 :
C.isAvailableAcrossAndOutOfSeq(ARM::LR,
TRI);
5879 if (LRIsAvailable) {
5883 CandidatesWithoutStackFixups.push_back(
C);
5888 else if (findRegisterToSaveLRTo(
C)) {
5892 CandidatesWithoutStackFixups.push_back(
C);
5897 else if (
C.isAvailableInsideSeq(ARM::SP,
TRI)) {
5900 CandidatesWithoutStackFixups.push_back(
C);
5906 NumBytesNoStackCalls += SequenceSize;
5912 if (NumBytesNoStackCalls <=
5913 RepeatedSequenceLocs.size() * Costs.
CallDefault) {
5914 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
5916 if (RepeatedSequenceLocs.size() < MinRepeats)
5917 return std::nullopt;
5942 return std::make_unique<outliner::OutlinedFunction>(
5943 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
5946bool ARMBaseInstrInfo::checkAndUpdateStackOffset(
MachineInstr *
MI,
5949 int SPIdx =
MI->findRegisterUseOperandIdx(ARM::SP,
nullptr);
5974 unsigned NumOps =
MI->getDesc().getNumOperands();
5975 unsigned ImmIdx =
NumOps - 3;
5979 int64_t OffVal =
Offset.getImm();
5985 unsigned NumBits = 0;
6014 assert((
Fixup & 3) == 0 &&
"Can't encode this offset!");
6034 assert(((OffVal * Scale +
Fixup) & (Scale - 1)) == 0 &&
6035 "Can't encode this offset!");
6036 OffVal +=
Fixup / Scale;
6038 unsigned Mask = (1 << NumBits) - 1;
6040 if (OffVal <= Mask) {
6042 MI->getOperand(ImmIdx).setImm(OffVal);
6050 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
6054 const Function &CFn =
C.getMF()->getFunction();
6061 ARMGenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
6069 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
6088 unsigned &Flags)
const {
6091 assert(
MBB.getParent()->getRegInfo().tracksLiveness() &&
6092 "Suitable Machine Function for outlining must track liveness");
6100 bool R12AvailableInBlock = LRU.
available(ARM::R12);
6101 bool CPSRAvailableInBlock = LRU.
available(ARM::CPSR);
6105 if (R12AvailableInBlock && CPSRAvailableInBlock)
6113 if (R12AvailableInBlock && !LRU.
available(ARM::R12))
6115 if (CPSRAvailableInBlock && !LRU.
available(ARM::CPSR))
6125 bool LRIsAvailable =
6126 MBB.isReturnBlock() && !
MBB.back().isCall()
6138 unsigned Flags)
const {
6144 unsigned Opc =
MI.getOpcode();
6145 if (
Opc == ARM::tPICADD ||
Opc == ARM::PICADD ||
Opc == ARM::PICSTR ||
6146 Opc == ARM::PICSTRB ||
Opc == ARM::PICSTRH ||
Opc == ARM::PICLDR ||
6147 Opc == ARM::PICLDRB ||
Opc == ARM::PICLDRH ||
Opc == ARM::PICLDRSB ||
6148 Opc == ARM::PICLDRSH ||
Opc == ARM::t2LDRpci_pic ||
6149 Opc == ARM::t2MOVi16_ga_pcrel ||
Opc == ARM::t2MOVTi16_ga_pcrel ||
6150 Opc == ARM::t2MOV_ga_pcrel)
6154 if (
Opc == ARM::t2BF_LabelPseudo ||
Opc == ARM::t2DoLoopStart ||
6155 Opc == ARM::t2DoLoopStartTP ||
Opc == ARM::t2WhileLoopStart ||
6156 Opc == ARM::t2WhileLoopStartLR ||
Opc == ARM::t2WhileLoopStartTP ||
6157 Opc == ARM::t2LoopDec ||
Opc == ARM::t2LoopEnd ||
6158 Opc == ARM::t2LoopEndDec)
6162 uint64_t MIFlags =
MCID.TSFlags;
6167 if (
MI.isTerminator())
6173 if (
MI.readsRegister(ARM::LR,
TRI) ||
MI.readsRegister(ARM::PC,
TRI))
6181 if (MOP.isGlobal()) {
6190 (Callee->getName() ==
"\01__gnu_mcount_nc" ||
6191 Callee->getName() ==
"\01mcount" || Callee->getName() ==
"__mcount"))
6203 return UnknownCallOutlineType;
6211 return UnknownCallOutlineType;
6219 return UnknownCallOutlineType;
6227 if (
MI.modifiesRegister(ARM::LR,
TRI) ||
MI.modifiesRegister(ARM::PC,
TRI))
6231 if (
MI.modifiesRegister(ARM::SP,
TRI) ||
MI.readsRegister(ARM::SP,
TRI)) {
6244 bool MightNeedStackFixUp =
6248 if (!MightNeedStackFixUp)
6254 if (
MI.modifiesRegister(ARM::SP,
TRI))
6259 if (checkAndUpdateStackOffset(&
MI, Subtarget.getStackAlignment().value(),
6268 if (
MI.readsRegister(ARM::ITSTATE,
TRI) ||
6269 MI.modifiesRegister(ARM::ITSTATE,
TRI))
6273 if (
MI.isCFIInstruction())
6288 int Align = std::max(Subtarget.getStackAlignment().value(),
uint64_t(8));
6290 assert(Align >= 8 && Align <= 256);
6292 assert(Subtarget.isThumb2());
6304 unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
6318 CFIBuilder.buildDefCFAOffset(Align);
6323 CFIBuilder.buildOffset(ARM::LR, -LROffset);
6326 CFIBuilder.buildOffset(ARM::RA_AUTH_CODE, -Align);
6332 bool CFI,
bool Auth)
const {
6333 int Align = Subtarget.getStackAlignment().value();
6336 assert(Subtarget.isThumb2());
6348 unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
6352 if (!Subtarget.isThumb())
6354 MIB.
addImm(Subtarget.getStackAlignment().value())
6362 CFIBuilder.buildDefCFAOffset(0);
6363 CFIBuilder.buildRestore(ARM::LR);
6365 CFIBuilder.buildUndefined(ARM::RA_AUTH_CODE);
6379 bool isThumb = Subtarget.isThumb();
6380 unsigned FuncOp =
isThumb ? 2 : 0;
6381 unsigned Opc =
Call->getOperand(FuncOp).isReg()
6382 ?
isThumb ? ARM::tTAILJMPr : ARM::TAILJMPr
6383 :
isThumb ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd
6387 .
add(
Call->getOperand(FuncOp));
6390 Call->eraseFromParent();
6395 return MI.isCall() && !
MI.isReturn();
6403 Et = std::prev(
MBB.end());
6408 if (!
MBB.isLiveIn(ARM::LR))
6409 MBB.addLiveIn(ARM::LR);
6413 saveLROnStack(
MBB, It,
true, Auth);
6418 "Can only fix up stack references once");
6419 fixupPostOutline(
MBB);
6422 restoreLRFromStack(
MBB, Et,
true, Auth);
6442 fixupPostOutline(
MBB);
6451 bool isThumb = Subtarget.isThumb();
6457 ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND
6463 It =
MBB.insert(It, MIB);
6477 It =
MBB.insert(It, CallMIB);
6484 Register Reg = findRegisterToSaveLRTo(
C);
6485 assert(Reg != 0 &&
"No callee-saved register available?");
6492 CallPt =
MBB.insert(It, CallMIB);
6500 if (!
MBB.isLiveIn(ARM::LR))
6501 MBB.addLiveIn(ARM::LR);
6504 CallPt =
MBB.insert(It, CallMIB);
6515bool ARMBaseInstrInfo::isReMaterializableImpl(
6549 static int constexpr MAX_STAGES = 30;
6550 static int constexpr LAST_IS_USE = MAX_STAGES;
6551 static int constexpr SEEN_AS_LIVE = MAX_STAGES + 1;
6552 typedef std::bitset<MAX_STAGES + 2> IterNeed;
6553 typedef std::map<Register, IterNeed> IterNeeds;
6556 const IterNeeds &CIN);
6568 : EndLoop(EndLoop), LoopCount(LoopCount),
6570 TII(MF->getSubtarget().getInstrInfo()) {}
6572 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
6574 return MI == EndLoop ||
MI == LoopCount;
6577 bool shouldUseSchedule(SwingSchedulerDAG &SSD, SMSchedule &SMS)
override {
6578 if (tooMuchRegisterPressure(SSD, SMS))
6584 std::optional<bool> createTripCountGreaterCondition(
6585 int TC, MachineBasicBlock &
MBB,
6586 SmallVectorImpl<MachineOperand> &
Cond)
override {
6595 }
else if (EndLoop->
getOpcode() == ARM::t2LoopEnd) {
6598 MachineInstr *LoopDec =
nullptr;
6600 if (
I.getOpcode() == ARM::t2LoopDec)
6602 assert(LoopDec &&
"Unable to find copied LoopDec");
6616 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
6618 void adjustTripCount(
int TripCountAdjust)
override {}
6622 const IterNeeds &CIN) {
6624 for (
const auto &
N : CIN) {
6625 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6626 for (
int I = 0;
I < Cnt; ++
I)
6631 for (
const auto &
N : CIN) {
6632 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6633 for (
int I = 0;
I < Cnt; ++
I)
6641 IterNeeds CrossIterationNeeds;
6646 for (
auto &SU : SSD.
SUnits) {
6649 for (
auto &S : SU.Succs)
6653 CrossIterationNeeds[
Reg.
id()].set(0);
6654 }
else if (S.isAssignedRegDep()) {
6656 if (OStg >= 0 && OStg != Stg) {
6659 CrossIterationNeeds[
Reg.
id()] |= ((1 << (OStg - Stg)) - 1);
6668 std::vector<SUnit *> ProposedSchedule;
6672 std::deque<SUnit *> Instrs =
6674 std::sort(Instrs.begin(), Instrs.end(),
6675 [](
SUnit *
A,
SUnit *
B) { return A->NodeNum > B->NodeNum; });
6682 for (
auto *SU : ProposedSchedule)
6686 if (!MO.isReg() || !MO.getReg())
6689 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6690 if (CIter == CrossIterationNeeds.end() || CIter->second[LAST_IS_USE] ||
6691 CIter->second[SEEN_AS_LIVE])
6693 if (MO.isDef() && !MO.isDead())
6694 CIter->second.set(SEEN_AS_LIVE);
6695 else if (MO.isUse())
6696 CIter->second.set(LAST_IS_USE);
6698 for (
auto &CI : CrossIterationNeeds)
6699 CI.second.reset(LAST_IS_USE);
6705 RPTracker.init(MF, &RegClassInfo,
nullptr, EndLoop->
getParent(),
6708 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6710 for (
auto *SU : ProposedSchedule) {
6712 RPTracker.setPos(std::next(CurInstI));
6718 if (!MO.isReg() || !MO.getReg())
6721 if (MO.isDef() && !MO.isDead()) {
6722 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6723 if (CIter != CrossIterationNeeds.end()) {
6724 CIter->second.reset(0);
6725 CIter->second.reset(SEEN_AS_LIVE);
6729 for (
auto &S : SU->Preds) {
6731 if (S.isAssignedRegDep()) {
6733 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6734 if (CIter != CrossIterationNeeds.end()) {
6736 assert(Stg2 <= Stg &&
"Data dependence upon earlier stage");
6737 if (Stg - Stg2 < MAX_STAGES)
6738 CIter->second.set(Stg - Stg2);
6739 CIter->second.set(SEEN_AS_LIVE);
6744 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6747 auto &
P = RPTracker.getPressure().MaxSetPressure;
6748 for (
unsigned I = 0,
E =
P.size();
I <
E; ++
I) {
6750 if (
I == ARM::DQuad_with_ssub_0 ||
I == ARM::DTripleSpc_with_ssub_0 ||
6751 I == ARM::DTriple_with_qsub_0_in_QPR)
6763std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
6767 if (Preheader == LoopBB)
6768 Preheader = *std::next(LoopBB->
pred_begin());
6770 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2Bcc) {
6776 for (
auto &L : LoopBB->
instrs()) {
6783 return std::make_unique<ARMPipelinerLoopInfo>(&*
I, CCSetter);
6797 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2LoopEnd) {
6798 for (
auto &L : LoopBB->
instrs())
6803 Register LoopDecResult =
I->getOperand(0).getReg();
6806 if (!LoopDec || LoopDec->
getOpcode() != ARM::t2LoopDec)
6809 for (
auto &J : Preheader->
instrs())
6810 if (J.getOpcode() == ARM::t2DoLoopStart)
6814 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)
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction 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 const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
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.