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"
101struct ARMLoadStoreOpt {
112 bool isThumb1, isThumb2;
120 struct MemOpQueueEntry {
132 struct MergeCandidate {
137 unsigned LatestMIIdx;
140 unsigned EarliestMIIdx;
147 bool CanMergeToLSMulti;
150 bool CanMergeToLSDouble;
163 unsigned Base,
unsigned WordOffset,
170 ArrayRef<std::pair<unsigned, bool>> Regs,
177 ArrayRef<std::pair<unsigned, bool>> Regs,
179 void FormCandidates(
const MemOpQueue &MemOps);
180 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
211char ARMLoadStoreOptLegacy::ID = 0;
222 for (
const auto &MO :
MI.operands()) {
225 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
235 unsigned Opcode =
MI.getOpcode();
236 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
237 unsigned NumOperands =
MI.getDesc().getNumOperands();
238 unsigned OffField =
MI.getOperand(NumOperands - 3).getImm();
240 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
241 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
242 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
243 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
247 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
248 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
263 return MI.getOperand(1);
267 return MI.getOperand(0);
364 case ARM::tLDMIA_UPD:
365 case ARM::tSTMIA_UPD:
366 case ARM::t2LDMIA_RET:
368 case ARM::t2LDMIA_UPD:
370 case ARM::t2STMIA_UPD:
372 case ARM::VLDMSIA_UPD:
374 case ARM::VSTMSIA_UPD:
376 case ARM::VLDMDIA_UPD:
378 case ARM::VSTMDIA_UPD:
392 case ARM::t2LDMDB_UPD:
394 case ARM::t2STMDB_UPD:
395 case ARM::VLDMSDB_UPD:
396 case ARM::VSTMSDB_UPD:
397 case ARM::VLDMDDB_UPD:
398 case ARM::VSTMDDB_UPD:
410 return Opc == ARM::tLDRi ||
Opc == ARM::tLDRspi;
414 return Opc == ARM::t2LDRi12 ||
Opc == ARM::t2LDRi8;
422 return Opc == ARM::tSTRi ||
Opc == ARM::tSTRspi;
426 return Opc == ARM::t2STRi12 ||
Opc == ARM::t2STRi8;
455 switch (
MI->getOpcode()) {
482 case ARM::tLDMIA_UPD:
483 case ARM::tSTMIA_UPD:
490 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 4;
493 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 8;
505 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
509 bool InsertSub =
false;
510 unsigned Opc =
MBBI->getOpcode();
512 if (
MBBI->readsRegister(
Base,
nullptr)) {
515 Opc == ARM::tLDRi ||
Opc == ARM::tLDRHi ||
Opc == ARM::tLDRBi;
517 Opc == ARM::tSTRi ||
Opc == ARM::tSTRHi ||
Opc == ARM::tSTRBi;
519 if (IsLoad || IsStore) {
525 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
532 if (
Offset >= 0 && !(IsStore && InstrSrcReg ==
Base))
536 }
else if ((
Opc == ARM::tSUBi8 ||
Opc == ARM::tADDi8) &&
542 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
544 MO.
getImm() + WordOffset * 4 :
545 MO.
getImm() - WordOffset * 4 ;
577 if (
MBBI->killsRegister(
Base,
nullptr) ||
578 MBBI->definesRegister(
Base,
nullptr))
601 if (LiveRegsValid && LiveRegPos ==
MI)
602 LiveRegsValid =
false;
603 return MI->eraseFromParent();
617void ARMLoadStoreOpt::moveLiveRegsBefore(
const MachineBasicBlock &
MBB,
620 if (!LiveRegsValid) {
624 LiveRegsValid =
true;
627 while (LiveRegPos != Before) {
629 if (!LiveRegPos->isDebugInstr())
636 for (
const std::pair<unsigned, bool> &R : Regs)
645MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
647 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
649 ArrayRef<std::pair<unsigned, bool>> Regs,
651 unsigned NumRegs = Regs.size();
656 bool SafeToClobberCPSR = !isThumb1 ||
660 bool Writeback = isThumb1;
666 assert(
Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
667 if (Opcode == ARM::tLDRi)
669 else if (Opcode == ARM::tSTRi)
676 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
678 if (
Offset == 4 && haveIBAndDA) {
680 }
else if (
Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
682 }
else if (
Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
685 }
else if (
Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
698 if (!SafeToClobberCPSR)
705 NewBase = Regs[NumRegs-1].first;
709 moveLiveRegsBefore(
MBB, InsertBefore);
713 for (
const std::pair<unsigned, bool> &R : Regs)
716 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
721 int BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2ADDspImm
725 : (isThumb1 &&
Offset < 8)
727 : isThumb1 ?
ARM::tADDi8 :
ARM::ADDri;
733 BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2SUBspImm
737 : isThumb1 ?
ARM::tSUBi8 :
ARM::SUBri;
746 bool KillOldBase = BaseKill &&
755 if (
Base != NewBase &&
756 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
774 if (BaseOpc == ARM::tADDrSPi) {
775 assert(
Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
813 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
816 MachineInstrBuilder MIB;
819 assert(isThumb1 &&
"expected Writeback only inThumb1");
820 if (Opcode == ARM::tLDMIA) {
823 Opcode = ARM::tLDMIA_UPD;
835 UpdateBaseRegUses(
MBB, InsertBefore,
DL,
Base, NumRegs, Pred, PredReg);
844 for (
const std::pair<unsigned, bool> &R : Regs)
852MachineInstr *ARMLoadStoreOpt::CreateLoadStoreDouble(
854 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
856 ArrayRef<std::pair<unsigned, bool>> Regs,
859 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
860 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
863 MachineInstrBuilder MIB =
BuildMI(
MBB, InsertBefore,
DL,
864 TII->get(LoadStoreOpcode));
866 MIB.
addReg(Regs[0].first, RegState::Define)
867 .
addReg(Regs[1].first, RegState::Define);
878MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
879 const MachineInstr *
First = Cand.Instrs.front();
880 unsigned Opcode =
First->getOpcode();
883 SmallVector<unsigned, 4> ImpDefs;
884 DenseSet<unsigned> KilledRegs;
885 DenseSet<unsigned> UsedRegs;
887 for (
const MachineInstr *
MI : Cand.Instrs) {
890 bool IsKill = MO.
isKill();
900 for (
const MachineOperand &MO :
MI->implicit_operands()) {
909 if (
MI->readsRegister(DefReg,
nullptr))
919 MachineInstr *LatestMI = Cand.Instrs[Cand.LatestMIIdx];
928 MachineInstr *Merged =
nullptr;
929 if (Cand.CanMergeToLSDouble)
930 Merged = CreateLoadStoreDouble(
MBB, InsertBefore,
Offset,
Base, BaseKill,
931 Opcode, Pred, PredReg,
DL, Regs,
933 if (!Merged && Cand.CanMergeToLSMulti)
934 Merged = CreateLoadStoreMulti(
MBB, InsertBefore,
Offset,
Base, BaseKill,
935 Opcode, Pred, PredReg,
DL, Regs, Cand.Instrs);
941 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
942 bool EarliestAtBegin =
false;
944 EarliestAtBegin =
true;
946 EarliestI = std::prev(EarliestI);
950 for (MachineInstr *
MI : Cand.Instrs)
957 EarliestI = std::next(EarliestI);
963 for (MachineInstr &
MI : FixupRange) {
964 for (
unsigned &ImpDefReg : ImpDefs) {
965 for (MachineOperand &MO :
MI.implicit_operands()) {
977 for (
unsigned ImpDef : ImpDefs)
978 MIB.
addReg(ImpDef, RegState::ImplicitDefine);
982 for (MachineInstr &
MI : FixupRange) {
983 for (MachineOperand &MO :
MI.uses()) {
1009 unsigned Opcode =
MI.getOpcode();
1022void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
1023 const MachineInstr *FirstMI = MemOps[0].MI;
1028 unsigned SIndex = 0;
1029 unsigned EIndex = MemOps.size();
1032 const MachineInstr *
MI = MemOps[SIndex].MI;
1033 int Offset = MemOps[SIndex].Offset;
1036 unsigned PRegNum = PMO.
isUndef() ? std::numeric_limits<unsigned>::max()
1037 :
TRI->getEncodingValue(PReg);
1038 unsigned Latest = SIndex;
1039 unsigned Earliest = SIndex;
1041 bool CanMergeToLSDouble =
1047 CanMergeToLSDouble =
false;
1049 bool CanMergeToLSMulti =
true;
1052 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1053 CanMergeToLSMulti =
false;
1057 if (PReg == ARM::SP || PReg == ARM::PC)
1058 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1062 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1077 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++
Count) {
1078 int NewOffset = MemOps[
I].Offset;
1083 if (
Reg == ARM::SP ||
Reg == ARM::PC)
1089 unsigned RegNum = MO.
isUndef() ? std::numeric_limits<unsigned>::max()
1090 :
TRI->getEncodingValue(
Reg);
1091 bool PartOfLSMulti = CanMergeToLSMulti;
1092 if (PartOfLSMulti) {
1094 if (RegNum <= PRegNum)
1095 PartOfLSMulti =
false;
1099 else if (!isNotVFP && RegNum != PRegNum+1)
1100 PartOfLSMulti =
false;
1103 bool PartOfLSDouble = CanMergeToLSDouble &&
Count <= 1;
1105 if (!PartOfLSMulti && !PartOfLSDouble)
1107 CanMergeToLSMulti &= PartOfLSMulti;
1108 CanMergeToLSDouble &= PartOfLSDouble;
1111 unsigned Position = MemOps[
I].Position;
1112 if (Position < MemOps[Latest].Position)
1114 else if (Position > MemOps[Earliest].Position)
1122 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1123 for (
unsigned C = SIndex, CE = SIndex +
Count;
C <
CE; ++
C)
1124 Candidate->Instrs.push_back(MemOps[
C].
MI);
1125 Candidate->LatestMIIdx = Latest - SIndex;
1126 Candidate->EarliestMIIdx = Earliest - SIndex;
1127 Candidate->InsertPos = MemOps[Latest].Position;
1129 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1130 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1131 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1132 Candidates.push_back(Candidate);
1135 }
while (SIndex < EIndex);
1212 switch (
MI.getOpcode()) {
1213 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1214 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1216 case ARM::t2SUBspImm:
1217 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1219 case ARM::t2ADDspImm:
1220 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1221 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1222 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1227 if (
MI.getOperand(0).getReg() !=
Reg ||
1228 MI.getOperand(1).getReg() !=
Reg ||
1230 MIPredReg != PredReg)
1235 return MI.getOperand(2).getImm() * Scale;
1246 if (
MBBI == BeginMBBI)
1251 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1255 return Offset == 0 ? EndMBBI : PrevMBBI;
1267 while (NextMBBI != EndMBBI) {
1269 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1271 if (NextMBBI == EndMBBI)
1285 if (
Reg == ARM::SP || NextMBBI->readsRegister(
Reg,
TRI) ||
1286 NextMBBI->definesRegister(
Reg,
TRI))
1306bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *
MI) {
1308 if (isThumb1)
return false;
1311 const MachineOperand &BaseOP =
MI->getOperand(0);
1313 bool BaseKill = BaseOP.
isKill();
1316 unsigned Opcode =
MI->getOpcode();
1348 bool HighRegsUsed =
false;
1350 if (MO.
getReg() >= ARM::R8) {
1351 HighRegsUsed =
true;
1361 if (MergeInstr !=
MBB.
end()) {
1388 return ARM::LDR_PRE_IMM;
1390 return ARM::STR_PRE_IMM;
1401 return ARM::t2LDR_PRE;
1404 return ARM::t2STR_PRE;
1413 return ARM::LDR_POST_IMM;
1415 return ARM::STR_POST_IMM;
1426 return ARM::t2LDR_POST;
1428 case ARM::t2LDRBi12:
1429 return ARM::t2LDRB_POST;
1430 case ARM::t2LDRSBi8:
1431 case ARM::t2LDRSBi12:
1432 return ARM::t2LDRSB_POST;
1434 case ARM::t2LDRHi12:
1435 return ARM::t2LDRH_POST;
1436 case ARM::t2LDRSHi8:
1437 case ARM::t2LDRSHi12:
1438 return ARM::t2LDRSH_POST;
1441 return ARM::t2STR_POST;
1443 case ARM::t2STRBi12:
1444 return ARM::t2STRB_POST;
1446 case ARM::t2STRHi12:
1447 return ARM::t2STRH_POST;
1449 case ARM::MVE_VLDRBS16:
1450 return ARM::MVE_VLDRBS16_post;
1451 case ARM::MVE_VLDRBS32:
1452 return ARM::MVE_VLDRBS32_post;
1453 case ARM::MVE_VLDRBU16:
1454 return ARM::MVE_VLDRBU16_post;
1455 case ARM::MVE_VLDRBU32:
1456 return ARM::MVE_VLDRBU32_post;
1457 case ARM::MVE_VLDRHS32:
1458 return ARM::MVE_VLDRHS32_post;
1459 case ARM::MVE_VLDRHU32:
1460 return ARM::MVE_VLDRHU32_post;
1461 case ARM::MVE_VLDRBU8:
1462 return ARM::MVE_VLDRBU8_post;
1463 case ARM::MVE_VLDRHU16:
1464 return ARM::MVE_VLDRHU16_post;
1465 case ARM::MVE_VLDRWU32:
1466 return ARM::MVE_VLDRWU32_post;
1467 case ARM::MVE_VSTRB16:
1468 return ARM::MVE_VSTRB16_post;
1469 case ARM::MVE_VSTRB32:
1470 return ARM::MVE_VSTRB32_post;
1471 case ARM::MVE_VSTRH32:
1472 return ARM::MVE_VSTRH32_post;
1473 case ARM::MVE_VSTRBU8:
1474 return ARM::MVE_VSTRBU8_post;
1475 case ARM::MVE_VSTRHU16:
1476 return ARM::MVE_VSTRHU16_post;
1477 case ARM::MVE_VSTRWU32:
1478 return ARM::MVE_VSTRWU32_post;
1486bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *
MI) {
1489 if (isThumb1)
return false;
1494 unsigned Opcode =
MI->getOpcode();
1496 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1497 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1498 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1500 if (
MI->getOperand(2).getImm() != 0)
1507 if (
MI->getOperand(0).getReg() ==
Base)
1519 if (!isAM5 &&
Offset == Bytes) {
1521 }
else if (
Offset == -Bytes) {
1525 if (MergeInstr ==
MBB.
end())
1529 if ((isAM5 &&
Offset != Bytes) ||
1547 MachineOperand &MO =
MI->getOperand(0);
1561 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1598 MachineOperand &MO =
MI->getOperand(0);
1602 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1631bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &
MI) {
1632 unsigned Opcode =
MI.getOpcode();
1633 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1634 "Must have t2STRDi8 or t2LDRDi8");
1635 if (
MI.getOperand(3).getImm() != 0)
1641 const MachineOperand &BaseOp =
MI.getOperand(2);
1643 const MachineOperand &Reg0Op =
MI.getOperand(0);
1644 const MachineOperand &Reg1Op =
MI.getOperand(1);
1657 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1660 if (MergeInstr ==
MBB.
end())
1662 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1671 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1674 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1679 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1680 TII->get(NewOpc).getNumOperands() == 7 &&
1681 "Unexpected number of operands in Opcode specification.");
1684 for (
const MachineOperand &MO :
MI.implicit_operands())
1696 unsigned Opcode =
MI.getOpcode();
1716 if (!
MI.getOperand(1).isReg())
1721 if (!
MI.hasOneMemOperand())
1740 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isUndef())
1744 if (
MI.getOperand(1).isUndef())
1752 bool isDef,
unsigned NewOpc,
unsigned Reg,
1753 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1778bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &
MBB,
1780 MachineInstr *
MI = &*
MBBI;
1781 unsigned Opcode =
MI->getOpcode();
1784 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1787 const MachineOperand &BaseOp =
MI->getOperand(2);
1789 Register EvenReg =
MI->getOperand(0).getReg();
1790 Register OddReg =
MI->getOperand(1).getReg();
1791 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1792 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1796 bool Errata602117 = EvenReg ==
BaseReg &&
1797 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->
isCortexM3();
1799 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1800 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1802 if (!Errata602117 && !NonConsecutiveRegs)
1805 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1806 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1807 bool EvenDeadKill = isLd ?
1808 MI->getOperand(0).isDead() :
MI->getOperand(0).isKill();
1809 bool EvenUndef =
MI->getOperand(0).isUndef();
1810 bool OddDeadKill = isLd ?
1811 MI->getOperand(1).isDead() :
MI->getOperand(1).isKill();
1812 bool OddUndef =
MI->getOperand(1).isUndef();
1813 bool BaseKill = BaseOp.
isKill();
1814 bool BaseUndef = BaseOp.
isUndef();
1815 assert((isT2 || !
MI->getOperand(3).getReg().isValid()) &&
1816 "register offset not handled below");
1821 if (OddRegNum > EvenRegNum && OffImm == 0) {
1824 unsigned NewOpc = (isLd)
1825 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1826 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1850 unsigned NewOpc = (isLd)
1851 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1852 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1855 unsigned NewOpc2 = (isLd)
1856 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1857 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1860 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1861 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1863 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
MI);
1865 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1868 if (OddReg == EvenReg && EvenDeadKill) {
1872 EvenDeadKill =
false;
1876 if (EvenReg == BaseReg)
1877 EvenDeadKill =
false;
1879 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
1882 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1897bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &
MBB) {
1899 unsigned CurrBase = 0;
1900 unsigned CurrOpc = ~0
u;
1902 unsigned Position = 0;
1903 assert(Candidates.size() == 0);
1905 LiveRegsValid =
false;
1910 MBBI = std::prev(
I);
1911 if (FixInvalidRegPairOp(
MBB,
MBBI))
1916 unsigned Opcode =
MBBI->getOpcode();
1917 const MachineOperand &MO =
MBBI->getOperand(0);
1923 if (CurrBase == 0) {
1928 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1932 if (CurrOpc == Opcode && CurrBase ==
Base && CurrPred == Pred) {
1940 bool Overlap =
false;
1944 for (
const MemOpQueueEntry &
E : MemOps) {
1945 if (
TRI->regsOverlap(
Reg,
E.MI->getOperand(0).getReg())) {
1955 if (
Offset > MemOps.back().Offset) {
1956 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1959 MemOpQueue::iterator
MI, ME;
1960 for (
MI = MemOps.begin(), ME = MemOps.end();
MI != ME; ++
MI) {
1971 if (
MI != MemOps.end()) {
1972 MemOps.insert(
MI, MemOpQueueEntry(*
MBBI,
Offset, Position));
1983 }
else if (
MBBI->isDebugInstr()) {
1985 }
else if (
MBBI->getOpcode() == ARM::t2LDRDi8 ||
1986 MBBI->getOpcode() == ARM::t2STRDi8) {
1993 if (MemOps.size() > 0) {
1994 FormCandidates(MemOps);
2002 if (MemOps.size() > 0)
2003 FormCandidates(MemOps);
2007 auto LessThan = [](
const MergeCandidate*
M0,
const MergeCandidate *
M1) {
2008 return M0->InsertPos <
M1->InsertPos;
2014 for (
const MergeCandidate *Candidate : Candidates) {
2015 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
2016 MachineInstr *Merged = MergeOpsUpdate(*Candidate);
2021 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
2022 MergeBaseUpdateLSDouble(*Merged);
2024 MergeBaseUpdateLSMultiple(Merged);
2026 for (MachineInstr *
MI : Candidate->Instrs) {
2027 if (MergeBaseUpdateLoadStore(
MI))
2032 assert(Candidate->Instrs.size() == 1);
2033 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
2039 for (MachineInstr *
MI : MergeBaseCandidates)
2040 MergeBaseUpdateLSDouble(*
MI);
2041 MergeBaseCandidates.clear();
2056bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &
MBB) {
2058 if (isThumb1)
return false;
2063 (
MBBI->getOpcode() == ARM::BX_RET ||
2064 MBBI->getOpcode() == ARM::tBX_RET ||
2065 MBBI->getOpcode() == ARM::MOVPCLR)) {
2068 while (PrevI->isDebugInstr() && PrevI !=
MBB.
begin())
2070 MachineInstr &PrevMI = *PrevI;
2072 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
2073 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
2074 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
2076 if (MO.
getReg() != ARM::LR)
2078 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
2079 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
2080 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
2091bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &
MBB) {
2094 MBBI->getOpcode() != ARM::tBX_RET)
2099 if (Prev->getOpcode() != ARM::tMOVr ||
2100 !Prev->definesRegister(ARM::LR,
nullptr))
2103 for (
auto Use : Prev->uses())
2105 assert(STI->hasV4TOps());
2118bool ARMLoadStoreOpt::runOnMachineFunction(
2123 AFI = Fn.
getInfo<ARMFunctionInfo>();
2126 RCI = &RegClassInfo;
2131 bool Modified =
false, ModifiedLDMReturn =
false;
2132 for (MachineBasicBlock &
MBB : Fn) {
2135 ModifiedLDMReturn |= MergeReturnIntoLDM(
MBB);
2145 if (ModifiedLDMReturn)
2152bool ARMLoadStoreOptLegacy::runOnMachineFunction(
MachineFunction &MF) {
2155 ARMLoadStoreOpt Impl;
2156 return Impl.runOnMachineFunction(
2157 MF, getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI());
2160#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \
2161 "ARM pre- register allocation load / store optimization pass"
2167struct ARMPreAllocLoadStoreOpt {
2190 bool DistributeIncrements();
2201 StringRef getPassName()
const override {
2214char ARMPreAllocLoadStoreOptLegacy::ID = 0;
2227 cl::init(8),
cl::Hidden);
2229bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn,
2237 TD = &Fn.getDataLayout();
2239 TII = STI->getInstrInfo();
2240 TRI = STI->getRegisterInfo();
2241 MRI = &Fn.getRegInfo();
2244 bool Modified = DistributeIncrements();
2246 Modified |= RescheduleLoadStoreInstrs(&MFI);
2251bool ARMPreAllocLoadStoreOptLegacy::runOnMachineFunction(
MachineFunction &Fn) {
2255 ARMPreAllocLoadStoreOpt Impl;
2256 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2257 MachineDominatorTree *DT =
2258 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2259 return Impl.runOnMachineFunction(Fn, AA, DT);
2272 if (
I->isDebugInstr() || MemOps.
count(&*
I))
2274 if (
I->isCall() ||
I->isTerminator() ||
I->hasUnmodeledSideEffects())
2276 if (
I->mayStore() || (!isLd &&
I->mayLoad()))
2278 if (
I->mayAlias(
AA, *
MemOp,
false))
2280 for (
unsigned j = 0,
NumOps =
I->getNumOperands(); j !=
NumOps; ++j) {
2293 if (MemRegs.
size() <= 4)
2296 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2299bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
2300 MachineInstr *Op0, MachineInstr *Op1,
DebugLoc &dl,
unsigned &NewOpc,
2304 if (!STI->hasV5TEOps())
2310 if (Opcode == ARM::LDRi12) {
2312 }
else if (Opcode == ARM::STRi12) {
2314 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2315 NewOpc = ARM::t2LDRDi8;
2318 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2319 NewOpc = ARM::t2STRDi8;
2336 if (Alignment < ReqAlign)
2342 int Limit = (1 << 8) * Scale;
2343 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2352 int Limit = (1 << 8) * Scale;
2353 if (OffImm >= Limit || (OffImm & (Scale-1)))
2359 if (FirstReg == SecondReg)
2367bool ARMPreAllocLoadStoreOpt::RescheduleOps(
2368 MachineBasicBlock *
MBB, SmallVectorImpl<MachineInstr *> &
Ops,
unsigned Base,
2369 bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
2371 bool RetVal =
false;
2378 return LOffset > ROffset;
2385 while (
Ops.size() > 1) {
2386 unsigned FirstLoc = ~0
U;
2387 unsigned LastLoc = 0;
2388 MachineInstr *FirstOp =
nullptr;
2389 MachineInstr *LastOp =
nullptr;
2391 unsigned LastOpcode = 0;
2392 unsigned LastBytes = 0;
2393 unsigned NumMove = 0;
2398 if (LastOpcode && LSMOpcode != LastOpcode)
2405 if (Bytes != LastBytes ||
Offset != (LastOffset + (
int)Bytes))
2417 LastOpcode = LSMOpcode;
2419 unsigned Loc = MI2LocMap[
Op];
2420 if (Loc <= FirstLoc) {
2424 if (Loc >= LastLoc) {
2433 SmallPtrSet<MachineInstr*, 4> MemOps;
2434 SmallSet<unsigned, 4> MemRegs;
2435 for (
size_t i =
Ops.size() - NumMove, e =
Ops.size(); i != e; ++i) {
2442 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2445 MemOps, MemRegs,
TRI, AA);
2447 for (
unsigned i = 0; i != NumMove; ++i)
2452 while (InsertPos !=
MBB->
end() &&
2453 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2458 MachineInstr *Op0 =
Ops.back();
2459 MachineInstr *Op1 =
Ops[
Ops.size()-2];
2464 unsigned NewOpc = 0;
2467 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2468 FirstReg, SecondReg, BaseReg,
2469 Offset, PredReg, Pred, isT2)) {
2473 const MCInstrDesc &MCID =
TII->get(NewOpc);
2480 MachineInstrBuilder MIB =
BuildMI(*
MBB, InsertPos, dl, MCID)
2481 .
addReg(FirstReg, RegState::Define)
2482 .
addReg(SecondReg, RegState::Define)
2494 MachineInstrBuilder MIB =
BuildMI(*
MBB, InsertPos, dl, MCID)
2517 for (
unsigned i = 0; i != NumMove; ++i) {
2518 MachineInstr *
Op =
Ops.pop_back_val();
2529 NumLdStMoved += NumMove;
2540 if (
MI->isNonListDebugValue()) {
2541 auto &
Op =
MI->getOperand(0);
2545 for (
unsigned I = 2;
I <
MI->getNumOperands();
I++) {
2546 auto &
Op =
MI->getOperand(
I);
2560 auto RegIt = RegisterMap.find(
Op.getReg());
2561 if (RegIt == RegisterMap.end())
2563 auto &InstrVec = RegIt->getSecond();
2570 MI->getDebugLoc()->getInlinedAt());
2575ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *
MBB) {
2576 bool RetVal =
false;
2578 DenseMap<MachineInstr *, unsigned> MI2LocMap;
2579 using Base2InstMap = DenseMap<unsigned, SmallVector<MachineInstr *, 4>>;
2580 using BaseVec = SmallVector<unsigned, 4>;
2581 Base2InstMap Base2LdsMap;
2582 Base2InstMap Base2StsMap;
2588 SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> RegisterMap;
2595 MachineInstr &
MI = *
MBBI;
2596 if (
MI.isCall() ||
MI.isTerminator()) {
2602 if (!
MI.isDebugInstr())
2603 MI2LocMap[&
MI] = ++Loc;
2611 int Opc =
MI.getOpcode();
2615 bool StopHere =
false;
2616 auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
2619 BI->second.push_back(&
MI);
2620 Bases.push_back(
Base);
2623 for (
const MachineInstr *
MI : BI->second) {
2630 BI->second.push_back(&
MI);
2634 FindBases(Base2LdsMap, LdBases);
2636 FindBases(Base2StsMap, StBases);
2647 for (
unsigned Base : LdBases) {
2648 SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[
Base];
2650 RetVal |= RescheduleOps(
MBB, Lds,
Base,
true, MI2LocMap, RegisterMap);
2654 for (
unsigned Base : StBases) {
2655 SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[
Base];
2657 RetVal |= RescheduleOps(
MBB, Sts,
Base,
false, MI2LocMap, RegisterMap);
2661 Base2LdsMap.clear();
2662 Base2StsMap.clear();
2818 SmallDenseMap<DebugVariable, MachineInstr *, 8> DbgValueSinkCandidates;
2821 SmallDenseMap<MachineInstr *, SmallVector<Register>, 8> InstrMap;
2823 MachineInstr &
MI = *
MBBI;
2825 auto PopulateRegisterAndInstrMapForDebugInstr = [&](
Register Reg) {
2826 auto RegIt = RegisterMap.
find(
Reg);
2827 if (RegIt == RegisterMap.
end())
2829 auto &InstrVec = RegIt->getSecond();
2830 InstrVec.push_back(&
MI);
2831 InstrMap[&
MI].push_back(
Reg);
2834 if (
MI.isDebugValue()) {
2836 "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");
2844 PopulateRegisterAndInstrMapForDebugInstr(
Op.getReg());
2852 auto InstrIt = DbgValueSinkCandidates.
find(DbgVar);
2853 if (InstrIt != DbgValueSinkCandidates.
end()) {
2854 auto *
Instr = InstrIt->getSecond();
2855 auto RegIt = InstrMap.
find(Instr);
2856 if (RegIt != InstrMap.
end()) {
2857 const auto &RegVec = RegIt->getSecond();
2860 for (
auto &
Reg : RegVec) {
2861 auto RegIt = RegisterMap.
find(
Reg);
2862 if (RegIt == RegisterMap.
end())
2864 auto &InstrVec = RegIt->getSecond();
2865 auto IsDbgVar = [&](MachineInstr *
I) ->
bool {
2867 return Var == DbgVar;
2873 [&](MachineOperand &
Op) {
Op.setReg(0); });
2876 DbgValueSinkCandidates[DbgVar] = &
MI;
2880 auto Opc =
MI.getOpcode();
2883 auto Reg =
MI.getOperand(0).getReg();
2884 auto RegIt = RegisterMap.
find(
Reg);
2885 if (RegIt == RegisterMap.
end())
2887 auto &DbgInstrVec = RegIt->getSecond();
2888 if (!DbgInstrVec.size())
2890 for (
auto *DbgInstr : DbgInstrVec) {
2892 auto *ClonedMI =
MI.getMF()->CloneMachineInstr(DbgInstr);
2901 DbgValueSinkCandidates.
erase(DbgVar);
2904 [&](MachineOperand &
Op) {
Op.setReg(0); });
2907 if (DbgInstr->isDebugValueList())
2921 switch (
MI.getOpcode()) {
2922 case ARM::MVE_VLDRBS16:
2923 case ARM::MVE_VLDRBS32:
2924 case ARM::MVE_VLDRBU16:
2925 case ARM::MVE_VLDRBU32:
2926 case ARM::MVE_VLDRHS32:
2927 case ARM::MVE_VLDRHU32:
2928 case ARM::MVE_VLDRBU8:
2929 case ARM::MVE_VLDRHU16:
2930 case ARM::MVE_VLDRWU32:
2931 case ARM::MVE_VSTRB16:
2932 case ARM::MVE_VSTRB32:
2933 case ARM::MVE_VSTRH32:
2934 case ARM::MVE_VSTRBU8:
2935 case ARM::MVE_VSTRHU16:
2936 case ARM::MVE_VSTRWU32:
2938 case ARM::t2LDRHi12:
2939 case ARM::t2LDRSHi8:
2940 case ARM::t2LDRSHi12:
2942 case ARM::t2LDRBi12:
2943 case ARM::t2LDRSBi8:
2944 case ARM::t2LDRSBi12:
2946 case ARM::t2STRBi12:
2948 case ARM::t2STRHi12:
2950 case ARM::MVE_VLDRBS16_post:
2951 case ARM::MVE_VLDRBS32_post:
2952 case ARM::MVE_VLDRBU16_post:
2953 case ARM::MVE_VLDRBU32_post:
2954 case ARM::MVE_VLDRHS32_post:
2955 case ARM::MVE_VLDRHU32_post:
2956 case ARM::MVE_VLDRBU8_post:
2957 case ARM::MVE_VLDRHU16_post:
2958 case ARM::MVE_VLDRWU32_post:
2959 case ARM::MVE_VSTRB16_post:
2960 case ARM::MVE_VSTRB32_post:
2961 case ARM::MVE_VSTRH32_post:
2962 case ARM::MVE_VSTRBU8_post:
2963 case ARM::MVE_VSTRHU16_post:
2964 case ARM::MVE_VSTRWU32_post:
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:
2986 switch (
MI.getOpcode()) {
2987 case ARM::MVE_VLDRBS16_post:
2988 case ARM::MVE_VLDRBS32_post:
2989 case ARM::MVE_VLDRBU16_post:
2990 case ARM::MVE_VLDRBU32_post:
2991 case ARM::MVE_VLDRHS32_post:
2992 case ARM::MVE_VLDRHU32_post:
2993 case ARM::MVE_VLDRBU8_post:
2994 case ARM::MVE_VLDRHU16_post:
2995 case ARM::MVE_VLDRWU32_post:
2996 case ARM::MVE_VSTRB16_post:
2997 case ARM::MVE_VSTRB32_post:
2998 case ARM::MVE_VSTRH32_post:
2999 case ARM::MVE_VSTRBU8_post:
3000 case ARM::MVE_VSTRHU16_post:
3001 case ARM::MVE_VSTRWU32_post:
3008 switch (
MI.getOpcode()) {
3009 case ARM::MVE_VLDRBS16_pre:
3010 case ARM::MVE_VLDRBS32_pre:
3011 case ARM::MVE_VLDRBU16_pre:
3012 case ARM::MVE_VLDRBU32_pre:
3013 case ARM::MVE_VLDRHS32_pre:
3014 case ARM::MVE_VLDRHU32_pre:
3015 case ARM::MVE_VLDRBU8_pre:
3016 case ARM::MVE_VLDRHU16_pre:
3017 case ARM::MVE_VLDRWU32_pre:
3018 case ARM::MVE_VSTRB16_pre:
3019 case ARM::MVE_VSTRB32_pre:
3020 case ARM::MVE_VSTRH32_pre:
3021 case ARM::MVE_VSTRBU8_pre:
3022 case ARM::MVE_VSTRHU16_pre:
3023 case ARM::MVE_VSTRWU32_pre:
3036 int &CodesizeEstimate) {
3045 CodesizeEstimate += 1;
3046 return Imm < 0 && -
Imm < ((1 << 8) * 1);
3059 MI->getOperand(BaseOp).setReg(NewBaseReg);
3067 int OldOffset =
MI->getOperand(BaseOp + 1).getImm();
3069 MI->getOperand(BaseOp + 1).setImm(OldOffset -
Offset);
3071 unsigned ConvOpcode;
3072 switch (
MI->getOpcode()) {
3073 case ARM::t2LDRHi12:
3074 ConvOpcode = ARM::t2LDRHi8;
3076 case ARM::t2LDRSHi12:
3077 ConvOpcode = ARM::t2LDRSHi8;
3079 case ARM::t2LDRBi12:
3080 ConvOpcode = ARM::t2LDRBi8;
3082 case ARM::t2LDRSBi12:
3083 ConvOpcode = ARM::t2LDRSBi8;
3085 case ARM::t2STRHi12:
3086 ConvOpcode = ARM::t2STRHi8;
3088 case ARM::t2STRBi12:
3089 ConvOpcode = ARM::t2STRBi8;
3095 "Illegal Address Immediate after convert!");
3099 .
add(
MI->getOperand(0))
3100 .
add(
MI->getOperand(1))
3102 .
add(
MI->getOperand(3))
3103 .
add(
MI->getOperand(4))
3105 MI->eraseFromParent();
3124 TRC =
TII->getRegClass(
MCID, 2);
3135 .
add(
MI->getOperand(0))
3136 .
add(
MI->getOperand(1))
3138 .
add(
MI->getOperand(3))
3139 .
add(
MI->getOperand(4))
3140 .
add(
MI->getOperand(5))
3143 if (
MI->mayLoad()) {
3145 .
add(
MI->getOperand(0))
3147 .
add(
MI->getOperand(1))
3149 .
add(
MI->getOperand(3))
3150 .
add(
MI->getOperand(4))
3155 .
add(
MI->getOperand(0))
3156 .
add(
MI->getOperand(1))
3158 .
add(
MI->getOperand(3))
3159 .
add(
MI->getOperand(4))
3183bool ARMPreAllocLoadStoreOpt::DistributeIncrements(
Register Base) {
3186 MachineInstr *BaseAccess =
nullptr;
3187 MachineInstr *PrePostInc =
nullptr;
3192 SmallPtrSet<MachineInstr *, 8> OtherAccesses;
3203 if (!
Use.getOperand(BaseOp).isReg() ||
3204 Use.getOperand(BaseOp).getReg() !=
Base)
3208 else if (
Use.getOperand(BaseOp + 1).getImm() == 0)
3211 OtherAccesses.
insert(&Use);
3214 int IncrementOffset;
3220 if (
Increment->definesRegister(ARM::CPSR,
nullptr) ||
3224 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on VirtualReg "
3225 <<
Base.virtRegIndex() <<
"\n");
3229 for (MachineInstr &Use :
3231 if (&Use == BaseAccess || (
Use.getOpcode() != TargetOpcode::PHI &&
3233 LLVM_DEBUG(
dbgs() <<
" BaseAccess doesn't dominate use of increment\n");
3243 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on postinc\n");
3247 else if (PrePostInc) {
3255 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on already "
3256 <<
"indexed VirtualReg " <<
Base.virtRegIndex() <<
"\n");
3259 BaseAccess = PrePostInc;
3273 SmallPtrSet<MachineInstr *, 4> SuccessorAccesses;
3274 int CodesizeEstimate = -1;
3275 for (
auto *Use : OtherAccesses) {
3277 SuccessorAccesses.
insert(Use);
3280 Use->getOperand(BaseOp + 1).getImm() -
3282 TII, CodesizeEstimate)) {
3283 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on use\n");
3286 }
else if (!DT->
dominates(Use, BaseAccess)) {
3288 dbgs() <<
" Unknown dominance relation between Base and Use\n");
3292 if (STI->
hasMinSize() && CodesizeEstimate > 0) {
3293 LLVM_DEBUG(
dbgs() <<
" Expected to grow instructions under minsize\n");
3301 NewBaseReg =
Increment->getOperand(0).getReg();
3302 MachineInstr *BaseAccessPost =
3306 (void)BaseAccessPost;
3310 for (
auto *Use : SuccessorAccesses) {
3319 Op.setIsKill(
false);
3323bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
3325 SmallSetVector<Register, 4> Visited;
3326 for (
auto &
MBB : *MF) {
3327 for (
auto &
MI :
MBB) {
3329 if (BaseOp == -1 || !
MI.getOperand(BaseOp).isReg())
3333 if (!
Base.isVirtual())
3340 for (
auto Base : Visited)
3349 return new ARMPreAllocLoadStoreOptLegacy();
3350 return new ARMLoadStoreOptLegacy();
3356 ARMLoadStoreOpt Impl;
3357 bool Changed = Impl.runOnMachineFunction(
3370 ARMPreAllocLoadStoreOpt Impl;
3376 bool Changed = Impl.runOnMachineFunction(MF,
AA, DT);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isLoadSingle(unsigned Opc)
static int getMemoryOpOffset(const MachineInstr &MI)
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 ContainsReg(ArrayRef< std::pair< unsigned, bool > > Regs, unsigned Reg)
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 unsigned getLSMultipleTransferSize(const MachineInstr *MI)
static bool isLegalOrConvertibleAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII, int &CodesizeEstimate)
static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode)
static bool isT1i32Load(unsigned Opc)
static void AdjustBaseAndOffset(MachineInstr *MI, Register NewBaseReg, int Offset, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
arm ldst static false bool definesCPSR(const MachineInstr &MI)
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 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 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 bool isMemoryOp(const MachineInstr &MI)
Returns true if instruction is a memory operation that this pass is capable of operating on.
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.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister 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)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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 manager for alias analyses.
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...
bool isThumb2Function() const
bool isThumbFunction() const
bool shouldSignReturnAddress() const
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const ARMBaseInstrInfo * getInstrInfo() const override
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
Align getDualLoadStoreAlignment() const
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents analyses that only rely on functions' control flow.
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)
FunctionPass class - This class is used to implement most global optimizations.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
void addReg(MCRegister Reg)
Adds register units covered by physical register Reg.
LLVM_ABI void stepBackward(const MachineInstr &MI)
Updates liveness when stepping backwards over the instruction MI.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
Describe properties that are true of each instruction in the target description file.
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI 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.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI 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.
LLVM_ABI 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.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
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.
Properties which a MachineFunction may have at a given point in time.
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & 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.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
LLVM_ABI 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.
LLVM_ABI 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,...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
ArrayRef< MCPhysReg > getOrder(const TargetRegisterClass *RC) const
getOrder - Returns the preferred allocation order for RC.
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.
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.
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.
virtual bool isLegalAddImmediate(int64_t) const
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
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
LLVM Value Representation.
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.
Abstract Attribute helper functions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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)
@ CE
Windows NT (Windows on ARM)
This namespace contains all of the command line option processing machinery.
initializer< Ty > init(const Ty &Val)
NodeAddr< InstrNode * > Instr
NodeAddr< UseNode * > Use
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
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)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr RegState getDeadRegState(bool B)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
unsigned M1(unsigned Val)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr RegState getDefRegState(bool B)
FunctionPass * createARMLoadStoreOptLegacyPass(bool PreAlloc=false)
Returns an instance of the load / store optimization pass.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
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.
@ Increment
Incrementally increasing token ID.
int getAddSubImmediate(MachineInstr &MI)
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
constexpr RegState getUndefRegState(bool B)
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.