71 #define DEBUG_TYPE "arm-ldst-opt" 73 STATISTIC(NumLDMGened ,
"Number of ldm instructions generated");
74 STATISTIC(NumSTMGened ,
"Number of stm instructions generated");
75 STATISTIC(NumVLDMGened,
"Number of vldm instructions generated");
76 STATISTIC(NumVSTMGened,
"Number of vstm instructions generated");
77 STATISTIC(NumLdStMoved,
"Number of load / store instructions moved");
78 STATISTIC(NumLDRDFormed,
"Number of ldrd created before allocation");
79 STATISTIC(NumSTRDFormed,
"Number of strd created before allocation");
80 STATISTIC(NumLDRD2LDM,
"Number of ldrd instructions turned back into ldm");
81 STATISTIC(NumSTRD2STM,
"Number of strd instructions turned back into stm");
82 STATISTIC(NumLDRD2LDR,
"Number of ldrd instructions turned back into ldr's");
83 STATISTIC(NumSTRD2STR,
"Number of strd instructions turned back into str's");
94 #define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass" 113 bool RegClassInfoValid;
114 bool isThumb1, isThumb2;
130 struct MemOpQueueEntry {
135 MemOpQueueEntry(
MachineInstr &MI,
int Offset,
unsigned Position)
142 struct MergeCandidate {
147 unsigned LatestMIIdx;
150 unsigned EarliestMIIdx;
157 bool CanMergeToLSMulti;
160 bool CanMergeToLSDouble;
171 unsigned Base,
unsigned WordOffset,
175 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
177 ArrayRef<std::pair<unsigned, bool>> Regs);
180 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
182 ArrayRef<std::pair<unsigned, bool>> Regs)
const;
183 void FormCandidates(
const MemOpQueue &MemOps);
184 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
203 for (
const auto &MO : MI.operands()) {
206 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
217 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
221 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
222 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
223 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
224 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
228 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
229 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
345 case ARM::tLDMIA_UPD:
346 case ARM::tSTMIA_UPD:
347 case ARM::t2LDMIA_RET:
349 case ARM::t2LDMIA_UPD:
351 case ARM::t2STMIA_UPD:
353 case ARM::VLDMSIA_UPD:
355 case ARM::VSTMSIA_UPD:
357 case ARM::VLDMDIA_UPD:
359 case ARM::VSTMDIA_UPD:
373 case ARM::t2LDMDB_UPD:
375 case ARM::t2STMDB_UPD:
376 case ARM::VLDMSDB_UPD:
377 case ARM::VSTMSDB_UPD:
378 case ARM::VLDMDDB_UPD:
379 case ARM::VSTMDDB_UPD:
391 return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;
395 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
403 return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;
407 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
415 return isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
463 case ARM::tLDMIA_UPD:
464 case ARM::tSTMIA_UPD:
486 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
489 for (; MBBI != MBB.
end(); ++MBBI) {
490 bool InsertSub =
false;
491 unsigned Opc = MBBI->getOpcode();
493 if (MBBI->readsRegister(Base)) {
496 Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;
498 Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;
500 if (IsLoad || IsStore) {
506 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
513 if (Offset >= 0 && !(IsStore && InstrSrcReg == Base))
517 }
else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&
518 !definesCPSR(*MBBI)) {
523 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
524 Offset = (Opc == ARM::tSUBi8) ?
525 MO.
getImm() + WordOffset * 4 :
526 MO.
getImm() - WordOffset * 4 ;
527 if (Offset >= 0 && TL->isLegalAddImmediate(Offset)) {
540 }
else if (definesCPSR(*MBBI) || MBBI->isCall() || MBBI->isBranch()) {
549 BuildMI(MBB, MBBI, DL,
TII->get(ARM::tSUBi8), Base)
552 .addImm(WordOffset * 4)
558 if (MBBI->killsRegister(Base) || MBBI->definesRegister(Base))
569 if (MBBI != MBB.
end()) --MBBI;
570 BuildMI(MBB, MBBI, DL,
TII->get(ARM::tSUBi8), Base)
573 .addImm(WordOffset * 4)
581 if (!RegClassInfoValid) {
582 RegClassInfo.runOnMachineFunction(*MF);
583 RegClassInfoValid =
true;
586 for (
unsigned Reg : RegClassInfo.getOrder(&RegClass))
587 if (!LiveRegs.contains(
Reg))
598 if (!LiveRegsValid) {
600 LiveRegs.addLiveOuts(MBB);
601 LiveRegPos = MBB.
end();
602 LiveRegsValid =
true;
605 while (LiveRegPos != Before) {
607 LiveRegs.stepBackward(*LiveRegPos);
613 for (
const std::pair<unsigned, bool> &R : Regs)
624 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
626 ArrayRef<std::pair<unsigned, bool>> Regs) {
627 unsigned NumRegs = Regs.size();
632 bool SafeToClobberCPSR = !isThumb1 ||
636 bool Writeback = isThumb1;
642 assert(Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
643 if (Opcode == ARM::tLDRi)
645 else if (Opcode == ARM::tSTRi)
652 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
654 if (Offset == 4 && haveIBAndDA) {
656 }
else if (Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
658 }
else if (Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
661 }
else if (Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
674 if (!SafeToClobberCPSR)
681 NewBase = Regs[NumRegs-1].first;
685 moveLiveRegsBefore(MBB, InsertBefore);
689 for (
const std::pair<unsigned, bool> &R : Regs)
690 LiveRegs.addReg(R.first);
692 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
698 isThumb2 ? ARM::t2ADDri :
699 (isThumb1 && Base == ARM::SP) ? ARM::tADDrSPi :
700 (isThumb1 && Offset < 8) ? ARM::tADDi3 :
701 isThumb1 ? ARM::tADDi8 : ARM::ADDri;
706 isThumb2 ? ARM::t2SUBri :
707 (isThumb1 && Offset < 8 && Base != ARM::SP) ? ARM::tSUBi3 :
708 isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
711 if (!TL->isLegalAddImmediate(Offset))
717 bool KillOldBase = BaseKill &&
726 if (Base != NewBase &&
727 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
734 BuildMI(MBB, InsertBefore, DL,
TII->get(ARM::tMOVSr), NewBase)
737 BuildMI(MBB, InsertBefore, DL,
TII->get(ARM::tMOVr), NewBase)
745 if (BaseOpc == ARM::tADDrSPi) {
746 assert(Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
747 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
752 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
758 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
784 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
790 assert(isThumb1 &&
"expected Writeback only inThumb1");
791 if (Opcode == ARM::tLDMIA) {
794 Opcode = ARM::tLDMIA_UPD;
797 MIB =
BuildMI(MBB, InsertBefore, DL,
TII->get(Opcode));
806 UpdateBaseRegUses(MBB, InsertBefore, DL, Base, NumRegs, Pred, PredReg);
809 MIB =
BuildMI(MBB, InsertBefore, DL,
TII->get(Opcode));
815 for (
const std::pair<unsigned, bool> &R : Regs)
823 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
825 ArrayRef<std::pair<unsigned, bool>> Regs)
const {
827 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
828 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
832 TII->get(LoadStoreOpcode));
845 MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
857 bool IsKill = MO.
isKill();
860 Regs.
push_back(std::make_pair(Reg, IsKill));
871 unsigned DefReg = MO.
getReg();
887 iterator InsertBefore = std::next(iterator(LatestMI));
892 unsigned PredReg = 0;
896 if (Cand.CanMergeToLSDouble)
897 Merged = CreateLoadStoreDouble(MBB, InsertBefore, Offset, Base, BaseKill,
898 Opcode, Pred, PredReg, DL, Regs);
899 if (!Merged && Cand.CanMergeToLSMulti)
900 Merged = CreateLoadStoreMulti(MBB, InsertBefore, Offset, Base, BaseKill,
901 Opcode, Pred, PredReg, DL, Regs);
907 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
908 bool EarliestAtBegin =
false;
909 if (EarliestI == MBB.
begin()) {
910 EarliestAtBegin =
true;
912 EarliestI = std::prev(EarliestI);
921 EarliestI = MBB.
begin();
923 EarliestI = std::next(EarliestI);
924 auto FixupRange =
make_range(EarliestI, iterator(Merged));
930 for (
unsigned &ImpDefReg : ImpDefs) {
932 if (!MO.isReg() || MO.getReg() != ImpDefReg)
943 for (
unsigned ImpDef : ImpDefs)
950 if (!MO.isReg() || !MO.isKill())
952 if (UsedRegs.
count(MO.getReg()))
966 return (Value % 4) == 0 && Value < 1024;
988 void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
995 unsigned EIndex = MemOps.size();
999 int Offset = MemOps[SIndex].Offset;
1001 unsigned PReg = PMO.
getReg();
1003 :
TRI->getEncodingValue(PReg);
1004 unsigned Latest = SIndex;
1005 unsigned Earliest = SIndex;
1007 bool CanMergeToLSDouble =
1011 if (STI->isCortexM3() &&
isi32Load(Opcode) &&
1013 CanMergeToLSDouble =
false;
1015 bool CanMergeToLSMulti =
true;
1018 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1019 CanMergeToLSMulti =
false;
1023 if (PReg == ARM::SP || PReg == ARM::PC)
1024 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1028 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1043 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++Count) {
1044 int NewOffset = MemOps[
I].Offset;
1045 if (NewOffset != Offset + (
int)
Size)
1049 if (Reg == ARM::SP || Reg == ARM::PC)
1056 :
TRI->getEncodingValue(Reg);
1057 bool PartOfLSMulti = CanMergeToLSMulti;
1058 if (PartOfLSMulti) {
1060 if (RegNum <= PRegNum)
1061 PartOfLSMulti =
false;
1065 else if (!isNotVFP && RegNum != PRegNum+1)
1066 PartOfLSMulti =
false;
1069 bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;
1071 if (!PartOfLSMulti && !PartOfLSDouble)
1073 CanMergeToLSMulti &= PartOfLSMulti;
1074 CanMergeToLSDouble &= PartOfLSDouble;
1078 if (Position < MemOps[Latest].Position)
1080 else if (Position > MemOps[Earliest].Position)
1088 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1089 for (
unsigned C = SIndex, CE = SIndex + Count;
C < CE; ++
C)
1090 Candidate->Instrs.push_back(MemOps[
C].MI);
1091 Candidate->LatestMIIdx = Latest - SIndex;
1092 Candidate->EarliestMIIdx = Earliest - SIndex;
1093 Candidate->InsertPos = MemOps[Latest].Position;
1095 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1096 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1097 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1098 Candidates.push_back(Candidate);
1101 }
while (SIndex < EIndex);
1179 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1180 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1182 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1184 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1185 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1186 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1194 MIPredReg != PredReg)
1197 if (CheckCPSRDef && definesCPSR(MI))
1210 if (MBBI == BeginMBBI)
1215 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1219 return Offset == 0 ? EndMBBI : PrevMBBI;
1231 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1233 if (NextMBBI == EndMBBI)
1237 return Offset == 0 ? EndMBBI : NextMBBI;
1252 bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(
MachineInstr *
MI) {
1254 if (isThumb1)
return false;
1257 unsigned Base = BaseOP.
getReg();
1258 bool BaseKill = BaseOP.
isKill();
1259 unsigned PredReg = 0;
1277 if (Mode ==
ARM_AM::ia && Offset == -Bytes) {
1279 }
else if (Mode ==
ARM_AM::ib && Offset == -Bytes) {
1293 bool HighRegsUsed =
false;
1296 HighRegsUsed =
true;
1301 MergeInstr = MBB.
end();
1306 if (MergeInstr != MBB.
end())
1307 MBB.
erase(MergeInstr);
1313 .addImm(Pred).
addReg(PredReg);
1316 for (
unsigned OpNum = 3, e = MI->
getNumOperands(); OpNum != e; ++OpNum)
1330 return ARM::LDR_PRE_IMM;
1332 return ARM::STR_PRE_IMM;
1334 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1336 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1338 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1340 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1343 return ARM::t2LDR_PRE;
1346 return ARM::t2STR_PRE;
1355 return ARM::LDR_POST_IMM;
1357 return ARM::STR_POST_IMM;
1359 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1361 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1363 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1365 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1368 return ARM::t2LDR_POST;
1371 return ARM::t2STR_POST;
1378 bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(
MachineInstr *MI) {
1381 if (isThumb1)
return false;
1387 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1388 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1389 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1401 unsigned PredReg = 0;
1410 if (!isAM5 && Offset == Bytes) {
1412 }
else if (Offset == -Bytes) {
1416 if (Offset == Bytes) {
1418 }
else if (!isAM5 && Offset == -Bytes) {
1423 MBB.
erase(MergeInstr);
1437 .addImm(Pred).
addReg(PredReg)
1443 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1469 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1472 BuildMI(MBB, MBBI, DL,
TII->get(NewOpc), Base)
1480 BuildMI(MBB, MBBI, DL,
TII->get(NewOpc), Base)
1492 bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(
MachineInstr &MI)
const {
1494 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1495 "Must have t2STRDi8 or t2LDRDi8");
1502 unsigned Base = BaseOp.
getReg();
1505 if (Reg0Op.
getReg() == Base || Reg1Op.
getReg() == Base)
1516 if (Offset == 8 || Offset == -8) {
1517 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1520 if (Offset == 8 || Offset == -8) {
1521 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1525 MBB.
erase(MergeInstr);
1529 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1532 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1537 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1538 TII->get(NewOpc).getNumOperands() == 7 &&
1539 "Unexpected number of operands in Opcode specification.");
1607 bool isDef,
unsigned NewOpc,
unsigned Reg,
1608 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1632 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1636 unsigned BaseReg = BaseOp.
getReg();
1639 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1640 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1644 bool Errata602117 = EvenReg == BaseReg &&
1645 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();
1647 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1648 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1650 if (!Errata602117 && !NonConsecutiveRegs)
1653 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1654 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1655 bool EvenDeadKill = isLd ?
1658 bool OddDeadKill = isLd ?
1661 bool BaseKill = BaseOp.
isKill();
1662 bool BaseUndef = BaseOp.
isUndef();
1664 "register offset not handled below");
1666 unsigned PredReg = 0;
1669 if (OddRegNum > EvenRegNum && OffImm == 0) {
1672 unsigned NewOpc = (isLd)
1673 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1674 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1676 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(NewOpc))
1678 .addImm(Pred).
addReg(PredReg)
1683 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(NewOpc))
1685 .addImm(Pred).
addReg(PredReg)
1694 unsigned NewOpc = (isLd)
1695 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1696 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1699 unsigned NewOpc2 = (isLd)
1700 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1701 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1704 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1705 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1706 InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
1707 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII);
1708 InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
1709 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII);
1711 if (OddReg == EvenReg && EvenDeadKill) {
1715 EvenDeadKill =
false;
1719 if (EvenReg == BaseReg)
1720 EvenDeadKill =
false;
1721 InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
1722 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII);
1723 InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
1724 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII);
1732 MBBI = MBB.
erase(MBBI);
1740 unsigned CurrBase = 0;
1741 unsigned CurrOpc = ~0u;
1744 assert(Candidates.size() == 0);
1745 assert(MergeBaseCandidates.size() == 0);
1746 LiveRegsValid =
false;
1751 MBBI = std::prev(
I);
1752 if (FixInvalidRegPairOp(MBB, MBBI))
1757 unsigned Opcode = MBBI->getOpcode();
1761 unsigned PredReg = 0;
1764 if (CurrBase == 0) {
1769 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
1773 if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
1781 bool Overlap =
false;
1783 Overlap = (Base ==
Reg);
1785 for (
const MemOpQueueEntry &
E : MemOps) {
1786 if (
TRI->regsOverlap(Reg,
E.MI->getOperand(0).getReg())) {
1796 if (Offset > MemOps.back().Offset) {
1797 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
1800 MemOpQueue::iterator
MI, ME;
1801 for (MI = MemOps.begin(), ME = MemOps.end(); MI != ME; ++
MI) {
1802 if (Offset < MI->Offset) {
1806 if (Offset == MI->Offset) {
1812 if (MI != MemOps.end()) {
1813 MemOps.insert(MI, MemOpQueueEntry(*MBBI, Offset, Position));
1824 }
else if (MBBI->isDebugInstr()) {
1826 }
else if (MBBI->getOpcode() == ARM::t2LDRDi8 ||
1827 MBBI->getOpcode() == ARM::t2STRDi8) {
1830 MergeBaseCandidates.push_back(&*MBBI);
1834 if (MemOps.size() > 0) {
1835 FormCandidates(MemOps);
1843 if (MemOps.size() > 0)
1844 FormCandidates(MemOps);
1848 auto LessThan = [](
const MergeCandidate* M0,
const MergeCandidate *M1) {
1849 return M0->InsertPos < M1->InsertPos;
1854 bool Changed =
false;
1855 for (
const MergeCandidate *Candidate : Candidates) {
1856 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
1862 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
1863 MergeBaseUpdateLSDouble(*Merged);
1865 MergeBaseUpdateLSMultiple(Merged);
1868 if (MergeBaseUpdateLoadStore(MI))
1873 assert(Candidate->Instrs.size() == 1);
1874 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
1881 MergeBaseUpdateLSDouble(*MI);
1882 MergeBaseCandidates.clear();
1899 if (isThumb1)
return false;
1900 if (MBB.
empty())
return false;
1903 if (MBBI != MBB.
begin() && MBBI != MBB.
end() &&
1904 (MBBI->getOpcode() == ARM::BX_RET ||
1905 MBBI->getOpcode() == ARM::tBX_RET ||
1906 MBBI->getOpcode() == ARM::MOVPCLR)) {
1909 while (PrevI->isDebugInstr() && PrevI != MBB.
begin())
1913 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
1914 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
1915 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
1917 if (MO.
getReg() != ARM::LR)
1919 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
1920 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
1921 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
1932 if (
Info.getReg() == ARM::LR) {
1933 Info.setRestored(
false);
1945 if (MBBI == MBB.
begin() || MBBI == MBB.
end() ||
1946 MBBI->getOpcode() != ARM::tBX_RET)
1951 if (Prev->getOpcode() != ARM::tMOVr || !Prev->definesRegister(ARM::LR))
1954 for (
auto Use : Prev->uses())
1956 assert(STI->hasV4TOps());
1957 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(ARM::tBX))
1960 .copyImplicitOps(*MBBI);
1977 TII = STI->getInstrInfo();
1978 TRI = STI->getRegisterInfo();
1980 RegClassInfoValid =
false;
1981 isThumb2 = AFI->isThumb2Function();
1982 isThumb1 = AFI->isThumbFunction() && !isThumb2;
1988 Modified |= LoadStoreMultipleOpti(MBB);
1989 if (STI->hasV5TOps())
1990 Modified |= MergeReturnIntoLDM(MBB);
1992 Modified |= CombineMovBx(MBB);
1999 #define ARM_PREALLOC_LOAD_STORE_OPT_NAME \ 2000 "ARM pre- register allocation load / store optimization pass" 2021 StringRef getPassName()
const override {
2032 unsigned &NewOpc,
unsigned &EvenReg,
2033 unsigned &OddReg,
unsigned &BaseReg,
2039 unsigned Base,
bool isLd,
2055 TD = &Fn.getDataLayout();
2056 STI = &
static_cast<const ARMSubtarget &
>(Fn.getSubtarget());
2057 TII = STI->getInstrInfo();
2058 TRI = STI->getRegisterInfo();
2059 MRI = &Fn.getRegInfo();
2061 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2065 Modified |= RescheduleLoadStoreInstrs(&MFI);
2080 if (I->isDebugInstr() || MemOps.
count(&*I))
2082 if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects())
2084 if (I->mayStore() || (!isLd && I->mayLoad()))
2086 if (I->mayAlias(AA, *MemOp,
false))
2088 for (
unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
2095 if (Reg != Base && !MemRegs.
count(Reg))
2096 AddedRegPressure.
insert(Reg);
2101 if (MemRegs.
size() <= 4)
2104 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2111 unsigned &SecondReg,
2112 unsigned &BaseReg,
int &Offset,
2117 if (!STI->hasV5TEOps())
2123 if (Opcode == ARM::LDRi12) {
2125 }
else if (Opcode == ARM::STRi12) {
2127 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2128 NewOpc = ARM::t2LDRDi8;
2131 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2132 NewOpc = ARM::t2STRDi8;
2147 const Function &Func = MF->getFunction();
2148 unsigned ReqAlign = STI->hasV6Ops()
2151 if (Align < ReqAlign)
2157 int Limit = (1 << 8) * Scale;
2158 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2167 int Limit = (1 << 8) * Scale;
2168 if (OffImm >= Limit || (OffImm & (Scale-1)))
2174 if (FirstReg == SecondReg)
2184 unsigned Base,
bool isLd,
2186 bool RetVal =
false;
2192 assert(LHS == RHS || LOffset != ROffset);
2193 return LOffset > ROffset;
2200 while (Ops.
size() > 1) {
2201 unsigned FirstLoc = ~0U;
2202 unsigned LastLoc = 0;
2206 unsigned LastOpcode = 0;
2207 unsigned LastBytes = 0;
2208 unsigned NumMove = 0;
2209 for (
int i = Ops.
size() - 1; i >= 0; --i) {
2214 if (LastOpcode && LSMOpcode != LastOpcode)
2221 if (Bytes != LastBytes || Offset != (LastOffset + (
int)Bytes))
2233 LastOpcode = LSMOpcode;
2235 unsigned Loc = MI2LocMap[
Op];
2236 if (Loc <= FirstLoc) {
2240 if (Loc >= LastLoc) {
2251 for (
size_t i = Ops.
size() - NumMove, e = Ops.
size(); i != e; ++i) {
2258 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2261 MemOps, MemRegs,
TRI, AA);
2263 for (
unsigned i = 0; i != NumMove; ++i)
2268 while (InsertPos != MBB->
end() &&
2269 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2276 unsigned FirstReg = 0, SecondReg = 0;
2277 unsigned BaseReg = 0, PredReg = 0;
2280 unsigned NewOpc = 0;
2283 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2284 FirstReg, SecondReg, BaseReg,
2285 Offset, PredReg, Pred, isT2)) {
2291 MRI->constrainRegClass(FirstReg, TRC);
2292 MRI->constrainRegClass(SecondReg, TRC);
2333 for (
unsigned i = 0; i != NumMove; ++i) {
2336 MBB->
splice(InsertPos, MBB, Op);
2340 NumLdStMoved += NumMove;
2351 bool RetVal =
false;
2363 for (; MBBI !=
E; ++MBBI) {
2372 MI2LocMap[&MI] = ++Loc;
2376 unsigned PredReg = 0;
2385 bool StopHere =
false;
2388 Base2LdsMap.
find(Base);
2389 if (BI != Base2LdsMap.
end()) {
2390 for (
unsigned i = 0, e = BI->second.
size(); i != e; ++i) {
2397 BI->second.push_back(&MI);
2399 Base2LdsMap[Base].push_back(&MI);
2404 Base2StsMap.
find(Base);
2405 if (BI != Base2StsMap.
end()) {
2406 for (
unsigned i = 0, e = BI->second.
size(); i != e; ++i) {
2413 BI->second.push_back(&MI);
2415 Base2StsMap[Base].push_back(&MI);
2429 for (
unsigned i = 0, e = LdBases.
size(); i != e; ++i) {
2430 unsigned Base = LdBases[i];
2433 RetVal |= RescheduleOps(MBB, Lds, Base,
true, MI2LocMap);
2437 for (
unsigned i = 0, e = StBases.
size(); i != e; ++i) {
2438 unsigned Base = StBases[i];
2441 RetVal |= RescheduleOps(MBB, Sts, Base,
false, MI2LocMap);
2445 Base2LdsMap.
clear();
2446 Base2StsMap.
clear();
2458 return new ARMPreAllocLoadStoreOpt();
2459 return new ARMLoadStoreOpt();
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand *> MMOs) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
A parsed version of the target data layout string in and methods for querying it. ...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
static bool isT1i32Load(unsigned Opc)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
bool isCall(QueryType Type=AnyInBundle) const
This class represents lattice values for constants.
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, unsigned Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before...
static unsigned getImmScale(unsigned Opc)
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
const ARMTargetLowering * getTargetLowering() const override
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
static IntegerType * getInt64Ty(LLVMContext &C)
static int isIncrementOrDecrement(const MachineInstr &MI, unsigned Reg, ARMCC::CondCodes Pred, unsigned PredReg)
Check if the given instruction increments or decrements a register and return the amount it is increm...
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
AnalysisUsage & addRequired()
static uint32_t getAlignment(const MCSectionCOFF &Sec)
A description of a memory reference used in the backend.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, MachineBasicBlock::iterator I, MachineBasicBlock::iterator E, SmallPtrSetImpl< MachineInstr *> &MemOps, SmallSet< unsigned, 4 > &MemRegs, const TargetRegisterInfo *TRI, AliasAnalysis *AA)
A Use represents the edge between a Value definition and its users.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Position
Position to insert a new instruction relative to an existing instruction.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode)
unsigned char getAM3Offset(unsigned AM3Opc)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
iterator getLastNonDebugInstr()
Returns an iterator to the last non-debug instruction in the basic block, or end().
unsigned getUndefRegState(bool B)
Analysis containing CSE Info
unsigned getKillRegState(bool B)
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
TargetInstrInfo - Interface to description of machine instruction set.
iterator find(const_arg_type_t< KeyT > Val)
#define ARM_PREALLOC_LOAD_STORE_OPT_NAME
unsigned getDeadRegState(bool B)
unsigned getDefRegState(bool B)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
MachineInstrBundleIterator< MachineInstr > iterator
unsigned char getAM5Offset(unsigned AM5Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
unsigned const MachineRegisterInfo * MRI
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool isT2i32Load(unsigned Opc)
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< iterator, bool > insert(const ValueT &V)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Register is known to be fully dead.
Represent the analysis usage information of a pass.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, unsigned &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition, otherwise returns AL.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static bool isMemoryOp(const MachineInstr &MI)
Returns true if instruction is a memory operation that this pass is capable of operating on...
bool isDebugInstr() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t getAlignment() const
Return the minimum known alignment in bytes of the actual memory reference.
static cl::opt< bool > AssumeMisalignedLoadStores("arm-assume-misaligned-load-store", cl::Hidden, cl::init(false), cl::desc("Be more conservative in ARM load/store opt"))
This switch disables formation of double/multi instructions that could potentially lead to (new) alig...
FunctionPass * createARMLoadStoreOptimizationPass(bool PreAlloc=false)
Returns an instance of the load / store optimization pass.
void sort(IteratorTy Start, IteratorTy End)
static bool mayCombineMisaligned(const TargetSubtargetInfo &STI, const MachineInstr &MI)
Return true for loads/stores that can be combined to a double/multi operation without increasing the ...
static MachineBasicBlock::iterator findIncDecBefore(MachineBasicBlock::iterator MBBI, unsigned Reg, ARMCC::CondCodes Pred, unsigned PredReg, int &Offset)
Searches for an increment or decrement of Reg before MBBI.
static bool isi32Store(unsigned Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static void InsertLDR_STR(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int Offset, bool isDef, unsigned NewOpc, unsigned Reg, bool RegDeadKill, bool RegUndef, unsigned BaseReg, bool BaseKill, bool BaseUndef, ARMCC::CondCodes Pred, unsigned PredReg, const TargetInstrInfo *TII)
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
bool regsOverlap(unsigned regA, unsigned regB) const
Returns true if the two registers are equal or alias each other.
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly. ...
INITIALIZE_PASS(ARMLoadStoreOpt, "arm-ldst-opt", ARM_LOAD_STORE_OPT_NAME, false, false) static bool definesCPSR(const MachineInstr &MI)
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
#define ARM_LOAD_STORE_OPT_NAME
unsigned getTransientStackAlignment() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
iterator_range< mop_iterator > implicit_operands()
static const MachineOperand & getLoadStoreBaseOp(const MachineInstr &MI)
unsigned succ_size() const
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineFunctionProperties & set(Property P)
TargetSubtargetInfo - Generic base class for all target subtargets.
static bool isARMLowRegister(unsigned Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
Representation of each machine instruction.
static bool isT2i32Store(unsigned Opc)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
static bool isValidLSDoubleOffset(int Offset)
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
LLVM_NODISCARD bool empty() const
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
void setReg(unsigned Reg)
Change the register this operand corresponds to.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
bool optForMinSize() const
Optimize this function for minimum size (-Oz).
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr *> OtherMIs) const
virtual const TargetFrameLowering * getFrameLowering() const
static bool isLoadSingle(unsigned Opc)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, ARM_AM::AMSubMode Mode)
static bool isi32Load(unsigned Opc)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getLSMultipleTransferSize(const MachineInstr *MI)
LLVM Value Representation.
static int getLoadStoreMultipleOpcode(unsigned Opcode, ARM_AM::AMSubMode Mode)
static const MachineOperand & getLoadStoreRegOp(const MachineInstr &MI)
static MachineBasicBlock::iterator findIncDecAfter(MachineBasicBlock::iterator MBBI, unsigned Reg, ARMCC::CondCodes Pred, unsigned PredReg, int &Offset)
Searches for a increment or decrement of Reg after MBBI.
StringRef - Represent a constant reference to a string, i.e.
AddrOpc getAM5Op(unsigned AM5Opc)
static bool isVolatile(Instruction *Inst)
static bool isT1i32Store(unsigned Opc)
static int getMemoryOpOffset(const MachineInstr &MI)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
const MachineOperand & getOperand(unsigned i) const
static bool ContainsReg(const ArrayRef< std::pair< unsigned, bool >> &Regs, unsigned Reg)
Properties which a MachineFunction may have at a given point in time.
This file describes how to lower LLVM code to machine code.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.