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 RegClassInfoValid;
113 bool isThumb1, isThumb2;
120 struct MemOpQueueEntry {
132 struct MergeCandidate {
137 unsigned LatestMIIdx;
140 unsigned EarliestMIIdx;
147 bool CanMergeToLSMulti;
150 bool CanMergeToLSDouble;
161 unsigned Base,
unsigned WordOffset,
168 ArrayRef<std::pair<unsigned, bool>> Regs,
175 ArrayRef<std::pair<unsigned, bool>> Regs,
177 void FormCandidates(
const MemOpQueue &MemOps);
178 MachineInstr *MergeOpsUpdate(
const MergeCandidate &Cand);
208char ARMLoadStoreOptLegacy::ID = 0;
216 for (
const auto &MO :
MI.operands()) {
219 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
229 unsigned Opcode =
MI.getOpcode();
230 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
231 unsigned NumOperands =
MI.getDesc().getNumOperands();
232 unsigned OffField =
MI.getOperand(NumOperands - 3).getImm();
234 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
235 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
236 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
237 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
241 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
242 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
257 return MI.getOperand(1);
261 return MI.getOperand(0);
358 case ARM::tLDMIA_UPD:
359 case ARM::tSTMIA_UPD:
360 case ARM::t2LDMIA_RET:
362 case ARM::t2LDMIA_UPD:
364 case ARM::t2STMIA_UPD:
366 case ARM::VLDMSIA_UPD:
368 case ARM::VSTMSIA_UPD:
370 case ARM::VLDMDIA_UPD:
372 case ARM::VSTMDIA_UPD:
386 case ARM::t2LDMDB_UPD:
388 case ARM::t2STMDB_UPD:
389 case ARM::VLDMSDB_UPD:
390 case ARM::VSTMSDB_UPD:
391 case ARM::VLDMDDB_UPD:
392 case ARM::VSTMDDB_UPD:
404 return Opc == ARM::tLDRi ||
Opc == ARM::tLDRspi;
408 return Opc == ARM::t2LDRi12 ||
Opc == ARM::t2LDRi8;
416 return Opc == ARM::tSTRi ||
Opc == ARM::tSTRspi;
420 return Opc == ARM::t2STRi12 ||
Opc == ARM::t2STRi8;
449 switch (
MI->getOpcode()) {
476 case ARM::tLDMIA_UPD:
477 case ARM::tSTMIA_UPD:
484 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 4;
487 return (
MI->getNumOperands() -
MI->getDesc().getNumOperands() + 1) * 8;
499 assert(isThumb1 &&
"Can only update base register uses for Thumb1!");
503 bool InsertSub =
false;
504 unsigned Opc =
MBBI->getOpcode();
506 if (
MBBI->readsRegister(
Base,
nullptr)) {
509 Opc == ARM::tLDRi ||
Opc == ARM::tLDRHi ||
Opc == ARM::tLDRBi;
511 Opc == ARM::tSTRi ||
Opc == ARM::tSTRHi ||
Opc == ARM::tSTRBi;
513 if (IsLoad || IsStore) {
519 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
526 if (
Offset >= 0 && !(IsStore && InstrSrcReg ==
Base))
530 }
else if ((
Opc == ARM::tSUBi8 ||
Opc == ARM::tADDi8) &&
531 !definesCPSR(*
MBBI)) {
536 MBBI->getOperand(
MBBI->getDesc().getNumOperands() - 3);
538 MO.
getImm() + WordOffset * 4 :
539 MO.
getImm() - WordOffset * 4 ;
553 }
else if (definesCPSR(*
MBBI) ||
MBBI->isCall() ||
MBBI->isBranch()) {
571 if (
MBBI->killsRegister(
Base,
nullptr) ||
572 MBBI->definesRegister(
Base,
nullptr))
595 if (!RegClassInfoValid) {
597 RegClassInfoValid =
true;
600 for (
unsigned Reg : RegClassInfo.
getOrder(&RegClass))
609void ARMLoadStoreOpt::moveLiveRegsBefore(
const MachineBasicBlock &
MBB,
612 if (!LiveRegsValid) {
616 LiveRegsValid =
true;
619 while (LiveRegPos != Before) {
621 if (!LiveRegPos->isDebugInstr())
628 for (
const std::pair<unsigned, bool> &R : Regs)
637MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
639 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
641 ArrayRef<std::pair<unsigned, bool>> Regs,
643 unsigned NumRegs = Regs.size();
648 bool SafeToClobberCPSR = !isThumb1 ||
652 bool Writeback = isThumb1;
658 assert(
Base != ARM::SP &&
"Thumb1 does not allow SP in register list");
659 if (Opcode == ARM::tLDRi)
661 else if (Opcode == ARM::tSTRi)
668 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
670 if (
Offset == 4 && haveIBAndDA) {
672 }
else if (
Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA) {
674 }
else if (
Offset == -4 * (
int)NumRegs && isNotVFP && !isThumb1) {
677 }
else if (
Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
690 if (!SafeToClobberCPSR)
697 NewBase = Regs[NumRegs-1].first;
701 moveLiveRegsBefore(
MBB, InsertBefore);
705 for (
const std::pair<unsigned, bool> &R : Regs)
708 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
713 int BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2ADDspImm
717 : (isThumb1 &&
Offset < 8)
719 : isThumb1 ?
ARM::tADDi8 :
ARM::ADDri;
725 BaseOpc = isThumb2 ? (BaseKill &&
Base == ARM::SP ? ARM::t2SUBspImm
729 : isThumb1 ?
ARM::tSUBi8 :
ARM::SUBri;
738 bool KillOldBase = BaseKill &&
747 if (
Base != NewBase &&
748 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
766 if (BaseOpc == ARM::tADDrSPi) {
767 assert(
Offset % 4 == 0 &&
"tADDrSPi offset is scaled by 4");
805 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
808 MachineInstrBuilder MIB;
811 assert(isThumb1 &&
"expected Writeback only inThumb1");
812 if (Opcode == ARM::tLDMIA) {
815 Opcode = ARM::tLDMIA_UPD;
827 UpdateBaseRegUses(
MBB, InsertBefore,
DL,
Base, NumRegs, Pred, PredReg);
836 for (
const std::pair<unsigned, bool> &R : Regs)
844MachineInstr *ARMLoadStoreOpt::CreateLoadStoreDouble(
846 int Offset,
unsigned Base,
bool BaseKill,
unsigned Opcode,
848 ArrayRef<std::pair<unsigned, bool>> Regs,
851 assert((IsLoad ||
isi32Store(Opcode)) &&
"Must have integer load or store");
852 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;
855 MachineInstrBuilder MIB =
BuildMI(
MBB, InsertBefore,
DL,
856 TII->get(LoadStoreOpcode));
858 MIB.
addReg(Regs[0].first, RegState::Define)
859 .
addReg(Regs[1].first, RegState::Define);
870MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(
const MergeCandidate &Cand) {
871 const MachineInstr *
First = Cand.Instrs.front();
872 unsigned Opcode =
First->getOpcode();
875 SmallVector<unsigned, 4> ImpDefs;
876 DenseSet<unsigned> KilledRegs;
877 DenseSet<unsigned> UsedRegs;
879 for (
const MachineInstr *
MI : Cand.Instrs) {
882 bool IsKill = MO.
isKill();
892 for (
const MachineOperand &MO :
MI->implicit_operands()) {
901 if (
MI->readsRegister(DefReg,
nullptr))
911 MachineInstr *LatestMI = Cand.Instrs[Cand.LatestMIIdx];
920 MachineInstr *Merged =
nullptr;
921 if (Cand.CanMergeToLSDouble)
922 Merged = CreateLoadStoreDouble(
MBB, InsertBefore,
Offset,
Base, BaseKill,
923 Opcode, Pred, PredReg,
DL, Regs,
925 if (!Merged && Cand.CanMergeToLSMulti)
926 Merged = CreateLoadStoreMulti(
MBB, InsertBefore,
Offset,
Base, BaseKill,
927 Opcode, Pred, PredReg,
DL, Regs, Cand.Instrs);
933 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
934 bool EarliestAtBegin =
false;
936 EarliestAtBegin =
true;
938 EarliestI = std::prev(EarliestI);
942 for (MachineInstr *
MI : Cand.Instrs)
949 EarliestI = std::next(EarliestI);
955 for (MachineInstr &
MI : FixupRange) {
956 for (
unsigned &ImpDefReg : ImpDefs) {
957 for (MachineOperand &MO :
MI.implicit_operands()) {
969 for (
unsigned ImpDef : ImpDefs)
970 MIB.
addReg(ImpDef, RegState::ImplicitDefine);
974 for (MachineInstr &
MI : FixupRange) {
975 for (MachineOperand &MO :
MI.uses()) {
1001 unsigned Opcode =
MI.getOpcode();
1014void ARMLoadStoreOpt::FormCandidates(
const MemOpQueue &MemOps) {
1015 const MachineInstr *FirstMI = MemOps[0].MI;
1020 unsigned SIndex = 0;
1021 unsigned EIndex = MemOps.size();
1024 const MachineInstr *
MI = MemOps[SIndex].MI;
1025 int Offset = MemOps[SIndex].Offset;
1028 unsigned PRegNum = PMO.
isUndef() ? std::numeric_limits<unsigned>::max()
1029 :
TRI->getEncodingValue(PReg);
1030 unsigned Latest = SIndex;
1031 unsigned Earliest = SIndex;
1033 bool CanMergeToLSDouble =
1039 CanMergeToLSDouble =
false;
1041 bool CanMergeToLSMulti =
true;
1044 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
1045 CanMergeToLSMulti =
false;
1049 if (PReg == ARM::SP || PReg == ARM::PC)
1050 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1054 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1069 for (
unsigned I = SIndex+1;
I < EIndex; ++
I, ++
Count) {
1070 int NewOffset = MemOps[
I].Offset;
1075 if (
Reg == ARM::SP ||
Reg == ARM::PC)
1081 unsigned RegNum = MO.
isUndef() ? std::numeric_limits<unsigned>::max()
1082 :
TRI->getEncodingValue(
Reg);
1083 bool PartOfLSMulti = CanMergeToLSMulti;
1084 if (PartOfLSMulti) {
1086 if (RegNum <= PRegNum)
1087 PartOfLSMulti =
false;
1091 else if (!isNotVFP && RegNum != PRegNum+1)
1092 PartOfLSMulti =
false;
1095 bool PartOfLSDouble = CanMergeToLSDouble &&
Count <= 1;
1097 if (!PartOfLSMulti && !PartOfLSDouble)
1099 CanMergeToLSMulti &= PartOfLSMulti;
1100 CanMergeToLSDouble &= PartOfLSDouble;
1103 unsigned Position = MemOps[
I].Position;
1104 if (Position < MemOps[Latest].Position)
1106 else if (Position > MemOps[Earliest].Position)
1114 MergeCandidate *Candidate =
new(
Allocator.Allocate()) MergeCandidate;
1115 for (
unsigned C = SIndex, CE = SIndex +
Count;
C <
CE; ++
C)
1116 Candidate->Instrs.push_back(MemOps[
C].
MI);
1117 Candidate->LatestMIIdx = Latest - SIndex;
1118 Candidate->EarliestMIIdx = Earliest - SIndex;
1119 Candidate->InsertPos = MemOps[Latest].Position;
1121 CanMergeToLSMulti = CanMergeToLSDouble =
false;
1122 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
1123 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
1124 Candidates.push_back(Candidate);
1127 }
while (SIndex < EIndex);
1204 switch (
MI.getOpcode()) {
1205 case ARM::tADDi8: Scale = 4; CheckCPSRDef =
true;
break;
1206 case ARM::tSUBi8: Scale = -4; CheckCPSRDef =
true;
break;
1208 case ARM::t2SUBspImm:
1209 case ARM::SUBri: Scale = -1; CheckCPSRDef =
true;
break;
1211 case ARM::t2ADDspImm:
1212 case ARM::ADDri: Scale = 1; CheckCPSRDef =
true;
break;
1213 case ARM::tADDspi: Scale = 4; CheckCPSRDef =
false;
break;
1214 case ARM::tSUBspi: Scale = -4; CheckCPSRDef =
false;
break;
1219 if (
MI.getOperand(0).getReg() !=
Reg ||
1220 MI.getOperand(1).getReg() !=
Reg ||
1222 MIPredReg != PredReg)
1225 if (CheckCPSRDef && definesCPSR(
MI))
1227 return MI.getOperand(2).getImm() * Scale;
1238 if (
MBBI == BeginMBBI)
1243 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
1247 return Offset == 0 ? EndMBBI : PrevMBBI;
1259 while (NextMBBI != EndMBBI) {
1261 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
1263 if (NextMBBI == EndMBBI)
1277 if (
Reg == ARM::SP || NextMBBI->readsRegister(
Reg,
TRI) ||
1278 NextMBBI->definesRegister(
Reg,
TRI))
1298bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *
MI) {
1300 if (isThumb1)
return false;
1303 const MachineOperand &BaseOP =
MI->getOperand(0);
1305 bool BaseKill = BaseOP.
isKill();
1308 unsigned Opcode =
MI->getOpcode();
1318 MachineBasicBlock &
MBB = *
MI->getParent();
1340 bool HighRegsUsed =
false;
1342 if (MO.
getReg() >= ARM::R8) {
1343 HighRegsUsed =
true;
1353 if (MergeInstr !=
MBB.
end()) {
1380 return ARM::LDR_PRE_IMM;
1382 return ARM::STR_PRE_IMM;
1393 return ARM::t2LDR_PRE;
1396 return ARM::t2STR_PRE;
1405 return ARM::LDR_POST_IMM;
1407 return ARM::STR_POST_IMM;
1418 return ARM::t2LDR_POST;
1420 case ARM::t2LDRBi12:
1421 return ARM::t2LDRB_POST;
1422 case ARM::t2LDRSBi8:
1423 case ARM::t2LDRSBi12:
1424 return ARM::t2LDRSB_POST;
1426 case ARM::t2LDRHi12:
1427 return ARM::t2LDRH_POST;
1428 case ARM::t2LDRSHi8:
1429 case ARM::t2LDRSHi12:
1430 return ARM::t2LDRSH_POST;
1433 return ARM::t2STR_POST;
1435 case ARM::t2STRBi12:
1436 return ARM::t2STRB_POST;
1438 case ARM::t2STRHi12:
1439 return ARM::t2STRH_POST;
1441 case ARM::MVE_VLDRBS16:
1442 return ARM::MVE_VLDRBS16_post;
1443 case ARM::MVE_VLDRBS32:
1444 return ARM::MVE_VLDRBS32_post;
1445 case ARM::MVE_VLDRBU16:
1446 return ARM::MVE_VLDRBU16_post;
1447 case ARM::MVE_VLDRBU32:
1448 return ARM::MVE_VLDRBU32_post;
1449 case ARM::MVE_VLDRHS32:
1450 return ARM::MVE_VLDRHS32_post;
1451 case ARM::MVE_VLDRHU32:
1452 return ARM::MVE_VLDRHU32_post;
1453 case ARM::MVE_VLDRBU8:
1454 return ARM::MVE_VLDRBU8_post;
1455 case ARM::MVE_VLDRHU16:
1456 return ARM::MVE_VLDRHU16_post;
1457 case ARM::MVE_VLDRWU32:
1458 return ARM::MVE_VLDRWU32_post;
1459 case ARM::MVE_VSTRB16:
1460 return ARM::MVE_VSTRB16_post;
1461 case ARM::MVE_VSTRB32:
1462 return ARM::MVE_VSTRB32_post;
1463 case ARM::MVE_VSTRH32:
1464 return ARM::MVE_VSTRH32_post;
1465 case ARM::MVE_VSTRBU8:
1466 return ARM::MVE_VSTRBU8_post;
1467 case ARM::MVE_VSTRHU16:
1468 return ARM::MVE_VSTRHU16_post;
1469 case ARM::MVE_VSTRWU32:
1470 return ARM::MVE_VSTRWU32_post;
1478bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *
MI) {
1481 if (isThumb1)
return false;
1486 unsigned Opcode =
MI->getOpcode();
1488 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
1489 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
1490 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
1492 if (
MI->getOperand(2).getImm() != 0)
1499 if (
MI->getOperand(0).getReg() ==
Base)
1505 MachineBasicBlock &
MBB = *
MI->getParent();
1511 if (!isAM5 &&
Offset == Bytes) {
1513 }
else if (
Offset == -Bytes) {
1517 if (MergeInstr ==
MBB.
end())
1521 if ((isAM5 &&
Offset != Bytes) ||
1539 MachineOperand &MO =
MI->getOperand(0);
1553 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1590 MachineOperand &MO =
MI->getOperand(0);
1594 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1623bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &
MI)
const {
1624 unsigned Opcode =
MI.getOpcode();
1625 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1626 "Must have t2STRDi8 or t2LDRDi8");
1627 if (
MI.getOperand(3).getImm() != 0)
1633 const MachineOperand &BaseOp =
MI.getOperand(2);
1635 const MachineOperand &Reg0Op =
MI.getOperand(0);
1636 const MachineOperand &Reg1Op =
MI.getOperand(1);
1643 MachineBasicBlock &
MBB = *
MI.getParent();
1649 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1652 if (MergeInstr ==
MBB.
end())
1654 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1663 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1666 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1671 assert(
TII->get(Opcode).getNumOperands() == 6 &&
1672 TII->get(NewOpc).getNumOperands() == 7 &&
1673 "Unexpected number of operands in Opcode specification.");
1676 for (
const MachineOperand &MO :
MI.implicit_operands())
1688 unsigned Opcode =
MI.getOpcode();
1708 if (!
MI.getOperand(1).isReg())
1713 if (!
MI.hasOneMemOperand())
1732 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isUndef())
1736 if (
MI.getOperand(1).isUndef())
1744 bool isDef,
unsigned NewOpc,
unsigned Reg,
1745 bool RegDeadKill,
bool RegUndef,
unsigned BaseReg,
1770bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &
MBB,
1772 MachineInstr *
MI = &*
MBBI;
1773 unsigned Opcode =
MI->getOpcode();
1776 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
1779 const MachineOperand &BaseOp =
MI->getOperand(2);
1781 Register EvenReg =
MI->getOperand(0).getReg();
1782 Register OddReg =
MI->getOperand(1).getReg();
1783 unsigned EvenRegNum =
TRI->getDwarfRegNum(EvenReg,
false);
1784 unsigned OddRegNum =
TRI->getDwarfRegNum(OddReg,
false);
1788 bool Errata602117 = EvenReg ==
BaseReg &&
1789 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->
isCortexM3();
1791 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
1792 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);
1794 if (!Errata602117 && !NonConsecutiveRegs)
1797 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1798 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1799 bool EvenDeadKill = isLd ?
1800 MI->getOperand(0).isDead() :
MI->getOperand(0).isKill();
1801 bool EvenUndef =
MI->getOperand(0).isUndef();
1802 bool OddDeadKill = isLd ?
1803 MI->getOperand(1).isDead() :
MI->getOperand(1).isKill();
1804 bool OddUndef =
MI->getOperand(1).isUndef();
1805 bool BaseKill = BaseOp.
isKill();
1806 bool BaseUndef = BaseOp.
isUndef();
1807 assert((isT2 ||
MI->getOperand(3).getReg() == ARM::NoRegister) &&
1808 "register offset not handled below");
1813 if (OddRegNum > EvenRegNum && OffImm == 0) {
1816 unsigned NewOpc = (isLd)
1817 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1818 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1842 unsigned NewOpc = (isLd)
1843 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1844 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1847 unsigned NewOpc2 = (isLd)
1848 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1849 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1852 if (isLd &&
TRI->regsOverlap(EvenReg, BaseReg)) {
1853 assert(!
TRI->regsOverlap(OddReg, BaseReg));
1855 false, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
MI);
1857 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1860 if (OddReg == EvenReg && EvenDeadKill) {
1864 EvenDeadKill =
false;
1868 if (EvenReg == BaseReg)
1869 EvenDeadKill =
false;
1871 EvenUndef, BaseReg,
false, BaseUndef, Pred, PredReg,
TII,
1874 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg,
TII,
1889bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &
MBB) {
1891 unsigned CurrBase = 0;
1892 unsigned CurrOpc = ~0
u;
1894 unsigned Position = 0;
1895 assert(Candidates.size() == 0);
1897 LiveRegsValid =
false;
1902 MBBI = std::prev(
I);
1903 if (FixInvalidRegPairOp(
MBB,
MBBI))
1908 unsigned Opcode =
MBBI->getOpcode();
1909 const MachineOperand &MO =
MBBI->getOperand(0);
1915 if (CurrBase == 0) {
1920 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1924 if (CurrOpc == Opcode && CurrBase ==
Base && CurrPred == Pred) {
1932 bool Overlap =
false;
1936 for (
const MemOpQueueEntry &
E : MemOps) {
1937 if (
TRI->regsOverlap(
Reg,
E.MI->getOperand(0).getReg())) {
1947 if (
Offset > MemOps.back().Offset) {
1948 MemOps.push_back(MemOpQueueEntry(*
MBBI,
Offset, Position));
1951 MemOpQueue::iterator
MI, ME;
1952 for (
MI = MemOps.begin(), ME = MemOps.end();
MI != ME; ++
MI) {
1963 if (
MI != MemOps.end()) {
1964 MemOps.insert(
MI, MemOpQueueEntry(*
MBBI,
Offset, Position));
1975 }
else if (
MBBI->isDebugInstr()) {
1977 }
else if (
MBBI->getOpcode() == ARM::t2LDRDi8 ||
1978 MBBI->getOpcode() == ARM::t2STRDi8) {
1985 if (MemOps.size() > 0) {
1986 FormCandidates(MemOps);
1994 if (MemOps.size() > 0)
1995 FormCandidates(MemOps);
1999 auto LessThan = [](
const MergeCandidate*
M0,
const MergeCandidate *
M1) {
2000 return M0->InsertPos <
M1->InsertPos;
2006 for (
const MergeCandidate *Candidate : Candidates) {
2007 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
2008 MachineInstr *Merged = MergeOpsUpdate(*Candidate);
2013 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
2014 MergeBaseUpdateLSDouble(*Merged);
2016 MergeBaseUpdateLSMultiple(Merged);
2018 for (MachineInstr *
MI : Candidate->Instrs) {
2019 if (MergeBaseUpdateLoadStore(
MI))
2024 assert(Candidate->Instrs.size() == 1);
2025 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
2031 for (MachineInstr *
MI : MergeBaseCandidates)
2032 MergeBaseUpdateLSDouble(*
MI);
2033 MergeBaseCandidates.clear();
2048bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &
MBB) {
2050 if (isThumb1)
return false;
2055 (
MBBI->getOpcode() == ARM::BX_RET ||
2056 MBBI->getOpcode() == ARM::tBX_RET ||
2057 MBBI->getOpcode() == ARM::MOVPCLR)) {
2060 while (PrevI->isDebugInstr() && PrevI !=
MBB.
begin())
2062 MachineInstr &PrevMI = *PrevI;
2064 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
2065 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
2066 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
2068 if (MO.
getReg() != ARM::LR)
2070 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
2071 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
2072 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
2083bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &
MBB) {
2086 MBBI->getOpcode() != ARM::tBX_RET)
2091 if (Prev->getOpcode() != ARM::tMOVr ||
2092 !Prev->definesRegister(ARM::LR,
nullptr))
2095 for (
auto Use : Prev->uses())
2097 assert(STI->hasV4TOps());
2110bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
2114 AFI = Fn.
getInfo<ARMFunctionInfo>();
2118 RegClassInfoValid =
false;
2122 bool Modified =
false, ModifiedLDMReturn =
false;
2123 for (MachineBasicBlock &
MBB : Fn) {
2126 ModifiedLDMReturn |= MergeReturnIntoLDM(
MBB);
2136 if (ModifiedLDMReturn)
2143bool ARMLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &MF) {
2146 ARMLoadStoreOpt Impl;
2147 return Impl.runOnMachineFunction(MF);
2150#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \
2151 "ARM pre- register allocation load / store optimization pass"
2157struct ARMPreAllocLoadStoreOpt {
2180 bool DistributeIncrements();
2191 StringRef getPassName()
const override {
2204char ARMPreAllocLoadStoreOptLegacy::ID = 0;
2217 cl::init(8),
cl::Hidden);
2219bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn,
2227 TD = &Fn.getDataLayout();
2229 TII = STI->getInstrInfo();
2230 TRI = STI->getRegisterInfo();
2231 MRI = &Fn.getRegInfo();
2234 bool Modified = DistributeIncrements();
2236 Modified |= RescheduleLoadStoreInstrs(&MFI);
2241bool ARMPreAllocLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &Fn) {
2245 ARMPreAllocLoadStoreOpt Impl;
2246 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2247 MachineDominatorTree *DT =
2248 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2249 return Impl.runOnMachineFunction(Fn, AA, DT);
2262 if (
I->isDebugInstr() || MemOps.
count(&*
I))
2264 if (
I->isCall() ||
I->isTerminator() ||
I->hasUnmodeledSideEffects())
2266 if (
I->mayStore() || (!isLd &&
I->mayLoad()))
2268 if (
I->mayAlias(
AA, *
MemOp,
false))
2270 for (
unsigned j = 0,
NumOps =
I->getNumOperands(); j !=
NumOps; ++j) {
2283 if (MemRegs.
size() <= 4)
2286 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
2289bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
2290 MachineInstr *Op0, MachineInstr *Op1,
DebugLoc &dl,
unsigned &NewOpc,
2294 if (!STI->hasV5TEOps())
2300 if (Opcode == ARM::LDRi12) {
2302 }
else if (Opcode == ARM::STRi12) {
2304 }
else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
2305 NewOpc = ARM::t2LDRDi8;
2308 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
2309 NewOpc = ARM::t2STRDi8;
2326 if (Alignment < ReqAlign)
2332 int Limit = (1 << 8) * Scale;
2333 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
2342 int Limit = (1 << 8) * Scale;
2343 if (OffImm >= Limit || (OffImm & (Scale-1)))
2349 if (FirstReg == SecondReg)
2357bool ARMPreAllocLoadStoreOpt::RescheduleOps(
2358 MachineBasicBlock *
MBB, SmallVectorImpl<MachineInstr *> &
Ops,
unsigned Base,
2359 bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
2361 bool RetVal =
false;
2368 return LOffset > ROffset;
2375 while (
Ops.size() > 1) {
2376 unsigned FirstLoc = ~0
U;
2377 unsigned LastLoc = 0;
2378 MachineInstr *FirstOp =
nullptr;
2379 MachineInstr *LastOp =
nullptr;
2381 unsigned LastOpcode = 0;
2382 unsigned LastBytes = 0;
2383 unsigned NumMove = 0;
2388 if (LastOpcode && LSMOpcode != LastOpcode)
2395 if (Bytes != LastBytes ||
Offset != (LastOffset + (
int)Bytes))
2407 LastOpcode = LSMOpcode;
2409 unsigned Loc = MI2LocMap[
Op];
2410 if (Loc <= FirstLoc) {
2414 if (Loc >= LastLoc) {
2423 SmallPtrSet<MachineInstr*, 4> MemOps;
2424 SmallSet<unsigned, 4> MemRegs;
2425 for (
size_t i =
Ops.size() - NumMove, e =
Ops.size(); i != e; ++i) {
2432 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
2435 MemOps, MemRegs,
TRI, AA);
2437 for (
unsigned i = 0; i != NumMove; ++i)
2442 while (InsertPos !=
MBB->
end() &&
2443 (MemOps.
count(&*InsertPos) || InsertPos->isDebugInstr()))
2448 MachineInstr *Op0 =
Ops.back();
2449 MachineInstr *Op1 =
Ops[
Ops.size()-2];
2454 unsigned NewOpc = 0;
2457 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
2458 FirstReg, SecondReg, BaseReg,
2459 Offset, PredReg, Pred, isT2)) {
2463 const MCInstrDesc &MCID =
TII->get(NewOpc);
2470 MachineInstrBuilder MIB =
BuildMI(*
MBB, InsertPos, dl, MCID)
2471 .
addReg(FirstReg, RegState::Define)
2472 .
addReg(SecondReg, RegState::Define)
2484 MachineInstrBuilder MIB =
BuildMI(*
MBB, InsertPos, dl, MCID)
2507 for (
unsigned i = 0; i != NumMove; ++i) {
2508 MachineInstr *
Op =
Ops.pop_back_val();
2519 NumLdStMoved += NumMove;
2530 if (
MI->isNonListDebugValue()) {
2531 auto &
Op =
MI->getOperand(0);
2535 for (
unsigned I = 2;
I <
MI->getNumOperands();
I++) {
2536 auto &
Op =
MI->getOperand(
I);
2550 auto RegIt = RegisterMap.find(
Op.getReg());
2551 if (RegIt == RegisterMap.end())
2553 auto &InstrVec = RegIt->getSecond();
2560 MI->getDebugLoc()->getInlinedAt());
2565ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *
MBB) {
2566 bool RetVal =
false;
2568 DenseMap<MachineInstr *, unsigned> MI2LocMap;
2569 using Base2InstMap = DenseMap<unsigned, SmallVector<MachineInstr *, 4>>;
2570 using BaseVec = SmallVector<unsigned, 4>;
2571 Base2InstMap Base2LdsMap;
2572 Base2InstMap Base2StsMap;
2578 SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> RegisterMap;
2585 MachineInstr &
MI = *
MBBI;
2586 if (
MI.isCall() ||
MI.isTerminator()) {
2592 if (!
MI.isDebugInstr())
2593 MI2LocMap[&
MI] = ++Loc;
2601 int Opc =
MI.getOpcode();
2605 bool StopHere =
false;
2606 auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
2609 BI->second.push_back(&
MI);
2610 Bases.push_back(
Base);
2613 for (
const MachineInstr *
MI : BI->second) {
2620 BI->second.push_back(&
MI);
2624 FindBases(Base2LdsMap, LdBases);
2626 FindBases(Base2StsMap, StBases);
2637 for (
unsigned Base : LdBases) {
2638 SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[
Base];
2640 RetVal |= RescheduleOps(
MBB, Lds,
Base,
true, MI2LocMap, RegisterMap);
2644 for (
unsigned Base : StBases) {
2645 SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[
Base];
2647 RetVal |= RescheduleOps(
MBB, Sts,
Base,
false, MI2LocMap, RegisterMap);
2651 Base2LdsMap.clear();
2652 Base2StsMap.clear();
2808 SmallDenseMap<DebugVariable, MachineInstr *, 8> DbgValueSinkCandidates;
2811 SmallDenseMap<MachineInstr *, SmallVector<Register>, 8> InstrMap;
2813 MachineInstr &
MI = *
MBBI;
2815 auto PopulateRegisterAndInstrMapForDebugInstr = [&](
Register Reg) {
2816 auto RegIt = RegisterMap.
find(
Reg);
2817 if (RegIt == RegisterMap.
end())
2819 auto &InstrVec = RegIt->getSecond();
2820 InstrVec.push_back(&
MI);
2821 InstrMap[&
MI].push_back(
Reg);
2824 if (
MI.isDebugValue()) {
2826 "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");
2834 PopulateRegisterAndInstrMapForDebugInstr(
Op.getReg());
2842 auto InstrIt = DbgValueSinkCandidates.
find(DbgVar);
2843 if (InstrIt != DbgValueSinkCandidates.
end()) {
2844 auto *
Instr = InstrIt->getSecond();
2845 auto RegIt = InstrMap.
find(Instr);
2846 if (RegIt != InstrMap.
end()) {
2847 const auto &RegVec = RegIt->getSecond();
2850 for (
auto &
Reg : RegVec) {
2851 auto RegIt = RegisterMap.
find(
Reg);
2852 if (RegIt == RegisterMap.
end())
2854 auto &InstrVec = RegIt->getSecond();
2855 auto IsDbgVar = [&](MachineInstr *
I) ->
bool {
2857 return Var == DbgVar;
2863 [&](MachineOperand &
Op) {
Op.setReg(0); });
2866 DbgValueSinkCandidates[DbgVar] = &
MI;
2870 auto Opc =
MI.getOpcode();
2873 auto Reg =
MI.getOperand(0).getReg();
2874 auto RegIt = RegisterMap.
find(
Reg);
2875 if (RegIt == RegisterMap.
end())
2877 auto &DbgInstrVec = RegIt->getSecond();
2878 if (!DbgInstrVec.size())
2880 for (
auto *DbgInstr : DbgInstrVec) {
2882 auto *ClonedMI =
MI.getMF()->CloneMachineInstr(DbgInstr);
2891 DbgValueSinkCandidates.
erase(DbgVar);
2894 [&](MachineOperand &
Op) {
Op.setReg(0); });
2897 if (DbgInstr->isDebugValueList())
2911 switch (
MI.getOpcode()) {
2912 case ARM::MVE_VLDRBS16:
2913 case ARM::MVE_VLDRBS32:
2914 case ARM::MVE_VLDRBU16:
2915 case ARM::MVE_VLDRBU32:
2916 case ARM::MVE_VLDRHS32:
2917 case ARM::MVE_VLDRHU32:
2918 case ARM::MVE_VLDRBU8:
2919 case ARM::MVE_VLDRHU16:
2920 case ARM::MVE_VLDRWU32:
2921 case ARM::MVE_VSTRB16:
2922 case ARM::MVE_VSTRB32:
2923 case ARM::MVE_VSTRH32:
2924 case ARM::MVE_VSTRBU8:
2925 case ARM::MVE_VSTRHU16:
2926 case ARM::MVE_VSTRWU32:
2928 case ARM::t2LDRHi12:
2929 case ARM::t2LDRSHi8:
2930 case ARM::t2LDRSHi12:
2932 case ARM::t2LDRBi12:
2933 case ARM::t2LDRSBi8:
2934 case ARM::t2LDRSBi12:
2936 case ARM::t2STRBi12:
2938 case ARM::t2STRHi12:
2940 case ARM::MVE_VLDRBS16_post:
2941 case ARM::MVE_VLDRBS32_post:
2942 case ARM::MVE_VLDRBU16_post:
2943 case ARM::MVE_VLDRBU32_post:
2944 case ARM::MVE_VLDRHS32_post:
2945 case ARM::MVE_VLDRHU32_post:
2946 case ARM::MVE_VLDRBU8_post:
2947 case ARM::MVE_VLDRHU16_post:
2948 case ARM::MVE_VLDRWU32_post:
2949 case ARM::MVE_VSTRB16_post:
2950 case ARM::MVE_VSTRB32_post:
2951 case ARM::MVE_VSTRH32_post:
2952 case ARM::MVE_VSTRBU8_post:
2953 case ARM::MVE_VSTRHU16_post:
2954 case ARM::MVE_VSTRWU32_post:
2955 case ARM::MVE_VLDRBS16_pre:
2956 case ARM::MVE_VLDRBS32_pre:
2957 case ARM::MVE_VLDRBU16_pre:
2958 case ARM::MVE_VLDRBU32_pre:
2959 case ARM::MVE_VLDRHS32_pre:
2960 case ARM::MVE_VLDRHU32_pre:
2961 case ARM::MVE_VLDRBU8_pre:
2962 case ARM::MVE_VLDRHU16_pre:
2963 case ARM::MVE_VLDRWU32_pre:
2964 case ARM::MVE_VSTRB16_pre:
2965 case ARM::MVE_VSTRB32_pre:
2966 case ARM::MVE_VSTRH32_pre:
2967 case ARM::MVE_VSTRBU8_pre:
2968 case ARM::MVE_VSTRHU16_pre:
2969 case ARM::MVE_VSTRWU32_pre:
2976 switch (
MI.getOpcode()) {
2977 case ARM::MVE_VLDRBS16_post:
2978 case ARM::MVE_VLDRBS32_post:
2979 case ARM::MVE_VLDRBU16_post:
2980 case ARM::MVE_VLDRBU32_post:
2981 case ARM::MVE_VLDRHS32_post:
2982 case ARM::MVE_VLDRHU32_post:
2983 case ARM::MVE_VLDRBU8_post:
2984 case ARM::MVE_VLDRHU16_post:
2985 case ARM::MVE_VLDRWU32_post:
2986 case ARM::MVE_VSTRB16_post:
2987 case ARM::MVE_VSTRB32_post:
2988 case ARM::MVE_VSTRH32_post:
2989 case ARM::MVE_VSTRBU8_post:
2990 case ARM::MVE_VSTRHU16_post:
2991 case ARM::MVE_VSTRWU32_post:
2998 switch (
MI.getOpcode()) {
2999 case ARM::MVE_VLDRBS16_pre:
3000 case ARM::MVE_VLDRBS32_pre:
3001 case ARM::MVE_VLDRBU16_pre:
3002 case ARM::MVE_VLDRBU32_pre:
3003 case ARM::MVE_VLDRHS32_pre:
3004 case ARM::MVE_VLDRHU32_pre:
3005 case ARM::MVE_VLDRBU8_pre:
3006 case ARM::MVE_VLDRHU16_pre:
3007 case ARM::MVE_VLDRWU32_pre:
3008 case ARM::MVE_VSTRB16_pre:
3009 case ARM::MVE_VSTRB32_pre:
3010 case ARM::MVE_VSTRH32_pre:
3011 case ARM::MVE_VSTRBU8_pre:
3012 case ARM::MVE_VSTRHU16_pre:
3013 case ARM::MVE_VSTRWU32_pre:
3026 int &CodesizeEstimate) {
3035 CodesizeEstimate += 1;
3036 return Imm < 0 && -Imm < ((1 << 8) * 1);
3049 MI->getOperand(BaseOp).setReg(NewBaseReg);
3057 int OldOffset =
MI->getOperand(BaseOp + 1).getImm();
3059 MI->getOperand(BaseOp + 1).setImm(OldOffset -
Offset);
3061 unsigned ConvOpcode;
3062 switch (
MI->getOpcode()) {
3063 case ARM::t2LDRHi12:
3064 ConvOpcode = ARM::t2LDRHi8;
3066 case ARM::t2LDRSHi12:
3067 ConvOpcode = ARM::t2LDRSHi8;
3069 case ARM::t2LDRBi12:
3070 ConvOpcode = ARM::t2LDRBi8;
3072 case ARM::t2LDRSBi12:
3073 ConvOpcode = ARM::t2LDRSBi8;
3075 case ARM::t2STRHi12:
3076 ConvOpcode = ARM::t2STRHi8;
3078 case ARM::t2STRBi12:
3079 ConvOpcode = ARM::t2STRBi8;
3085 "Illegal Address Immediate after convert!");
3089 .
add(
MI->getOperand(0))
3090 .
add(
MI->getOperand(1))
3092 .
add(
MI->getOperand(3))
3093 .
add(
MI->getOperand(4))
3095 MI->eraseFromParent();
3114 TRC =
TII->getRegClass(
MCID, 2);
3125 .
add(
MI->getOperand(0))
3126 .
add(
MI->getOperand(1))
3128 .
add(
MI->getOperand(3))
3129 .
add(
MI->getOperand(4))
3130 .
add(
MI->getOperand(5))
3133 if (
MI->mayLoad()) {
3135 .
add(
MI->getOperand(0))
3137 .
add(
MI->getOperand(1))
3139 .
add(
MI->getOperand(3))
3140 .
add(
MI->getOperand(4))
3145 .
add(
MI->getOperand(0))
3146 .
add(
MI->getOperand(1))
3148 .
add(
MI->getOperand(3))
3149 .
add(
MI->getOperand(4))
3173bool ARMPreAllocLoadStoreOpt::DistributeIncrements(
Register Base) {
3176 MachineInstr *BaseAccess =
nullptr;
3177 MachineInstr *PrePostInc =
nullptr;
3182 SmallPtrSet<MachineInstr *, 8> OtherAccesses;
3193 if (!
Use.getOperand(BaseOp).isReg() ||
3194 Use.getOperand(BaseOp).getReg() !=
Base)
3198 else if (
Use.getOperand(BaseOp + 1).getImm() == 0)
3201 OtherAccesses.
insert(&Use);
3204 int IncrementOffset;
3210 if (
Increment->definesRegister(ARM::CPSR,
nullptr) ||
3214 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on VirtualReg "
3215 <<
Base.virtRegIndex() <<
"\n");
3219 for (MachineInstr &Use :
3221 if (&Use == BaseAccess || (
Use.getOpcode() != TargetOpcode::PHI &&
3223 LLVM_DEBUG(
dbgs() <<
" BaseAccess doesn't dominate use of increment\n");
3233 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on postinc\n");
3237 else if (PrePostInc) {
3245 LLVM_DEBUG(
dbgs() <<
"\nAttempting to distribute increments on already "
3246 <<
"indexed VirtualReg " <<
Base.virtRegIndex() <<
"\n");
3249 BaseAccess = PrePostInc;
3263 SmallPtrSet<MachineInstr *, 4> SuccessorAccesses;
3264 int CodesizeEstimate = -1;
3265 for (
auto *Use : OtherAccesses) {
3267 SuccessorAccesses.
insert(Use);
3270 Use->getOperand(BaseOp + 1).getImm() -
3272 TII, CodesizeEstimate)) {
3273 LLVM_DEBUG(
dbgs() <<
" Illegal addressing mode immediate on use\n");
3276 }
else if (!DT->
dominates(Use, BaseAccess)) {
3278 dbgs() <<
" Unknown dominance relation between Base and Use\n");
3282 if (STI->
hasMinSize() && CodesizeEstimate > 0) {
3283 LLVM_DEBUG(
dbgs() <<
" Expected to grow instructions under minsize\n");
3291 NewBaseReg =
Increment->getOperand(0).getReg();
3292 MachineInstr *BaseAccessPost =
3296 (void)BaseAccessPost;
3300 for (
auto *Use : SuccessorAccesses) {
3309 Op.setIsKill(
false);
3313bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
3315 SmallSetVector<Register, 4> Visited;
3316 for (
auto &
MBB : *MF) {
3317 for (
auto &
MI :
MBB) {
3319 if (BaseOp == -1 || !
MI.getOperand(BaseOp).isReg())
3323 if (!
Base.isVirtual())
3330 for (
auto Base : Visited)
3339 return new ARMPreAllocLoadStoreOptLegacy();
3340 return new ARMLoadStoreOptLegacy();
3346 ARMLoadStoreOpt Impl;
3347 bool Changed = Impl.runOnMachineFunction(MF);
3358 ARMPreAllocLoadStoreOpt Impl;
3364 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)
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< 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)
#define INITIALIZE_PASS(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
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
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.
LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)
runOnFunction - Prepare to answer questions about MF.
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)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ 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 >
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.