15 #define DEBUG_TYPE "arm-ldst-opt"
45 STATISTIC(NumLDMGened ,
"Number of ldm instructions generated");
46 STATISTIC(NumSTMGened ,
"Number of stm instructions generated");
47 STATISTIC(NumVLDMGened,
"Number of vldm instructions generated");
48 STATISTIC(NumVSTMGened,
"Number of vstm instructions generated");
49 STATISTIC(NumLdStMoved,
"Number of load / store instructions moved");
50 STATISTIC(NumLDRDFormed,
"Number of ldrd created before allocation");
51 STATISTIC(NumSTRDFormed,
"Number of strd created before allocation");
52 STATISTIC(NumLDRD2LDM,
"Number of ldrd instructions turned back into ldm");
53 STATISTIC(NumSTRD2STM,
"Number of strd instructions turned back into stm");
54 STATISTIC(NumLDRD2LDR,
"Number of ldrd instructions turned back into ldr's");
55 STATISTIC(NumSTRD2STR,
"Number of strd instructions turned back into str's");
74 virtual const char *getPassName()
const {
75 return "ARM load / store optimization pass";
79 struct MemOpQueueEntry {
86 MemOpQueueEntry(
int o,
unsigned r,
bool k,
unsigned p,
88 : Offset(o),
Reg(r), isKill(k), Position(p), MBBI(i), Merged(
false) {}
91 typedef MemOpQueue::iterator MemOpQueueIter;
94 const MemOpQueue &MemOps,
unsigned DefReg,
95 unsigned RangeBegin,
unsigned RangeEnd);
98 int Offset,
unsigned Base,
bool BaseKill,
int Opcode,
101 ArrayRef<std::pair<unsigned, bool> > Regs,
105 unsigned memOpsBegin,
107 unsigned insertAfter,
118 int Opcode,
unsigned Size,
120 unsigned Scratch, MemOpQueue &MemOps,
220 case ARM::t2LDMIA_RET:
222 case ARM::t2LDMIA_UPD:
224 case ARM::t2STMIA_UPD:
226 case ARM::VLDMSIA_UPD:
228 case ARM::VSTMSIA_UPD:
230 case ARM::VLDMDIA_UPD:
232 case ARM::VSTMDIA_UPD:
246 case ARM::t2LDMDB_UPD:
248 case ARM::t2STMDB_UPD:
249 case ARM::VLDMSDB_UPD:
250 case ARM::VSTMSDB_UPD:
251 case ARM::VLDMDDB_UPD:
252 case ARM::VSTMDDB_UPD:
267 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
275 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
288 int Offset,
unsigned Base,
bool BaseKill,
290 unsigned PredReg,
unsigned Scratch,
DebugLoc dl,
291 ArrayRef<std::pair<unsigned, bool> > Regs,
294 unsigned NumRegs = Regs.size();
301 bool haveIBAndDA = isNotVFP && !isThumb2;
302 if (Offset == 4 && haveIBAndDA)
304 else if (Offset == -4 * (
int)NumRegs + 4 && haveIBAndDA)
306 else if (Offset == -4 * (
int)NumRegs && isNotVFP)
309 else if (Offset != 0) {
324 NewBase = Regs[NumRegs-1].first;
331 int BaseOpc = !isThumb2 ? ARM::ADDri : ARM::t2ADDri;
333 BaseOpc = !isThumb2 ? ARM::SUBri : ARM::t2SUBri;
336 int ImmedOffset = isThumb2
338 if (ImmedOffset == -1)
342 BuildMI(MBB, MBBI, dl,
TII->get(BaseOpc), NewBase)
349 bool isDef = (
isi32Load(Opcode) || Opcode == ARM::VLDRS ||
350 Opcode == ARM::VLDRD);
352 if (!Opcode)
return false;
355 .addImm(Pred).
addReg(PredReg);
356 for (
unsigned i = 0; i != NumRegs; ++i)
361 for (
unsigned i = 0, e = ImpDefs.
size(); i != e; ++i)
377 void ARMLoadStoreOpt::findUsesOfImpDef(
379 unsigned DefReg,
unsigned RangeBegin,
unsigned RangeEnd) {
380 std::map<unsigned, MachineOperand *> Uses;
381 unsigned LastLivePos = RangeEnd;
387 for (
unsigned i = 0; i < MemOps.size(); ++i) {
389 unsigned MIPosition = MemOps[i].Position;
390 if (MIPosition <= RangeBegin || MIPosition > RangeEnd)
396 LastLivePos = std::min(LastLivePos, MIPosition);
405 LastLivePos = std::min(LastLivePos, MIPosition);
407 Uses[MIPosition] = UseOp;
412 for (std::map<unsigned, MachineOperand *>::iterator
I = Uses.begin(),
417 if (
I->first > LastLivePos)
427 unsigned memOpsBegin,
unsigned memOpsEnd,
428 unsigned insertAfter,
int Offset,
429 unsigned Base,
bool BaseKill,
437 const unsigned insertPos = memOps[insertAfter].Position;
440 for (
unsigned i = 0, e = memOps.size(); i != e; ++i) {
441 if (i == memOpsBegin) {
446 if (memOps[i].Position < insertPos && memOps[i].isKill) {
447 unsigned Reg = memOps[i].Reg;
456 for (
unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
457 unsigned Reg = memOps[i].Reg;
460 bool isKill = memOps[i].isKill || KilledRegs.
count(Reg);
461 Regs.
push_back(std::make_pair(Reg, isKill));
465 if (!MO->isReg() || !MO->isDef() || !MO->isImplicit() || MO->isDead())
467 unsigned DefReg = MO->getReg();
468 if (std::find(ImpDefs.
begin(), ImpDefs.
end(), DefReg) == ImpDefs.
end())
474 findUsesOfImpDef(UsesOfImpDefs, memOps, DefReg, memOps[i].Position,
482 if (!MergeOps(MBB, Loc, Offset, Base, BaseKill, Opcode,
483 Pred, PredReg, Scratch, dl, Regs, ImpDefs))
494 E = UsesOfImpDefs.
end();
498 for (
unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
500 if (Regs[i-memOpsBegin].second) {
501 unsigned Reg = Regs[i-memOpsBegin].first;
502 if (KilledRegs.
count(Reg)) {
503 unsigned j = Killer[
Reg];
504 int Idx = memOps[j].MBBI->findRegisterUseOperandIdx(Reg,
true);
505 assert(Idx >= 0 &&
"Cannot find killing operand");
506 memOps[j].MBBI->getOperand(Idx).setIsKill(
false);
507 memOps[j].isKill =
false;
509 memOps[i].isKill =
true;
511 MBB.
erase(memOps[i].MBBI);
514 memOps[i].Merged =
true;
515 memOps[i].MBBI = Merges.
back();
516 memOps[i].Position = insertPos;
524 unsigned Base,
int Opcode,
unsigned Size,
526 unsigned Scratch, MemOpQueue &MemOps,
529 int Offset = MemOps[SIndex].Offset;
530 int SOffset = Offset;
531 unsigned insertAfter = SIndex;
535 unsigned PReg = PMO.
getReg();
536 unsigned PRegNum = PMO.
isUndef() ? UINT_MAX : TRI->getEncodingValue(PReg);
538 unsigned Limit = ~0U;
558 for (
unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
559 int NewOffset = MemOps[i].Offset;
561 unsigned Reg = MO.
getReg();
562 unsigned RegNum = MO.
isUndef() ? UINT_MAX : TRI->getEncodingValue(Reg);
566 if (Reg != ARM::SP &&
567 NewOffset == Offset + (
int)Size &&
568 ((isNotVFP && RegNum > PRegNum) ||
569 ((Count < Limit) && RegNum == PRegNum+1)) &&
572 (!STI->isSwift() || isNotVFP || Count != 1 || !(PRegNum & 0x1))) {
578 MergeOpsUpdate(MBB, MemOps, SIndex, i, insertAfter, SOffset,
579 Base,
false, Opcode, Pred, PredReg, Scratch, dl, Merges);
580 MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch,
585 if (MemOps[i].Position > MemOps[insertAfter].Position)
589 bool BaseKill = Loc->findRegisterUseOperandIdx(Base,
true) != -1;
590 MergeOpsUpdate(MBB, MemOps, SIndex, MemOps.size(), insertAfter, SOffset,
591 Base, BaseKill, Opcode, Pred, PredReg, Scratch, dl, Merges);
610 unsigned Bytes,
unsigned Limit,
612 unsigned MyPredReg = 0;
616 bool CheckCPSRDef =
false;
618 default:
return false;
628 if (Bytes == 0 || (Limit && Bytes >= Limit))
631 unsigned Scale = (MI->
getOpcode() == ARM::tSUBspi) ? 4 : 1;
636 MyPredReg == PredReg))
643 unsigned Bytes,
unsigned Limit,
645 unsigned MyPredReg = 0;
649 bool CheckCPSRDef =
false;
651 default:
return false;
660 if (Bytes == 0 || (Limit && Bytes >= Limit))
664 unsigned Scale = (MI->
getOpcode() == ARM::tADDspi) ? 4 : 1;
669 MyPredReg == PredReg))
798 unsigned PredReg = 0;
809 bool DoMerge =
false;
814 if (MBBI != BeginMBBI) {
816 while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
833 if (!DoMerge && MBBI != EndMBBI) {
835 while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
860 .addImm(Pred).
addReg(PredReg);
863 for (
unsigned OpNum = 3, e = MI->
getNumOperands(); OpNum != e; ++OpNum)
877 return ARM::LDR_PRE_IMM;
879 return ARM::STR_PRE_IMM;
881 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
883 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
885 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
887 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
890 return ARM::t2LDR_PRE;
893 return ARM::t2STR_PRE;
902 return ARM::LDR_POST_IMM;
904 return ARM::STR_POST_IMM;
906 return Mode ==
ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
908 return Mode ==
ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
910 return Mode ==
ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
912 return Mode ==
ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
915 return ARM::t2LDR_POST;
918 return ARM::t2STR_POST;
936 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
937 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
938 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
945 bool isLd =
isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD;
951 unsigned PredReg = 0;
953 bool DoMerge =
false;
957 unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100);
961 if (MBBI != BeginMBBI) {
963 while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
980 if (!DoMerge && MBBI != EndMBBI) {
982 while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
1013 .addImm(Pred).
addReg(PredReg)
1019 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1020 int Offset = AddSub ==
ARM_AM::sub ? -Bytes : Bytes;
1031 int Offset = AddSub ==
ARM_AM::sub ? -Bytes : Bytes;
1042 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1045 BuildMI(MBB, MBBI, dl, TII->
get(NewOpc), Base)
1049 int Offset = AddSub ==
ARM_AM::sub ? -Bytes : Bytes;
1051 BuildMI(MBB, MBBI, dl, TII->
get(NewOpc), Base)
1116 unsigned Position = MemOps[0].Position;
1117 for (
unsigned i = 1, e = MemOps.size(); i != e; ++i) {
1118 if (MemOps[i].Position < Position) {
1119 Position = MemOps[i].Position;
1120 Loc = MemOps[i].MBBI;
1124 if (Loc != MBB.
begin())
1125 RS->forward(
prior(Loc));
1130 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
1134 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
1135 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
1136 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
1137 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)
1154 int Offset,
bool isDef,
1156 unsigned Reg,
bool RegDeadKill,
bool RegUndef,
1157 unsigned BaseReg,
bool BaseKill,
bool BaseUndef,
1158 bool OffKill,
bool OffUndef,
1180 if (Opcode == ARM::LDRD || Opcode == ARM::STRD ||
1181 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) {
1183 unsigned BaseReg = BaseOp.
getReg();
1186 unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg,
false);
1187 unsigned OddRegNum = TRI->getDwarfRegNum(OddReg,
false);
1190 bool Errata602117 = EvenReg == BaseReg && STI->isCortexM3();
1191 if (!Errata602117 &&
1192 ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum))
1196 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
1197 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
1198 bool EvenDeadKill = isLd ?
1201 bool OddDeadKill = isLd ?
1204 bool BaseKill = BaseOp.
isKill();
1205 bool BaseUndef = BaseOp.
isUndef();
1209 unsigned PredReg = 0;
1212 if (OddRegNum > EvenRegNum && OffImm == 0) {
1215 unsigned NewOpc = (isLd)
1216 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
1217 : (isT2 ? ARM::t2STMIA : ARM::STMIA);
1219 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->
get(NewOpc))
1221 .addImm(Pred).
addReg(PredReg)
1226 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->
get(NewOpc))
1228 .addImm(Pred).
addReg(PredReg)
1238 unsigned NewOpc = (isLd)
1239 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1240 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1243 unsigned NewOpc2 = (isLd)
1244 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
1245 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
1250 (BaseKill || OffKill) &&
1251 (TRI->regsOverlap(EvenReg, BaseReg))) {
1252 assert(!TRI->regsOverlap(OddReg, BaseReg));
1254 OddReg, OddDeadKill,
false,
1255 BaseReg,
false, BaseUndef,
false, OffUndef,
1256 Pred, PredReg, TII, isT2);
1259 EvenReg, EvenDeadKill,
false,
1260 BaseReg, BaseKill, BaseUndef, OffKill, OffUndef,
1261 Pred, PredReg, TII, isT2);
1263 if (OddReg == EvenReg && EvenDeadKill) {
1267 EvenDeadKill =
false;
1271 if (EvenReg == BaseReg)
1272 EvenDeadKill =
false;
1274 EvenReg, EvenDeadKill, EvenUndef,
1275 BaseReg,
false, BaseUndef,
false, OffUndef,
1276 Pred, PredReg, TII, isT2);
1279 OddReg, OddDeadKill, OddUndef,
1280 BaseReg, BaseKill, BaseUndef, OffKill, OffUndef,
1281 Pred, PredReg, TII, isT2);
1299 unsigned NumMerges = 0;
1300 unsigned NumMemOps = 0;
1302 unsigned CurrBase = 0;
1304 unsigned CurrSize = 0;
1306 unsigned CurrPredReg = 0;
1307 unsigned Position = 0;
1310 RS->enterBasicBlock(&MBB);
1313 if (FixInvalidRegPairOp(MBB, MBBI))
1316 bool Advance =
false;
1317 bool TryMerge =
false;
1318 bool Clobber =
false;
1322 int Opcode = MBBI->getOpcode();
1325 unsigned Reg = MO.
getReg();
1327 unsigned Base = MBBI->getOperand(1).getReg();
1328 unsigned PredReg = 0;
1340 Clobber = (
isi32Load(Opcode) && Base == MBBI->getOperand(0).getReg());
1349 bool Overlap =
false;
1350 for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end(); I != E; ++
I) {
1351 if (TRI->regsOverlap(Reg, I->MBBI->getOperand(0).getReg())) {
1357 if (CurrBase == 0 && !Clobber) {
1363 CurrPredReg = PredReg;
1364 MemOps.push_back(MemOpQueueEntry(Offset, Reg, isKill, Position, MBBI));
1367 }
else if (!Overlap) {
1373 if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
1376 if (Offset > MemOps.back().Offset) {
1377 MemOps.push_back(MemOpQueueEntry(Offset, Reg, isKill,
1382 for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end();
1384 if (Offset < I->Offset) {
1385 MemOps.insert(I, MemOpQueueEntry(Offset, Reg, isKill,
1390 }
else if (Offset == I->Offset) {
1400 if (MBBI->isDebugValue()) {
1405 }
else if (Advance) {
1415 if (NumMemOps > 1) {
1418 AdvanceRS(MBB, MemOps);
1420 unsigned Scratch = RS->FindUnusedReg(&ARM::GPRRegClass);
1422 RS->forward(
prior(MBBI));
1426 MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,
1427 CurrPred, CurrPredReg, Scratch, MemOps, Merges);
1431 for (
unsigned i = 0, e = Merges.
size(); i < e; ++i)
1432 if (MergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
1434 NumMerges += Merges.
size();
1438 for (
unsigned i = 0; i != NumMemOps; ++i)
1439 if (!MemOps[i].Merged)
1440 if (MergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI))
1444 RS->skipTo(
prior(MBBI));
1445 }
else if (NumMemOps == 1) {
1448 if (MergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
1450 RS->forward(
prior(MBBI));
1466 if (!Advance && !isMemOp && MBBI != E) {
1472 return NumMerges > 0;
1486 if (MBB.
empty())
return false;
1489 if (MBBI != MBB.
begin() &&
1490 (MBBI->getOpcode() == ARM::BX_RET ||
1491 MBBI->getOpcode() == ARM::tBX_RET ||
1492 MBBI->getOpcode() == ARM::MOVPCLR)) {
1495 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
1496 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
1497 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
1499 if (MO.
getReg() != ARM::LR)
1501 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
1502 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
1503 Opcode == ARM::LDMIA_UPD) &&
"Unsupported multiple load-return!");
1521 isThumb2 = AFI->isThumb2Function();
1523 bool Modified =
false;
1527 Modified |= LoadStoreMultipleOpti(MBB);
1529 Modified |= MergeReturnIntoLDM(MBB);
1555 virtual const char *getPassName()
const {
1556 return "ARM pre- register allocation load / store optimization pass";
1561 unsigned &NewOpc,
unsigned &EvenReg,
1562 unsigned &OddReg,
unsigned &BaseReg,
1568 unsigned Base,
bool isLd,
1575 bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(
MachineFunction &Fn) {
1583 bool Modified =
false;
1586 Modified |= RescheduleLoadStoreInstrs(MFI);
1602 if (I->isDebugValue() || MemOps.
count(&*I))
1604 if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects())
1606 if (isLd && I->mayStore())
1618 for (
unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
1622 unsigned Reg = MO.
getReg();
1625 if (Reg != Base && !MemRegs.
count(Reg))
1626 AddedRegPressure.
insert(Reg);
1631 if (MemRegs.
size() <= 4)
1634 return AddedRegPressure.
size() <= MemRegs.
size() * 2;
1657 unsigned &NewOpc,
unsigned &EvenReg,
1658 unsigned &OddReg,
unsigned &BaseReg,
1659 int &Offset,
unsigned &PredReg,
1663 if (!STI->hasV5TEOps())
1669 if (Opcode == ARM::LDRi12)
1671 else if (Opcode == ARM::STRi12)
1673 else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
1674 NewOpc = ARM::t2LDRDi8;
1677 }
else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
1678 NewOpc = ARM::t2STRDi8;
1693 unsigned ReqAlign = STI->hasV6Ops()
1696 if (Align < ReqAlign)
1702 int Limit = (1 << 8) * Scale;
1703 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
1712 int Limit = (1 << 8) * Scale;
1713 if (OffImm >= Limit || (OffImm & (Scale-1)))
1719 if (EvenReg == OddReg)
1728 struct OffsetCompare {
1732 assert(LHS == RHS || LOffset != ROffset);
1733 return LOffset > ROffset;
1740 unsigned Base,
bool isLd,
1742 bool RetVal =
false;
1745 std::sort(Ops.
begin(), Ops.
end(), OffsetCompare());
1751 while (Ops.
size() > 1) {
1752 unsigned FirstLoc = ~0U;
1753 unsigned LastLoc = 0;
1757 unsigned LastOpcode = 0;
1758 unsigned LastBytes = 0;
1759 unsigned NumMove = 0;
1760 for (
int i = Ops.
size() - 1; i >= 0; --i) {
1762 unsigned Loc = MI2LocMap[Op];
1763 if (Loc <= FirstLoc) {
1767 if (Loc >= LastLoc) {
1774 if (LastOpcode && LSMOpcode != LastOpcode)
1780 if (Bytes != LastBytes || Offset != (LastOffset + (
int)Bytes))
1783 LastOffset = Offset;
1785 LastOpcode = LSMOpcode;
1795 for (
int i = NumMove-1; i >= 0; --i) {
1802 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;
1805 MemOps, MemRegs, TRI);
1807 for (
unsigned i = 0; i != NumMove; ++i)
1812 while (InsertPos != MBB->
end()
1813 && (MemOps.
count(InsertPos) || InsertPos->isDebugValue()))
1820 unsigned EvenReg = 0, OddReg = 0;
1821 unsigned BaseReg = 0, PredReg = 0;
1824 unsigned NewOpc = 0;
1827 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
1828 EvenReg, OddReg, BaseReg,
1829 Offset, PredReg, Pred, isT2)) {
1835 MRI->constrainRegClass(EvenReg, TRC);
1836 MRI->constrainRegClass(OddReg, TRC);
1851 DEBUG(
dbgs() <<
"Formed " << *MIB <<
"\n");
1865 DEBUG(
dbgs() <<
"Formed " << *MIB <<
"\n");
1875 for (
unsigned i = 0; i != NumMove; ++i) {
1878 MBB->
splice(InsertPos, MBB, Op);
1882 NumLdStMoved += NumMove;
1893 bool RetVal =
false;
1905 for (; MBBI != E; ++MBBI) {
1914 MI2LocMap[MI] = ++Loc;
1918 unsigned PredReg = 0;
1923 bool isLd =
isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
1927 bool StopHere =
false;
1930 Base2LdsMap.
find(Base);
1931 if (BI != Base2LdsMap.
end()) {
1932 for (
unsigned i = 0, e = BI->second.
size(); i != e; ++i) {
1939 BI->second.push_back(MI);
1941 Base2LdsMap[Base].push_back(MI);
1946 Base2StsMap.
find(Base);
1947 if (BI != Base2StsMap.
end()) {
1948 for (
unsigned i = 0, e = BI->second.
size(); i != e; ++i) {
1955 BI->second.push_back(MI);
1957 Base2StsMap[Base].push_back(MI);
1971 for (
unsigned i = 0, e = LdBases.
size(); i != e; ++i) {
1972 unsigned Base = LdBases[i];
1975 RetVal |= RescheduleOps(MBB, Lds, Base,
true, MI2LocMap);
1979 for (
unsigned i = 0, e = StBases.
size(); i != e; ++i) {
1980 unsigned Base = StBases[i];
1983 RetVal |= RescheduleOps(MBB, Sts, Base,
false, MI2LocMap);
1987 Base2LdsMap.
clear();
1988 Base2StsMap.
clear();
2002 return new ARMPreAllocLoadStoreOpt();
2003 return new ARMLoadStoreOpt();
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
void push_back(const T &Elt)
AMSubMode getLoadStoreMultipleSubMode(int Opcode)
const MachineFunction * getParent() const
instr_iterator erase(instr_iterator I)
LLVMContext & getContext() const
static unsigned char getAM3Offset(unsigned AM3Opc)
static bool isMatchingIncrement(MachineInstr *MI, unsigned Base, unsigned Bytes, unsigned Limit, ARMCC::CondCodes Pred, unsigned PredReg)
const MCInstrDesc & getDesc() const
static IntegerType * getInt64Ty(LLVMContext &C)
bool isTerminator(QueryType Type=AnyInBundle) const
const HexagonInstrInfo * TII
static bool definesCPSR(MachineInstr *MI)
#define llvm_unreachable(msg)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static int getMemoryOpOffset(const MachineInstr *MI)
ID
LLVM Calling Convention Representation.
const MachineInstrBuilder & addImm(int64_t Val) const
unsigned getNumOperands() const
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=NULL) const
bool count(PtrType Ptr) const
count - Return true if the specified pointer is in the set.
static int getT2SOImmVal(unsigned Arg)
uint64_t getAlignment() const
iterator getLastNonDebugInstr()
unsigned getUndefRegState(bool B)
size_t size() const
size - Get the array size.
unsigned getKillRegState(bool B)
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)
const MachineBasicBlock * getParent() const
bool isDebugValue() const
unsigned getDeadRegState(bool B)
mmo_iterator memoperands_end() const
unsigned getDefRegState(bool B)
bundle_iterator< MachineInstr, instr_iterator > iterator
bool regsOverlap(unsigned regA, unsigned regB) const
static unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg)
static unsigned char getAM5Offset(unsigned AM5Opc)
static bool isT2i32Load(unsigned Opc)
const MachineOperand & getOperand(unsigned i) const
ItTy next(ItTy it, Dist n)
bool hasOneMemOperand() const
static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode)
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
STATISTIC(NumLDMGened,"Number of ldm instructions generated")
const MCInstrDesc & get(unsigned Opcode) const
FunctionPass * createARMLoadStoreOptimizationPass(bool PreAlloc=false)
static bool isi32Store(unsigned Opc)
virtual const TargetInstrInfo * getInstrInfo() const
MachineOperand * findRegisterUseOperand(unsigned Reg, bool isKill=false, const TargetRegisterInfo *TRI=NULL)
bool memoperands_empty() const
void setDesc(const MCInstrDesc &tid)
const STC & getSubtarget() const
static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, MachineBasicBlock::iterator I, MachineBasicBlock::iterator E, SmallPtrSet< MachineInstr *, 4 > &MemOps, SmallSet< unsigned, 4 > &MemRegs, const TargetRegisterInfo *TRI)
static bool isMemoryOp(const MachineInstr *MI)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
static AddrOpc getAM3Op(unsigned AM3Opc)
static unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
static int getSOImmVal(unsigned Arg)
static unsigned getLSMultipleTransferSize(MachineInstr *MI)
bool count(const T &V) const
count - Return true if the element is in the set.
static bool isT2i32Store(unsigned Opc)
void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI)
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
MachineRegisterInfo & getRegInfo()
static void InsertLDR_STR(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int Offset, bool isDef, DebugLoc dl, unsigned NewOpc, unsigned Reg, bool RegDeadKill, bool RegUndef, unsigned BaseReg, bool BaseKill, bool BaseUndef, bool OffKill, bool OffUndef, ARMCC::CondCodes Pred, unsigned PredReg, const TargetInstrInfo *TII, bool isT2)
void setReg(unsigned Reg)
virtual const DataLayout * getDataLayout() const
bool isCall(QueryType Type=AnyInBundle) const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const TargetMachine & getTarget() const
virtual const TargetRegisterInfo * getRegisterInfo() const
static AddrOpc getAM5Op(unsigned AM5Opc)
static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, ARM_AM::AMSubMode Mode)
unsigned getReg() const
getReg - Returns the register number.
bool isValid() const
isValid - Returns true until all the operands have been visited.
static bool isi32Load(unsigned Opc)
static bool isMatchingDecrement(MachineInstr *MI, unsigned Base, unsigned Bytes, unsigned Limit, ARMCC::CondCodes Pred, unsigned PredReg)
static void concatenateMemOperands(MachineInstr *MI, MachineInstr *Op0, MachineInstr *Op1)
Copy Op0 and Op1 operands into a new array assigned to MI.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction. Note that variadic (isVari...
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
BasicBlockListType::iterator iterator
ItTy prior(ItTy it, Dist n)
const MCRegisterInfo & MRI
iterator find(const KeyT &Val)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num)
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd)
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
DebugLoc getDebugLoc() const
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.