70 #define DEBUG_TYPE "arm-ldst-opt" 72 STATISTIC(NumLDMGened ,
"Number of ldm instructions generated");
73 STATISTIC(NumSTMGened ,
"Number of stm instructions generated");
74 STATISTIC(NumVLDMGened,
"Number of vldm instructions generated");
75 STATISTIC(NumVSTMGened,
"Number of vstm instructions generated");
76 STATISTIC(NumLdStMoved,
"Number of load / store instructions moved");
77 STATISTIC(NumLDRDFormed,
"Number of ldrd created before allocation");
78 STATISTIC(NumSTRDFormed,
"Number of strd created before allocation");
79 STATISTIC(NumLDRD2LDM,
"Number of ldrd instructions turned back into ldm");
80 STATISTIC(NumSTRD2STM,
"Number of strd instructions turned back into stm");
81 STATISTIC(NumLDRD2LDR,
"Number of ldrd instructions turned back into ldr's");
82 STATISTIC(NumSTRD2STR,
"Number of strd instructions turned back into str's");
93 #define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass" 112 bool RegClassInfoValid;
113 bool isThumb1, isThumb2;
129 struct MemOpQueueEntry {
134 MemOpQueueEntry(
MachineInstr &MI,
int Offset,
unsigned Position)
141 struct MergeCandidate {
146 unsigned LatestMIIdx;
149 unsigned EarliestMIIdx;
156 bool CanMergeToLSMulti;
159 bool CanMergeToLSDouble;
170 unsigned Base,
unsigned WordOffset,
174 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
176 ArrayRef<std::pair<unsigned, bool>> Regs,
180 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
182 ArrayRef<std::pair<unsigned, bool>> Regs,
184 void FormCandidates(
const MemOpQueue &MemOps);
185 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
204 for (
const auto &MO : MI.operands()) {
207 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
218 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
222 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
223 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
224 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
225 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
229 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
230 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
346 case ARM::tLDMIA_UPD:
347 case ARM::tSTMIA_UPD:
348 case ARM::t2LDMIA_RET:
350 case ARM::t2LDMIA_UPD:
352 case ARM::t2STMIA_UPD:
354 case ARM::VLDMSIA_UPD:
356 case ARM::VSTMSIA_UPD:
358 case ARM::VLDMDIA_UPD:
360 case ARM::VSTMDIA_UPD:
374 case ARM::t2LDMDB_UPD:
376 case ARM::t2STMDB_UPD:
377 case ARM::VLDMSDB_UPD:
378 case ARM::VSTMSDB_UPD:
379 case ARM::VLDMDDB_UPD:
380 case ARM::VSTMDDB_UPD:
392 return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;
396 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
404 return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;
408 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
416 return isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
464 case ARM::tLDMIA_UPD:
465 case ARM::tSTMIA_UPD:
487 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
490 for (; MBBI != MBB.
end(); ++MBBI) {
491 bool InsertSub =
false;
492 unsigned Opc = MBBI->getOpcode();
494 if (MBBI->readsRegister(Base)) {
497 Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;
499 Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;
501 if (IsLoad || IsStore) {
507 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
514 if (Offset >= 0 && !(IsStore && InstrSrcReg == Base))
518 }
else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&
519 !definesCPSR(*MBBI)) {
524 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
525 Offset = (Opc == ARM::tSUBi8) ?
526 MO.
getImm() + WordOffset * 4 :
527 MO.
getImm() - WordOffset * 4 ;
528 if (Offset >= 0 && TL->isLegalAddImmediate(Offset)) {
541 }
else if (definesCPSR(*MBBI) || MBBI->isCall() || MBBI->isBranch()) {
550 BuildMI(MBB, MBBI, DL,
TII->get(ARM::tSUBi8), Base)
553 .addImm(WordOffset * 4)
559 if (MBBI->killsRegister(Base) || MBBI->definesRegister(Base))
570 if (MBBI != MBB.
end()) --MBBI;
571 BuildMI(MBB, MBBI, DL,
TII->get(ARM::tSUBi8), Base)
574 .addImm(WordOffset * 4)
582 if (!RegClassInfoValid) {
583 RegClassInfo.runOnMachineFunction(*MF);
584 RegClassInfoValid =
true;
587 for (
unsigned Reg : RegClassInfo.getOrder(&RegClass))
588 if (!LiveRegs.contains(
Reg))
599 if (!LiveRegsValid) {
601 LiveRegs.addLiveOuts(MBB);
602 LiveRegPos = MBB.
end();
603 LiveRegsValid =
true;
606 while (LiveRegPos != Before) {
608 LiveRegs.stepBackward(*LiveRegPos);
614 for (
const std::pair<unsigned, bool> &R : Regs)
625 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
627 ArrayRef<std::pair<unsigned, bool>> Regs,
629 unsigned NumRegs = Regs.size();
634 bool SafeToClobberCPSR = !isThumb1 ||
638 bool Writeback = isThumb1;
644 assert(Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
645 if (Opcode == ARM::tLDRi)
647 else if (Opcode == ARM::tSTRi)
654 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
656 if (Offset == 4 && haveIBAndDA) {
658 }
else if (Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
660 }
else if (Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
663 }
else if (Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
676 if (!SafeToClobberCPSR)
683 NewBase = Regs[NumRegs-1].first;
687 moveLiveRegsBefore(MBB, InsertBefore);
691 for (
const std::pair<unsigned, bool> &R : Regs)
692 LiveRegs.addReg(R.first);
694 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
700 isThumb2 ? ARM::t2ADDri :
701 (isThumb1 && Base == ARM::SP) ? ARM::tADDrSPi :
702 (isThumb1 && Offset < 8) ? ARM::tADDi3 :
703 isThumb1 ? ARM::tADDi8 : ARM::ADDri;
708 isThumb2 ? ARM::t2SUBri :
709 (isThumb1 && Offset < 8 && Base != ARM::SP) ? ARM::tSUBi3 :
710 isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
713 if (!TL->isLegalAddImmediate(Offset))
719 bool KillOldBase = BaseKill &&
728 if (Base != NewBase &&
729 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
736 BuildMI(MBB, InsertBefore, DL,
TII->get(ARM::tMOVSr), NewBase)
739 BuildMI(MBB, InsertBefore, DL,
TII->get(ARM::tMOVr), NewBase)
747 if (BaseOpc == ARM::tADDrSPi) {
748 assert(Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
749 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
754 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
760 BuildMI(MBB, InsertBefore, DL,
TII->get(BaseOpc), NewBase)
786 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
792 assert(isThumb1 &&
"expected Writeback only inThumb1");
793 if (Opcode == ARM::tLDMIA) {
796 Opcode = ARM::tLDMIA_UPD;
799 MIB =
BuildMI(MBB, InsertBefore, DL,
TII->get(Opcode));
808 UpdateBaseRegUses(MBB, InsertBefore, DL, Base, NumRegs, Pred, PredReg);
811 MIB =
BuildMI(MBB, InsertBefore, DL,
TII->get(Opcode));
817 for (
const std::pair<unsigned, bool> &R : Regs)
827 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
829 ArrayRef<std::pair<unsigned, bool>> Regs,
832 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
833 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
837 TII->get(LoadStoreOpcode));
851 MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
863 bool IsKill = MO.
isKill();
866 Regs.
push_back(std::make_pair(Reg, IsKill));
893 iterator InsertBefore = std::next(iterator(LatestMI));
898 unsigned PredReg = 0;
902 if (Cand.CanMergeToLSDouble)
903 Merged = CreateLoadStoreDouble(MBB, InsertBefore, Offset, Base, BaseKill,
904 Opcode, Pred, PredReg, DL, Regs,
906 if (!Merged && Cand.CanMergeToLSMulti)
907 Merged = CreateLoadStoreMulti(MBB, InsertBefore, Offset, Base, BaseKill,
908 Opcode, Pred, PredReg, DL, Regs, Cand.Instrs);
914 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
915 bool EarliestAtBegin =
false;
916 if (EarliestI == MBB.
begin()) {
917 EarliestAtBegin =
true;
919 EarliestI = std::prev(EarliestI);
928 EarliestI = MBB.
begin();
930 EarliestI = std::next(EarliestI);
931 auto FixupRange =
make_range(EarliestI, iterator(Merged));
937 for (
unsigned &ImpDefReg : ImpDefs) {
939 if (!MO.isReg() || MO.getReg() != ImpDefReg)
950 for (
unsigned ImpDef : ImpDefs)
957 if (!MO.isReg() || !MO.isKill())
959 if (UsedRegs.
count(MO.getReg()))
973 return (Value % 4) == 0 && Value < 1024;
995 void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
1001 unsigned SIndex = 0;
1002 unsigned EIndex = MemOps.size();
1006 int Offset = MemOps[SIndex].Offset;
1010 :
TRI->getEncodingValue(PReg);
1011 unsigned Latest = SIndex;
1012 unsigned Earliest = SIndex;
1014 bool CanMergeToLSDouble =
1018 if (STI->isCortexM3() &&
isi32Load(Opcode) &&
1020 CanMergeToLSDouble =
false;
1022 bool CanMergeToLSMulti =
true;
1025 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1026 CanMergeToLSMulti =
false;
1030 if (PReg == ARM::SP || PReg == ARM::PC)
1031 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1035 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1050 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++Count) {
1051 int NewOffset = MemOps[
I].Offset;
1052 if (NewOffset != Offset + (
int)
Size)
1056 if (Reg == ARM::SP || Reg == ARM::PC)
1063 :
TRI->getEncodingValue(Reg);
1064 bool PartOfLSMulti = CanMergeToLSMulti;
1065 if (PartOfLSMulti) {
1067 if (RegNum <= PRegNum)
1068 PartOfLSMulti =
false;
1072 else if (!isNotVFP && RegNum != PRegNum+1)
1073 PartOfLSMulti =
false;
1076 bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;
1078 if (!PartOfLSMulti && !PartOfLSDouble)
1080 CanMergeToLSMulti &= PartOfLSMulti;
1081 CanMergeToLSDouble &= PartOfLSDouble;
1085 if (Position < MemOps[Latest].Position)
1087 else if (Position > MemOps[Earliest].Position)
1095 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1096 for (
unsigned C = SIndex, CE = SIndex + Count;
C < CE; ++
C)
1097 Candidate->Instrs.push_back(MemOps[
C].MI);
1098 Candidate->LatestMIIdx = Latest - SIndex;
1099 Candidate->EarliestMIIdx = Earliest - SIndex;
1100 Candidate->InsertPos = MemOps[Latest].Position;
1102 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1103 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1104 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1105 Candidates.push_back(Candidate);
1108 }
while (SIndex < EIndex);
1186 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1187 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1189 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1191 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1192 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1193 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1201 MIPredReg != PredReg)
1204 if (CheckCPSRDef && definesCPSR(MI))
1217 if (MBBI == BeginMBBI)
1222 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1226 return Offset == 0 ? EndMBBI : PrevMBBI;
1238 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1240 if (NextMBBI == EndMBBI)
1244 return Offset == 0 ? EndMBBI : NextMBBI;
1259 bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(
MachineInstr *
MI) {
1261 if (isThumb1)
return false;
1265 bool BaseKill = BaseOP.
isKill();
1266 unsigned PredReg = 0;
1284 if (Mode ==
ARM_AM::ia && Offset == -Bytes) {
1286 }
else if (Mode ==
ARM_AM::ib && Offset == -Bytes) {
1297 if (!STI->hasMinSize() || !BaseKill)
1300 bool HighRegsUsed =
false;
1303 HighRegsUsed =
true;
1308 MergeInstr = MBB.
end();
1313 if (MergeInstr != MBB.
end())
1314 MBB.
erase(MergeInstr);
1320 .addImm(Pred).
addReg(PredReg);
1337 return ARM::LDR_PRE_IMM;
1339 return ARM::STR_PRE_IMM;
1341 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1343 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1345 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1347 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1350 return ARM::t2LDR_PRE;
1353 return ARM::t2STR_PRE;
1362 return ARM::LDR_POST_IMM;
1364 return ARM::STR_POST_IMM;
1366 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1368 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1370 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1372 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1375 return ARM::t2LDR_POST;
1378 return ARM::t2STR_POST;
1385 bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(
MachineInstr *MI) {
1388 if (isThumb1)
return false;
1394 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1395 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1396 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1408 unsigned PredReg = 0;
1417 if (!isAM5 && Offset == Bytes) {
1419 }
else if (Offset == -Bytes) {
1423 if (Offset == Bytes) {
1425 }
else if (!isAM5 && Offset == -Bytes) {
1430 MBB.
erase(MergeInstr);
1444 .addImm(Pred).
addReg(PredReg)
1451 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1480 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1483 BuildMI(MBB, MBBI, DL,
TII->get(NewOpc), Base)
1492 BuildMI(MBB, MBBI, DL,
TII->get(NewOpc), Base)
1505 bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(
MachineInstr &MI)
const {
1507 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1508 "Must have t2STRDi8 or t2LDRDi8");
1518 if (Reg0Op.
getReg() == Base || Reg1Op.
getReg() == Base)
1529 if (Offset == 8 || Offset == -8) {
1530 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1533 if (Offset == 8 || Offset == -8) {
1534 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1538 MBB.
erase(MergeInstr);
1542 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1545 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1550 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1551 TII->get(NewOpc).getNumOperands() == 7 &&
1552 "Unexpected number of operands in Opcode specification.");
1622 bool isDef,
unsigned NewOpc,
unsigned Reg,
1623 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1654 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1661 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1662 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1666 bool Errata602117 = EvenReg == BaseReg &&
1667 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();
1669 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1670 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1672 if (!Errata602117 && !NonConsecutiveRegs)
1675 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1676 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1677 bool EvenDeadKill = isLd ?
1680 bool OddDeadKill = isLd ?
1683 bool BaseKill = BaseOp.
isKill();
1684 bool BaseUndef = BaseOp.
isUndef();
1686 "register offset not handled below");
1688 unsigned PredReg = 0;
1691 if (OddRegNum > EvenRegNum && OffImm == 0) {
1694 unsigned NewOpc = (isLd)
1695 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1696 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1698 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(NewOpc))
1700 .addImm(Pred).
addReg(PredReg)
1706 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(NewOpc))
1708 .addImm(Pred).
addReg(PredReg)
1718 unsigned NewOpc = (isLd)
1719 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1720 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1723 unsigned NewOpc2 = (isLd)
1724 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1725 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1728 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1729 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1730 InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
1731 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII, MI);
1732 InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
1733 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1736 if (OddReg == EvenReg && EvenDeadKill) {
1740 EvenDeadKill =
false;
1744 if (EvenReg == BaseReg)
1745 EvenDeadKill =
false;
1746 InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
1747 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
1749 InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
1750 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1759 MBBI = MBB.
erase(MBBI);
1767 unsigned CurrBase = 0;
1768 unsigned CurrOpc = ~0u;
1771 assert(Candidates.size() == 0);
1772 assert(MergeBaseCandidates.size() == 0);
1773 LiveRegsValid =
false;
1778 MBBI = std::prev(
I);
1779 if (FixInvalidRegPairOp(MBB, MBBI))
1784 unsigned Opcode = MBBI->getOpcode();
1788 unsigned PredReg = 0;
1791 if (CurrBase == 0) {
1796 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
1800 if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
1808 bool Overlap =
false;
1810 Overlap = (Base ==
Reg);
1812 for (
const MemOpQueueEntry &
E : MemOps) {
1813 if (
TRI->regsOverlap(Reg,
E.MI->getOperand(0).getReg())) {
1823 if (Offset > MemOps.back().Offset) {
1824 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
1827 MemOpQueue::iterator
MI, ME;
1828 for (MI = MemOps.begin(), ME = MemOps.end(); MI != ME; ++
MI) {
1829 if (Offset < MI->Offset) {
1833 if (Offset == MI->Offset) {
1839 if (MI != MemOps.end()) {
1840 MemOps.insert(MI, MemOpQueueEntry(*MBBI, Offset, Position));
1851 }
else if (MBBI->isDebugInstr()) {
1853 }
else if (MBBI->getOpcode() == ARM::t2LDRDi8 ||
1854 MBBI->getOpcode() == ARM::t2STRDi8) {
1857 MergeBaseCandidates.push_back(&*MBBI);
1861 if (MemOps.size() > 0) {
1862 FormCandidates(MemOps);
1870 if (MemOps.size() > 0)
1871 FormCandidates(MemOps);
1875 auto LessThan = [](
const MergeCandidate* M0,
const MergeCandidate *M1) {
1876 return M0->InsertPos < M1->InsertPos;
1881 bool Changed =
false;
1882 for (
const MergeCandidate *Candidate : Candidates) {
1883 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
1889 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
1890 MergeBaseUpdateLSDouble(*Merged);
1892 MergeBaseUpdateLSMultiple(Merged);
1895 if (MergeBaseUpdateLoadStore(MI))
1900 assert(Candidate->Instrs.size() == 1);
1901 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
1908 MergeBaseUpdateLSDouble(*MI);
1909 MergeBaseCandidates.clear();
1926 if (isThumb1)
return false;
1927 if (MBB.
empty())
return false;
1930 if (MBBI != MBB.
begin() && MBBI != MBB.
end() &&
1931 (MBBI->getOpcode() == ARM::BX_RET ||
1932 MBBI->getOpcode() == ARM::tBX_RET ||
1933 MBBI->getOpcode() == ARM::MOVPCLR)) {
1936 while (PrevI->isDebugInstr() && PrevI != MBB.
begin())
1940 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
1941 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
1942 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
1944 if (MO.
getReg() != ARM::LR)
1946 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
1947 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
1948 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
1959 if (
Info.getReg() == ARM::LR) {
1960 Info.setRestored(
false);
1972 if (MBBI == MBB.
begin() || MBBI == MBB.
end() ||
1973 MBBI->getOpcode() != ARM::tBX_RET)
1978 if (Prev->getOpcode() != ARM::tMOVr || !Prev->definesRegister(ARM::LR))
1981 for (
auto Use : Prev->uses())
1983 assert(STI->hasV4TOps());
1984 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
TII->get(ARM::tBX))
1987 .copyImplicitOps(*MBBI);
2004 TII = STI->getInstrInfo();
2005 TRI = STI->getRegisterInfo();
2007 RegClassInfoValid =
false;
2008 isThumb2 = AFI->isThumb2Function();
2009 isThumb1 = AFI->isThumbFunction() && !isThumb2;
2015 Modified |= LoadStoreMultipleOpti(MBB);
2016 if (STI->hasV5TOps())
2017 Modified |= MergeReturnIntoLDM(MBB);
2019 Modified |= CombineMovBx(MBB);
2026 #define ARM_PREALLOC_LOAD_STORE_OPT_NAME \ 2027 "ARM pre- register allocation load / store optimization pass" 2048 StringRef getPassName()
const override {
2059 unsigned &NewOpc,
unsigned &EvenReg,
2060 unsigned &OddReg,
unsigned &BaseReg,
2066 unsigned Base,
bool isLd,
2083 bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn) {
2089 TII = STI->getInstrInfo();
2090 TRI = STI->getRegisterInfo();
2093 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2097 Modified |= RescheduleLoadStoreInstrs(&MFI);
2112 if (I->isDebugInstr() || MemOps.
count(&*I))
2114 if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects())
2116 if (I->mayStore() || (!isLd && I->mayLoad()))
2118 if (I->mayAlias(AA, *MemOp,
false))
2120 for (
unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
2127 if (Reg != Base && !MemRegs.
count(Reg))
2128 AddedRegPressure.
insert(Reg);
2133 if (MemRegs.
size() <= 4)
2136 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2143 unsigned &SecondReg,
2144 unsigned &BaseReg,
int &Offset,
2149 if (!STI->hasV5TEOps())
2155 if (Opcode == ARM::LDRi12) {
2157 }
else if (Opcode == ARM::STRi12) {
2159 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2160 NewOpc = ARM::t2LDRDi8;
2163 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2164 NewOpc = ARM::t2STRDi8;
2180 const Function &Func = MF->getFunction();
2181 unsigned ReqAlign = STI->hasV6Ops()
2184 if (Align < ReqAlign)
2190 int Limit = (1 << 8) * Scale;
2191 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2200 int Limit = (1 << 8) * Scale;
2201 if (OffImm >= Limit || (OffImm & (Scale-1)))
2207 if (FirstReg == SecondReg)
2217 unsigned Base,
bool isLd,
2219 bool RetVal =
false;
2225 assert(LHS == RHS || LOffset != ROffset);
2226 return LOffset > ROffset;
2233 while (Ops.
size() > 1) {
2234 unsigned FirstLoc = ~0U;
2235 unsigned LastLoc = 0;
2239 unsigned LastOpcode = 0;
2240 unsigned LastBytes = 0;
2241 unsigned NumMove = 0;
2242 for (
int i = Ops.
size() - 1; i >= 0; --i) {
2247 if (LastOpcode && LSMOpcode != LastOpcode)
2254 if (Bytes != LastBytes || Offset != (LastOffset + (
int)Bytes))
2259 if (NumMove == InstReorderLimit)
2266 LastOpcode = LSMOpcode;
2268 unsigned Loc = MI2LocMap[
Op];
2269 if (Loc <= FirstLoc) {
2273 if (Loc >= LastLoc) {
2284 for (
size_t i = Ops.
size() - NumMove,
e = Ops.
size(); i !=
e; ++i) {
2291 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2294 MemOps, MemRegs,
TRI, AA);
2296 for (
unsigned i = 0; i != NumMove; ++i)
2301 while (InsertPos != MBB->
end() &&
2302 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2309 unsigned FirstReg = 0, SecondReg = 0;
2310 unsigned BaseReg = 0, PredReg = 0;
2313 unsigned NewOpc = 0;
2316 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2317 FirstReg, SecondReg, BaseReg,
2318 Offset, PredReg, Pred, isT2)) {
2324 MRI->constrainRegClass(FirstReg, TRC);
2325 MRI->constrainRegClass(SecondReg, TRC);
2366 for (
unsigned i = 0; i != NumMove; ++i) {
2369 MBB->
splice(InsertPos, MBB, Op);
2373 NumLdStMoved += NumMove;
2384 bool RetVal =
false;
2390 Base2InstMap Base2LdsMap;
2391 Base2InstMap Base2StsMap;
2399 for (; MBBI !=
E; ++MBBI) {
2408 MI2LocMap[&MI] = ++Loc;
2412 unsigned PredReg = 0;
2420 bool StopHere =
false;
2421 auto FindBases = [&] (Base2InstMap &Base2Ops, BaseVec &Bases) {
2422 MapIt BI = Base2Ops.find(Base);
2423 if (BI == Base2Ops.end()) {
2424 Base2Ops[Base].push_back(&MI);
2425 Bases.push_back(Base);
2428 for (
unsigned i = 0,
e = BI->second.size(); i !=
e; ++i) {
2435 BI->second.push_back(&MI);
2439 FindBases(Base2LdsMap, LdBases);
2441 FindBases(Base2StsMap, StBases);
2452 for (
unsigned i = 0,
e = LdBases.size(); i !=
e; ++i) {
2453 unsigned Base = LdBases[i];
2456 RetVal |= RescheduleOps(MBB, Lds, Base,
true, MI2LocMap);
2460 for (
unsigned i = 0,
e = StBases.size(); i !=
e; ++i) {
2461 unsigned Base = StBases[i];
2464 RetVal |= RescheduleOps(MBB, Sts, Base,
false, MI2LocMap);
2468 Base2LdsMap.clear();
2469 Base2StsMap.clear();
2481 return new ARMPreAllocLoadStoreOpt();
2482 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. ...
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
static bool isT1i32Load(unsigned Opc)
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.
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...
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher...
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...
bool regsOverlap(Register regA, Register regB) const
Returns true if the two registers are equal or alias each other.
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().
void setReg(Register Reg)
Change the register this operand corresponds to.
unsigned getUndefRegState(bool B)
Analysis containing CSE Info
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getKillRegState(bool B)
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
TargetInstrInfo - Interface to description of machine instruction set.
#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.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
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 isAtomic(Instruction *I)
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
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.
Align max(MaybeAlign Lhs, Align Rhs)
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
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)
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.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
virtual const TargetFrameLowering * getFrameLowering() const
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr *> OtherMIs) const
static bool isLoadSingle(unsigned Opc)
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.
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, MachineInstr *MI)
AddrOpc getAM5Op(unsigned AM5Opc)
Register getReg() const
getReg - Returns the register number.
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
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
static bool ContainsReg(const ArrayRef< std::pair< unsigned, bool >> &Regs, unsigned Reg)
Properties which a MachineFunction may have at a given point in time.
Wrapper class representing virtual and physical registers.
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.