74#define DEBUG_TYPE "arm-ldst-opt"
76STATISTIC(NumLDMGened ,
"Number of ldm instructions generated");
77STATISTIC(NumSTMGened ,
"Number of stm instructions generated");
78STATISTIC(NumVLDMGened,
"Number of vldm instructions generated");
79STATISTIC(NumVSTMGened,
"Number of vstm instructions generated");
80STATISTIC(NumLdStMoved,
"Number of load / store instructions moved");
81STATISTIC(NumLDRDFormed,
"Number of ldrd created before allocation");
82STATISTIC(NumSTRDFormed,
"Number of strd created before allocation");
83STATISTIC(NumLDRD2LDM,
"Number of ldrd instructions turned back into ldm");
84STATISTIC(NumSTRD2STM,
"Number of strd instructions turned back into stm");
85STATISTIC(NumLDRD2LDR,
"Number of ldrd instructions turned back into ldr's");
86STATISTIC(NumSTRD2STR,
"Number of strd instructions turned back into str's");
97#define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass"
116 bool RegClassInfoValid;
117 bool isThumb1, isThumb2;
125 MachineFunctionProperties::Property::NoVRegs);
133 struct MemOpQueueEntry {
139 :
MI(&
MI), Offset(Offset), Position(Position) {}
145 struct MergeCandidate {
150 unsigned LatestMIIdx;
153 unsigned EarliestMIIdx;
160 bool CanMergeToLSMulti;
163 bool CanMergeToLSDouble;
174 unsigned Base,
unsigned WordOffset,
178 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
180 ArrayRef<std::pair<unsigned, bool>> Regs,
184 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
186 ArrayRef<std::pair<unsigned, bool>> Regs,
188 void FormCandidates(
const MemOpQueue &MemOps);
189 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
202char ARMLoadStoreOpt::ID = 0;
208 for (
const auto &MO :
MI.operands()) {
211 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
221 unsigned Opcode =
MI.getOpcode();
222 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
223 unsigned NumOperands =
MI.getDesc().getNumOperands();
224 unsigned OffField =
MI.getOperand(NumOperands - 3).getImm();
226 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
227 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
228 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
229 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
233 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
234 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
249 return MI.getOperand(1);
253 return MI.getOperand(0);
350 case ARM::tLDMIA_UPD:
351 case ARM::tSTMIA_UPD:
352 case ARM::t2LDMIA_RET:
354 case ARM::t2LDMIA_UPD:
356 case ARM::t2STMIA_UPD:
358 case ARM::VLDMSIA_UPD:
360 case ARM::VSTMSIA_UPD:
362 case ARM::VLDMDIA_UPD:
364 case ARM::VSTMDIA_UPD:
378 case ARM::t2LDMDB_UPD:
380 case ARM::t2STMDB_UPD:
381 case ARM::VLDMSDB_UPD:
382 case ARM::VSTMSDB_UPD:
383 case ARM::VLDMDDB_UPD:
384 case ARM::VSTMDDB_UPD:
396 return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;
400 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
408 return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;
412 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
420 return isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
441 switch (
MI->getOpcode()) {
468 case ARM::tLDMIA_UPD:
469 case ARM::tSTMIA_UPD:
476 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 4;
479 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 8;
491 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
495 bool InsertSub =
false;
496 unsigned Opc =
MBBI->getOpcode();
498 if (
MBBI->readsRegister(
Base,
nullptr)) {
501 Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;
503 Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;
505 if (IsLoad || IsStore) {
511 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
518 if (
Offset >= 0 && !(IsStore && InstrSrcReg ==
Base))
522 }
else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&
523 !definesCPSR(*
MBBI)) {
528 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
529 Offset = (Opc == ARM::tSUBi8) ?
530 MO.
getImm() + WordOffset * 4 :
531 MO.
getImm() - WordOffset * 4 ;
545 }
else if (definesCPSR(*
MBBI) ||
MBBI->isCall() ||
MBBI->isBranch()) {
563 if (
MBBI->killsRegister(
Base,
nullptr) ||
564 MBBI->definesRegister(
Base,
nullptr))
587 if (!RegClassInfoValid) {
588 RegClassInfo.runOnMachineFunction(*MF);
589 RegClassInfoValid =
true;
592 for (
unsigned Reg : RegClassInfo.getOrder(&RegClass))
593 if (LiveRegs.available(Reg) && !MF->getRegInfo().isReserved(Reg))
604 if (!LiveRegsValid) {
606 LiveRegs.addLiveOuts(
MBB);
608 LiveRegsValid =
true;
611 while (LiveRegPos !=
Before) {
613 LiveRegs.stepBackward(*LiveRegPos);
619 for (
const std::pair<unsigned, bool> &R : Regs)
630 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
632 ArrayRef<std::pair<unsigned, bool>> Regs,
634 unsigned NumRegs = Regs.size();
639 bool SafeToClobberCPSR = !isThumb1 ||
643 bool Writeback = isThumb1;
649 assert(
Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
650 if (Opcode == ARM::tLDRi)
652 else if (Opcode == ARM::tSTRi)
659 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
661 if (
Offset == 4 && haveIBAndDA) {
663 }
else if (
Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
665 }
else if (
Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
668 }
else if (
Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
681 if (!SafeToClobberCPSR)
688 NewBase = Regs[NumRegs-1].first;
692 moveLiveRegsBefore(
MBB, InsertBefore);
696 for (
const std::pair<unsigned, bool> &R : Regs)
697 LiveRegs.addReg(
R.first);
699 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
704 int BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2ADDspImm
706 : (isThumb1 &&
Base == ARM::SP)
708 : (isThumb1 &&
Offset < 8)
710 : isThumb1 ? ARM::tADDi8 : ARM::ADDri;
716 BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2SUBspImm
720 : isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
723 if (!TL->isLegalAddImmediate(
Offset))
729 bool KillOldBase = BaseKill &&
738 if (
Base != NewBase &&
739 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
757 if (BaseOpc == ARM::tADDrSPi) {
758 assert(
Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
796 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
802 assert(isThumb1 &&
"expected Writeback only inThumb1");
803 if (Opcode == ARM::tLDMIA) {
806 Opcode = ARM::tLDMIA_UPD;
818 UpdateBaseRegUses(
MBB, InsertBefore,
DL,
Base, NumRegs, Pred, PredReg);
827 for (
const std::pair<unsigned, bool> &R : Regs)
837 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
839 ArrayRef<std::pair<unsigned, bool>> Regs,
842 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
843 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
847 TII->get(LoadStoreOpcode));
861MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
863 unsigned Opcode =
First->getOpcode();
873 bool IsKill = MO.
isKill();
876 Regs.
push_back(std::make_pair(Reg, IsKill));
892 if (
MI->readsRegister(DefReg,
nullptr))
903 iterator InsertBefore = std::next(iterator(LatestMI));
912 if (Cand.CanMergeToLSDouble)
913 Merged = CreateLoadStoreDouble(
MBB, InsertBefore,
Offset,
Base, BaseKill,
914 Opcode, Pred, PredReg,
DL, Regs,
916 if (!Merged && Cand.CanMergeToLSMulti)
917 Merged = CreateLoadStoreMulti(
MBB, InsertBefore,
Offset,
Base, BaseKill,
918 Opcode, Pred, PredReg,
DL, Regs, Cand.Instrs);
924 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
925 bool EarliestAtBegin =
false;
927 EarliestAtBegin =
true;
929 EarliestI = std::prev(EarliestI);
940 EarliestI = std::next(EarliestI);
941 auto FixupRange =
make_range(EarliestI, iterator(Merged));
947 for (
unsigned &ImpDefReg : ImpDefs) {
960 for (
unsigned ImpDef : ImpDefs)
992 unsigned Opcode =
MI.getOpcode();
1005void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
1011 unsigned SIndex = 0;
1012 unsigned EIndex = MemOps.size();
1016 int Offset = MemOps[SIndex].Offset;
1019 unsigned PRegNum = PMO.
isUndef() ? std::numeric_limits<unsigned>::max()
1020 :
TRI->getEncodingValue(PReg);
1021 unsigned Latest = SIndex;
1022 unsigned Earliest = SIndex;
1024 bool CanMergeToLSDouble =
1028 if (STI->isCortexM3() &&
isi32Load(Opcode) &&
1030 CanMergeToLSDouble =
false;
1032 bool CanMergeToLSMulti =
true;
1035 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1036 CanMergeToLSMulti =
false;
1040 if (PReg == ARM::SP || PReg == ARM::PC)
1041 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1045 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1060 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++Count) {
1061 int NewOffset = MemOps[
I].Offset;
1066 if (Reg == ARM::SP || Reg == ARM::PC)
1072 unsigned RegNum = MO.
isUndef() ? std::numeric_limits<unsigned>::max()
1073 :
TRI->getEncodingValue(
Reg);
1074 bool PartOfLSMulti = CanMergeToLSMulti;
1075 if (PartOfLSMulti) {
1077 if (RegNum <= PRegNum)
1078 PartOfLSMulti =
false;
1082 else if (!isNotVFP && RegNum != PRegNum+1)
1083 PartOfLSMulti =
false;
1086 bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;
1088 if (!PartOfLSMulti && !PartOfLSDouble)
1090 CanMergeToLSMulti &= PartOfLSMulti;
1091 CanMergeToLSDouble &= PartOfLSDouble;
1094 unsigned Position = MemOps[
I].Position;
1095 if (Position < MemOps[Latest].Position)
1097 else if (Position > MemOps[Earliest].Position)
1105 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1106 for (
unsigned C = SIndex, CE = SIndex + Count;
C <
CE; ++
C)
1107 Candidate->Instrs.push_back(MemOps[
C].MI);
1108 Candidate->LatestMIIdx = Latest - SIndex;
1109 Candidate->EarliestMIIdx = Earliest - SIndex;
1110 Candidate->InsertPos = MemOps[Latest].Position;
1112 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1113 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1114 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1115 Candidates.push_back(Candidate);
1118 }
while (SIndex < EIndex);
1195 switch (
MI.getOpcode()) {
1196 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1197 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1199 case ARM::t2SUBspImm:
1200 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1202 case ARM::t2ADDspImm:
1203 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1204 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1205 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1210 if (
MI.getOperand(0).getReg() != Reg ||
1211 MI.getOperand(1).getReg() != Reg ||
1213 MIPredReg != PredReg)
1216 if (CheckCPSRDef && definesCPSR(
MI))
1218 return MI.getOperand(2).getImm() * Scale;
1229 if (
MBBI == BeginMBBI)
1234 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1238 return Offset == 0 ? EndMBBI : PrevMBBI;
1250 while (NextMBBI != EndMBBI) {
1252 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1254 if (NextMBBI == EndMBBI)
1268 if (Reg == ARM::SP || NextMBBI->readsRegister(Reg,
TRI) ||
1269 NextMBBI->definesRegister(Reg,
TRI))
1289bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(
MachineInstr *
MI) {
1291 if (isThumb1)
return false;
1296 bool BaseKill = BaseOP.
isKill();
1299 unsigned Opcode =
MI->getOpcode();
1328 if (!STI->hasMinSize() || !BaseKill)
1331 bool HighRegsUsed =
false;
1333 if (MO.
getReg() >= ARM::R8) {
1334 HighRegsUsed =
true;
1344 if (MergeInstr !=
MBB.
end()) {
1371 return ARM::LDR_PRE_IMM;
1373 return ARM::STR_PRE_IMM;
1375 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1377 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1379 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1381 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1384 return ARM::t2LDR_PRE;
1387 return ARM::t2STR_PRE;
1396 return ARM::LDR_POST_IMM;
1398 return ARM::STR_POST_IMM;
1400 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
1402 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
1404 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
1406 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
1409 return ARM::t2LDR_POST;
1411 case ARM::t2LDRBi12:
1412 return ARM::t2LDRB_POST;
1413 case ARM::t2LDRSBi8:
1414 case ARM::t2LDRSBi12:
1415 return ARM::t2LDRSB_POST;
1417 case ARM::t2LDRHi12:
1418 return ARM::t2LDRH_POST;
1419 case ARM::t2LDRSHi8:
1420 case ARM::t2LDRSHi12:
1421 return ARM::t2LDRSH_POST;
1424 return ARM::t2STR_POST;
1426 case ARM::t2STRBi12:
1427 return ARM::t2STRB_POST;
1429 case ARM::t2STRHi12:
1430 return ARM::t2STRH_POST;
1432 case ARM::MVE_VLDRBS16:
1433 return ARM::MVE_VLDRBS16_post;
1434 case ARM::MVE_VLDRBS32:
1435 return ARM::MVE_VLDRBS32_post;
1436 case ARM::MVE_VLDRBU16:
1437 return ARM::MVE_VLDRBU16_post;
1438 case ARM::MVE_VLDRBU32:
1439 return ARM::MVE_VLDRBU32_post;
1440 case ARM::MVE_VLDRHS32:
1441 return ARM::MVE_VLDRHS32_post;
1442 case ARM::MVE_VLDRHU32:
1443 return ARM::MVE_VLDRHU32_post;
1444 case ARM::MVE_VLDRBU8:
1445 return ARM::MVE_VLDRBU8_post;
1446 case ARM::MVE_VLDRHU16:
1447 return ARM::MVE_VLDRHU16_post;
1448 case ARM::MVE_VLDRWU32:
1449 return ARM::MVE_VLDRWU32_post;
1450 case ARM::MVE_VSTRB16:
1451 return ARM::MVE_VSTRB16_post;
1452 case ARM::MVE_VSTRB32:
1453 return ARM::MVE_VSTRB32_post;
1454 case ARM::MVE_VSTRH32:
1455 return ARM::MVE_VSTRH32_post;
1456 case ARM::MVE_VSTRBU8:
1457 return ARM::MVE_VSTRBU8_post;
1458 case ARM::MVE_VSTRHU16:
1459 return ARM::MVE_VSTRHU16_post;
1460 case ARM::MVE_VSTRWU32:
1461 return ARM::MVE_VSTRWU32_post;
1469bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(
MachineInstr *
MI) {
1472 if (isThumb1)
return false;
1477 unsigned Opcode =
MI->getOpcode();
1479 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1480 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1481 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1483 if (
MI->getOperand(2).getImm() != 0)
1490 if (
MI->getOperand(0).getReg() ==
Base)
1502 if (!isAM5 &&
Offset == Bytes) {
1504 }
else if (
Offset == -Bytes) {
1508 if (MergeInstr ==
MBB.
end())
1512 if ((isAM5 &&
Offset != Bytes) ||
1544 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1585 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1614bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(
MachineInstr &
MI)
const {
1615 unsigned Opcode =
MI.getOpcode();
1616 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1617 "Must have t2STRDi8 or t2LDRDi8");
1618 if (
MI.getOperand(3).getImm() != 0)
1640 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1643 if (MergeInstr ==
MBB.
end())
1645 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1654 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1657 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1662 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1663 TII->get(NewOpc).getNumOperands() == 7 &&
1664 "Unexpected number of operands in Opcode specification.");
1679 unsigned Opcode =
MI.getOpcode();
1699 if (!
MI.getOperand(1).isReg())
1704 if (!
MI.hasOneMemOperand())
1723 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isUndef())
1727 if (
MI.getOperand(1).isUndef())
1735 bool isDef,
unsigned NewOpc,
unsigned Reg,
1736 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1764 unsigned Opcode =
MI->getOpcode();
1767 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1772 Register EvenReg =
MI->getOperand(0).getReg();
1773 Register OddReg =
MI->getOperand(1).getReg();
1774 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1775 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1779 bool Errata602117 = EvenReg == BaseReg &&
1780 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();
1782 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1783 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1785 if (!Errata602117 && !NonConsecutiveRegs)
1788 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1789 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1790 bool EvenDeadKill = isLd ?
1791 MI->getOperand(0).isDead() :
MI->getOperand(0).isKill();
1792 bool EvenUndef =
MI->getOperand(0).isUndef();
1793 bool OddDeadKill = isLd ?
1794 MI->getOperand(1).isDead() :
MI->getOperand(1).isKill();
1795 bool OddUndef =
MI->getOperand(1).isUndef();
1796 bool BaseKill = BaseOp.
isKill();
1797 bool BaseUndef = BaseOp.
isUndef();
1798 assert((isT2 ||
MI->getOperand(3).getReg() == ARM::NoRegister) &&
1799 "register offset not handled below");
1804 if (OddRegNum > EvenRegNum && OffImm == 0) {
1807 unsigned NewOpc = (isLd)
1808 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1809 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1831 unsigned NewOpc = (isLd)
1832 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1833 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1836 unsigned NewOpc2 = (isLd)
1837 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1838 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1841 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1842 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1844 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
MI);
1846 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1849 if (OddReg == EvenReg && EvenDeadKill) {
1853 EvenDeadKill =
false;
1857 if (EvenReg == BaseReg)
1858 EvenDeadKill =
false;
1860 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
1863 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1880 unsigned CurrBase = 0;
1881 unsigned CurrOpc = ~0
u;
1883 unsigned Position = 0;
1884 assert(Candidates.size() == 0);
1885 assert(MergeBaseCandidates.size() == 0);
1886 LiveRegsValid =
false;
1891 MBBI = std::prev(
I);
1892 if (FixInvalidRegPairOp(
MBB,
MBBI))
1897 unsigned Opcode =
MBBI->getOpcode();
1904 if (CurrBase == 0) {
1909 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1913 if (CurrOpc == Opcode && CurrBase ==
Base && CurrPred == Pred) {
1921 bool Overlap =
false;
1925 for (
const MemOpQueueEntry &E : MemOps) {
1926 if (
TRI->regsOverlap(Reg, E.MI->getOperand(0).getReg())) {
1936 if (
Offset > MemOps.back().Offset) {
1937 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1940 MemOpQueue::iterator
MI, ME;
1941 for (
MI = MemOps.begin(), ME = MemOps.end();
MI != ME; ++
MI) {
1942 if (Offset < MI->
Offset) {
1952 if (
MI != MemOps.end()) {
1953 MemOps.insert(
MI, MemOpQueueEntry(*
MBBI,
Offset, Position));
1964 }
else if (
MBBI->isDebugInstr()) {
1966 }
else if (
MBBI->getOpcode() == ARM::t2LDRDi8 ||
1967 MBBI->getOpcode() == ARM::t2STRDi8) {
1970 MergeBaseCandidates.push_back(&*
MBBI);
1974 if (MemOps.size() > 0) {
1975 FormCandidates(MemOps);
1983 if (MemOps.size() > 0)
1984 FormCandidates(MemOps);
1988 auto LessThan = [](
const MergeCandidate*
M0,
const MergeCandidate *
M1) {
1989 return M0->InsertPos <
M1->InsertPos;
1994 bool Changed =
false;
1995 for (
const MergeCandidate *Candidate : Candidates) {
1996 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
2002 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
2003 MergeBaseUpdateLSDouble(*Merged);
2005 MergeBaseUpdateLSMultiple(Merged);
2008 if (MergeBaseUpdateLoadStore(
MI))
2013 assert(Candidate->Instrs.size() == 1);
2014 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
2021 MergeBaseUpdateLSDouble(*
MI);
2022 MergeBaseCandidates.clear();
2039 if (isThumb1)
return false;
2044 (
MBBI->getOpcode() == ARM::BX_RET ||
2045 MBBI->getOpcode() == ARM::tBX_RET ||
2046 MBBI->getOpcode() == ARM::MOVPCLR)) {
2049 while (PrevI->isDebugInstr() && PrevI !=
MBB.
begin())
2053 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
2054 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
2055 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
2057 if (MO.
getReg() != ARM::LR)
2059 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
2060 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
2061 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
2075 MBBI->getOpcode() != ARM::tBX_RET)
2080 if (Prev->getOpcode() != ARM::tMOVr ||
2081 !Prev->definesRegister(ARM::LR,
nullptr))
2084 for (
auto Use : Prev->uses())
2086 assert(STI->hasV4TOps());
2107 TII = STI->getInstrInfo();
2108 TRI = STI->getRegisterInfo();
2110 RegClassInfoValid =
false;
2111 isThumb2 = AFI->isThumb2Function();
2112 isThumb1 = AFI->isThumbFunction() && !isThumb2;
2114 bool Modified =
false, ModifiedLDMReturn =
false;
2117 if (STI->hasV5TOps() && !AFI->shouldSignReturnAddress())
2118 ModifiedLDMReturn |= MergeReturnIntoLDM(
MBB);
2128 if (ModifiedLDMReturn)
2135#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \
2136 "ARM pre- register allocation load / store optimization pass"
2179 bool DistributeIncrements();
2185char ARMPreAllocLoadStoreOpt::ID = 0;
2196 cl::init(8), cl::Hidden);
2198bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn) {
2202 TD = &Fn.getDataLayout();
2204 TII = STI->getInstrInfo();
2205 TRI = STI->getRegisterInfo();
2206 MRI = &Fn.getRegInfo();
2207 DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2209 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2211 bool Modified = DistributeIncrements();
2213 Modified |= RescheduleLoadStoreInstrs(&MFI);
2228 if (
I->isDebugInstr() || MemOps.
count(&*
I))
2230 if (
I->isCall() ||
I->isTerminator() ||
I->hasUnmodeledSideEffects())
2232 if (
I->mayStore() || (!isLd &&
I->mayLoad()))
2234 if (
I->mayAlias(AA, *
MemOp,
false))
2236 for (
unsigned j = 0, NumOps =
I->getNumOperands(); j != NumOps; ++j) {
2244 AddedRegPressure.
insert(Reg);
2249 if (MemRegs.
size() <= 4)
2252 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2255bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
2260 if (!STI->hasV5TEOps())
2266 if (Opcode == ARM::LDRi12) {
2268 }
else if (Opcode == ARM::STRi12) {
2270 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2271 NewOpc = ARM::t2LDRDi8;
2274 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2275 NewOpc = ARM::t2STRDi8;
2291 Align ReqAlign = STI->getDualLoadStoreAlignment();
2292 if (Alignment < ReqAlign)
2298 int Limit = (1 << 8) * Scale;
2299 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2308 int Limit = (1 << 8) * Scale;
2309 if (OffImm >= Limit || (OffImm & (Scale-1)))
2315 if (FirstReg == SecondReg)
2323bool ARMPreAllocLoadStoreOpt::RescheduleOps(
2327 bool RetVal =
false;
2333 assert(LHS == RHS || LOffset != ROffset);
2334 return LOffset > ROffset;
2341 while (Ops.
size() > 1) {
2342 unsigned FirstLoc = ~0
U;
2343 unsigned LastLoc = 0;
2347 unsigned LastOpcode = 0;
2348 unsigned LastBytes = 0;
2349 unsigned NumMove = 0;
2354 if (LastOpcode && LSMOpcode != LastOpcode)
2361 if (Bytes != LastBytes ||
Offset != (LastOffset + (
int)Bytes))
2373 LastOpcode = LSMOpcode;
2375 unsigned Loc = MI2LocMap[
Op];
2376 if (Loc <= FirstLoc) {
2380 if (Loc >= LastLoc) {
2391 for (
size_t i = Ops.
size() - NumMove, e = Ops.
size(); i != e; ++i) {
2398 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2401 MemOps, MemRegs,
TRI, AA);
2403 for (
unsigned i = 0; i != NumMove; ++i)
2408 while (InsertPos !=
MBB->
end() &&
2409 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2420 unsigned NewOpc = 0;
2423 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2424 FirstReg, SecondReg, BaseReg,
2425 Offset, PredReg, Pred, isT2)) {
2431 MRI->constrainRegClass(FirstReg, TRC);
2432 MRI->constrainRegClass(SecondReg, TRC);
2473 for (
unsigned i = 0; i != NumMove; ++i) {
2485 NumLdStMoved += NumMove;
2496 if (
MI->isNonListDebugValue()) {
2497 auto &
Op =
MI->getOperand(0);
2501 for (
unsigned I = 2;
I <
MI->getNumOperands();
I++) {
2502 auto &
Op =
MI->getOperand(
I);
2516 auto RegIt = RegisterMap.find(
Op.getReg());
2517 if (RegIt == RegisterMap.end())
2519 auto &InstrVec = RegIt->getSecond();
2520 for (
unsigned I = 0;
I < InstrVec.size();
I++)
2521 if (InstrVec[
I] == InstrToReplace)
2522 InstrVec[
I] = DbgValueListInstr;
2528 MI->getDebugLoc()->getInlinedAt());
2534 bool RetVal =
false;
2540 Base2InstMap Base2LdsMap;
2541 Base2InstMap Base2StsMap;
2555 if (
MI.isCall() ||
MI.isTerminator()) {
2561 if (!
MI.isDebugInstr())
2562 MI2LocMap[&
MI] = ++Loc;
2570 int Opc =
MI.getOpcode();
2574 bool StopHere =
false;
2575 auto FindBases = [&] (Base2InstMap &Base2Ops, BaseVec &Bases) {
2576 MapIt BI = Base2Ops.find(
Base);
2577 if (BI == Base2Ops.end()) {
2578 Base2Ops[
Base].push_back(&
MI);
2579 Bases.push_back(
Base);
2589 BI->second.push_back(&
MI);
2593 FindBases(Base2LdsMap, LdBases);
2595 FindBases(Base2StsMap, StBases);
2606 for (
unsigned Base : LdBases) {
2609 RetVal |= RescheduleOps(
MBB, Lds,
Base,
true, MI2LocMap, RegisterMap);
2613 for (
unsigned Base : StBases) {
2616 RetVal |= RescheduleOps(
MBB, Sts,
Base,
false, MI2LocMap, RegisterMap);
2620 Base2LdsMap.clear();
2621 Base2StsMap.clear();
2784 auto PopulateRegisterAndInstrMapForDebugInstr = [&](
Register Reg) {
2785 auto RegIt = RegisterMap.
find(Reg);
2786 if (RegIt == RegisterMap.
end())
2788 auto &InstrVec = RegIt->getSecond();
2789 InstrVec.push_back(&
MI);
2790 InstrMap[&
MI].push_back(Reg);
2793 if (
MI.isDebugValue()) {
2795 "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");
2803 PopulateRegisterAndInstrMapForDebugInstr(
Op.getReg());
2811 auto InstrIt = DbgValueSinkCandidates.
find(DbgVar);
2812 if (InstrIt != DbgValueSinkCandidates.
end()) {
2813 auto *
Instr = InstrIt->getSecond();
2814 auto RegIt = InstrMap.
find(Instr);
2815 if (RegIt != InstrMap.
end()) {
2816 const auto &RegVec = RegIt->getSecond();
2819 for (
auto &Reg : RegVec) {
2820 auto RegIt = RegisterMap.
find(Reg);
2821 if (RegIt == RegisterMap.
end())
2823 auto &InstrVec = RegIt->getSecond();
2826 return Var == DbgVar;
2835 DbgValueSinkCandidates[DbgVar] = &
MI;
2839 auto Opc =
MI.getOpcode();
2842 auto Reg =
MI.getOperand(0).getReg();
2843 auto RegIt = RegisterMap.
find(Reg);
2844 if (RegIt == RegisterMap.
end())
2846 auto &DbgInstrVec = RegIt->getSecond();
2847 if (!DbgInstrVec.size())
2849 for (
auto *DbgInstr : DbgInstrVec) {
2851 auto *ClonedMI =
MI.getMF()->CloneMachineInstr(DbgInstr);
2857 auto DbgIt = DbgValueSinkCandidates.
find(DbgVar);
2861 if (DbgIt != DbgValueSinkCandidates.
end())
2862 DbgValueSinkCandidates.
erase(DbgIt);
2868 if (DbgInstr->isDebugValueList())
2882 switch (
MI.getOpcode()) {
2883 case ARM::MVE_VLDRBS16:
2884 case ARM::MVE_VLDRBS32:
2885 case ARM::MVE_VLDRBU16:
2886 case ARM::MVE_VLDRBU32:
2887 case ARM::MVE_VLDRHS32:
2888 case ARM::MVE_VLDRHU32:
2889 case ARM::MVE_VLDRBU8:
2890 case ARM::MVE_VLDRHU16:
2891 case ARM::MVE_VLDRWU32:
2892 case ARM::MVE_VSTRB16:
2893 case ARM::MVE_VSTRB32:
2894 case ARM::MVE_VSTRH32:
2895 case ARM::MVE_VSTRBU8:
2896 case ARM::MVE_VSTRHU16:
2897 case ARM::MVE_VSTRWU32:
2899 case ARM::t2LDRHi12:
2900 case ARM::t2LDRSHi8:
2901 case ARM::t2LDRSHi12:
2903 case ARM::t2LDRBi12:
2904 case ARM::t2LDRSBi8:
2905 case ARM::t2LDRSBi12:
2907 case ARM::t2STRBi12:
2909 case ARM::t2STRHi12:
2911 case ARM::MVE_VLDRBS16_post:
2912 case ARM::MVE_VLDRBS32_post:
2913 case ARM::MVE_VLDRBU16_post:
2914 case ARM::MVE_VLDRBU32_post:
2915 case ARM::MVE_VLDRHS32_post:
2916 case ARM::MVE_VLDRHU32_post:
2917 case ARM::MVE_VLDRBU8_post:
2918 case ARM::MVE_VLDRHU16_post:
2919 case ARM::MVE_VLDRWU32_post:
2920 case ARM::MVE_VSTRB16_post:
2921 case ARM::MVE_VSTRB32_post:
2922 case ARM::MVE_VSTRH32_post:
2923 case ARM::MVE_VSTRBU8_post:
2924 case ARM::MVE_VSTRHU16_post:
2925 case ARM::MVE_VSTRWU32_post:
2926 case ARM::MVE_VLDRBS16_pre:
2927 case ARM::MVE_VLDRBS32_pre:
2928 case ARM::MVE_VLDRBU16_pre:
2929 case ARM::MVE_VLDRBU32_pre:
2930 case ARM::MVE_VLDRHS32_pre:
2931 case ARM::MVE_VLDRHU32_pre:
2932 case ARM::MVE_VLDRBU8_pre:
2933 case ARM::MVE_VLDRHU16_pre:
2934 case ARM::MVE_VLDRWU32_pre:
2935 case ARM::MVE_VSTRB16_pre:
2936 case ARM::MVE_VSTRB32_pre:
2937 case ARM::MVE_VSTRH32_pre:
2938 case ARM::MVE_VSTRBU8_pre:
2939 case ARM::MVE_VSTRHU16_pre:
2940 case ARM::MVE_VSTRWU32_pre:
2947 switch (
MI.getOpcode()) {
2948 case ARM::MVE_VLDRBS16_post:
2949 case ARM::MVE_VLDRBS32_post:
2950 case ARM::MVE_VLDRBU16_post:
2951 case ARM::MVE_VLDRBU32_post:
2952 case ARM::MVE_VLDRHS32_post:
2953 case ARM::MVE_VLDRHU32_post:
2954 case ARM::MVE_VLDRBU8_post:
2955 case ARM::MVE_VLDRHU16_post:
2956 case ARM::MVE_VLDRWU32_post:
2957 case ARM::MVE_VSTRB16_post:
2958 case ARM::MVE_VSTRB32_post:
2959 case ARM::MVE_VSTRH32_post:
2960 case ARM::MVE_VSTRBU8_post:
2961 case ARM::MVE_VSTRHU16_post:
2962 case ARM::MVE_VSTRWU32_post:
2969 switch (
MI.getOpcode()) {
2970 case ARM::MVE_VLDRBS16_pre:
2971 case ARM::MVE_VLDRBS32_pre:
2972 case ARM::MVE_VLDRBU16_pre:
2973 case ARM::MVE_VLDRBU32_pre:
2974 case ARM::MVE_VLDRHS32_pre:
2975 case ARM::MVE_VLDRHU32_pre:
2976 case ARM::MVE_VLDRBU8_pre:
2977 case ARM::MVE_VLDRHU16_pre:
2978 case ARM::MVE_VLDRWU32_pre:
2979 case ARM::MVE_VSTRB16_pre:
2980 case ARM::MVE_VSTRB32_pre:
2981 case ARM::MVE_VSTRH32_pre:
2982 case ARM::MVE_VSTRBU8_pre:
2983 case ARM::MVE_VSTRHU16_pre:
2984 case ARM::MVE_VSTRWU32_pre:
2997 int &CodesizeEstimate) {
3006 CodesizeEstimate += 1;
3007 return Imm < 0 && -Imm < ((1 << 8) * 1);
3020 MI->getOperand(BaseOp).setReg(NewBaseReg);
3026 MRI.constrainRegClass(NewBaseReg, TRC);
3028 int OldOffset =
MI->getOperand(BaseOp + 1).getImm();
3030 MI->getOperand(BaseOp + 1).setImm(OldOffset -
Offset);
3032 unsigned ConvOpcode;
3033 switch (
MI->getOpcode()) {
3034 case ARM::t2LDRHi12:
3035 ConvOpcode = ARM::t2LDRHi8;
3037 case ARM::t2LDRSHi12:
3038 ConvOpcode = ARM::t2LDRSHi8;
3040 case ARM::t2LDRBi12:
3041 ConvOpcode = ARM::t2LDRBi8;
3043 case ARM::t2LDRSBi12:
3044 ConvOpcode = ARM::t2LDRSBi8;
3046 case ARM::t2STRHi12:
3047 ConvOpcode = ARM::t2STRHi8;
3049 case ARM::t2STRBi12:
3050 ConvOpcode = ARM::t2STRBi8;
3056 "Illegal Address Immediate after convert!");
3060 .
add(
MI->getOperand(0))
3061 .
add(
MI->getOperand(1))
3063 .
add(
MI->getOperand(3))
3064 .
add(
MI->getOperand(4))
3066 MI->eraseFromParent();
3083 MRI.constrainRegClass(NewReg, TRC);
3085 TRC =
TII->getRegClass(MCID, 2,
TRI, *MF);
3086 MRI.constrainRegClass(
MI->getOperand(1).getReg(), TRC);
3094 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3096 .
add(
MI->getOperand(0))
3097 .
add(
MI->getOperand(1))
3099 .
add(
MI->getOperand(3))
3100 .
add(
MI->getOperand(4))
3101 .
add(
MI->getOperand(5))
3104 if (
MI->mayLoad()) {
3105 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3106 .
add(
MI->getOperand(0))
3108 .
add(
MI->getOperand(1))
3110 .
add(
MI->getOperand(3))
3111 .
add(
MI->getOperand(4))
3114 return BuildMI(*
MI->getParent(),
MI,
MI->getDebugLoc(), MCID)
3116 .
add(
MI->getOperand(0))
3117 .
add(
MI->getOperand(1))
3119 .
add(
MI->getOperand(3))
3120 .
add(
MI->getOperand(4))
3144bool ARMPreAllocLoadStoreOpt::DistributeIncrements(
Register Base) {
3154 for (
auto &
Use :
MRI->use_nodbg_instructions(
Base)) {
3164 if (!
Use.getOperand(BaseOp).isReg() ||
3165 Use.getOperand(BaseOp).getReg() !=
Base)
3169 else if (
Use.getOperand(BaseOp + 1).getImm() == 0)
3175 int IncrementOffset;
3177 if (BaseAccess && Increment) {
3181 if (
Increment->definesRegister(ARM::CPSR,
nullptr) ||
3185 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on VirtualReg "
3186 <<
Base.virtRegIndex() <<
"\n");
3191 MRI->use_nodbg_instructions(
Increment->getOperand(0).getReg())) {
3192 if (&
Use == BaseAccess || (
Use.getOpcode() != TargetOpcode::PHI &&
3193 !DT->dominates(BaseAccess, &
Use))) {
3194 LLVM_DEBUG(
dbgs() <<
" BaseAccess doesn't dominate use of increment\n");
3204 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on postinc\n");
3208 else if (PrePostInc) {
3216 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on already "
3217 <<
"indexed VirtualReg " <<
Base.virtRegIndex() <<
"\n");
3220 BaseAccess = PrePostInc;
3235 int CodesizeEstimate = -1;
3236 for (
auto *
Use : OtherAccesses) {
3237 if (DT->dominates(BaseAccess,
Use)) {
3241 Use->getOperand(BaseOp + 1).getImm() -
3243 TII, CodesizeEstimate)) {
3244 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on use\n");
3247 }
else if (!DT->dominates(
Use, BaseAccess)) {
3249 dbgs() <<
" Unknown dominance relation between Base and Use\n");
3253 if (STI->hasMinSize() && CodesizeEstimate > 0) {
3254 LLVM_DEBUG(
dbgs() <<
" Expected to grow instructions under minsize\n");
3262 NewBaseReg =
Increment->getOperand(0).getReg();
3267 (void)BaseAccessPost;
3271 for (
auto *
Use : SuccessorAccesses) {
3280 Op.setIsKill(
false);
3284bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
3285 bool Changed =
false;
3287 for (
auto &
MBB : *MF) {
3288 for (
auto &
MI :
MBB) {
3290 if (BaseOp == -1 || !
MI.getOperand(BaseOp).isReg())
3301 for (
auto Base : Visited)
3302 Changed |= DistributeIncrements(
Base);
3310 return new ARMPreAllocLoadStoreOpt();
3311 return new ARMLoadStoreOpt();
unsigned const MachineRegisterInfo * MRI
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
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.
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.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
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)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ 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.
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)
static bool isARMLowRegister(unsigned Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
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)
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.