72#define DEBUG_TYPE "arm-ldst-opt"
74STATISTIC(NumLDMGened ,
"Number of ldm instructions generated");
75STATISTIC(NumSTMGened ,
"Number of stm instructions generated");
76STATISTIC(NumVLDMGened,
"Number of vldm instructions generated");
77STATISTIC(NumVSTMGened,
"Number of vstm instructions generated");
78STATISTIC(NumLdStMoved,
"Number of load / store instructions moved");
79STATISTIC(NumLDRDFormed,
"Number of ldrd created before allocation");
80STATISTIC(NumSTRDFormed,
"Number of strd created before allocation");
81STATISTIC(NumLDRD2LDM,
"Number of ldrd instructions turned back into ldm");
82STATISTIC(NumSTRD2STM,
"Number of strd instructions turned back into stm");
83STATISTIC(NumLDRD2LDR,
"Number of ldrd instructions turned back into ldr's");
84STATISTIC(NumSTRD2STR,
"Number of strd instructions turned back into str's");
95#define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass"
114 bool RegClassInfoValid;
115 bool isThumb1, isThumb2;
123 MachineFunctionProperties::Property::NoVRegs);
131 struct MemOpQueueEntry {
137 :
MI(&
MI), Offset(Offset), Position(Position) {}
143 struct MergeCandidate {
148 unsigned LatestMIIdx;
151 unsigned EarliestMIIdx;
158 bool CanMergeToLSMulti;
161 bool CanMergeToLSDouble;
172 unsigned Base,
unsigned WordOffset,
176 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
178 ArrayRef<std::pair<unsigned, bool>> Regs,
182 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
184 ArrayRef<std::pair<unsigned, bool>> Regs,
186 void FormCandidates(
const MemOpQueue &MemOps);
187 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
200char ARMLoadStoreOpt::ID = 0;
206 for (
const auto &MO :
MI.operands()) {
209 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
219 unsigned Opcode =
MI.getOpcode();
220 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
221 unsigned NumOperands =
MI.getDesc().getNumOperands();
222 unsigned OffField =
MI.getOperand(NumOperands - 3).getImm();
224 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
225 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
226 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
227 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
231 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
232 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
247 return MI.getOperand(1);
251 return MI.getOperand(0);
348 case ARM::tLDMIA_UPD:
349 case ARM::tSTMIA_UPD:
350 case ARM::t2LDMIA_RET:
352 case ARM::t2LDMIA_UPD:
354 case ARM::t2STMIA_UPD:
356 case ARM::VLDMSIA_UPD:
358 case ARM::VSTMSIA_UPD:
360 case ARM::VLDMDIA_UPD:
362 case ARM::VSTMDIA_UPD:
376 case ARM::t2LDMDB_UPD:
378 case ARM::t2STMDB_UPD:
379 case ARM::VLDMSDB_UPD:
380 case ARM::VSTMSDB_UPD:
381 case ARM::VLDMDDB_UPD:
382 case ARM::VSTMDDB_UPD:
394 return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;
398 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
406 return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;
410 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
418 return isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
439 switch (
MI->getOpcode()) {
466 case ARM::tLDMIA_UPD:
467 case ARM::tSTMIA_UPD:
474 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 4;
477 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 8;
489 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
493 bool InsertSub =
false;
494 unsigned Opc =
MBBI->getOpcode();
496 if (
MBBI->readsRegister(
Base,
nullptr)) {
499 Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;
501 Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;
503 if (IsLoad || IsStore) {
509 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
516 if (
Offset >= 0 && !(IsStore && InstrSrcReg ==
Base))
520 }
else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&
521 !definesCPSR(*
MBBI)) {
526 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
527 Offset = (Opc == ARM::tSUBi8) ?
528 MO.
getImm() + WordOffset * 4 :
529 MO.
getImm() - WordOffset * 4 ;
543 }
else if (definesCPSR(*
MBBI) ||
MBBI->isCall() ||
MBBI->isBranch()) {
561 if (
MBBI->killsRegister(
Base,
nullptr) ||
562 MBBI->definesRegister(
Base,
nullptr))
585 if (!RegClassInfoValid) {
586 RegClassInfo.runOnMachineFunction(*MF);
587 RegClassInfoValid =
true;
590 for (
unsigned Reg : RegClassInfo.getOrder(&RegClass))
591 if (LiveRegs.available(Reg) && !MF->getRegInfo().isReserved(Reg))
602 if (!LiveRegsValid) {
604 LiveRegs.addLiveOuts(
MBB);
606 LiveRegsValid =
true;
609 while (LiveRegPos !=
Before) {
611 LiveRegs.stepBackward(*LiveRegPos);
617 for (
const std::pair<unsigned, bool> &R : Regs)
628 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
630 ArrayRef<std::pair<unsigned, bool>> Regs,
632 unsigned NumRegs = Regs.size();
637 bool SafeToClobberCPSR = !isThumb1 ||
641 bool Writeback = isThumb1;
647 assert(
Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
648 if (Opcode == ARM::tLDRi)
650 else if (Opcode == ARM::tSTRi)
657 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
659 if (
Offset == 4 && haveIBAndDA) {
661 }
else if (
Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
663 }
else if (
Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
666 }
else if (
Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
679 if (!SafeToClobberCPSR)
686 NewBase = Regs[NumRegs-1].first;
690 moveLiveRegsBefore(
MBB, InsertBefore);
694 for (
const std::pair<unsigned, bool> &R : Regs)
695 LiveRegs.addReg(
R.first);
697 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
702 int BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2ADDspImm
704 : (isThumb1 &&
Base == ARM::SP)
706 : (isThumb1 &&
Offset < 8)
708 : isThumb1 ? ARM::tADDi8 : ARM::ADDri;
714 BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2SUBspImm
718 : isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
721 if (!TL->isLegalAddImmediate(
Offset))
727 bool KillOldBase = BaseKill &&
736 if (
Base != NewBase &&
737 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
755 if (BaseOpc == ARM::tADDrSPi) {
756 assert(
Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
794 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
800 assert(isThumb1 &&
"expected Writeback only inThumb1");
801 if (Opcode == ARM::tLDMIA) {
804 Opcode = ARM::tLDMIA_UPD;
816 UpdateBaseRegUses(
MBB, InsertBefore,
DL,
Base, NumRegs, Pred, PredReg);
825 for (
const std::pair<unsigned, bool> &R : Regs)
835 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
837 ArrayRef<std::pair<unsigned, bool>> Regs,
840 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
841 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
845 TII->get(LoadStoreOpcode));
859MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
861 unsigned Opcode =
First->getOpcode();
871 bool IsKill = MO.
isKill();
874 Regs.
push_back(std::make_pair(Reg, IsKill));
890 if (
MI->readsRegister(DefReg,
nullptr))
901 iterator InsertBefore = std::next(iterator(LatestMI));
910 if (Cand.CanMergeToLSDouble)
911 Merged = CreateLoadStoreDouble(
MBB, InsertBefore,
Offset,
Base, BaseKill,
912 Opcode, Pred, PredReg,
DL, Regs,
914 if (!Merged && Cand.CanMergeToLSMulti)
915 Merged = CreateLoadStoreMulti(
MBB, InsertBefore,
Offset,
Base, BaseKill,
916 Opcode, Pred, PredReg,
DL, Regs, Cand.Instrs);
922 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
923 bool EarliestAtBegin =
false;
925 EarliestAtBegin =
true;
927 EarliestI = std::prev(EarliestI);
938 EarliestI = std::next(EarliestI);
939 auto FixupRange =
make_range(EarliestI, iterator(Merged));
945 for (
unsigned &ImpDefReg : ImpDefs) {
958 for (
unsigned ImpDef : ImpDefs)
990 unsigned Opcode =
MI.getOpcode();
1003void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
1009 unsigned SIndex = 0;
1010 unsigned EIndex = MemOps.size();
1014 int Offset = MemOps[SIndex].Offset;
1017 unsigned PRegNum = PMO.
isUndef() ? std::numeric_limits<unsigned>::max()
1018 :
TRI->getEncodingValue(PReg);
1019 unsigned Latest = SIndex;
1020 unsigned Earliest = SIndex;
1022 bool CanMergeToLSDouble =
1026 if (STI->isCortexM3() &&
isi32Load(Opcode) &&
1028 CanMergeToLSDouble =
false;
1030 bool CanMergeToLSMulti =
true;
1033 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1034 CanMergeToLSMulti =
false;
1038 if (PReg == ARM::SP || PReg == ARM::PC)
1039 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1043 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1058 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++Count) {
1059 int NewOffset = MemOps[
I].Offset;
1064 if (Reg == ARM::SP || Reg == ARM::PC)
1070 unsigned RegNum = MO.
isUndef() ? std::numeric_limits<unsigned>::max()
1071 :
TRI->getEncodingValue(
Reg);
1072 bool PartOfLSMulti = CanMergeToLSMulti;
1073 if (PartOfLSMulti) {
1075 if (RegNum <= PRegNum)
1076 PartOfLSMulti =
false;
1080 else if (!isNotVFP && RegNum != PRegNum+1)
1081 PartOfLSMulti =
false;
1084 bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;
1086 if (!PartOfLSMulti && !PartOfLSDouble)
1088 CanMergeToLSMulti &= PartOfLSMulti;
1089 CanMergeToLSDouble &= PartOfLSDouble;
1092 unsigned Position = MemOps[
I].Position;
1093 if (Position < MemOps[Latest].Position)
1095 else if (Position > MemOps[Earliest].Position)
1103 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1104 for (
unsigned C = SIndex, CE = SIndex + Count;
C <
CE; ++
C)
1105 Candidate->Instrs.push_back(MemOps[
C].MI);
1106 Candidate->LatestMIIdx = Latest - SIndex;
1107 Candidate->EarliestMIIdx = Earliest - SIndex;
1108 Candidate->InsertPos = MemOps[Latest].Position;
1110 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1111 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1112 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1113 Candidates.push_back(Candidate);
1116 }
while (SIndex < EIndex);
1193 switch (
MI.getOpcode()) {
1194 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1195 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1197 case ARM::t2SUBspImm:
1198 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1200 case ARM::t2ADDspImm:
1201 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1202 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1203 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1208 if (
MI.getOperand(0).getReg() != Reg ||
1209 MI.getOperand(1).getReg() != Reg ||
1211 MIPredReg != PredReg)
1214 if (CheckCPSRDef && definesCPSR(
MI))
1216 return MI.getOperand(2).getImm() * Scale;
1227 if (
MBBI == BeginMBBI)
1232 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1236 return Offset == 0 ? EndMBBI : PrevMBBI;
1248 while (NextMBBI != EndMBBI) {
1250 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1252 if (NextMBBI == EndMBBI)
1266 if (Reg == ARM::SP || NextMBBI->readsRegister(Reg,
TRI) ||
1267 NextMBBI->definesRegister(Reg,
TRI))
1287bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(
MachineInstr *
MI) {
1289 if (isThumb1)
return false;
1294 bool BaseKill = BaseOP.
isKill();
1297 unsigned Opcode =
MI->getOpcode();
1326 if (!STI->hasMinSize() || !BaseKill)
1329 bool HighRegsUsed =
false;
1331 if (MO.
getReg() >= ARM::R8) {
1332 HighRegsUsed =
true;
1342 if (MergeInstr !=
MBB.
end()) {
1369 return ARM::LDR_PRE_IMM;
1371 return ARM::STR_PRE_IMM;
1373 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1375 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1377 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1379 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1382 return ARM::t2LDR_PRE;
1385 return ARM::t2STR_PRE;
1394 return ARM::LDR_POST_IMM;
1396 return ARM::STR_POST_IMM;
1398 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1400 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1402 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1404 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1407 return ARM::t2LDR_POST;
1409 case ARM::t2LDRBi12:
1410 return ARM::t2LDRB_POST;
1411 case ARM::t2LDRSBi8:
1412 case ARM::t2LDRSBi12:
1413 return ARM::t2LDRSB_POST;
1415 case ARM::t2LDRHi12:
1416 return ARM::t2LDRH_POST;
1417 case ARM::t2LDRSHi8:
1418 case ARM::t2LDRSHi12:
1419 return ARM::t2LDRSH_POST;
1422 return ARM::t2STR_POST;
1424 case ARM::t2STRBi12:
1425 return ARM::t2STRB_POST;
1427 case ARM::t2STRHi12:
1428 return ARM::t2STRH_POST;
1430 case ARM::MVE_VLDRBS16:
1431 return ARM::MVE_VLDRBS16_post;
1432 case ARM::MVE_VLDRBS32:
1433 return ARM::MVE_VLDRBS32_post;
1434 case ARM::MVE_VLDRBU16:
1435 return ARM::MVE_VLDRBU16_post;
1436 case ARM::MVE_VLDRBU32:
1437 return ARM::MVE_VLDRBU32_post;
1438 case ARM::MVE_VLDRHS32:
1439 return ARM::MVE_VLDRHS32_post;
1440 case ARM::MVE_VLDRHU32:
1441 return ARM::MVE_VLDRHU32_post;
1442 case ARM::MVE_VLDRBU8:
1443 return ARM::MVE_VLDRBU8_post;
1444 case ARM::MVE_VLDRHU16:
1445 return ARM::MVE_VLDRHU16_post;
1446 case ARM::MVE_VLDRWU32:
1447 return ARM::MVE_VLDRWU32_post;
1448 case ARM::MVE_VSTRB16:
1449 return ARM::MVE_VSTRB16_post;
1450 case ARM::MVE_VSTRB32:
1451 return ARM::MVE_VSTRB32_post;
1452 case ARM::MVE_VSTRH32:
1453 return ARM::MVE_VSTRH32_post;
1454 case ARM::MVE_VSTRBU8:
1455 return ARM::MVE_VSTRBU8_post;
1456 case ARM::MVE_VSTRHU16:
1457 return ARM::MVE_VSTRHU16_post;
1458 case ARM::MVE_VSTRWU32:
1459 return ARM::MVE_VSTRWU32_post;
1467bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(
MachineInstr *
MI) {
1470 if (isThumb1)
return false;
1475 unsigned Opcode =
MI->getOpcode();
1477 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1478 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1479 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1481 if (
MI->getOperand(2).getImm() != 0)
1488 if (
MI->getOperand(0).getReg() ==
Base)
1500 if (!isAM5 &&
Offset == Bytes) {
1502 }
else if (
Offset == -Bytes) {
1506 if (MergeInstr ==
MBB.
end())
1510 if ((isAM5 &&
Offset != Bytes) ||
1542 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1583 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1612bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(
MachineInstr &
MI)
const {
1613 unsigned Opcode =
MI.getOpcode();
1614 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1615 "Must have t2STRDi8 or t2LDRDi8");
1616 if (
MI.getOperand(3).getImm() != 0)
1638 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1641 if (MergeInstr ==
MBB.
end())
1643 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1652 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1655 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1660 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1661 TII->get(NewOpc).getNumOperands() == 7 &&
1662 "Unexpected number of operands in Opcode specification.");
1677 unsigned Opcode =
MI.getOpcode();
1697 if (!
MI.getOperand(1).isReg())
1702 if (!
MI.hasOneMemOperand())
1721 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isUndef())
1725 if (
MI.getOperand(1).isUndef())
1733 bool isDef,
unsigned NewOpc,
unsigned Reg,
1734 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1762 unsigned Opcode =
MI->getOpcode();
1765 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1770 Register EvenReg =
MI->getOperand(0).getReg();
1771 Register OddReg =
MI->getOperand(1).getReg();
1772 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1773 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1777 bool Errata602117 = EvenReg == BaseReg &&
1778 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();
1780 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1781 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1783 if (!Errata602117 && !NonConsecutiveRegs)
1786 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1787 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1788 bool EvenDeadKill = isLd ?
1789 MI->getOperand(0).isDead() :
MI->getOperand(0).isKill();
1790 bool EvenUndef =
MI->getOperand(0).isUndef();
1791 bool OddDeadKill = isLd ?
1792 MI->getOperand(1).isDead() :
MI->getOperand(1).isKill();
1793 bool OddUndef =
MI->getOperand(1).isUndef();
1794 bool BaseKill = BaseOp.
isKill();
1795 bool BaseUndef = BaseOp.
isUndef();
1796 assert((isT2 ||
MI->getOperand(3).getReg() == ARM::NoRegister) &&
1797 "register offset not handled below");
1802 if (OddRegNum > EvenRegNum && OffImm == 0) {
1805 unsigned NewOpc = (isLd)
1806 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1807 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1829 unsigned NewOpc = (isLd)
1830 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1831 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1834 unsigned NewOpc2 = (isLd)
1835 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1836 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1839 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1840 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1842 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
MI);
1844 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1847 if (OddReg == EvenReg && EvenDeadKill) {
1851 EvenDeadKill =
false;
1855 if (EvenReg == BaseReg)
1856 EvenDeadKill =
false;
1858 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
1861 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1878 unsigned CurrBase = 0;
1879 unsigned CurrOpc = ~0
u;
1881 unsigned Position = 0;
1882 assert(Candidates.size() == 0);
1883 assert(MergeBaseCandidates.size() == 0);
1884 LiveRegsValid =
false;
1889 MBBI = std::prev(
I);
1890 if (FixInvalidRegPairOp(
MBB,
MBBI))
1895 unsigned Opcode =
MBBI->getOpcode();
1902 if (CurrBase == 0) {
1907 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1911 if (CurrOpc == Opcode && CurrBase ==
Base && CurrPred == Pred) {
1919 bool Overlap =
false;
1923 for (
const MemOpQueueEntry &E : MemOps) {
1924 if (
TRI->regsOverlap(Reg, E.MI->getOperand(0).getReg())) {
1934 if (
Offset > MemOps.back().Offset) {
1935 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1938 MemOpQueue::iterator
MI, ME;
1939 for (
MI = MemOps.begin(), ME = MemOps.end();
MI != ME; ++
MI) {
1940 if (Offset < MI->
Offset) {
1950 if (
MI != MemOps.end()) {
1951 MemOps.insert(
MI, MemOpQueueEntry(*
MBBI,
Offset, Position));
1962 }
else if (
MBBI->isDebugInstr()) {
1964 }
else if (
MBBI->getOpcode() == ARM::t2LDRDi8 ||
1965 MBBI->getOpcode() == ARM::t2STRDi8) {
1968 MergeBaseCandidates.push_back(&*
MBBI);
1972 if (MemOps.size() > 0) {
1973 FormCandidates(MemOps);
1981 if (MemOps.size() > 0)
1982 FormCandidates(MemOps);
1986 auto LessThan = [](
const MergeCandidate*
M0,
const MergeCandidate *
M1) {
1987 return M0->InsertPos <
M1->InsertPos;
1992 bool Changed =
false;
1993 for (
const MergeCandidate *Candidate : Candidates) {
1994 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
2000 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
2001 MergeBaseUpdateLSDouble(*Merged);
2003 MergeBaseUpdateLSMultiple(Merged);
2006 if (MergeBaseUpdateLoadStore(
MI))
2011 assert(Candidate->Instrs.size() == 1);
2012 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
2019 MergeBaseUpdateLSDouble(*
MI);
2020 MergeBaseCandidates.clear();
2037 if (isThumb1)
return false;
2042 (
MBBI->getOpcode() == ARM::BX_RET ||
2043 MBBI->getOpcode() == ARM::tBX_RET ||
2044 MBBI->getOpcode() == ARM::MOVPCLR)) {
2047 while (PrevI->isDebugInstr() && PrevI !=
MBB.
begin())
2051 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
2052 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
2053 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
2055 if (MO.
getReg() != ARM::LR)
2057 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
2058 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
2059 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
2073 MBBI->getOpcode() != ARM::tBX_RET)
2078 if (Prev->getOpcode() != ARM::tMOVr ||
2079 !Prev->definesRegister(ARM::LR,
nullptr))
2082 for (
auto Use : Prev->uses())
2084 assert(STI->hasV4TOps());
2105 TII = STI->getInstrInfo();
2106 TRI = STI->getRegisterInfo();
2108 RegClassInfoValid =
false;
2109 isThumb2 = AFI->isThumb2Function();
2110 isThumb1 = AFI->isThumbFunction() && !isThumb2;
2112 bool Modified =
false, ModifiedLDMReturn =
false;
2115 if (STI->hasV5TOps() && !AFI->shouldSignReturnAddress())
2116 ModifiedLDMReturn |= MergeReturnIntoLDM(
MBB);
2126 if (ModifiedLDMReturn)
2133#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \
2134 "ARM pre- register allocation load / store optimization pass"
2177 bool DistributeIncrements();
2183char ARMPreAllocLoadStoreOpt::ID = 0;
2194 cl::init(8), cl::Hidden);
2196bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn) {
2200 TD = &Fn.getDataLayout();
2202 TII = STI->getInstrInfo();
2203 TRI = STI->getRegisterInfo();
2204 MRI = &Fn.getRegInfo();
2205 DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2207 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2209 bool Modified = DistributeIncrements();
2211 Modified |= RescheduleLoadStoreInstrs(&MFI);
2226 if (
I->isDebugInstr() || MemOps.
count(&*
I))
2228 if (
I->isCall() ||
I->isTerminator() ||
I->hasUnmodeledSideEffects())
2230 if (
I->mayStore() || (!isLd &&
I->mayLoad()))
2232 if (
I->mayAlias(AA, *
MemOp,
false))
2234 for (
unsigned j = 0, NumOps =
I->getNumOperands(); j != NumOps; ++j) {
2242 AddedRegPressure.
insert(Reg);
2247 if (MemRegs.
size() <= 4)
2250 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2253bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
2258 if (!STI->hasV5TEOps())
2264 if (Opcode == ARM::LDRi12) {
2266 }
else if (Opcode == ARM::STRi12) {
2268 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2269 NewOpc = ARM::t2LDRDi8;
2272 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2273 NewOpc = ARM::t2STRDi8;
2289 Align ReqAlign = STI->getDualLoadStoreAlignment();
2290 if (Alignment < ReqAlign)
2296 int Limit = (1 << 8) * Scale;
2297 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2306 int Limit = (1 << 8) * Scale;
2307 if (OffImm >= Limit || (OffImm & (Scale-1)))
2313 if (FirstReg == SecondReg)
2321bool ARMPreAllocLoadStoreOpt::RescheduleOps(
2325 bool RetVal =
false;
2331 assert(LHS == RHS || LOffset != ROffset);
2332 return LOffset > ROffset;
2339 while (Ops.
size() > 1) {
2340 unsigned FirstLoc = ~0
U;
2341 unsigned LastLoc = 0;
2345 unsigned LastOpcode = 0;
2346 unsigned LastBytes = 0;
2347 unsigned NumMove = 0;
2352 if (LastOpcode && LSMOpcode != LastOpcode)
2359 if (Bytes != LastBytes ||
Offset != (LastOffset + (
int)Bytes))
2371 LastOpcode = LSMOpcode;
2373 unsigned Loc = MI2LocMap[
Op];
2374 if (Loc <= FirstLoc) {
2378 if (Loc >= LastLoc) {
2389 for (
size_t i = Ops.
size() - NumMove, e = Ops.
size(); i != e; ++i) {
2396 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2399 MemOps, MemRegs,
TRI, AA);
2401 for (
unsigned i = 0; i != NumMove; ++i)
2406 while (InsertPos !=
MBB->
end() &&
2407 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2418 unsigned NewOpc = 0;
2421 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2422 FirstReg, SecondReg, BaseReg,
2423 Offset, PredReg, Pred, isT2)) {
2429 MRI->constrainRegClass(FirstReg, TRC);
2430 MRI->constrainRegClass(SecondReg, TRC);
2471 for (
unsigned i = 0; i != NumMove; ++i) {
2483 NumLdStMoved += NumMove;
2494 if (
MI->isNonListDebugValue()) {
2495 auto &
Op =
MI->getOperand(0);
2499 for (
unsigned I = 2;
I <
MI->getNumOperands();
I++) {
2500 auto &
Op =
MI->getOperand(
I);
2514 auto RegIt = RegisterMap.find(
Op.getReg());
2515 if (RegIt == RegisterMap.end())
2517 auto &InstrVec = RegIt->getSecond();
2524 MI->getDebugLoc()->getInlinedAt());
2530 bool RetVal =
false;
2535 Base2InstMap Base2LdsMap;
2536 Base2InstMap Base2StsMap;
2550 if (
MI.isCall() ||
MI.isTerminator()) {
2556 if (!
MI.isDebugInstr())
2557 MI2LocMap[&
MI] = ++Loc;
2565 int Opc =
MI.getOpcode();
2569 bool StopHere =
false;
2570 auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
2573 BI->second.push_back(&
MI);
2574 Bases.push_back(
Base);
2584 BI->second.push_back(&
MI);
2588 FindBases(Base2LdsMap, LdBases);
2590 FindBases(Base2StsMap, StBases);
2601 for (
unsigned Base : LdBases) {
2604 RetVal |= RescheduleOps(
MBB, Lds,
Base,
true, MI2LocMap, RegisterMap);
2608 for (
unsigned Base : StBases) {
2611 RetVal |= RescheduleOps(
MBB, Sts,
Base,
false, MI2LocMap, RegisterMap);
2615 Base2LdsMap.clear();
2616 Base2StsMap.clear();
2779 auto PopulateRegisterAndInstrMapForDebugInstr = [&](
Register Reg) {
2780 auto RegIt = RegisterMap.
find(Reg);
2781 if (RegIt == RegisterMap.
end())
2783 auto &InstrVec = RegIt->getSecond();
2784 InstrVec.push_back(&
MI);
2785 InstrMap[&
MI].push_back(Reg);
2788 if (
MI.isDebugValue()) {
2790 "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");
2798 PopulateRegisterAndInstrMapForDebugInstr(
Op.getReg());
2806 auto InstrIt = DbgValueSinkCandidates.
find(DbgVar);
2807 if (InstrIt != DbgValueSinkCandidates.
end()) {
2808 auto *
Instr = InstrIt->getSecond();
2809 auto RegIt = InstrMap.
find(Instr);
2810 if (RegIt != InstrMap.
end()) {
2811 const auto &RegVec = RegIt->getSecond();
2814 for (
auto &Reg : RegVec) {
2815 auto RegIt = RegisterMap.
find(Reg);
2816 if (RegIt == RegisterMap.
end())
2818 auto &InstrVec = RegIt->getSecond();
2821 return Var == DbgVar;
2830 DbgValueSinkCandidates[DbgVar] = &
MI;
2834 auto Opc =
MI.getOpcode();
2837 auto Reg =
MI.getOperand(0).getReg();
2838 auto RegIt = RegisterMap.
find(Reg);
2839 if (RegIt == RegisterMap.
end())
2841 auto &DbgInstrVec = RegIt->getSecond();
2842 if (!DbgInstrVec.size())
2844 for (
auto *DbgInstr : DbgInstrVec) {
2846 auto *ClonedMI =
MI.getMF()->CloneMachineInstr(DbgInstr);
2852 auto DbgIt = DbgValueSinkCandidates.
find(DbgVar);
2856 if (DbgIt != DbgValueSinkCandidates.
end())
2857 DbgValueSinkCandidates.
erase(DbgIt);
2863 if (DbgInstr->isDebugValueList())
2877 switch (
MI.getOpcode()) {
2878 case ARM::MVE_VLDRBS16:
2879 case ARM::MVE_VLDRBS32:
2880 case ARM::MVE_VLDRBU16:
2881 case ARM::MVE_VLDRBU32:
2882 case ARM::MVE_VLDRHS32:
2883 case ARM::MVE_VLDRHU32:
2884 case ARM::MVE_VLDRBU8:
2885 case ARM::MVE_VLDRHU16:
2886 case ARM::MVE_VLDRWU32:
2887 case ARM::MVE_VSTRB16:
2888 case ARM::MVE_VSTRB32:
2889 case ARM::MVE_VSTRH32:
2890 case ARM::MVE_VSTRBU8:
2891 case ARM::MVE_VSTRHU16:
2892 case ARM::MVE_VSTRWU32:
2894 case ARM::t2LDRHi12:
2895 case ARM::t2LDRSHi8:
2896 case ARM::t2LDRSHi12:
2898 case ARM::t2LDRBi12:
2899 case ARM::t2LDRSBi8:
2900 case ARM::t2LDRSBi12:
2902 case ARM::t2STRBi12:
2904 case ARM::t2STRHi12:
2906 case ARM::MVE_VLDRBS16_post:
2907 case ARM::MVE_VLDRBS32_post:
2908 case ARM::MVE_VLDRBU16_post:
2909 case ARM::MVE_VLDRBU32_post:
2910 case ARM::MVE_VLDRHS32_post:
2911 case ARM::MVE_VLDRHU32_post:
2912 case ARM::MVE_VLDRBU8_post:
2913 case ARM::MVE_VLDRHU16_post:
2914 case ARM::MVE_VLDRWU32_post:
2915 case ARM::MVE_VSTRB16_post:
2916 case ARM::MVE_VSTRB32_post:
2917 case ARM::MVE_VSTRH32_post:
2918 case ARM::MVE_VSTRBU8_post:
2919 case ARM::MVE_VSTRHU16_post:
2920 case ARM::MVE_VSTRWU32_post:
2921 case ARM::MVE_VLDRBS16_pre:
2922 case ARM::MVE_VLDRBS32_pre:
2923 case ARM::MVE_VLDRBU16_pre:
2924 case ARM::MVE_VLDRBU32_pre:
2925 case ARM::MVE_VLDRHS32_pre:
2926 case ARM::MVE_VLDRHU32_pre:
2927 case ARM::MVE_VLDRBU8_pre:
2928 case ARM::MVE_VLDRHU16_pre:
2929 case ARM::MVE_VLDRWU32_pre:
2930 case ARM::MVE_VSTRB16_pre:
2931 case ARM::MVE_VSTRB32_pre:
2932 case ARM::MVE_VSTRH32_pre:
2933 case ARM::MVE_VSTRBU8_pre:
2934 case ARM::MVE_VSTRHU16_pre:
2935 case ARM::MVE_VSTRWU32_pre:
2942 switch (
MI.getOpcode()) {
2943 case ARM::MVE_VLDRBS16_post:
2944 case ARM::MVE_VLDRBS32_post:
2945 case ARM::MVE_VLDRBU16_post:
2946 case ARM::MVE_VLDRBU32_post:
2947 case ARM::MVE_VLDRHS32_post:
2948 case ARM::MVE_VLDRHU32_post:
2949 case ARM::MVE_VLDRBU8_post:
2950 case ARM::MVE_VLDRHU16_post:
2951 case ARM::MVE_VLDRWU32_post:
2952 case ARM::MVE_VSTRB16_post:
2953 case ARM::MVE_VSTRB32_post:
2954 case ARM::MVE_VSTRH32_post:
2955 case ARM::MVE_VSTRBU8_post:
2956 case ARM::MVE_VSTRHU16_post:
2957 case ARM::MVE_VSTRWU32_post:
2964 switch (
MI.getOpcode()) {
2965 case ARM::MVE_VLDRBS16_pre:
2966 case ARM::MVE_VLDRBS32_pre:
2967 case ARM::MVE_VLDRBU16_pre:
2968 case ARM::MVE_VLDRBU32_pre:
2969 case ARM::MVE_VLDRHS32_pre:
2970 case ARM::MVE_VLDRHU32_pre:
2971 case ARM::MVE_VLDRBU8_pre:
2972 case ARM::MVE_VLDRHU16_pre:
2973 case ARM::MVE_VLDRWU32_pre:
2974 case ARM::MVE_VSTRB16_pre:
2975 case ARM::MVE_VSTRB32_pre:
2976 case ARM::MVE_VSTRH32_pre:
2977 case ARM::MVE_VSTRBU8_pre:
2978 case ARM::MVE_VSTRHU16_pre:
2979 case ARM::MVE_VSTRWU32_pre:
2992 int &CodesizeEstimate) {
3001 CodesizeEstimate += 1;
3002 return Imm < 0 && -Imm < ((1 << 8) * 1);
3015 MI->getOperand(BaseOp).setReg(NewBaseReg);
3021 MRI.constrainRegClass(NewBaseReg, TRC);
3023 int OldOffset =
MI->getOperand(BaseOp + 1).getImm();
3025 MI->getOperand(BaseOp + 1).setImm(OldOffset -
Offset);
3027 unsigned ConvOpcode;
3028 switch (
MI->getOpcode()) {
3029 case ARM::t2LDRHi12:
3030 ConvOpcode = ARM::t2LDRHi8;
3032 case ARM::t2LDRSHi12:
3033 ConvOpcode = ARM::t2LDRSHi8;
3035 case ARM::t2LDRBi12:
3036 ConvOpcode = ARM::t2LDRBi8;
3038 case ARM::t2LDRSBi12:
3039 ConvOpcode = ARM::t2LDRSBi8;
3041 case ARM::t2STRHi12:
3042 ConvOpcode = ARM::t2STRHi8;
3044 case ARM::t2STRBi12:
3045 ConvOpcode = ARM::t2STRBi8;
3051 "Illegal Address Immediate after convert!");
3055 .
add(
MI->getOperand(0))
3056 .
add(
MI->getOperand(1))
3058 .
add(
MI->getOperand(3))
3059 .
add(
MI->getOperand(4))
3061 MI->eraseFromParent();
3078 MRI.constrainRegClass(NewReg, TRC);
3080 TRC =
TII->getRegClass(MCID, 2,
TRI, *MF);
3081 MRI.constrainRegClass(
MI->getOperand(1).getReg(), TRC);
3089 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3091 .
add(
MI->getOperand(0))
3092 .
add(
MI->getOperand(1))
3094 .
add(
MI->getOperand(3))
3095 .
add(
MI->getOperand(4))
3096 .
add(
MI->getOperand(5))
3099 if (
MI->mayLoad()) {
3100 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3101 .
add(
MI->getOperand(0))
3103 .
add(
MI->getOperand(1))
3105 .
add(
MI->getOperand(3))
3106 .
add(
MI->getOperand(4))
3109 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3111 .
add(
MI->getOperand(0))
3112 .
add(
MI->getOperand(1))
3114 .
add(
MI->getOperand(3))
3115 .
add(
MI->getOperand(4))
3139bool ARMPreAllocLoadStoreOpt::DistributeIncrements(
Register Base) {
3149 for (
auto &
Use :
MRI->use_nodbg_instructions(
Base)) {
3159 if (!
Use.getOperand(BaseOp).isReg() ||
3160 Use.getOperand(BaseOp).getReg() !=
Base)
3164 else if (
Use.getOperand(BaseOp + 1).getImm() == 0)
3170 int IncrementOffset;
3172 if (BaseAccess && Increment) {
3176 if (
Increment->definesRegister(ARM::CPSR,
nullptr) ||
3180 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on VirtualReg "
3181 <<
Base.virtRegIndex() <<
"\n");
3186 MRI->use_nodbg_instructions(
Increment->getOperand(0).getReg())) {
3187 if (&
Use == BaseAccess || (
Use.getOpcode() != TargetOpcode::PHI &&
3189 LLVM_DEBUG(
dbgs() <<
" BaseAccess doesn't dominate use of increment\n");
3199 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on postinc\n");
3203 else if (PrePostInc) {
3211 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on already "
3212 <<
"indexed VirtualReg " <<
Base.virtRegIndex() <<
"\n");
3215 BaseAccess = PrePostInc;
3230 int CodesizeEstimate = -1;
3231 for (
auto *
Use : OtherAccesses) {
3236 Use->getOperand(BaseOp + 1).getImm() -
3238 TII, CodesizeEstimate)) {
3239 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on use\n");
3244 dbgs() <<
" Unknown dominance relation between Base and Use\n");
3248 if (STI->hasMinSize() && CodesizeEstimate > 0) {
3249 LLVM_DEBUG(
dbgs() <<
" Expected to grow instructions under minsize\n");
3257 NewBaseReg =
Increment->getOperand(0).getReg();
3262 (void)BaseAccessPost;
3266 for (
auto *
Use : SuccessorAccesses) {
3275 Op.setIsKill(
false);
3279bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
3280 bool Changed =
false;
3282 for (
auto &
MBB : *MF) {
3283 for (
auto &
MI :
MBB) {
3285 if (BaseOp == -1 || !
MI.getOperand(BaseOp).isReg())
3289 if (!
Base.isVirtual())
3296 for (
auto Base : Visited)
3297 Changed |= DistributeIncrements(
Base);
3305 return new ARMPreAllocLoadStoreOpt();
3306 return new ARMLoadStoreOpt();
unsigned const MachineRegisterInfo * MRI
static bool isLoadSingle(unsigned Opc)
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
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)
static bool isPreIndex(MachineInstr &MI)
static void forEachDbgRegOperand(MachineInstr *MI, std::function< void(MachineOperand &)> Fn)
static bool isPostIndex(MachineInstr &MI)
static int getLoadStoreMultipleOpcode(unsigned Opcode, ARM_AM::AMSubMode Mode)
static bool isMemoryOp(const MachineInstr &MI)
Returns true if instruction is a memory operation that this pass is capable of operating on.
static unsigned getLSMultipleTransferSize(const MachineInstr *MI)
static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode)
static bool isT1i32Load(unsigned Opc)
static bool ContainsReg(const ArrayRef< std::pair< unsigned, bool > > &Regs, unsigned Reg)
static void AdjustBaseAndOffset(MachineInstr *MI, Register NewBaseReg, int Offset, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
static MachineInstr * createPostIncLoadStore(MachineInstr *MI, int Offset, Register NewReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
static bool isi32Store(unsigned Opc)
static MachineBasicBlock::iterator findIncDecAfter(MachineBasicBlock::iterator MBBI, Register Reg, ARMCC::CondCodes Pred, Register PredReg, int &Offset, const TargetRegisterInfo *TRI)
Searches for a increment or decrement of Reg after MBBI.
static MachineBasicBlock::iterator findIncDecBefore(MachineBasicBlock::iterator MBBI, Register Reg, ARMCC::CondCodes Pred, Register PredReg, int &Offset)
Searches for an increment or decrement of Reg before MBBI.
static int getMemoryOpOffset(const MachineInstr &MI)
static const MachineOperand & getLoadStoreBaseOp(const MachineInstr &MI)
static void updateRegisterMapForDbgValueListAfterMove(SmallDenseMap< Register, SmallVector< MachineInstr * >, 8 > &RegisterMap, MachineInstr *DbgValueListInstr, MachineInstr *InstrToReplace)
arm prera ldst static false cl::opt< unsigned > InstReorderLimit("arm-prera-ldst-opt-reorder-limit", cl::init(8), cl::Hidden)
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)
static int isIncrementOrDecrement(const MachineInstr &MI, Register Reg, ARMCC::CondCodes Pred, Register PredReg)
Check if the given instruction increments or decrements a register and return the amount it is increm...
static bool isT2i32Store(unsigned Opc)
static bool isLegalOrConvertableAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII, int &CodesizeEstimate)
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 int getBaseOperandIndex(MachineInstr &MI)
static bool isT2i32Load(unsigned Opc)
static bool isi32Load(unsigned Opc)
static unsigned getImmScale(unsigned Opc)
static bool isT1i32Store(unsigned Opc)
#define ARM_PREALLOC_LOAD_STORE_OPT_NAME
#define ARM_LOAD_STORE_OPT_NAME
static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, ARM_AM::AMSubMode Mode)
static const MachineOperand & getLoadStoreRegOp(const MachineInstr &MI)
static bool isValidLSDoubleOffset(int Offset)
static DebugVariable createDebugVariableFromMachineInstr(MachineInstr *MI)
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...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file defines the BumpPtrAllocator interface.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
const HexagonInstrInfo * TII
static MaybeAlign getAlign(Value *Ptr)
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
static void updateLRRestored(MachineFunction &MF)
Update the IsRestored flag on LR if it is spilled, based on the return instructions.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
const ARMTargetLowering * getTargetLowering() const override
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Identifies a unique instance of a variable.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
Implements a dense probed hash-table based set.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FunctionPass class - This class is used to implement most global optimizations.
A set of register units used to track register liveness.
Describe properties that are true of each instruction in the target description file.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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...
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr kills the specified register.
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
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.
void setReg(Register Reg)
Change the register this operand corresponds to.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
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.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
StringRef - Represent a constant reference to a string, i.e.
Align getTransientStackAlign() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
TargetInstrInfo - Interface to description of machine instruction set.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetFrameLowering * getFrameLowering() const
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
void dump() const
Support for debugging, callable in GDB: V->dump()
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
AddrOpc getAM5Op(unsigned AM5Opc)
unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
unsigned char getAM5Offset(unsigned AM5Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Define
Register definition.
@ Kill
The last use of a register.
@ CE
Windows NT (Windows on ARM)
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
NodeAddr< InstrNode * > Instr
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.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
APFloat abs(APFloat X)
Returns the absolute value of the argument.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)
unsigned getDeadRegState(bool B)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
FunctionPass * createARMLoadStoreOptimizationPass(bool PreAlloc=false)
Returns an instance of the load / store optimization pass.
unsigned M1(unsigned Val)
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
unsigned getUndefRegState(bool B)
unsigned getDefRegState(bool B)
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
unsigned getKillRegState(bool B)
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
int getAddSubImmediate(MachineInstr &MI)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Description of the encoding of one expression Op.