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");
453 MI.getOperand(1).setReg(ARM::NoRegister);
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();
939 return MIB.
addReg(Reg, State);
943 return MIB.
addReg(Reg, State, SubIdx);
948 Register SrcReg,
bool isKill,
int FI,
961 switch (
TRI.getSpillSize(*RC)) {
963 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
974 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
981 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
988 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
995 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1006 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1013 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1014 if (Subtarget.hasV5TEOps()) {
1017 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1028 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
1034 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1050 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1051 Subtarget.hasMVEIntegerOps()) {
1056 .addMemOperand(MMO);
1062 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1065 Subtarget.hasNEON()) {
1079 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1080 AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1086 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1087 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1088 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1090 Subtarget.hasNEON()) {
1099 }
else if (Subtarget.hasMVEIntegerOps()) {
1111 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1112 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1113 AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1119 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1120 Subtarget.hasMVEIntegerOps()) {
1125 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1131 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_1, {});
1132 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_2, {});
1133 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_3, {});
1134 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_4, {});
1135 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_5, {});
1136 MIB =
AddDReg(MIB, SrcReg, ARM::dsub_6, {});
1137 AddDReg(MIB, SrcReg, ARM::dsub_7, {});
1147 int &FrameIndex)
const {
1148 switch (
MI.getOpcode()) {
1152 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1153 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1154 MI.getOperand(3).getImm() == 0) {
1155 FrameIndex =
MI.getOperand(1).getIndex();
1156 return MI.getOperand(0).getReg();
1165 case ARM::VSTR_P0_off:
1166 case ARM::VSTR_FPSCR_NZCVQC_off:
1167 case ARM::MVE_VSTRWU32:
1168 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1169 MI.getOperand(2).getImm() == 0) {
1170 FrameIndex =
MI.getOperand(1).getIndex();
1171 return MI.getOperand(0).getReg();
1175 case ARM::VST1d64TPseudo:
1176 case ARM::VST1d64QPseudo:
1177 if (
MI.getOperand(0).isFI() &&
MI.getOperand(2).getSubReg() == 0) {
1178 FrameIndex =
MI.getOperand(0).getIndex();
1179 return MI.getOperand(2).getReg();
1183 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1184 FrameIndex =
MI.getOperand(1).getIndex();
1185 return MI.getOperand(0).getReg();
1188 case ARM::MQQPRStore:
1189 case ARM::MQQQQPRStore:
1190 if (
MI.getOperand(1).isFI()) {
1191 FrameIndex =
MI.getOperand(1).getIndex();
1192 return MI.getOperand(0).getReg();
1201 int &FrameIndex)
const {
1203 if (
MI.mayStore() && hasStoreToStackSlot(
MI,
Accesses) &&
1220 if (
I !=
MBB.end())
DL =
I->getDebugLoc();
1229 switch (
TRI.getSpillSize(*RC)) {
1231 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
1241 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
1247 }
else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
1253 }
else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
1259 }
else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1269 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1275 }
else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1278 if (Subtarget.hasV5TEOps()) {
1301 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1314 }
else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1315 Subtarget.hasMVEIntegerOps()) {
1317 MIB.addFrameIndex(FI)
1319 .addMemOperand(MMO);
1325 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1327 Subtarget.hasNEON()) {
1348 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1349 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1350 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1352 Subtarget.hasNEON()) {
1358 }
else if (Subtarget.hasMVEIntegerOps()) {
1378 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1379 Subtarget.hasMVEIntegerOps()) {
1383 }
else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1407 int &FrameIndex)
const {
1408 switch (
MI.getOpcode()) {
1412 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isReg() &&
1413 MI.getOperand(3).isImm() &&
MI.getOperand(2).getReg() == 0 &&
1414 MI.getOperand(3).getImm() == 0) {
1415 FrameIndex =
MI.getOperand(1).getIndex();
1416 return MI.getOperand(0).getReg();
1425 case ARM::VLDR_P0_off:
1426 case ARM::VLDR_FPSCR_NZCVQC_off:
1427 case ARM::MVE_VLDRWU32:
1428 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
1429 MI.getOperand(2).getImm() == 0) {
1430 FrameIndex =
MI.getOperand(1).getIndex();
1431 return MI.getOperand(0).getReg();
1435 case ARM::VLD1d8TPseudo:
1436 case ARM::VLD1d16TPseudo:
1437 case ARM::VLD1d32TPseudo:
1438 case ARM::VLD1d64TPseudo:
1439 case ARM::VLD1d8QPseudo:
1440 case ARM::VLD1d16QPseudo:
1441 case ARM::VLD1d32QPseudo:
1442 case ARM::VLD1d64QPseudo:
1443 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1444 FrameIndex =
MI.getOperand(1).getIndex();
1445 return MI.getOperand(0).getReg();
1449 if (
MI.getOperand(1).isFI() &&
MI.getOperand(0).getSubReg() == 0) {
1450 FrameIndex =
MI.getOperand(1).getIndex();
1451 return MI.getOperand(0).getReg();
1454 case ARM::MQQPRLoad:
1455 case ARM::MQQQQPRLoad:
1456 if (
MI.getOperand(1).isFI()) {
1457 FrameIndex =
MI.getOperand(1).getIndex();
1458 return MI.getOperand(0).getReg();
1467 int &FrameIndex)
const {
1469 if (
MI.mayLoad() && hasLoadFromStackSlot(
MI,
Accesses) &&
1483 bool isThumb2 = Subtarget.
isThumb2();
1490 if (isThumb1 || !
MI->getOperand(1).isDead()) {
1492 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA_UPD
1493 : isThumb1 ? ARM::tLDMIA_UPD
1497 LDM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
1500 if (isThumb1 || !
MI->getOperand(0).isDead()) {
1501 MachineOperand STWb(
MI->getOperand(0));
1502 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA_UPD
1503 : isThumb1 ? ARM::tSTMIA_UPD
1507 STM =
BuildMI(*BB,
MI, dl,
TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
1510 MachineOperand LDBase(
MI->getOperand(3));
1513 MachineOperand STBase(
MI->getOperand(2));
1522 [&
TRI](
const unsigned &Reg1,
const unsigned &Reg2) ->
bool {
1523 return TRI.getEncodingValue(Reg1) <
1524 TRI.getEncodingValue(Reg2);
1527 for (
const auto &
Reg : ScratchRegs) {
1536 if (
MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) {
1537 expandLoadStackGuard(
MI);
1538 MI.getParent()->erase(
MI);
1542 if (
MI.getOpcode() == ARM::MEMCPY) {
1551 if (!
MI.isCopy() || Subtarget.dontWidenVMOVS() || !Subtarget.hasFP64())
1556 Register DstRegS =
MI.getOperand(0).getReg();
1557 Register SrcRegS =
MI.getOperand(1).getReg();
1558 if (!ARM::SPRRegClass.
contains(DstRegS, SrcRegS))
1563 TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, &ARM::DPRRegClass);
1565 TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, &ARM::DPRRegClass);
1566 if (!DstRegD || !SrcRegD)
1572 if (!
MI.definesRegister(DstRegD,
TRI) ||
MI.readsRegister(DstRegD,
TRI))
1576 if (
MI.getOperand(0).isDead())
1585 int ImpDefIdx =
MI.findRegisterDefOperandIdx(DstRegD,
nullptr);
1586 if (ImpDefIdx != -1)
1587 MI.removeOperand(ImpDefIdx);
1590 MI.setDesc(
get(ARM::VMOVD));
1591 MI.getOperand(0).setReg(DstRegD);
1592 MI.getOperand(1).setReg(SrcRegD);
1599 MI.getOperand(1).setIsUndef();
1604 if (
MI.getOperand(1).isKill()) {
1605 MI.getOperand(1).setIsKill(
false);
1606 MI.addRegisterKilled(SrcRegS,
TRI,
true);
1620 assert(MCPE.isMachineConstantPoolEntry() &&
1621 "Expecting a machine constantpool entry!");
1671 case ARM::tLDRpci_pic:
1672 case ARM::t2LDRpci_pic: {
1692 switch (
I->getOpcode()) {
1693 case ARM::tLDRpci_pic:
1694 case ARM::t2LDRpci_pic: {
1696 unsigned CPI =
I->getOperand(1).getIndex();
1698 I->getOperand(1).setIndex(CPI);
1699 I->getOperand(2).setImm(PCLabelId);
1703 if (!
I->isBundledWithSucc())
1714 if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic ||
1715 Opcode == ARM::tLDRpci || Opcode == ARM::tLDRpci_pic ||
1716 Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1717 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1718 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1719 Opcode == ARM::t2MOV_ga_pcrel) {
1730 if (Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1731 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1732 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1733 Opcode == ARM::t2MOV_ga_pcrel)
1745 if (isARMCP0 && isARMCP1) {
1751 }
else if (!isARMCP0 && !isARMCP1) {
1755 }
else if (Opcode == ARM::PICLDR) {
1763 if (Addr0 != Addr1) {
1799 int64_t &Offset2)
const {
1801 if (Subtarget.isThumb1Only())
return false;
1806 auto IsLoadOpcode = [&](
unsigned Opcode) {
1821 case ARM::t2LDRSHi8:
1823 case ARM::t2LDRBi12:
1824 case ARM::t2LDRSHi12:
1865 int64_t Offset1, int64_t Offset2,
1866 unsigned NumLoads)
const {
1868 if (Subtarget.isThumb1Only())
return false;
1870 assert(Offset2 > Offset1);
1872 if ((Offset2 - Offset1) / 8 > 64)
1903 if (
MI.isDebugInstr())
1907 if (
MI.isTerminator() ||
MI.isPosition())
1911 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
1925 while (++
I !=
MBB->end() &&
I->isDebugInstr())
1927 if (
I !=
MBB->end() &&
I->getOpcode() == ARM::t2IT)
1938 if (!
MI.isCall() &&
MI.definesRegister(ARM::SP,
nullptr))
1946 unsigned NumCycles,
unsigned ExtraPredCycles,
1954 if (
MBB.getParent()->getFunction().hasOptSize()) {
1956 if (!Pred->empty()) {
1958 if (LastMI->
getOpcode() == ARM::t2Bcc) {
1967 MBB, 0, 0, Probability);
1972 unsigned TCycles,
unsigned TExtra,
1974 unsigned FCycles,
unsigned FExtra,
1983 if (Subtarget.isThumb2() &&
TBB.getParent()->getFunction().hasMinSize()) {
1991 const unsigned ScalingUpFactor = 1024;
1993 unsigned PredCost = (TCycles + FCycles + TExtra + FExtra) * ScalingUpFactor;
1994 unsigned UnpredCost;
1995 if (!Subtarget.hasBranchPredictor()) {
1998 unsigned NotTakenBranchCost = 1;
1999 unsigned TakenBranchCost = Subtarget.getMispredictionPenalty();
2000 unsigned TUnpredCycles, FUnpredCycles;
2003 TUnpredCycles = TCycles + NotTakenBranchCost;
2004 FUnpredCycles = TakenBranchCost;
2007 TUnpredCycles = TCycles + TakenBranchCost;
2008 FUnpredCycles = FCycles + NotTakenBranchCost;
2011 PredCost -= 1 * ScalingUpFactor;
2014 unsigned TUnpredCost = Probability.
scale(TUnpredCycles * ScalingUpFactor);
2015 unsigned FUnpredCost = Probability.
getCompl().
scale(FUnpredCycles * ScalingUpFactor);
2016 UnpredCost = TUnpredCost + FUnpredCost;
2019 if (Subtarget.isThumb2() && TCycles + FCycles > 4) {
2020 PredCost += ((TCycles + FCycles - 4) / 4) * ScalingUpFactor;
2023 unsigned TUnpredCost = Probability.
scale(TCycles * ScalingUpFactor);
2024 unsigned FUnpredCost =
2026 UnpredCost = TUnpredCost + FUnpredCost;
2027 UnpredCost += 1 * ScalingUpFactor;
2028 UnpredCost += Subtarget.getMispredictionPenalty() * ScalingUpFactor / 10;
2031 return PredCost <= UnpredCost;
2036 unsigned NumInsts)
const {
2040 if (!Subtarget.isThumb2())
2044 unsigned MaxInsts = Subtarget.restrictIT() ? 1 : 4;
2053 if (
MI.getOpcode() == ARM::t2Bcc &&
2065 if (Subtarget.isThumb2())
2076 return Subtarget.isProfitableToUnpredicate();
2084 int PIdx =
MI.findFirstPredOperandIdx();
2090 PredReg =
MI.getOperand(PIdx+1).getReg();
2099 if (
Opc == ARM::t2B)
2108 unsigned OpIdx2)
const {
2109 switch (
MI.getOpcode()) {
2111 case ARM::t2MOVCCr: {
2116 if (CC ==
ARMCC::AL || PredReg != ARM::CPSR)
2136 if (!Reg.isVirtual())
2150 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2157 if (MO.getReg().isPhysical())
2159 if (MO.isDef() && !MO.isDead())
2162 bool DontMoveAcrossStores =
true;
2163 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2171 bool PreferFalse)
const {
2172 assert((
MI.getOpcode() == ARM::MOVCCr ||
MI.getOpcode() == ARM::t2MOVCCr) &&
2173 "Unknown select instruction");
2176 bool Invert = !
DefMI;
2178 DefMI = canFoldIntoMOVCC(
MI.getOperand(1).getReg(), MRI,
this);
2185 Register DestReg =
MI.getOperand(0).getReg();
2201 i != e && !DefDesc.
operands()[i].isPredicate(); ++i)
2204 unsigned CondCode =
MI.getOperand(3).getImm();
2209 NewMI.
add(
MI.getOperand(4));
2220 NewMI.
add(FalseReg);
2231 if (
DefMI->getParent() !=
MI.getParent())
2235 DefMI->eraseFromParent();
2251 {ARM::ADDSri, ARM::ADDri},
2252 {ARM::ADDSrr, ARM::ADDrr},
2253 {ARM::ADDSrsi, ARM::ADDrsi},
2254 {ARM::ADDSrsr, ARM::ADDrsr},
2256 {ARM::SUBSri, ARM::SUBri},
2257 {ARM::SUBSrr, ARM::SUBrr},
2258 {ARM::SUBSrsi, ARM::SUBrsi},
2259 {ARM::SUBSrsr, ARM::SUBrsr},
2261 {ARM::RSBSri, ARM::RSBri},
2262 {ARM::RSBSrsi, ARM::RSBrsi},
2263 {ARM::RSBSrsr, ARM::RSBrsr},
2265 {ARM::tADDSi3, ARM::tADDi3},
2266 {ARM::tADDSi8, ARM::tADDi8},
2267 {ARM::tADDSrr, ARM::tADDrr},
2268 {ARM::tADCS, ARM::tADC},
2270 {ARM::tSUBSi3, ARM::tSUBi3},
2271 {ARM::tSUBSi8, ARM::tSUBi8},
2272 {ARM::tSUBSrr, ARM::tSUBrr},
2273 {ARM::tSBCS, ARM::tSBC},
2274 {ARM::tRSBS, ARM::tRSB},
2275 {ARM::tLSLSri, ARM::tLSLri},
2277 {ARM::t2ADDSri, ARM::t2ADDri},
2278 {ARM::t2ADDSrr, ARM::t2ADDrr},
2279 {ARM::t2ADDSrs, ARM::t2ADDrs},
2281 {ARM::t2SUBSri, ARM::t2SUBri},
2282 {ARM::t2SUBSrr, ARM::t2SUBrr},
2283 {ARM::t2SUBSrs, ARM::t2SUBrs},
2285 {ARM::t2RSBSri, ARM::t2RSBri},
2286 {ARM::t2RSBSrs, ARM::t2RSBrs},
2291 if (OldOpc == Entry.PseudoOpc)
2292 return Entry.MachineOpc;
2303 if (NumBytes == 0 && DestReg != BaseReg) {
2312 bool isSub = NumBytes < 0;
2313 if (isSub) NumBytes = -NumBytes;
2318 assert(ThisVal &&
"Didn't extract field correctly");
2321 NumBytes &= ~ThisVal;
2326 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
2339 unsigned NumBytes) {
2350 if (!IsPush && !IsPop)
2353 bool IsVFPPushPop =
MI->getOpcode() == ARM::VSTMDDB_UPD ||
2354 MI->getOpcode() == ARM::VLDMDIA_UPD;
2355 bool IsT1PushPop =
MI->getOpcode() == ARM::tPUSH ||
2356 MI->getOpcode() == ARM::tPOP ||
2357 MI->getOpcode() == ARM::tPOP_RET;
2359 assert((IsT1PushPop || (
MI->getOperand(0).getReg() == ARM::SP &&
2360 MI->getOperand(1).getReg() == ARM::SP)) &&
2361 "trying to fold sp update into non-sp-updating push/pop");
2366 if (NumBytes % (IsVFPPushPop ? 8 : 4) != 0)
2371 int RegListIdx = IsT1PushPop ? 2 : 4;
2374 unsigned RegsNeeded;
2377 RegsNeeded = NumBytes / 8;
2378 RegClass = &ARM::DPRRegClass;
2380 RegsNeeded = NumBytes / 4;
2381 RegClass = &ARM::GPRRegClass;
2391 unsigned FirstRegEnc = -1;
2394 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2399 TRI->getEncodingValue(MO.
getReg()) < FirstRegEnc)
2400 FirstRegEnc =
TRI->getEncodingValue(MO.
getReg());
2403 const MCPhysReg *CSRegs =
TRI->getCalleeSavedRegs(&MF);
2406 for (
int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2409 if (IsT1PushPop && CurRegEnc >
TRI->getEncodingValue(ARM::R7))
2416 false,
false,
true));
2426 MI->getParent()->computeRegisterLiveness(
TRI, CurReg,
MI) !=
2448 for (
int i =
MI->getNumOperands() - 1; i >= RegListIdx; --i)
2449 MI->removeOperand(i);
2462 unsigned Opcode =
MI.getOpcode();
2468 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
2471 if (Opcode == ARM::ADDri) {
2472 Offset +=
MI.getOperand(FrameRegIdx+1).getImm();
2475 MI.setDesc(
TII.get(ARM::MOVr));
2476 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2477 MI.removeOperand(FrameRegIdx+1);
2483 MI.setDesc(
TII.get(ARM::SUBri));
2489 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2490 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(
Offset);
2505 "Bit extraction didn't work?");
2506 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
2508 unsigned ImmIdx = 0;
2510 unsigned NumBits = 0;
2514 ImmIdx = FrameRegIdx + 1;
2515 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2519 ImmIdx = FrameRegIdx+2;
2526 ImmIdx = FrameRegIdx+2;
2537 ImmIdx = FrameRegIdx+1;
2545 ImmIdx = FrameRegIdx+1;
2555 ImmIdx = FrameRegIdx+1;
2556 InstrOffs =
MI.getOperand(ImmIdx).getImm();
2565 Offset += InstrOffs * Scale;
2566 assert((
Offset & (Scale-1)) == 0 &&
"Can't encode this offset!");
2576 int ImmedOffset =
Offset / Scale;
2577 unsigned Mask = (1 << NumBits) - 1;
2578 if ((
unsigned)
Offset <= Mask * Scale) {
2580 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
2586 ImmedOffset = -ImmedOffset;
2588 ImmedOffset |= 1 << NumBits;
2596 ImmedOffset = ImmedOffset & Mask;
2599 ImmedOffset = -ImmedOffset;
2601 ImmedOffset |= 1 << NumBits;
2617 Register &SrcReg2, int64_t &CmpMask,
2618 int64_t &CmpValue)
const {
2619 switch (
MI.getOpcode()) {
2624 SrcReg =
MI.getOperand(0).getReg();
2627 CmpValue =
MI.getOperand(1).getImm();
2632 SrcReg =
MI.getOperand(0).getReg();
2633 SrcReg2 =
MI.getOperand(1).getReg();
2639 SrcReg =
MI.getOperand(0).getReg();
2641 CmpMask =
MI.getOperand(1).getImm();
2654 int CmpMask,
bool CommonUse) {
2655 switch (
MI->getOpcode()) {
2658 if (CmpMask !=
MI->getOperand(2).getImm())
2660 if (SrcReg ==
MI->getOperand(CommonUse ? 1 : 0).getReg())
2750 switch (
MI->getOpcode()) {
2751 default:
return false;
2847 if (!
MI)
return false;
2850 if (CmpMask != ~0) {
2856 if (UI->getParent() != CmpInstr.
getParent())
2865 if (!
MI)
return false;
2874 if (
I ==
B)
return false;
2885 else if (
MI->getParent() != CmpInstr.
getParent() || CmpValue != 0) {
2890 if (CmpInstr.
getOpcode() == ARM::CMPri ||
2898 bool IsThumb1 =
false;
2915 if (
MI && IsThumb1) {
2917 if (
I != E && !
MI->readsRegister(ARM::CPSR,
TRI)) {
2918 bool CanReorder =
true;
2919 for (;
I != E; --
I) {
2920 if (
I->getOpcode() != ARM::tMOVi8) {
2926 MI =
MI->removeFromParent();
2937 bool SubAddIsThumb1 =
false;
2952 if (Instr.modifiesRegister(ARM::CPSR,
TRI) ||
2953 Instr.readsRegister(ARM::CPSR,
TRI))
2975 IsThumb1 = SubAddIsThumb1;
2990 bool isSafe =
false;
2993 while (!isSafe && ++
I != E) {
2995 for (
unsigned IO = 0, EO = Instr.getNumOperands();
2996 !isSafe && IO != EO; ++IO) {
3010 bool IsInstrVSel =
true;
3011 switch (Instr.getOpcode()) {
3013 IsInstrVSel =
false;
3047 bool IsSub =
Opc == ARM::SUBrr ||
Opc == ARM::t2SUBrr ||
3048 Opc == ARM::SUBri ||
Opc == ARM::t2SUBri ||
3049 Opc == ARM::tSUBrr ||
Opc == ARM::tSUBi3 ||
3051 unsigned OpI =
Opc != ARM::tSUBrr ? 1 : 2;
3063 std::make_pair(&((*I).getOperand(IO - 1)), NewCC));
3097 if (Succ->isLiveIn(ARM::CPSR))
3104 unsigned CPSRRegNum =
MI->getNumExplicitOperands() - 1;
3105 MI->getOperand(CPSRRegNum).setReg(ARM::CPSR);
3106 MI->getOperand(CPSRRegNum).setIsDef(
true);
3114 for (
auto &[MO,
Cond] : OperandsToUpdate)
3117 MI->clearRegisterDeads(ARM::CPSR);
3131 int64_t CmpMask, CmpValue;
3133 if (
Next !=
MI.getParent()->end() &&
3144 unsigned DefOpc =
DefMI.getOpcode();
3145 if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm &&
3146 DefOpc != ARM::tMOVi32imm)
3148 if (!
DefMI.getOperand(1).isImm())
3168 if (
UseMI.getOperand(
NumOps - 1).getReg() == ARM::CPSR)
3174 unsigned UseOpc =
UseMI.getOpcode();
3175 unsigned NewUseOpc = 0;
3177 uint32_t SOImmValV1 = 0, SOImmValV2 = 0;
3178 bool Commute =
false;
3180 default:
return false;
3188 case ARM::t2EORrr: {
3189 Commute =
UseMI.getOperand(2).getReg() != Reg;
3194 if (UseOpc == ARM::SUBrr && Commute)
3200 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::ADDri : ARM::SUBri;
3203 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::SUBri : ARM::ADDri;
3217 case ARM::ORRrr: NewUseOpc = ARM::ORRri;
break;
3218 case ARM::EORrr: NewUseOpc = ARM::EORri;
break;
3222 case ARM::t2SUBrr: {
3223 if (UseOpc == ARM::t2SUBrr && Commute)
3228 const bool ToSP =
DefMI.getOperand(0).getReg() == ARM::SP;
3229 const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
3230 const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
3232 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB;
3235 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD;
3250 case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri;
break;
3251 case ARM::t2EORrr: NewUseOpc = ARM::t2EORri;
break;
3258 unsigned OpIdx = Commute ? 2 : 1;
3260 bool isKill =
UseMI.getOperand(OpIdx).isKill();
3270 UseMI.getOperand(1).setReg(NewReg);
3271 UseMI.getOperand(1).setIsKill();
3272 UseMI.getOperand(2).ChangeToImmediate(SOImmValV2);
3273 DefMI.eraseFromParent();
3280 case ARM::t2ADDspImm:
3281 case ARM::t2SUBspImm:
3291 switch (
MI.getOpcode()) {
3295 assert(UOps >= 0 &&
"bad # UOps");
3303 unsigned ShOpVal =
MI.getOperand(3).getImm();
3308 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3316 if (!
MI.getOperand(2).getReg())
3319 unsigned ShOpVal =
MI.getOperand(3).getImm();
3324 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3334 case ARM::LDRSB_POST:
3335 case ARM::LDRSH_POST: {
3338 return (Rt == Rm) ? 4 : 3;
3341 case ARM::LDR_PRE_REG:
3342 case ARM::LDRB_PRE_REG: {
3347 unsigned ShOpVal =
MI.getOperand(4).getImm();
3352 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3358 case ARM::STR_PRE_REG:
3359 case ARM::STRB_PRE_REG: {
3360 unsigned ShOpVal =
MI.getOperand(4).getImm();
3365 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3372 case ARM::STRH_PRE: {
3382 case ARM::LDR_POST_REG:
3383 case ARM::LDRB_POST_REG:
3384 case ARM::LDRH_POST: {
3387 return (Rt == Rm) ? 3 : 2;
3390 case ARM::LDR_PRE_IMM:
3391 case ARM::LDRB_PRE_IMM:
3392 case ARM::LDR_POST_IMM:
3393 case ARM::LDRB_POST_IMM:
3394 case ARM::STRB_POST_IMM:
3395 case ARM::STRB_POST_REG:
3396 case ARM::STRB_PRE_IMM:
3397 case ARM::STRH_POST:
3398 case ARM::STR_POST_IMM:
3399 case ARM::STR_POST_REG:
3400 case ARM::STR_PRE_IMM:
3403 case ARM::LDRSB_PRE:
3404 case ARM::LDRSH_PRE: {
3411 unsigned ShOpVal =
MI.getOperand(4).getImm();
3416 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3429 return (Rt == Rn) ? 3 : 2;
3440 case ARM::LDRD_POST:
3441 case ARM::t2LDRD_POST:
3444 case ARM::STRD_POST:
3445 case ARM::t2STRD_POST:
3448 case ARM::LDRD_PRE: {
3455 return (Rt == Rn) ? 4 : 3;
3458 case ARM::t2LDRD_PRE: {
3461 return (Rt == Rn) ? 4 : 3;
3464 case ARM::STRD_PRE: {
3472 case ARM::t2STRD_PRE:
3475 case ARM::t2LDR_POST:
3476 case ARM::t2LDRB_POST:
3477 case ARM::t2LDRB_PRE:
3478 case ARM::t2LDRSBi12:
3479 case ARM::t2LDRSBi8:
3480 case ARM::t2LDRSBpci:
3482 case ARM::t2LDRH_POST:
3483 case ARM::t2LDRH_PRE:
3485 case ARM::t2LDRSB_POST:
3486 case ARM::t2LDRSB_PRE:
3487 case ARM::t2LDRSH_POST:
3488 case ARM::t2LDRSH_PRE:
3489 case ARM::t2LDRSHi12:
3490 case ARM::t2LDRSHi8:
3491 case ARM::t2LDRSHpci:
3495 case ARM::t2LDRDi8: {
3498 return (Rt == Rn) ? 3 : 2;
3501 case ARM::t2STRB_POST:
3502 case ARM::t2STRB_PRE:
3505 case ARM::t2STRH_POST:
3506 case ARM::t2STRH_PRE:
3508 case ARM::t2STR_POST:
3509 case ARM::t2STR_PRE:
3540 E =
MI.memoperands_end();
3542 Size += (*I)->getSize().getValue();
3549 return std::min(
Size / 4, 16U);
3554 unsigned UOps = 1 + NumRegs;
3558 case ARM::VLDMDIA_UPD:
3559 case ARM::VLDMDDB_UPD:
3560 case ARM::VLDMSIA_UPD:
3561 case ARM::VLDMSDB_UPD:
3562 case ARM::VSTMDIA_UPD:
3563 case ARM::VSTMDDB_UPD:
3564 case ARM::VSTMSIA_UPD:
3565 case ARM::VSTMSDB_UPD:
3566 case ARM::LDMIA_UPD:
3567 case ARM::LDMDA_UPD:
3568 case ARM::LDMDB_UPD:
3569 case ARM::LDMIB_UPD:
3570 case ARM::STMIA_UPD:
3571 case ARM::STMDA_UPD:
3572 case ARM::STMDB_UPD:
3573 case ARM::STMIB_UPD:
3574 case ARM::tLDMIA_UPD:
3575 case ARM::tSTMIA_UPD:
3576 case ARM::t2LDMIA_UPD:
3577 case ARM::t2LDMDB_UPD:
3578 case ARM::t2STMIA_UPD:
3579 case ARM::t2STMDB_UPD:
3582 case ARM::LDMIA_RET:
3584 case ARM::t2LDMIA_RET:
3593 if (!ItinData || ItinData->
isEmpty())
3597 unsigned Class =
Desc.getSchedClass();
3599 if (ItinUOps >= 0) {
3600 if (Subtarget.isSwift() && (
Desc.mayLoad() ||
Desc.mayStore()))
3606 unsigned Opc =
MI.getOpcode();
3625 case ARM::VLDMDIA_UPD:
3626 case ARM::VLDMDDB_UPD:
3628 case ARM::VLDMSIA_UPD:
3629 case ARM::VLDMSDB_UPD:
3631 case ARM::VSTMDIA_UPD:
3632 case ARM::VSTMDDB_UPD:
3634 case ARM::VSTMSIA_UPD:
3635 case ARM::VSTMSDB_UPD: {
3636 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands();
3637 return (NumRegs / 2) + (NumRegs % 2) + 1;
3640 case ARM::LDMIA_RET:
3645 case ARM::LDMIA_UPD:
3646 case ARM::LDMDA_UPD:
3647 case ARM::LDMDB_UPD:
3648 case ARM::LDMIB_UPD:
3653 case ARM::STMIA_UPD:
3654 case ARM::STMDA_UPD:
3655 case ARM::STMDB_UPD:
3656 case ARM::STMIB_UPD:
3658 case ARM::tLDMIA_UPD:
3659 case ARM::tSTMIA_UPD:
3663 case ARM::t2LDMIA_RET:
3666 case ARM::t2LDMIA_UPD:
3667 case ARM::t2LDMDB_UPD:
3670 case ARM::t2STMIA_UPD:
3671 case ARM::t2STMDB_UPD: {
3672 unsigned NumRegs =
MI.getNumOperands() -
Desc.getNumOperands() + 1;
3673 switch (Subtarget.getLdStMultipleTiming()) {
3684 unsigned UOps = (NumRegs / 2);
3690 unsigned UOps = (NumRegs / 2);
3693 if ((NumRegs % 2) || !
MI.hasOneMemOperand() ||
3694 (*
MI.memoperands_begin())->getAlign() <
Align(8))
3704std::optional<unsigned>
3707 unsigned DefIdx,
unsigned DefAlign)
const {
3716 DefCycle = RegNo / 2 + 1;
3721 bool isSLoad =
false;
3726 case ARM::VLDMSIA_UPD:
3727 case ARM::VLDMSDB_UPD:
3734 if ((isSLoad && (RegNo % 2)) || DefAlign < 8)
3738 DefCycle = RegNo + 2;
3744std::optional<unsigned>
3747 unsigned DefIdx,
unsigned DefAlign)
const {
3754 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3757 DefCycle = RegNo / 2;
3762 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3763 DefCycle = (RegNo / 2);
3766 if ((RegNo % 2) || DefAlign < 8)
3772 DefCycle = RegNo + 2;
3778std::optional<unsigned>
3781 unsigned UseIdx,
unsigned UseAlign)
const {
3787 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3789 UseCycle = RegNo / 2 + 1;
3792 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3794 bool isSStore =
false;
3799 case ARM::VSTMSIA_UPD:
3800 case ARM::VSTMSDB_UPD:
3807 if ((isSStore && (RegNo % 2)) || UseAlign < 8)
3811 UseCycle = RegNo + 2;
3817std::optional<unsigned>
3820 unsigned UseIdx,
unsigned UseAlign)
const {
3826 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3827 UseCycle = RegNo / 2;
3832 }
else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3833 UseCycle = (RegNo / 2);
3836 if ((RegNo % 2) || UseAlign < 8)
3847 unsigned DefIdx,
unsigned DefAlign,
const MCInstrDesc &UseMCID,
3848 unsigned UseIdx,
unsigned UseAlign)
const {
3858 std::optional<unsigned> DefCycle;
3859 bool LdmBypass =
false;
3866 case ARM::VLDMDIA_UPD:
3867 case ARM::VLDMDDB_UPD:
3869 case ARM::VLDMSIA_UPD:
3870 case ARM::VLDMSDB_UPD:
3871 DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3874 case ARM::LDMIA_RET:
3879 case ARM::LDMIA_UPD:
3880 case ARM::LDMDA_UPD:
3881 case ARM::LDMDB_UPD:
3882 case ARM::LDMIB_UPD:
3884 case ARM::tLDMIA_UPD:
3886 case ARM::t2LDMIA_RET:
3889 case ARM::t2LDMIA_UPD:
3890 case ARM::t2LDMDB_UPD:
3892 DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3900 std::optional<unsigned> UseCycle;
3907 case ARM::VSTMDIA_UPD:
3908 case ARM::VSTMDDB_UPD:
3910 case ARM::VSTMSIA_UPD:
3911 case ARM::VSTMSDB_UPD:
3912 UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3919 case ARM::STMIA_UPD:
3920 case ARM::STMDA_UPD:
3921 case ARM::STMDB_UPD:
3922 case ARM::STMIB_UPD:
3923 case ARM::tSTMIA_UPD:
3928 case ARM::t2STMIA_UPD:
3929 case ARM::t2STMDB_UPD:
3930 UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3938 if (UseCycle > *DefCycle + 1)
3939 return std::nullopt;
3941 UseCycle = *DefCycle - *UseCycle + 1;
3942 if (UseCycle > 0u) {
3948 UseCycle = *UseCycle - 1;
3950 UseClass, UseIdx)) {
3951 UseCycle = *UseCycle - 1;
3960 unsigned &DefIdx,
unsigned &Dist) {
3965 assert(
II->isInsideBundle() &&
"Empty bundle?");
3968 while (
II->isInsideBundle()) {
3969 Idx =
II->findRegisterDefOperandIdx(
Reg,
TRI,
false,
true);
3976 assert(Idx != -1 &&
"Cannot find bundled definition!");
3983 unsigned &UseIdx,
unsigned &Dist) {
3987 assert(
II->isInsideBundle() &&
"Empty bundle?");
3992 while (
II !=
E &&
II->isInsideBundle()) {
3993 Idx =
II->findRegisterUseOperandIdx(
Reg,
TRI,
false);
3996 if (
II->getOpcode() != ARM::t2IT)
4024 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4034 case ARM::t2LDRSHs: {
4036 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4037 if (ShAmt == 0 || ShAmt == 2)
4042 }
else if (Subtarget.
isSwift()) {
4049 unsigned ShOpVal =
DefMI.getOperand(3).getImm();
4054 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4065 case ARM::t2LDRSHs: {
4067 unsigned ShAmt =
DefMI.getOperand(3).getImm();
4068 if (ShAmt == 0 || ShAmt == 1 || ShAmt == 2 || ShAmt == 3)
4075 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment()) {
4082 case ARM::VLD1q8wb_fixed:
4083 case ARM::VLD1q16wb_fixed:
4084 case ARM::VLD1q32wb_fixed:
4085 case ARM::VLD1q64wb_fixed:
4086 case ARM::VLD1q8wb_register:
4087 case ARM::VLD1q16wb_register:
4088 case ARM::VLD1q32wb_register:
4089 case ARM::VLD1q64wb_register:
4096 case ARM::VLD2d8wb_fixed:
4097 case ARM::VLD2d16wb_fixed:
4098 case ARM::VLD2d32wb_fixed:
4099 case ARM::VLD2q8wb_fixed:
4100 case ARM::VLD2q16wb_fixed:
4101 case ARM::VLD2q32wb_fixed:
4102 case ARM::VLD2d8wb_register:
4103 case ARM::VLD2d16wb_register:
4104 case ARM::VLD2d32wb_register:
4105 case ARM::VLD2q8wb_register:
4106 case ARM::VLD2q16wb_register:
4107 case ARM::VLD2q32wb_register:
4112 case ARM::VLD3d8_UPD:
4113 case ARM::VLD3d16_UPD:
4114 case ARM::VLD3d32_UPD:
4115 case ARM::VLD1d64Twb_fixed:
4116 case ARM::VLD1d64Twb_register:
4117 case ARM::VLD3q8_UPD:
4118 case ARM::VLD3q16_UPD:
4119 case ARM::VLD3q32_UPD:
4124 case ARM::VLD4d8_UPD:
4125 case ARM::VLD4d16_UPD:
4126 case ARM::VLD4d32_UPD:
4127 case ARM::VLD1d64Qwb_fixed:
4128 case ARM::VLD1d64Qwb_register:
4129 case ARM::VLD4q8_UPD:
4130 case ARM::VLD4q16_UPD:
4131 case ARM::VLD4q32_UPD:
4132 case ARM::VLD1DUPq8:
4133 case ARM::VLD1DUPq16:
4134 case ARM::VLD1DUPq32:
4135 case ARM::VLD1DUPq8wb_fixed:
4136 case ARM::VLD1DUPq16wb_fixed:
4137 case ARM::VLD1DUPq32wb_fixed:
4138 case ARM::VLD1DUPq8wb_register:
4139 case ARM::VLD1DUPq16wb_register:
4140 case ARM::VLD1DUPq32wb_register:
4141 case ARM::VLD2DUPd8:
4142 case ARM::VLD2DUPd16:
4143 case ARM::VLD2DUPd32:
4144 case ARM::VLD2DUPd8wb_fixed:
4145 case ARM::VLD2DUPd16wb_fixed:
4146 case ARM::VLD2DUPd32wb_fixed:
4147 case ARM::VLD2DUPd8wb_register:
4148 case ARM::VLD2DUPd16wb_register:
4149 case ARM::VLD2DUPd32wb_register:
4150 case ARM::VLD4DUPd8:
4151 case ARM::VLD4DUPd16:
4152 case ARM::VLD4DUPd32:
4153 case ARM::VLD4DUPd8_UPD:
4154 case ARM::VLD4DUPd16_UPD:
4155 case ARM::VLD4DUPd32_UPD:
4157 case ARM::VLD1LNd16:
4158 case ARM::VLD1LNd32:
4159 case ARM::VLD1LNd8_UPD:
4160 case ARM::VLD1LNd16_UPD:
4161 case ARM::VLD1LNd32_UPD:
4163 case ARM::VLD2LNd16:
4164 case ARM::VLD2LNd32:
4165 case ARM::VLD2LNq16:
4166 case ARM::VLD2LNq32:
4167 case ARM::VLD2LNd8_UPD:
4168 case ARM::VLD2LNd16_UPD:
4169 case ARM::VLD2LNd32_UPD:
4170 case ARM::VLD2LNq16_UPD:
4171 case ARM::VLD2LNq32_UPD:
4173 case ARM::VLD4LNd16:
4174 case ARM::VLD4LNd32:
4175 case ARM::VLD4LNq16:
4176 case ARM::VLD4LNq32:
4177 case ARM::VLD4LNd8_UPD:
4178 case ARM::VLD4LNd16_UPD:
4179 case ARM::VLD4LNd32_UPD:
4180 case ARM::VLD4LNq16_UPD:
4181 case ARM::VLD4LNq32_UPD:
4195 if (!ItinData || ItinData->
isEmpty())
4196 return std::nullopt;
4202 unsigned DefAdj = 0;
4203 if (
DefMI.isBundle())
4212 unsigned UseAdj = 0;
4213 if (
UseMI.isBundle()) {
4217 return std::nullopt;
4220 return getOperandLatencyImpl(
4221 ItinData, *ResolvedDefMI, DefIdx, ResolvedDefMI->
getDesc(), DefAdj, DefMO,
4222 Reg, *ResolvedUseMI, UseIdx, ResolvedUseMI->
getDesc(), UseAdj);
4225std::optional<unsigned> ARMBaseInstrInfo::getOperandLatencyImpl(
4227 unsigned DefIdx,
const MCInstrDesc &DefMCID,
unsigned DefAdj,
4229 unsigned UseIdx,
const MCInstrDesc &UseMCID,
unsigned UseAdj)
const {
4230 if (Reg == ARM::CPSR) {
4231 if (
DefMI.getOpcode() == ARM::FMSTAT) {
4233 return Subtarget.
isLikeA9() ? 1 : 20;
4237 if (
UseMI.isBranch())
4256 return std::nullopt;
4258 unsigned DefAlign =
DefMI.hasOneMemOperand()
4259 ? (*
DefMI.memoperands_begin())->getAlign().value()
4261 unsigned UseAlign =
UseMI.hasOneMemOperand()
4262 ? (*
UseMI.memoperands_begin())->getAlign().value()
4267 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4270 return std::nullopt;
4273 int Adj = DefAdj + UseAdj;
4277 if (Adj >= 0 || (
int)*
Latency > -Adj) {
4284std::optional<unsigned>
4286 SDNode *DefNode,
unsigned DefIdx,
4287 SDNode *UseNode,
unsigned UseIdx)
const {
4293 if (isZeroCost(DefMCID.
Opcode))
4296 if (!ItinData || ItinData->
isEmpty())
4297 return DefMCID.
mayLoad() ? 3 : 1;
4300 std::optional<unsigned>
Latency =
4302 int Adj = Subtarget.getPreISelOperandLatencyAdjustment();
4303 int Threshold = 1 + Adj;
4309 unsigned DefAlign = !DefMN->memoperands_empty()
4310 ? (*DefMN->memoperands_begin())->getAlign().value()
4313 unsigned UseAlign = !UseMN->memoperands_empty()
4314 ? (*UseMN->memoperands_begin())->getAlign().value()
4317 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4319 return std::nullopt;
4322 (Subtarget.isCortexA8() || Subtarget.isLikeA9() ||
4323 Subtarget.isCortexA7())) {
4340 case ARM::t2LDRSHs: {
4343 if (ShAmt == 0 || ShAmt == 2)
4348 }
else if (DefIdx == 0 &&
Latency > 2U && Subtarget.isSwift()) {
4358 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4375 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment())
4382 case ARM::VLD1q8wb_register:
4383 case ARM::VLD1q16wb_register:
4384 case ARM::VLD1q32wb_register:
4385 case ARM::VLD1q64wb_register:
4386 case ARM::VLD1q8wb_fixed:
4387 case ARM::VLD1q16wb_fixed:
4388 case ARM::VLD1q32wb_fixed:
4389 case ARM::VLD1q64wb_fixed:
4393 case ARM::VLD2q8Pseudo:
4394 case ARM::VLD2q16Pseudo:
4395 case ARM::VLD2q32Pseudo:
4396 case ARM::VLD2d8wb_fixed:
4397 case ARM::VLD2d16wb_fixed:
4398 case ARM::VLD2d32wb_fixed:
4399 case ARM::VLD2q8PseudoWB_fixed:
4400 case ARM::VLD2q16PseudoWB_fixed:
4401 case ARM::VLD2q32PseudoWB_fixed:
4402 case ARM::VLD2d8wb_register:
4403 case ARM::VLD2d16wb_register:
4404 case ARM::VLD2d32wb_register:
4405 case ARM::VLD2q8PseudoWB_register:
4406 case ARM::VLD2q16PseudoWB_register:
4407 case ARM::VLD2q32PseudoWB_register:
4408 case ARM::VLD3d8Pseudo:
4409 case ARM::VLD3d16Pseudo:
4410 case ARM::VLD3d32Pseudo:
4411 case ARM::VLD1d8TPseudo:
4412 case ARM::VLD1d16TPseudo:
4413 case ARM::VLD1d32TPseudo:
4414 case ARM::VLD1d64TPseudo:
4415 case ARM::VLD1d64TPseudoWB_fixed:
4416 case ARM::VLD1d64TPseudoWB_register:
4417 case ARM::VLD3d8Pseudo_UPD:
4418 case ARM::VLD3d16Pseudo_UPD:
4419 case ARM::VLD3d32Pseudo_UPD:
4420 case ARM::VLD3q8Pseudo_UPD:
4421 case ARM::VLD3q16Pseudo_UPD:
4422 case ARM::VLD3q32Pseudo_UPD:
4423 case ARM::VLD3q8oddPseudo:
4424 case ARM::VLD3q16oddPseudo:
4425 case ARM::VLD3q32oddPseudo:
4426 case ARM::VLD3q8oddPseudo_UPD:
4427 case ARM::VLD3q16oddPseudo_UPD:
4428 case ARM::VLD3q32oddPseudo_UPD:
4429 case ARM::VLD4d8Pseudo:
4430 case ARM::VLD4d16Pseudo:
4431 case ARM::VLD4d32Pseudo:
4432 case ARM::VLD1d8QPseudo:
4433 case ARM::VLD1d16QPseudo:
4434 case ARM::VLD1d32QPseudo:
4435 case ARM::VLD1d64QPseudo:
4436 case ARM::VLD1d64QPseudoWB_fixed:
4437 case ARM::VLD1d64QPseudoWB_register:
4438 case ARM::VLD1q8HighQPseudo:
4439 case ARM::VLD1q8LowQPseudo_UPD:
4440 case ARM::VLD1q8HighTPseudo:
4441 case ARM::VLD1q8LowTPseudo_UPD:
4442 case ARM::VLD1q16HighQPseudo:
4443 case ARM::VLD1q16LowQPseudo_UPD:
4444 case ARM::VLD1q16HighTPseudo:
4445 case ARM::VLD1q16LowTPseudo_UPD:
4446 case ARM::VLD1q32HighQPseudo:
4447 case ARM::VLD1q32LowQPseudo_UPD:
4448 case ARM::VLD1q32HighTPseudo:
4449 case ARM::VLD1q32LowTPseudo_UPD:
4450 case ARM::VLD1q64HighQPseudo:
4451 case ARM::VLD1q64LowQPseudo_UPD:
4452 case ARM::VLD1q64HighTPseudo:
4453 case ARM::VLD1q64LowTPseudo_UPD:
4454 case ARM::VLD4d8Pseudo_UPD:
4455 case ARM::VLD4d16Pseudo_UPD:
4456 case ARM::VLD4d32Pseudo_UPD:
4457 case ARM::VLD4q8Pseudo_UPD:
4458 case ARM::VLD4q16Pseudo_UPD:
4459 case ARM::VLD4q32Pseudo_UPD:
4460 case ARM::VLD4q8oddPseudo:
4461 case ARM::VLD4q16oddPseudo:
4462 case ARM::VLD4q32oddPseudo:
4463 case ARM::VLD4q8oddPseudo_UPD:
4464 case ARM::VLD4q16oddPseudo_UPD:
4465 case ARM::VLD4q32oddPseudo_UPD:
4466 case ARM::VLD1DUPq8:
4467 case ARM::VLD1DUPq16:
4468 case ARM::VLD1DUPq32:
4469 case ARM::VLD1DUPq8wb_fixed:
4470 case ARM::VLD1DUPq16wb_fixed:
4471 case ARM::VLD1DUPq32wb_fixed:
4472 case ARM::VLD1DUPq8wb_register:
4473 case ARM::VLD1DUPq16wb_register:
4474 case ARM::VLD1DUPq32wb_register:
4475 case ARM::VLD2DUPd8:
4476 case ARM::VLD2DUPd16:
4477 case ARM::VLD2DUPd32:
4478 case ARM::VLD2DUPd8wb_fixed:
4479 case ARM::VLD2DUPd16wb_fixed:
4480 case ARM::VLD2DUPd32wb_fixed:
4481 case ARM::VLD2DUPd8wb_register:
4482 case ARM::VLD2DUPd16wb_register:
4483 case ARM::VLD2DUPd32wb_register:
4484 case ARM::VLD2DUPq8EvenPseudo:
4485 case ARM::VLD2DUPq8OddPseudo:
4486 case ARM::VLD2DUPq16EvenPseudo:
4487 case ARM::VLD2DUPq16OddPseudo:
4488 case ARM::VLD2DUPq32EvenPseudo:
4489 case ARM::VLD2DUPq32OddPseudo:
4490 case ARM::VLD3DUPq8EvenPseudo:
4491 case ARM::VLD3DUPq8OddPseudo:
4492 case ARM::VLD3DUPq16EvenPseudo:
4493 case ARM::VLD3DUPq16OddPseudo:
4494 case ARM::VLD3DUPq32EvenPseudo:
4495 case ARM::VLD3DUPq32OddPseudo:
4496 case ARM::VLD4DUPd8Pseudo:
4497 case ARM::VLD4DUPd16Pseudo:
4498 case ARM::VLD4DUPd32Pseudo:
4499 case ARM::VLD4DUPd8Pseudo_UPD:
4500 case ARM::VLD4DUPd16Pseudo_UPD:
4501 case ARM::VLD4DUPd32Pseudo_UPD:
4502 case ARM::VLD4DUPq8EvenPseudo:
4503 case ARM::VLD4DUPq8OddPseudo:
4504 case ARM::VLD4DUPq16EvenPseudo:
4505 case ARM::VLD4DUPq16OddPseudo:
4506 case ARM::VLD4DUPq32EvenPseudo:
4507 case ARM::VLD4DUPq32OddPseudo:
4508 case ARM::VLD1LNq8Pseudo:
4509 case ARM::VLD1LNq16Pseudo:
4510 case ARM::VLD1LNq32Pseudo:
4511 case ARM::VLD1LNq8Pseudo_UPD:
4512 case ARM::VLD1LNq16Pseudo_UPD:
4513 case ARM::VLD1LNq32Pseudo_UPD:
4514 case ARM::VLD2LNd8Pseudo:
4515 case ARM::VLD2LNd16Pseudo:
4516 case ARM::VLD2LNd32Pseudo:
4517 case ARM::VLD2LNq16Pseudo:
4518 case ARM::VLD2LNq32Pseudo:
4519 case ARM::VLD2LNd8Pseudo_UPD:
4520 case ARM::VLD2LNd16Pseudo_UPD:
4521 case ARM::VLD2LNd32Pseudo_UPD:
4522 case ARM::VLD2LNq16Pseudo_UPD:
4523 case ARM::VLD2LNq32Pseudo_UPD:
4524 case ARM::VLD4LNd8Pseudo:
4525 case ARM::VLD4LNd16Pseudo:
4526 case ARM::VLD4LNd32Pseudo:
4527 case ARM::VLD4LNq16Pseudo:
4528 case ARM::VLD4LNq32Pseudo:
4529 case ARM::VLD4LNd8Pseudo_UPD:
4530 case ARM::VLD4LNd16Pseudo_UPD:
4531 case ARM::VLD4LNd32Pseudo_UPD:
4532 case ARM::VLD4LNq16Pseudo_UPD:
4533 case ARM::VLD4LNq32Pseudo_UPD:
4543unsigned ARMBaseInstrInfo::getPredicationCost(
const MachineInstr &
MI)
const {
4544 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4553 if (
MCID.isCall() || (
MCID.hasImplicitDefOfPhysReg(ARM::CPSR) &&
4554 !Subtarget.cheapPredicableCPSRDef())) {
4564 unsigned *PredCost)
const {
4565 if (
MI.isCopyLike() ||
MI.isInsertSubreg() ||
MI.isRegSequence() ||
4571 if (
MI.isBundle()) {
4575 while (++
I !=
E &&
I->isInsideBundle()) {
4576 if (
I->getOpcode() != ARM::t2IT)
4577 Latency += getInstrLatency(ItinData, *
I, PredCost);
4582 const MCInstrDesc &MCID =
MI.getDesc();
4584 !Subtarget.cheapPredicableCPSRDef()))) {
4605 MI.hasOneMemOperand() ? (*
MI.memoperands_begin())->getAlign().value() : 0;
4607 if (Adj >= 0 || (
int)
Latency > -Adj) {
4615 if (!
Node->isMachineOpcode())
4618 if (!ItinData || ItinData->
isEmpty())
4621 unsigned Opcode =
Node->getMachineOpcode();
4631bool ARMBaseInstrInfo::hasHighOperandLatency(
const TargetSchedModel &SchedModel,
4636 unsigned UseIdx)
const {
4639 if (Subtarget.nonpipelinedVFP() &&
4654 unsigned DefIdx)
const {
4656 if (!ItinData || ItinData->
isEmpty())
4661 unsigned DefClass =
DefMI.getDesc().getSchedClass();
4662 std::optional<unsigned> DefCycle =
4664 return DefCycle && DefCycle <= 2U;
4672 ErrInfo =
"Pseudo flag setting opcodes only exist in Selection DAG";
4675 if (
MI.getOpcode() == ARM::tMOVr && !Subtarget.hasV6Ops()) {
4677 if (!ARM::hGPRRegClass.
contains(
MI.getOperand(0).getReg()) &&
4678 !ARM::hGPRRegClass.contains(
MI.getOperand(1).getReg())) {
4679 ErrInfo =
"Non-flag-setting Thumb1 mov is v6-only";
4683 if (
MI.getOpcode() == ARM::tPUSH ||
4684 MI.getOpcode() == ARM::tPOP ||
4685 MI.getOpcode() == ARM::tPOP_RET) {
4687 if (MO.isImplicit() || !MO.isReg())
4691 if (!(
MI.getOpcode() == ARM::tPUSH &&
Reg == ARM::LR) &&
4692 !(
MI.getOpcode() == ARM::tPOP_RET &&
Reg == ARM::PC)) {
4693 ErrInfo =
"Unsupported register in Thumb1 push/pop";
4699 if (
MI.getOpcode() == ARM::MVE_VMOV_q_rr) {
4700 assert(
MI.getOperand(4).isImm() &&
MI.getOperand(5).isImm());
4701 if ((
MI.getOperand(4).getImm() != 2 &&
MI.getOperand(4).getImm() != 3) ||
4702 MI.getOperand(4).getImm() !=
MI.getOperand(5).getImm() + 2) {
4703 ErrInfo =
"Incorrect array index for MVE_VMOV_q_rr";
4724 for (
auto Op :
MI.operands()) {
4731 ErrInfo =
"Incorrect AddrMode Imm for instruction";
4741 unsigned LoadImmOpc,
4742 unsigned LoadOpc)
const {
4743 assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&
4744 "ROPI/RWPI not currently supported with stack guard");
4752 if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) {
4753 assert(!Subtarget.isReadTPSoft() &&
4754 "TLS stack protector requires hardware TLS register");
4764 Module &M = *
MBB.getParent()->getFunction().getParent();
4765 Offset = M.getStackProtectorGuardOffset();
4770 unsigned AddOpc = (LoadImmOpc == ARM::MRC) ? ARM::ADDri : ARM::t2ADDri;
4781 bool IsIndirect = Subtarget.isGVIndirectSymbol(GV);
4784 if (Subtarget.isTargetMachO()) {
4786 }
else if (Subtarget.isTargetCOFF()) {
4789 else if (IsIndirect)
4791 }
else if (IsIndirect) {
4795 if (LoadImmOpc == ARM::tMOVi32imm) {
4798 ARMSysReg::lookupMClassSysRegByName(
"apsr_nzcvq")->Encoding;
4834 unsigned &AddSubOpc,
4835 bool &NegAcc,
bool &HasLane)
const {
4836 auto I = MLxEntryMap.find(Opcode);
4837 if (
I == MLxEntryMap.end())
4841 MulOpc = Entry.MulOpc;
4842 AddSubOpc = Entry.AddSubOpc;
4843 NegAcc = Entry.NegAcc;
4844 HasLane = Entry.HasLane;
4868std::pair<uint16_t, uint16_t>
4872 if (Subtarget.hasNEON()) {
4881 (
MI.getOpcode() == ARM::VMOVRS ||
MI.getOpcode() == ARM::VMOVSR ||
4882 MI.getOpcode() == ARM::VMOVS))
4889 return std::make_pair(
ExeNEON, 0);
4894 return std::make_pair(
ExeNEON, 0);
4897 return std::make_pair(
ExeVFP, 0);
4903 unsigned SReg,
unsigned &Lane) {
4905 TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);
4912 DReg =
TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
4914 assert(DReg &&
"S-register with no D super-register?");
4939 if (
MI.definesRegister(DReg,
TRI) ||
MI.readsRegister(DReg,
TRI)) {
4945 ImplicitSReg =
TRI->getSubReg(DReg,
4946 (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
4948 MI.getParent()->computeRegisterLiveness(
TRI, ImplicitSReg,
MI);
4963 unsigned DstReg, SrcReg;
4968 switch (
MI.getOpcode()) {
4980 assert(Subtarget.hasNEON() &&
"VORRd requires NEON");
4983 DstReg =
MI.getOperand(0).getReg();
4984 SrcReg =
MI.getOperand(1).getReg();
4986 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
4987 MI.removeOperand(i - 1);
4990 MI.setDesc(
get(ARM::VORRd));
5002 DstReg =
MI.getOperand(0).getReg();
5003 SrcReg =
MI.getOperand(1).getReg();
5005 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5006 MI.removeOperand(i - 1);
5013 MI.setDesc(
get(ARM::VGETLNi32));
5029 DstReg =
MI.getOperand(0).getReg();
5030 SrcReg =
MI.getOperand(1).getReg();
5038 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5039 MI.removeOperand(i - 1);
5043 MI.setDesc(
get(ARM::VSETLNi32));
5062 DstReg =
MI.getOperand(0).getReg();
5063 SrcReg =
MI.getOperand(1).getReg();
5065 unsigned DstLane = 0, SrcLane = 0;
5074 for (
unsigned i =
MI.getDesc().getNumOperands(); i; --i)
5075 MI.removeOperand(i - 1);
5080 MI.setDesc(
get(ARM::VDUPLN32d));
5114 MCRegister CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;
5115 bool CurUndef = !
MI.readsRegister(CurReg,
TRI);
5118 CurReg = SrcLane == 0 && DstLane == 0 ? DSrc : DDst;
5119 CurUndef = !
MI.readsRegister(CurReg,
TRI);
5124 if (SrcLane == DstLane)
5127 MI.setDesc(
get(ARM::VEXTd32));
5132 CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;
5133 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5136 CurReg = SrcLane == 0 && DstLane == 1 ? DSrc : DDst;
5137 CurUndef = CurReg == DSrc && !
MI.readsRegister(CurReg,
TRI);
5142 if (SrcLane != DstLane)
5148 if (ImplicitSReg != 0)
5174 auto PartialUpdateClearance = Subtarget.getPartialUpdateClearance();
5175 if (!PartialUpdateClearance)
5186 switch (
MI.getOpcode()) {
5192 case ARM::VMOVv4i16:
5193 case ARM::VMOVv2i32:
5194 case ARM::VMOVv2f32:
5195 case ARM::VMOVv1i64:
5196 UseOp =
MI.findRegisterUseOperandIdx(Reg,
TRI,
false);
5200 case ARM::VLD1LNd32:
5209 if (UseOp != -1 &&
MI.getOperand(UseOp).readsReg())
5213 if (Reg.isVirtual()) {
5215 if (!MO.
getSubReg() ||
MI.readsVirtualRegister(Reg))
5217 }
else if (ARM::SPRRegClass.
contains(Reg)) {
5220 TRI->getMatchingSuperReg(Reg, ARM::ssub_0, &ARM::DPRRegClass);
5221 if (!DReg || !
MI.definesRegister(DReg,
TRI))
5227 return PartialUpdateClearance;
5234 assert(OpNum <
MI.getDesc().getNumDefs() &&
"OpNum is not a def");
5239 assert(Reg.isPhysical() &&
"Can't break virtual register dependencies.");
5240 unsigned DReg = Reg;
5243 if (ARM::SPRRegClass.
contains(Reg)) {
5244 DReg = ARM::D0 + (Reg - ARM::S0) / 2;
5245 assert(
TRI->isSuperRegister(Reg, DReg) &&
"Register enums broken");
5248 assert(ARM::DPRRegClass.
contains(DReg) &&
"Can only break D-reg deps");
5249 assert(
MI.definesRegister(DReg,
TRI) &&
"MI doesn't clobber full D-reg");
5262 MI.addRegisterKilled(DReg,
TRI,
true);
5266 return Subtarget.hasFeature(ARM::HasV6KOps);
5270 if (
MI->getNumOperands() < 4)
5272 unsigned ShOpVal =
MI->getOperand(3).getImm();
5276 ((ShImm == 1 || ShImm == 2) &&
5286 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5287 assert(
MI.isRegSequenceLike() &&
"Invalid kind of instruction");
5289 switch (
MI.getOpcode()) {
5301 MOReg = &
MI.getOperand(2);
5313 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5314 assert(
MI.isExtractSubregLike() &&
"Invalid kind of instruction");
5316 switch (
MI.getOpcode()) {
5327 InputReg.
SubIdx = DefIdx == 0 ? ARM::ssub_0 : ARM::ssub_1;
5336 assert(DefIdx <
MI.getDesc().getNumDefs() &&
"Invalid definition index");
5337 assert(
MI.isInsertSubregLike() &&
"Invalid kind of instruction");
5339 switch (
MI.getOpcode()) {
5340 case ARM::VSETLNi32:
5341 case ARM::MVE_VMOV_to_lane_32:
5349 BaseReg.Reg = MOBaseReg.
getReg();
5352 InsertedReg.
Reg = MOInsertedReg.
getReg();
5360std::pair<unsigned, unsigned>
5363 return std::make_pair(TF & Mask, TF & ~Mask);
5368 using namespace ARMII;
5370 static const std::pair<unsigned, const char *> TargetFlags[] = {
5371 {MO_LO16,
"arm-lo16"}, {MO_HI16,
"arm-hi16"},
5372 {MO_LO_0_7,
"arm-lo-0-7"}, {MO_HI_0_7,
"arm-hi-0-7"},
5373 {MO_LO_8_15,
"arm-lo-8-15"}, {MO_HI_8_15,
"arm-hi-8-15"},
5380 using namespace ARMII;
5382 static const std::pair<unsigned, const char *> TargetFlags[] = {
5383 {MO_COFFSTUB,
"arm-coffstub"},
5384 {MO_GOT,
"arm-got"},
5385 {MO_SBREL,
"arm-sbrel"},
5386 {MO_DLLIMPORT,
"arm-dllimport"},
5387 {MO_SECREL,
"arm-secrel"},
5388 {MO_NONLAZY,
"arm-nonlazy"}};
5392std::optional<RegImmPair>
5395 unsigned Opcode =
MI.getOpcode();
5402 return std::nullopt;
5405 if (Opcode == ARM::SUBri)
5407 else if (Opcode != ARM::ADDri)
5408 return std::nullopt;
5413 if (!
MI.getOperand(1).isReg() || !
MI.getOperand(2).isImm())
5414 return std::nullopt;
5416 Offset =
MI.getOperand(2).getImm() * Sign;
5424 for (
auto I = From;
I != To; ++
I)
5425 if (
I->modifiesRegister(Reg,
TRI))
5438 if (CmpMI->modifiesRegister(ARM::CPSR,
TRI))
5440 if (CmpMI->readsRegister(ARM::CPSR,
TRI))
5446 if (CmpMI->getOpcode() != ARM::tCMPi8 && CmpMI->getOpcode() != ARM::t2CMPri)
5448 Register Reg = CmpMI->getOperand(0).getReg();
5451 if (Pred !=
ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)
5464 if (Subtarget->isThumb()) {
5466 return ForCodesize ? 2 : 1;
5467 if (Subtarget->hasV6T2Ops() && (Val <= 0xffff ||
5470 return ForCodesize ? 4 : 1;
5472 return ForCodesize ? 4 : 2;
5474 return ForCodesize ? 4 : 2;
5476 return ForCodesize ? 4 : 2;
5479 return ForCodesize ? 4 : 1;
5481 return ForCodesize ? 4 : 1;
5482 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)
5483 return ForCodesize ? 4 : 1;
5485 return ForCodesize ? 8 : 2;
5487 return ForCodesize ? 8 : 2;
5490 return ForCodesize ? 8 : 2;
5491 return ForCodesize ? 8 : 3;
5657 const ARMBaseRegisterInfo *ARI =
5658 static_cast<const ARMBaseRegisterInfo *
>(&
TRI);
5667 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
5668 C.isAvailableInsideSeq(
Reg,
TRI))
5682 for (;
I !=
E; ++
I) {
5686 if (
MI.modifiesRegister(ARM::LR, &
TRI))
5690 unsigned Opcode =
MI.getOpcode();
5691 if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR ||
5692 Opcode == ARM::SUBS_PC_LR || Opcode == ARM::tBX_RET ||
5693 Opcode == ARM::tBXNS_RET || Opcode == ARM::t2BXAUT_RET) {
5699 if (
MI.readsRegister(ARM::LR, &
TRI))
5708 auto Opcode =
MI.getOpcode();
5709 return (Opcode == ARM::BL || Opcode == ARM::BLX || Opcode == ARM::BLX_noip ||
5710 Opcode == ARM::tBL || Opcode == ARM::tBLXi || Opcode == ARM::tBLXr ||
5711 Opcode == ARM::tBLXr_noip);
5714std::optional<std::unique_ptr<outliner::OutlinedFunction>>
5717 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
5718 unsigned MinRepeats)
const {
5719 unsigned SequenceSize = 0;
5720 for (
auto &
MI : RepeatedSequenceLocs[0])
5724 unsigned FlagsSetInAll = 0xF;
5729 FlagsSetInAll &=
C.Flags;
5748 return C.isAnyUnavailableAcrossOrOutOfSeq({ARM::R12, ARM::CPSR},
TRI);
5756 llvm::erase_if(RepeatedSequenceLocs, CantGuaranteeValueAcrossCall);
5759 if (RepeatedSequenceLocs.size() < MinRepeats)
5760 return std::nullopt;
5779 if (std::distance(RepeatedSequenceLocs.begin(), NoBTI) >
5780 std::distance(NoBTI, RepeatedSequenceLocs.end()))
5781 RepeatedSequenceLocs.erase(NoBTI, RepeatedSequenceLocs.end());
5783 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoBTI);
5785 if (RepeatedSequenceLocs.size() < MinRepeats)
5786 return std::nullopt;
5796 if (std::distance(RepeatedSequenceLocs.begin(), NoPAC) >
5797 std::distance(NoPAC, RepeatedSequenceLocs.end()))
5798 RepeatedSequenceLocs.erase(NoPAC, RepeatedSequenceLocs.end());
5800 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoPAC);
5802 if (RepeatedSequenceLocs.size() < MinRepeats)
5803 return std::nullopt;
5809 auto SetCandidateCallInfo =
5810 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
5812 C.setCallInfo(CallID, NumBytesForCall);
5817 const auto &SomeMFI =
5820 if (SomeMFI.branchTargetEnforcement()) {
5829 if (SomeMFI.shouldSignReturnAddress(
true)) {
5839 if (RepeatedSequenceLocs[0].back().isTerminator()) {
5851 unsigned NumBytesNoStackCalls = 0;
5852 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
5857 const auto Last =
C.getMBB()->rbegin();
5858 const bool LRIsAvailable =
5859 C.getMBB()->isReturnBlock() && !
Last->isCall()
5862 :
C.isAvailableAcrossAndOutOfSeq(ARM::LR,
TRI);
5863 if (LRIsAvailable) {
5867 CandidatesWithoutStackFixups.push_back(
C);
5872 else if (findRegisterToSaveLRTo(
C)) {
5876 CandidatesWithoutStackFixups.push_back(
C);
5881 else if (
C.isAvailableInsideSeq(ARM::SP,
TRI)) {
5884 CandidatesWithoutStackFixups.push_back(
C);
5890 NumBytesNoStackCalls += SequenceSize;
5896 if (NumBytesNoStackCalls <=
5897 RepeatedSequenceLocs.size() * Costs.
CallDefault) {
5898 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
5900 if (RepeatedSequenceLocs.size() < MinRepeats)
5901 return std::nullopt;
5926 return std::make_unique<outliner::OutlinedFunction>(
5927 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
5930bool ARMBaseInstrInfo::checkAndUpdateStackOffset(
MachineInstr *
MI,
5933 int SPIdx =
MI->findRegisterUseOperandIdx(ARM::SP,
nullptr);
5958 unsigned NumOps =
MI->getDesc().getNumOperands();
5959 unsigned ImmIdx =
NumOps - 3;
5963 int64_t OffVal =
Offset.getImm();
5969 unsigned NumBits = 0;
5998 assert((
Fixup & 3) == 0 &&
"Can't encode this offset!");
6018 assert(((OffVal * Scale +
Fixup) & (Scale - 1)) == 0 &&
6019 "Can't encode this offset!");
6020 OffVal +=
Fixup / Scale;
6022 unsigned Mask = (1 << NumBits) - 1;
6024 if (OffVal <= Mask) {
6026 MI->getOperand(ImmIdx).setImm(OffVal);
6034 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
6038 const Function &CFn =
C.getMF()->getFunction();
6045 ARMGenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
6053 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
6072 unsigned &Flags)
const {
6075 assert(
MBB.getParent()->getRegInfo().tracksLiveness() &&
6076 "Suitable Machine Function for outlining must track liveness");
6084 bool R12AvailableInBlock = LRU.
available(ARM::R12);
6085 bool CPSRAvailableInBlock = LRU.
available(ARM::CPSR);
6089 if (R12AvailableInBlock && CPSRAvailableInBlock)
6097 if (R12AvailableInBlock && !LRU.
available(ARM::R12))
6099 if (CPSRAvailableInBlock && !LRU.
available(ARM::CPSR))
6109 bool LRIsAvailable =
6110 MBB.isReturnBlock() && !
MBB.back().isCall()
6122 unsigned Flags)
const {
6128 unsigned Opc =
MI.getOpcode();
6129 if (
Opc == ARM::tPICADD ||
Opc == ARM::PICADD ||
Opc == ARM::PICSTR ||
6130 Opc == ARM::PICSTRB ||
Opc == ARM::PICSTRH ||
Opc == ARM::PICLDR ||
6131 Opc == ARM::PICLDRB ||
Opc == ARM::PICLDRH ||
Opc == ARM::PICLDRSB ||
6132 Opc == ARM::PICLDRSH ||
Opc == ARM::t2LDRpci_pic ||
6133 Opc == ARM::t2MOVi16_ga_pcrel ||
Opc == ARM::t2MOVTi16_ga_pcrel ||
6134 Opc == ARM::t2MOV_ga_pcrel)
6138 if (
Opc == ARM::t2BF_LabelPseudo ||
Opc == ARM::t2DoLoopStart ||
6139 Opc == ARM::t2DoLoopStartTP ||
Opc == ARM::t2WhileLoopStart ||
6140 Opc == ARM::t2WhileLoopStartLR ||
Opc == ARM::t2WhileLoopStartTP ||
6141 Opc == ARM::t2LoopDec ||
Opc == ARM::t2LoopEnd ||
6142 Opc == ARM::t2LoopEndDec)
6146 uint64_t MIFlags =
MCID.TSFlags;
6151 if (
MI.isTerminator())
6157 if (
MI.readsRegister(ARM::LR,
TRI) ||
MI.readsRegister(ARM::PC,
TRI))
6165 if (MOP.isGlobal()) {
6174 (Callee->getName() ==
"\01__gnu_mcount_nc" ||
6175 Callee->getName() ==
"\01mcount" || Callee->getName() ==
"__mcount"))
6187 return UnknownCallOutlineType;
6195 return UnknownCallOutlineType;
6203 return UnknownCallOutlineType;
6211 if (
MI.modifiesRegister(ARM::LR,
TRI) ||
MI.modifiesRegister(ARM::PC,
TRI))
6215 if (
MI.modifiesRegister(ARM::SP,
TRI) ||
MI.readsRegister(ARM::SP,
TRI)) {
6228 bool MightNeedStackFixUp =
6232 if (!MightNeedStackFixUp)
6238 if (
MI.modifiesRegister(ARM::SP,
TRI))
6243 if (checkAndUpdateStackOffset(&
MI, Subtarget.getStackAlignment().value(),
6252 if (
MI.readsRegister(ARM::ITSTATE,
TRI) ||
6253 MI.modifiesRegister(ARM::ITSTATE,
TRI))
6257 if (
MI.isCFIInstruction())
6272 int Align = std::max(Subtarget.getStackAlignment().value(),
uint64_t(8));
6274 assert(Align >= 8 && Align <= 256);
6276 assert(Subtarget.isThumb2());
6288 unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
6302 CFIBuilder.buildDefCFAOffset(Align);
6307 CFIBuilder.buildOffset(ARM::LR, -LROffset);
6310 CFIBuilder.buildOffset(ARM::RA_AUTH_CODE, -Align);
6316 bool CFI,
bool Auth)
const {
6317 int Align = Subtarget.getStackAlignment().value();
6320 assert(Subtarget.isThumb2());
6332 unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
6336 if (!Subtarget.isThumb())
6338 MIB.
addImm(Subtarget.getStackAlignment().value())
6346 CFIBuilder.buildDefCFAOffset(0);
6347 CFIBuilder.buildRestore(ARM::LR);
6349 CFIBuilder.buildUndefined(ARM::RA_AUTH_CODE);
6363 bool isThumb = Subtarget.isThumb();
6364 unsigned FuncOp =
isThumb ? 2 : 0;
6365 unsigned Opc =
Call->getOperand(FuncOp).isReg()
6366 ?
isThumb ? ARM::tTAILJMPr : ARM::TAILJMPr
6367 :
isThumb ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd
6371 .
add(
Call->getOperand(FuncOp));
6374 Call->eraseFromParent();
6379 return MI.isCall() && !
MI.isReturn();
6387 Et = std::prev(
MBB.end());
6392 if (!
MBB.isLiveIn(ARM::LR))
6393 MBB.addLiveIn(ARM::LR);
6397 saveLROnStack(
MBB, It,
true, Auth);
6402 "Can only fix up stack references once");
6403 fixupPostOutline(
MBB);
6406 restoreLRFromStack(
MBB, Et,
true, Auth);
6426 fixupPostOutline(
MBB);
6435 bool isThumb = Subtarget.isThumb();
6441 ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND
6447 It =
MBB.insert(It, MIB);
6461 It =
MBB.insert(It, CallMIB);
6468 Register Reg = findRegisterToSaveLRTo(
C);
6469 assert(Reg != 0 &&
"No callee-saved register available?");
6476 CallPt =
MBB.insert(It, CallMIB);
6484 if (!
MBB.isLiveIn(ARM::LR))
6485 MBB.addLiveIn(ARM::LR);
6488 CallPt =
MBB.insert(It, CallMIB);
6499bool ARMBaseInstrInfo::isReMaterializableImpl(
6533 static int constexpr MAX_STAGES = 30;
6534 static int constexpr LAST_IS_USE = MAX_STAGES;
6535 static int constexpr SEEN_AS_LIVE = MAX_STAGES + 1;
6536 typedef std::bitset<MAX_STAGES + 2> IterNeed;
6537 typedef std::map<Register, IterNeed> IterNeeds;
6540 const IterNeeds &CIN);
6552 : EndLoop(EndLoop), LoopCount(LoopCount),
6554 TII(MF->getSubtarget().getInstrInfo()) {}
6556 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
6558 return MI == EndLoop ||
MI == LoopCount;
6561 bool shouldUseSchedule(SwingSchedulerDAG &SSD, SMSchedule &SMS)
override {
6562 if (tooMuchRegisterPressure(SSD, SMS))
6568 std::optional<bool> createTripCountGreaterCondition(
6569 int TC, MachineBasicBlock &
MBB,
6570 SmallVectorImpl<MachineOperand> &
Cond)
override {
6579 }
else if (EndLoop->
getOpcode() == ARM::t2LoopEnd) {
6582 MachineInstr *LoopDec =
nullptr;
6584 if (
I.getOpcode() == ARM::t2LoopDec)
6586 assert(LoopDec &&
"Unable to find copied LoopDec");
6592 .
addReg(ARM::NoRegister);
6600 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
6602 void adjustTripCount(
int TripCountAdjust)
override {}
6606 const IterNeeds &CIN) {
6608 for (
const auto &
N : CIN) {
6609 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6610 for (
int I = 0;
I < Cnt; ++
I)
6615 for (
const auto &
N : CIN) {
6616 int Cnt =
N.second.count() -
N.second[SEEN_AS_LIVE] * 2;
6617 for (
int I = 0;
I < Cnt; ++
I)
6625 IterNeeds CrossIterationNeeds;
6630 for (
auto &SU : SSD.
SUnits) {
6633 for (
auto &S : SU.Succs)
6637 CrossIterationNeeds[
Reg.
id()].set(0);
6638 }
else if (S.isAssignedRegDep()) {
6640 if (OStg >= 0 && OStg != Stg) {
6643 CrossIterationNeeds[
Reg.
id()] |= ((1 << (OStg - Stg)) - 1);
6652 std::vector<SUnit *> ProposedSchedule;
6656 std::deque<SUnit *> Instrs =
6658 std::sort(Instrs.begin(), Instrs.end(),
6659 [](
SUnit *
A,
SUnit *
B) { return A->NodeNum > B->NodeNum; });
6666 for (
auto *SU : ProposedSchedule)
6670 if (!MO.isReg() || !MO.getReg())
6673 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6674 if (CIter == CrossIterationNeeds.end() || CIter->second[LAST_IS_USE] ||
6675 CIter->second[SEEN_AS_LIVE])
6677 if (MO.isDef() && !MO.isDead())
6678 CIter->second.set(SEEN_AS_LIVE);
6679 else if (MO.isUse())
6680 CIter->second.set(LAST_IS_USE);
6682 for (
auto &CI : CrossIterationNeeds)
6683 CI.second.reset(LAST_IS_USE);
6689 RPTracker.init(MF, &RegClassInfo,
nullptr, EndLoop->
getParent(),
6692 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6694 for (
auto *SU : ProposedSchedule) {
6696 RPTracker.setPos(std::next(CurInstI));
6702 if (!MO.isReg() || !MO.getReg())
6705 if (MO.isDef() && !MO.isDead()) {
6706 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6707 if (CIter != CrossIterationNeeds.end()) {
6708 CIter->second.reset(0);
6709 CIter->second.reset(SEEN_AS_LIVE);
6713 for (
auto &S : SU->Preds) {
6715 if (S.isAssignedRegDep()) {
6717 auto CIter = CrossIterationNeeds.find(
Reg.
id());
6718 if (CIter != CrossIterationNeeds.end()) {
6720 assert(Stg2 <= Stg &&
"Data dependence upon earlier stage");
6721 if (Stg - Stg2 < MAX_STAGES)
6722 CIter->second.set(Stg - Stg2);
6723 CIter->second.set(SEEN_AS_LIVE);
6728 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6731 auto &
P = RPTracker.getPressure().MaxSetPressure;
6732 for (
unsigned I = 0,
E =
P.size();
I <
E; ++
I) {
6734 if (
I == ARM::DQuad_with_ssub_0 ||
I == ARM::DTripleSpc_with_ssub_0 ||
6735 I == ARM::DTriple_with_qsub_0_in_QPR)
6747std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
6751 if (Preheader == LoopBB)
6752 Preheader = *std::next(LoopBB->
pred_begin());
6754 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2Bcc) {
6760 for (
auto &L : LoopBB->
instrs()) {
6767 return std::make_unique<ARMPipelinerLoopInfo>(&*
I, CCSetter);
6781 if (
I != LoopBB->
end() &&
I->getOpcode() == ARM::t2LoopEnd) {
6782 for (
auto &L : LoopBB->
instrs())
6787 Register LoopDecResult =
I->getOperand(0).getReg();
6790 if (!LoopDec || LoopDec->
getOpcode() != ARM::t2LoopDec)
6793 for (
auto &J : Preheader->
instrs())
6794 if (J.getOpcode() == ARM::t2DoLoopStart)
6798 return std::make_unique<ARMPipelinerLoopInfo>(&*
I, LoopDec);
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isThumb(const MCSubtargetInfo &STI)
static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI, MachineInstr &MI, MCRegister DReg, unsigned Lane, MCRegister &ImplicitSReg)
getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane, set ImplicitSReg to a register n...
static const MachineInstr * getBundledUseMI(const TargetRegisterInfo *TRI, const MachineInstr &MI, unsigned Reg, unsigned &UseIdx, unsigned &Dist)
static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI)
Create a copy of a const pool value.
static bool isSuitableForMask(MachineInstr *&MI, Register SrcReg, int CmpMask, bool CommonUse)
isSuitableForMask - Identify a suitable 'and' instruction that operates on the given source register ...
static int adjustDefLatency(const ARMSubtarget &Subtarget, const MachineInstr &DefMI, const MCInstrDesc &DefMCID, unsigned DefAlign)
Return the number of cycles to add to (or subtract from) the static itinerary based on the def opcode...
static unsigned getNumMicroOpsSwiftLdSt(const InstrItineraryData *ItinData, const MachineInstr &MI)
static MCRegister getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI, unsigned SReg, unsigned &Lane)
static bool CanTransformInstrIntoTailCall(const MachineInstr &MI)
Return true if MI is a call instruction that the outliner can rewrite as a tail call.
static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[]
static bool isEligibleForITBlock(const MachineInstr *MI)
static ARMCC::CondCodes getCmpToAddCondition(ARMCC::CondCodes CC)
getCmpToAddCondition - assume the flags are set by CMP(a,b), return the condition code if we modify t...
static bool isOptimizeCompareCandidate(MachineInstr *MI, bool &IsThumb1)
static bool isLRAvailable(const TargetRegisterInfo &TRI, MachineBasicBlock::reverse_iterator I, MachineBasicBlock::reverse_iterator E)
static const ARM_MLxEntry ARM_MLxTable[]
static bool isRedundantFlagInstr(const MachineInstr *CmpI, Register SrcReg, Register SrcReg2, int64_t ImmValue, const MachineInstr *OI, bool &IsThumb1)
isRedundantFlagInstr - check whether the first instruction, whose only purpose is to update flags,...
static unsigned getNumMicroOpsSingleIssuePlusExtras(unsigned Opc, unsigned NumRegs)
static const MachineInstr * getBundledDefMI(const TargetRegisterInfo *TRI, const MachineInstr *MI, unsigned Reg, unsigned &DefIdx, unsigned &Dist)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
This file defines the DenseMap class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
PowerPC TLS Dynamic Call Fixup
TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallSet class.
This file defines the SmallVector class.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static bool isCPSRDefined(const MachineInstr &MI)
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction to set the zero flag so that we can remove a "comparis...
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const override
foldImmediate - 'Reg' is known to be defined by a move immediate instruction, try to fold the immedia...
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void copyFromCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister DestReg, bool KillSrc, const ARMSubtarget &Subtarget) const
unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr &MI) const override
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
unsigned getPartialRegUpdateClearance(const MachineInstr &, unsigned, const TargetRegisterInfo *) const override
unsigned getNumLDMAddresses(const MachineInstr &MI) const
Get the number of addresses by LDM or VLDM or zero for unknown.
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
bool produceSameValue(const MachineInstr &MI0, const MachineInstr &MI1, const MachineRegisterInfo *MRI) const override
void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
Analyze loop L, which must be a single-basic-block loop, and if the conditions can be understood enou...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Returns the size of the specified MachineInstr.
void copyToCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister SrcReg, bool KillSrc, const ARMSubtarget &Subtarget) const
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void mergeOutliningCandidateAttributes(Function &F, std::vector< outliner::Candidate > &Candidates) const override
const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, RegState State) const
bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override
ARM supports the MachineOutliner.
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
Enable outlining by default at -Oz.
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const override
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
bool isPredicated(const MachineInstr &MI) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const
bool isPredicable(const MachineInstr &MI) const override
isPredicable - Return true if the specified instruction can be predicated.
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const override
Specialization of TargetInstrInfo::describeLoadedValue, used to enhance debug entry value description...
std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
unsigned extraSizeToPredicateInstructions(const MachineFunction &MF, unsigned NumInsts) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
const ARMBaseRegisterInfo & getRegisterInfo() const
bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const override
areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are lo...
std::optional< unsigned > getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr &DefMI, unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const override
bool getRegSequenceLikeInputs(const MachineInstr &MI, unsigned DefIdx, SmallVectorImpl< RegSubRegPairAndIdx > &InputRegs) const override
Build the equivalent inputs of a REG_SEQUENCE for the given MI and DefIdx.
unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const override
bool getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPair &BaseReg, RegSubRegPairAndIdx &InsertedReg) const override
Build the equivalent inputs of a INSERT_SUBREG for the given MI and DefIdx.
bool expandPostRAPseudo(MachineInstr &MI) const override
outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MIT, unsigned Flags) const override
bool SubsumesPredicate(ArrayRef< MachineOperand > Pred1, ArrayRef< MachineOperand > Pred2) const override
bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, int64_t Offset2, unsigned NumLoads) const override
shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to determine (in conjunction w...
bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Pred) const override
std::pair< uint16_t, uint16_t > getExecutionDomain(const MachineInstr &MI) const override
VFP/NEON execution domains.
bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, MachineBasicBlock &FMBB) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool isFpMLxInstruction(unsigned Opcode) const
isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS instruction.
bool isSwiftFastImmShift(const MachineInstr *MI) const
Returns true if the instruction has a shift by immediate that can be executed in one cycle less.
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
ARMBaseInstrInfo(const ARMSubtarget &STI, const ARMBaseRegisterInfo &TRI)
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2 if h...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void breakPartialRegDependency(MachineInstr &, unsigned, const TargetRegisterInfo *TRI) const override
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
const ARMSubtarget & getSubtarget() const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
Commutes the operands in the given instruction.
bool getExtractSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPairAndIdx &InputReg) const override
Build the equivalent inputs of a EXTRACT_SUBREG for the given MI and DefIdx.
bool shouldSink(const MachineInstr &MI) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
bool isMachineBasicBlock() const
bool isGlobalValue() const
ARMCP::ARMCPModifier getModifier() const
bool mustAddCurrentAddress() const
virtual bool hasSameValue(ARMConstantPoolValue *ACPV)
hasSameValue - Return true if this ARM constpool value can share the same constantpool entry as anoth...
bool isBlockAddress() const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool isThumb2Function() const
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
bool isThumb1OnlyFunction() const
bool isThumbFunction() const
bool shouldSignReturnAddress() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
Align getStackAlignment() const
getStackAlignment - Returns the minimum alignment known to hold of the stack frame on entry to the fu...
bool enableMachinePipeliner() const override
Returns true if machine pipeliner should be enabled.
@ DoubleIssueCheckUnalignedAccess
Can load/store 2 registers/cycle, but needs an extra cycle if the access is not 64-bit aligned.
@ SingleIssue
Can load/store 1 register/cycle.
@ DoubleIssue
Can load/store 2 registers/cycle.
@ SingleIssuePlusExtras
Can load/store 1 register/cycle, but needs an extra cycle for address computation and potentially als...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type size() const
Returns the number of bits in this bitvector.
LLVM_ABI uint64_t scale(uint64_t Num) const
Scale a large integer.
BranchProbability getCompl() const
Helper class for creating CFI instructions and inserting them into MIR.
void buildRegister(MCRegister Reg1, MCRegister Reg2) const
void buildRestore(MCRegister Reg) const
ConstMIBundleOperands - Iterate over all operands in a const bundle of machine instructions.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasDLLImportStorageClass() const
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Reverses the branch condition of the specified condition list, returning false on success and true if...
Itinerary data supplied by a subtarget to be used by a target.
int getNumMicroOps(unsigned ItinClassIndx) const
Return the number of micro-ops that the given class decodes to.
std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
unsigned getStageLatency(unsigned ItinClassIndx) const
Return the total stage latency of the given class.
std::optional< unsigned > getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Compute and return the use operand latency of a given itinerary class and operand index if the value ...
bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Return true if there is a pipeline forwarding between instructions of itinerary classes DefClass and ...
bool isEmpty() const
Returns true if there are no itineraries.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Describe properties that are true of each instruction in the target description file.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool isCall() const
Return true if the instruction is a call.
unsigned getOpcode() const
Return the opcode number for this descriptor.
LLVM_ABI bool hasImplicitDefOfPhysReg(MCRegister Reg, const MCRegisterInfo *MRI=nullptr) const
Return true if this instruction implicitly defines the specified physical register.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
Wrapper class representing physical registers. Should be passed by value.
bool isValid() const
isValid - Returns true until all the operands have been visited.
unsigned pred_size() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Instructions::iterator instr_iterator
pred_iterator pred_begin()
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
LivenessQueryResult
Possible outcome of a register liveness query to computeRegisterLiveness()
@ LQR_Dead
Register is known to be fully dead.
@ LQR_Live
Register is known to be (at least partially) live.
@ LQR_Unknown
Register liveness not decidable from local neighborhood.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
const Constant * ConstVal
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
ArrayRef< MachineMemOperand * >::iterator mmo_iterator
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isImplicitDef() const
const MachineBasicBlock * getParent() const
bool isCopyLike() const
Return true if the instruction behaves like a copy.
bool isCall(QueryType Type=AnyInBundle) const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI int findFirstPredOperandIdx() const
Find the index of the first operand in the operand list that is used to represent the predicate.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool isRegSequence() const
bool isInsertSubreg() const
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI bool isIdenticalTo(const MachineInstr &Other, MICheckType Check=CheckDefs) const
Return true if this instruction is identical to Other.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
bool hasOptionalDef(QueryType Type=IgnoreBundle) const
Set if this instruction has an optional definition, e.g.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
use_instr_iterator use_instr_begin(Register RegNo) const
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static use_instr_iterator use_instr_end()
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
void AddHazardRecognizer(std::unique_ptr< ScheduleHazardRecognizer > &&)
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void increaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
LLVM_ABI void decreaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
unsigned getRegPressureSetLimit(unsigned Idx) const
Get the register unit limit for the given pressure set index.
LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)
runOnFunction - Prepare to answer questions about MF.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
@ Anti
A register anti-dependence (aka WAR).
This class represents the scheduled code.
unsigned getMaxStageCount()
Return the maximum stage count needed for this schedule.
int stageScheduled(SUnit *SU) const
Return the stage for a scheduled instruction.
int getInitiationInterval() const
Return the initiation interval for this schedule.
std::deque< SUnit * > & getInstructions(int cycle)
Return the instructions that are scheduled at the specified cycle.
int getFirstCycle() const
Return the first cycle in the completed schedule.
int getFinalCycle() const
Return the last cycle in the finalized schedule.
Scheduling unit. This is a node in the scheduling DAG.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
std::vector< SUnit > SUnits
The scheduling units.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const
Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const
Compute operand latency based on the available machine model.
const InstrItineraryData * getInstrItineraries() const
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Wrapper class representing a virtual register or register unit.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static CondCodes getOppositeCondition(CondCodes CC)
ARMII - This namespace holds all of the target specific flags that instruction info tracks.
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
AddrMode
ARM Addressing Modes.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned char getAM5FP16Offset(unsigned AM5Opc)
unsigned getSORegOffset(unsigned Op)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
unsigned getAM2Offset(unsigned AM2Opc)
unsigned getSOImmValRotate(unsigned Imm)
getSOImmValRotate - Try to handle Imm with an immediate shifter operand, computing the rotate amount ...
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
ShiftOpc getSORegShOp(unsigned Op)
AddrOpc getAM5Op(unsigned AM5Opc)
bool isSOImmTwoPartValNeg(unsigned V)
isSOImmTwoPartValNeg - Return true if the specified value can be obtained by two SOImmVal,...
unsigned getSOImmTwoPartSecond(unsigned V)
getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...
bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned getT2SOImmTwoPartSecond(unsigned Imm)
unsigned getT2SOImmTwoPartFirst(unsigned Imm)
bool isT2SOImmTwoPartVal(unsigned Imm)
unsigned char getAM5Offset(unsigned AM5Opc)
unsigned getSOImmTwoPartFirst(unsigned V)
getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...
AddrOpc getAM2Op(unsigned AM2Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
Define some predicates that are used for node matching.
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
constexpr T rotr(T V, int R)
static bool isIndirectCall(const MachineInstr &MI)
MachineInstr * findCMPToFoldIntoCBZ(MachineInstr *Br, const TargetRegisterInfo *TRI)
Search backwards from a tBcc to find a tCMPi8 against 0, meaning we can convert them to a tCBZ or tCB...
static bool isCondBranchOpcode(int Opc)
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
static bool isPushOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond)
static bool isVCTP(const MachineInstr *MI)
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
bool IsCPSRDead< MachineInstr >(const MachineInstr *MI)
constexpr RegState getKillRegState(bool B)
unsigned getBLXpredOpcode(const MachineFunction &MF)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
static bool isIndirectBranchOpcode(int Opc)
bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI)
Return true if Reg is defd between From and To.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isSEHInstruction(const MachineInstr &MI)
static bool isCalleeSavedRegister(MCRegister Reg, const MCPhysReg *CSRegs)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
auto reverse(ContainerTy &&C)
static bool isJumpTableBranchOpcode(int Opc)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static bool isPopOpcode(int Opc)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond, unsigned Inactive)
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg)
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII)
rewriteARMFrameIndex / rewriteT2FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
unsigned getMatchingCondBranchOpcode(unsigned Opc)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
static const char * ARMCondCodeToString(ARMCC::CondCodes CC)
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned gettBLXrOpcode(const MachineFunction &MF)
static bool isSpeculationBarrierEndBBOpcode(int Opc)
unsigned getBLXOpcode(const MachineFunction &MF)
void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB)
bool isV8EligibleForIT(const InstrType *Instr)
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
constexpr RegState getUndefRegState(bool B)
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
MCRegisterClass TargetRegisterClass
ARM_MLxEntry - Record information about MLA / MLS instructions.
Map pseudo instructions that imply an 'S' bit onto real opcodes.
OutlinerCosts(const ARMSubtarget &target)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr LaneBitmask getAll()
static constexpr LaneBitmask getNone()
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Used to describe a register and immediate addition.
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
An individual sequence of instructions to be replaced with a call to an outlined function.
The information necessary to create an outlined function for some class of candidate.