40#include "llvm/Config/llvm-config.h"
61#define DEBUG_TYPE "arm-cp-islands"
63#define ARM_CP_ISLANDS_OPT_NAME \
64 "ARM constant island placement and branch shortening pass"
66STATISTIC(NumSplit,
"Number of uncond branches inserted");
67STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
68STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
69STATISTIC(NumTBs,
"Number of table branches generated");
70STATISTIC(NumT2CPShrunk,
"Number of Thumb2 constantpool instructions shrunk");
71STATISTIC(NumT2BrShrunk,
"Number of Thumb2 immediate branches shrunk");
73STATISTIC(NumJTMoved,
"Number of jump table destination blocks moved");
74STATISTIC(NumJTInserted,
"Number of jump table intermediate blocks inserted");
75STATISTIC(NumLEInserted,
"Number of LE backwards branches inserted");
79 cl::desc(
"Adjust basic block layout to better use TB[BH]"));
83 cl::desc(
"The max number of iteration for converge"));
87 cl::desc(
"Use compressed jump tables in Thumb-1 by synthesizing an "
88 "equivalent to the TBB/TBH instructions"));
104 std::unique_ptr<ARMBasicBlockUtils> BBUtils =
nullptr;
109 std::vector<MachineBasicBlock*> WaterList;
115 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
136 bool KnownAlignment =
false;
139 bool neg,
bool soimm)
140 :
MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(
neg), IsSoImm(soimm) {
147 unsigned getMaxDisp()
const {
148 return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
154 std::vector<CPUser> CPUsers;
165 : CPEMI(cpemi), CPI(cpi), RefCount(
rc) {}
177 std::vector<std::vector<CPEntry>> CPEntries;
196 unsigned MaxDisp : 31;
200 ImmBranch(
MachineInstr *mi,
unsigned maxdisp,
bool cond,
unsigned ubr)
201 :
MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
205 std::vector<ImmBranch> ImmBranches;
222 bool isPositionIndependentOrROPI;
238 MachineFunctionProperties::Property::NoVRegs);
246 void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
247 void doInitialJumpTablePlacement(std::vector<MachineInstr *> &CPEMIs);
249 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
251 void scanFunctionJumpTables();
252 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
255 bool decrementCPEReferenceCount(
unsigned CPI,
MachineInstr* CPEMI);
257 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
258 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
259 water_iterator &WaterIter,
bool CloserWater);
260 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
262 bool handleConstantPoolUser(
unsigned CPUserIndex,
bool CloserWater);
264 bool removeUnusedCPEntries();
267 bool DoDump =
false);
269 CPUser &U,
unsigned &Growth);
270 bool fixupImmediateBr(ImmBranch &Br);
271 bool fixupConditionalBr(ImmBranch &Br);
272 bool fixupUnconditionalBr(ImmBranch &Br);
273 bool optimizeThumb2Instructions();
274 bool optimizeThumb2Branches();
275 bool reorderThumb2JumpTables();
277 unsigned &DeadSize,
bool &CanDeleteLEA,
279 bool optimizeThumb2JumpTables();
286 unsigned getUserOffset(CPUser&)
const;
290 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
291 unsigned Disp,
bool NegativeOK,
bool IsSoImm =
false);
292 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
294 return isOffsetInRange(UserOffset, TrialOffset,
295 U.getMaxDisp(), U.NegOk, U.IsSoImm);
301char ARMConstantIslands::ID = 0;
304void ARMConstantIslands::verify() {
309 return BBInfo[
LHS.getNumber()].postOffset() <
310 BBInfo[
RHS.getNumber()].postOffset();
312 LLVM_DEBUG(
dbgs() <<
"Verifying " << CPUsers.size() <<
" CP users.\n");
313 for (CPUser &U : CPUsers) {
314 unsigned UserOffset = getUserOffset(U);
317 if (isCPEntryInRange(U.MI, UserOffset, U.CPEMI, U.getMaxDisp()+2, U.NegOk,
330#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
335 for (
unsigned J = 0,
E = BBInfo.
size(); J !=
E; ++J) {
336 const BasicBlockInfo &BBI = BBInfo[J];
337 dbgs() << format(
"%08x %bb.%u\t", BBI.Offset, J)
338 <<
" kb=" << unsigned(BBI.KnownBits)
339 <<
" ua=" << unsigned(BBI.Unalign) <<
" pa=" << Log2(BBI.PostAlign)
340 << format(
" size=%#x\n", BBInfo[J].Size);
355 const Align Alignment = TLI->getPrefLoopAlignment();
359 bool Changed =
false;
360 bool PrevCanFallthough =
true;
361 for (
auto &
MBB : *MF) {
362 if (!PrevCanFallthough) {
373 if (
MI.getOpcode() == ARM::t2B &&
377 MI.getOpcode() == ARM::t2LoopEndDec) {
378 PrevCanFallthough =
true;
396 << MCP->getConstants().size() <<
" CP entries, aligned to "
397 << MCP->getConstantPoolAlign().value() <<
" bytes *****\n");
400 TII = STI->getInstrInfo();
401 isPositionIndependentOrROPI =
402 STI->getTargetLowering()->isPositionIndependent() || STI->isROPI();
404 DT = &getAnalysis<MachineDominatorTree>();
406 isThumb = AFI->isThumbFunction();
407 isThumb1 = AFI->isThumb1OnlyFunction();
408 isThumb2 = AFI->isThumb2Function();
413 if (STI->hardenSlsRetBr())
418 MF->RenumberBlocks();
422 bool MadeChange =
false;
424 scanFunctionJumpTables();
425 MadeChange |= reorderThumb2JumpTables();
427 T2JumpTables.clear();
429 MF->RenumberBlocks();
437 std::vector<MachineInstr*> CPEMIs;
439 doInitialConstPlacement(CPEMIs);
441 if (MF->getJumpTableInfo())
442 doInitialJumpTablePlacement(CPEMIs);
445 AFI->initPICLabelUId(CPEMIs.size());
450 initializeFunctionInfo(CPEMIs);
456 if (!T2JumpTables.empty())
457 MF->ensureAlignment(
Align(4));
460 MadeChange |= removeUnusedCPEntries();
464 unsigned NoCPIters = 0, NoBRIters = 0;
466 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
467 bool CPChange =
false;
468 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
472 CPChange |= handleConstantPoolUser(i, NoCPIters >=
CPMaxIteration / 2);
479 NewWaterList.
clear();
481 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
482 bool BRChange =
false;
483 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
484 BRChange |= fixupImmediateBr(ImmBranches[i]);
485 if (BRChange && ++NoBRIters > 30)
489 if (!CPChange && !BRChange)
495 if (isThumb2 && !STI->prefers32BitThumb())
496 MadeChange |= optimizeThumb2Instructions();
499 if (
isThumb && STI->hasV8MBaselineOps())
500 MadeChange |= optimizeThumb2Branches();
503 if (GenerateTBB && !STI->genExecuteOnly())
504 MadeChange |= optimizeThumb2JumpTables();
510 for (
unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
511 for (
unsigned j = 0, je = CPEntries[i].
size(); j != je; ++j) {
512 const CPEntry & CPE = CPEntries[i][j];
513 if (CPE.CPEMI && CPE.CPEMI->getOperand(1).isCPI())
514 AFI->recordCPEClone(i, CPE.CPI);
524 JumpTableEntryIndices.clear();
525 JumpTableUserIndices.clear();
526 BlockJumpTableRefCount.clear();
529 T2JumpTables.clear();
537ARMConstantIslands::doInitialConstPlacement(std::vector<MachineInstr*> &CPEMIs) {
543 const Align MaxAlign = MCP->getConstantPoolAlign();
544 const unsigned MaxLogAlign =
Log2(MaxAlign);
552 Align FuncAlign = MaxAlign;
554 FuncAlign =
Align(4);
555 MF->ensureAlignment(FuncAlign);
566 const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants();
569 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
570 unsigned Size = CPs[i].getSizeInBytes(TD);
571 Align Alignment = CPs[i].getAlign();
577 unsigned LogAlign =
Log2(Alignment);
582 CPEMIs.push_back(CPEMI);
586 for (
unsigned a = LogAlign + 1; a <= MaxLogAlign; ++a)
587 if (InsPoint[a] == InsAt)
591 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
593 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
594 <<
Size <<
", align = " << Alignment.
value() <<
'\n');
604void ARMConstantIslands::doInitialJumpTablePlacement(
605 std::vector<MachineInstr *> &CPEMIs) {
606 unsigned i = CPEntries.size();
607 auto MJTI = MF->getJumpTableInfo();
608 const std::vector<MachineJumpTableEntry> &
JT = MJTI->getJumpTables();
623 switch (
MI->getOpcode()) {
629 case ARM::BR_JTm_i12:
631 JTOpcode = ARM::JUMPTABLE_ADDRS;
634 JTOpcode = ARM::JUMPTABLE_INSTS;
638 JTOpcode = ARM::JUMPTABLE_TBB;
642 JTOpcode = ARM::JUMPTABLE_TBH;
646 unsigned NumOps =
MI->getDesc().getNumOperands();
648 MI->getOperand(NumOps - (
MI->isPredicable() ? 2 : 1));
658 CPEMIs.push_back(CPEMI);
659 CPEntries.emplace_back(1, CPEntry(CPEMI, JTI));
660 JumpTableEntryIndices.insert(std::make_pair(JTI, CPEntries.size() - 1));
661 if (!LastCorrectlyNumberedBB)
662 LastCorrectlyNumberedBB = &
MBB;
666 if (LastCorrectlyNumberedBB)
667 MF->RenumberBlocks(LastCorrectlyNumberedBB);
688 return TooDifficult || FBB ==
nullptr;
693ARMConstantIslands::CPEntry *
694ARMConstantIslands::findConstPoolEntry(
unsigned CPI,
696 std::vector<CPEntry> &CPEs = CPEntries[CPI];
699 for (CPEntry &CPE : CPEs)
700 if (CPE.CPEMI == CPEMI)
709 case ARM::CONSTPOOL_ENTRY:
711 case ARM::JUMPTABLE_TBB:
713 case ARM::JUMPTABLE_TBH:
715 case ARM::JUMPTABLE_INSTS:
717 case ARM::JUMPTABLE_ADDRS:
723 unsigned CPI = getCombinedIndex(CPEMI);
724 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
725 return MCP->getConstants()[CPI].getAlign();
739void ARMConstantIslands::scanFunctionJumpTables() {
743 (
I.getOpcode() == ARM::t2BR_JT ||
I.getOpcode() == ARM::tBR_JTr))
756 BlockJumpTableRefCount[
MBB] = std::numeric_limits<int>::max();
758 ++BlockJumpTableRefCount[
MBB];
765void ARMConstantIslands::
766initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
768 BBUtils->computeAllBlockSizes();
772 BBInfo.
front().KnownBits =
Log2(MF->getAlignment());
775 BBUtils->adjustBBOffsetsAfter(&MF->front());
782 WaterList.push_back(&
MBB);
785 if (
I.isDebugInstr())
788 unsigned Opc =
I.getOpcode();
799 T2JumpTables.push_back(&
I);
832 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
833 ImmBranches.push_back(ImmBranch(&
I, MaxOffs, isCond, UOpc));
836 if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET)
837 PushPopMIs.push_back(&
I);
839 if (Opc == ARM::CONSTPOOL_ENTRY || Opc == ARM::JUMPTABLE_ADDRS ||
840 Opc == ARM::JUMPTABLE_INSTS || Opc == ARM::JUMPTABLE_TBB ||
841 Opc == ARM::JUMPTABLE_TBH)
845 for (
unsigned op = 0, e =
I.getNumOperands();
op !=
e; ++
op)
846 if (
I.getOperand(
op).isCPI() ||
I.getOperand(
op).isJTI()) {
854 bool IsSoImm =
false;
862 case ARM::LEApcrelJT: {
870 unsigned CPI =
I.getOperand(
op).getIndex();
871 assert(CPI < CPEMIs.size());
873 const Align CPEAlign = getCPEAlign(CPEMI);
874 const unsigned LogCPEAlign =
Log2(CPEAlign);
875 if (LogCPEAlign >= 2)
883 case ARM::t2LEApcrel:
884 case ARM::t2LEApcrelJT:
889 case ARM::tLEApcrelJT:
899 case ARM::t2LDRSHpci:
901 case ARM::t2LDRSBpci:
925 unsigned CPI =
I.getOperand(
op).getIndex();
926 if (
I.getOperand(
op).isJTI()) {
927 JumpTableUserIndices.insert(std::make_pair(CPI, CPUsers.size()));
928 CPI = JumpTableEntryIndices[CPI];
932 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
933 CPUsers.push_back(CPUser(&
I, CPEMI, MaxOffs, NegOk, IsSoImm));
936 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
937 assert(CPE &&
"Cannot find a corresponding CPEntry!");
952 return LHS->getNumber() <
RHS->getNumber();
969 WaterList.insert(IP, NewBB);
979 LivePhysRegs LRs(*MF->getSubtarget().getRegisterInfo());
980 LRs.addLiveOuts(*OrigBB);
983 LRs.stepBackward(LiveMI);
989 MF->insert(
MBBI, NewBB);
998 unsigned Opc =
isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
1016 if (!
MRI.isReserved(L))
1022 MF->RenumberBlocks(NewBB);
1034 if (WaterBB == OrigBB)
1035 WaterList.
insert(std::next(IP), NewBB);
1037 WaterList.insert(IP, OrigBB);
1038 NewWaterList.
insert(OrigBB);
1045 BBUtils->computeBlockSize(OrigBB);
1049 BBUtils->computeBlockSize(NewBB);
1052 BBUtils->adjustBBOffsetsAfter(OrigBB);
1060unsigned ARMConstantIslands::getUserOffset(CPUser &U)
const {
1061 unsigned UserOffset = BBUtils->getOffsetOf(U.MI);
1064 const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];
1068 UserOffset += (
isThumb ? 4 : 8);
1077 if (
isThumb && U.KnownAlignment)
1089bool ARMConstantIslands::isOffsetInRange(
unsigned UserOffset,
1090 unsigned TrialOffset,
unsigned MaxDisp,
1091 bool NegativeOK,
bool IsSoImm) {
1092 if (UserOffset <= TrialOffset) {
1094 if (TrialOffset - UserOffset <= MaxDisp)
1097 }
else if (NegativeOK) {
1098 if (UserOffset - TrialOffset <= MaxDisp)
1109bool ARMConstantIslands::isWaterInRange(
unsigned UserOffset,
1113 const Align CPEAlign = getCPEAlign(U.CPEMI);
1114 const unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset(CPEAlign);
1115 unsigned NextBlockOffset;
1116 Align NextBlockAlignment;
1118 if (++NextBlock == MF->end()) {
1119 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
1121 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
1122 NextBlockAlignment = NextBlock->getAlignment();
1124 unsigned Size = U.CPEMI->getOperand(2).getImm();
1125 unsigned CPEEnd = CPEOffset +
Size;
1130 if (CPEEnd > NextBlockOffset) {
1131 Growth = CPEEnd - NextBlockOffset;
1139 if (CPEOffset < UserOffset)
1145 return isOffsetInRange(UserOffset, CPEOffset, U);
1150bool ARMConstantIslands::isCPEntryInRange(
MachineInstr *
MI,
unsigned UserOffset,
1152 bool NegOk,
bool DoDump) {
1153 unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
1158 unsigned Block =
MI->getParent()->getNumber();
1161 <<
" max delta=" << MaxDisp
1162 <<
format(
" insn address=%#x", UserOffset) <<
" in "
1165 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
1166 int(CPEOffset - UserOffset));
1170 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
1194bool ARMConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
1197 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1198 assert(CPE &&
"Unexpected!");
1199 if (--CPE->RefCount == 0) {
1200 removeDeadCPEMI(CPEMI);
1201 CPE->CPEMI =
nullptr;
1208unsigned ARMConstantIslands::getCombinedIndex(
const MachineInstr *CPEMI) {
1221int ARMConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset) {
1226 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
1233 unsigned CPI = getCombinedIndex(CPEMI);
1234 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1235 for (CPEntry &CPE : CPEs) {
1237 if (CPE.CPEMI == CPEMI)
1240 if (CPE.CPEMI ==
nullptr)
1242 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getMaxDisp(),
1244 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1247 U.CPEMI = CPE.CPEMI;
1251 MO.setIndex(CPE.CPI);
1258 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1269 return ((1<<10)-1)*2;
1271 return ((1<<23)-1)*2;
1276 return ((1<<23)-1)*4;
1287bool ARMConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1288 water_iterator &WaterIter,
1290 if (WaterList.empty())
1293 unsigned BestGrowth = ~0u;
1306 const Align CPEAlign = getCPEAlign(U.CPEMI);
1307 unsigned MinNoSplitDisp = BBInfo[UserBB->
getNumber()].postOffset(CPEAlign);
1308 if (CloserWater && MinNoSplitDisp > U.getMaxDisp() / 2)
1310 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1324 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1325 (WaterBB->
getNumber() < U.HighWaterMark->getNumber() ||
1326 NewWaterList.
count(WaterBB) || WaterBB == U.MI->getParent()) &&
1327 Growth < BestGrowth) {
1329 BestGrowth = Growth;
1332 <<
" Growth=" << Growth <<
'\n');
1334 if (CloserWater && WaterBB == U.MI->getParent())
1338 if (!CloserWater && BestGrowth == 0)
1344 return BestGrowth != ~0u;
1354void ARMConstantIslands::createNewWater(
unsigned CPUserIndex,
1355 unsigned UserOffset,
1357 CPUser &U = CPUsers[CPUserIndex];
1360 const Align CPEAlign = getCPEAlign(CPEMI);
1371 unsigned Delta = isThumb1 ? 2 : 4;
1373 unsigned CPEOffset = UserBBI.
postOffset(CPEAlign) + Delta;
1375 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1377 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1384 int UncondBr =
isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) :
ARM::
B;
1392 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1393 MaxDisp,
false, UncondBr));
1394 BBUtils->computeBlockSize(UserMBB);
1395 BBUtils->adjustBBOffsetsAfter(UserMBB);
1416 assert(
Align >= CPEAlign &&
"Over-aligned constant pool entry");
1419 unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;
1426 BaseInsertOffset -= 4;
1430 <<
" up=" << UPad <<
'\n');
1436 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1442 UserOffset +
TII->getInstSizeInBytes(*UserMI) + 1);
1457 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1458 I->getOpcode() != ARM::t2IT &&
1460 Offset +=
TII->getInstSizeInBytes(*
I),
I = std::next(
I)) {
1462 std::max(BaseInsertOffset,
Offset +
TII->getInstSizeInBytes(*
I) + 1);
1463 assert(
I != UserMBB->
end() &&
"Fell off end of block");
1467 unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
1471 unsigned CPUIndex = CPUserIndex+1;
1472 unsigned NumCPUsers = CPUsers.size();
1474 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1475 Offset < BaseInsertOffset;
1477 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1478 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI == &*
MI) {
1479 CPUser &U = CPUsers[CPUIndex];
1480 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1489 EndInsertOffset += U.CPEMI->getOperand(2).getImm();
1494 if (
MI->getOpcode() == ARM::t2IT)
1515 if (STI->isTargetWindows() &&
isThumb &&
MI->getOpcode() == ARM::t2MOVTi16 &&
1519 assert(
MI->getOpcode() == ARM::t2MOVi16 &&
1529 NewMBB = splitBlockBeforeInstr(&*
MI);
1536bool ARMConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex,
1538 CPUser &U = CPUsers[CPUserIndex];
1541 unsigned CPI = getCombinedIndex(CPEMI);
1544 unsigned UserOffset = getUserOffset(U);
1548 int result = findInRangeCPEntry(U, UserOffset);
1549 if (result==1)
return false;
1550 else if (result==2)
return true;
1554 unsigned ID = AFI->createPICLabelUId();
1560 if (findAvailableWater(U, UserOffset, IP, CloserWater)) {
1567 if (NewWaterList.
erase(WaterBB))
1568 NewWaterList.
insert(NewIsland);
1575 createNewWater(CPUserIndex, UserOffset, NewMBB);
1583 IP =
find(WaterList, WaterBB);
1584 if (IP != WaterList.end())
1585 NewWaterList.
erase(WaterBB);
1588 NewWaterList.
insert(NewIsland);
1601 if (IP != WaterList.end())
1602 WaterList.erase(IP);
1608 updateForInsertedWaterBlock(NewIsland);
1612 U.HighWaterMark = NewIsland;
1617 CPEntries[CPI].push_back(CPEntry(U.CPEMI,
ID, 1));
1621 decrementCPEReferenceCount(CPI, CPEMI);
1627 BBUtils->adjustBBSize(NewIsland,
Size);
1628 BBUtils->adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1638 dbgs() <<
" Moved CPE to #" <<
ID <<
" CPI=" << CPI
1639 <<
format(
" offset=%#x\n",
1640 BBUtils->getBBInfo()[NewIsland->
getNumber()].Offset));
1647void ARMConstantIslands::removeDeadCPEMI(
MachineInstr *CPEMI) {
1652 BBUtils->adjustBBSize(CPEBB, -
Size);
1654 if (CPEBB->
empty()) {
1664 BBUtils->adjustBBOffsetsAfter(CPEBB);
1674bool ARMConstantIslands::removeUnusedCPEntries() {
1675 unsigned MadeChange =
false;
1676 for (std::vector<CPEntry> &CPEs : CPEntries) {
1677 for (CPEntry &CPE : CPEs) {
1678 if (CPE.RefCount == 0 && CPE.CPEMI) {
1679 removeDeadCPEMI(CPE.CPEMI);
1680 CPE.CPEMI =
nullptr;
1691bool ARMConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1696 if (BBUtils->isBBInRange(
MI, DestBB, Br.MaxDisp))
1700 return fixupUnconditionalBr(Br);
1701 return fixupConditionalBr(Br);
1709ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1715 if (!AFI->isLRSpilled())
1719 Br.MaxDisp = (1 << 21) * 2;
1720 MI->setDesc(
TII->get(ARM::tBfar));
1723 BBUtils->adjustBBOffsetsAfter(
MBB);
1735ARMConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1769 if (BBUtils->isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1771 dbgs() <<
" Invert Bcc condition and swap its destination with "
1774 MI->getOperand(0).setMBB(NewDest);
1775 MI->getOperand(1).setImm(
CC);
1782 splitBlockBeforeInstr(
MI);
1785 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1786 BBUtils->adjustBBSize(
MBB, -delta);
1799 <<
" also invert condition and change dest. to "
1807 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1814 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1816 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1819 BBUtils->adjustBBSize(
MI->getParent(), -
TII->getInstSizeInBytes(*
MI));
1820 MI->eraseFromParent();
1821 BBUtils->adjustBBOffsetsAfter(
MBB);
1825bool ARMConstantIslands::optimizeThumb2Instructions() {
1826 bool MadeChange =
false;
1829 for (CPUser &U : CPUsers) {
1830 unsigned Opcode = U.MI->getOpcode();
1831 unsigned NewOpc = 0;
1836 case ARM::t2LEApcrel:
1838 NewOpc = ARM::tLEApcrel;
1845 NewOpc = ARM::tLDRpci;
1855 unsigned UserOffset = getUserOffset(U);
1856 unsigned MaxOffs = ((1 <<
Bits) - 1) * Scale;
1859 if (!U.KnownAlignment)
1863 if (isCPEntryInRange(U.MI, UserOffset, U.CPEMI, MaxOffs,
false,
true)) {
1865 U.MI->setDesc(
TII->get(NewOpc));
1867 BBUtils->adjustBBSize(
MBB, -2);
1868 BBUtils->adjustBBOffsetsAfter(
MBB);
1878bool ARMConstantIslands::optimizeThumb2Branches() {
1880 auto TryShrinkBranch = [
this](ImmBranch &Br) {
1881 unsigned Opcode = Br.MI->getOpcode();
1882 unsigned NewOpc = 0;
1899 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
1901 if (BBUtils->isBBInRange(Br.MI, DestBB, MaxOffs)) {
1903 Br.MI->setDesc(
TII->get(NewOpc));
1905 BBUtils->adjustBBSize(
MBB, -2);
1906 BBUtils->adjustBBOffsetsAfter(
MBB);
1916 unsigned NewOpc = 0;
1919 auto FindCmpForCBZ = [
this](ImmBranch &Br, ImmCompare &ImmCmp,
1921 ImmCmp.MI =
nullptr;
1926 if (!Br.MI->killsRegister(ARM::CPSR))
1930 unsigned NewOpc = 0;
1935 NewOpc = ARM::tCBNZ;
1941 unsigned BrOffset = BBUtils->getOffsetOf(Br.MI) + 4 - 2;
1943 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1944 if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
1948 auto *
TRI = STI->getRegisterInfo();
1950 if (!CmpMI || CmpMI->
getOpcode() != ARM::tCMPi8)
1954 ImmCmp.NewOpc = NewOpc;
1958 auto TryConvertToLE = [
this](ImmBranch &Br, ImmCompare &
Cmp) {
1959 if (Br.MI->getOpcode() != ARM::t2Bcc || !STI->hasLOB() ||
1965 if (BBUtils->getOffsetOf(
MBB) < BBUtils->getOffsetOf(DestBB) ||
1966 !BBUtils->isBBInRange(Br.MI, DestBB, 4094))
1969 if (!DT->dominates(DestBB,
MBB))
1974 Cmp.NewOpc =
Cmp.NewOpc == ARM::tCBZ ? ARM::tCBNZ : ARM::tCBZ;
1977 TII->get(ARM::t2LE));
1979 MIB.
add(Br.MI->getOperand(0));
1986 bool MadeChange =
false;
1993 for (ImmBranch &Br :
reverse(ImmBranches)) {
2001 if (FindCmpForCBZ(Br, Cmp, ExitBB) && TryConvertToLE(Br, Cmp)) {
2005 FindCmpForCBZ(Br, Cmp, DestBB);
2006 MadeChange |= TryShrinkBranch(Br);
2009 unsigned Opcode = Br.MI->getOpcode();
2010 if ((Opcode != ARM::tBcc && Opcode != ARM::t2LE) || !
Cmp.NewOpc)
2017 auto *
TRI = STI->getRegisterInfo();
2019 bool RegKilled =
false;
2022 if (KillMI->killsRegister(Reg,
TRI)) {
2023 KillMI->clearRegisterKills(Reg,
TRI);
2027 }
while (KillMI !=
Cmp.MI);
2035 .
addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags());
2037 Cmp.MI->eraseFromParent();
2039 if (Br.MI->getOpcode() == ARM::tBcc) {
2040 Br.MI->eraseFromParent();
2042 BBUtils->adjustBBSize(
MBB, -2);
2053 BBUtils->adjustBBOffsetsAfter(
MBB);
2063 if (
I.getOpcode() != ARM::t2ADDrs)
2066 if (
I.getOperand(0).getReg() != EntryReg)
2069 if (
I.getOperand(1).getReg() != BaseReg)
2082bool ARMConstantIslands::preserveBaseRegister(
MachineInstr *JumpMI,
2086 bool &BaseRegKill) {
2109 CanDeleteLEA =
true;
2110 BaseRegKill =
false;
2113 for (++
I; &*
I != JumpMI; ++
I) {
2119 for (
unsigned K = 0,
E =
I->getNumOperands(); K !=
E; ++K) {
2126 BaseRegKill = BaseRegKill || MO.
isKill();
2127 CanDeleteLEA =
false;
2137 for (++
I; &*
I != JumpMI; ++
I) {
2138 for (
unsigned K = 0,
E =
I->getNumOperands(); K !=
E; ++K) {
2145 RemovableAdd =
nullptr;
2151 DeadSize += isThumb2 ? 4 : 2;
2152 }
else if (BaseReg == EntryReg) {
2178 unsigned &DeadSize) {
2187 for (++
I; &*
I != JumpMI; ++
I) {
2188 if (
I->getOpcode() == ARM::t2ADDrs &&
I->getOperand(0).getReg() == EntryReg)
2197 for (++J; &*J != JumpMI; ++J) {
2198 for (
unsigned K = 0,
E = J->getNumOperands(); K !=
E; ++K) {
2216bool ARMConstantIslands::optimizeThumb2JumpTables() {
2217 bool MadeChange =
false;
2222 if (!MJTI)
return false;
2225 for (
unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) {
2229 unsigned JTOpIdx = NumOps - (
MI->isPredicable() ? 2 : 1);
2231 unsigned JTI = JTOP.getIndex();
2235 bool HalfWordOk =
true;
2236 unsigned JTOffset = BBUtils->getOffsetOf(
MI) + 4;
2237 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
2243 if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2)
2245 unsigned TBHLimit = ((1<<16)-1)*2;
2246 if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit)
2248 if (!ByteOk && !HalfWordOk)
2252 if (!ByteOk && !HalfWordOk)
2255 CPUser &
User = CPUsers[JumpTableUserIndices[JTI]];
2257 if (!
MI->getOperand(0).isKill())
2260 unsigned DeadSize = 0;
2261 bool CanDeleteLEA =
false;
2262 bool BaseRegKill =
false;
2264 unsigned IdxReg = ~0U;
2265 bool IdxRegKill =
true;
2267 IdxReg =
MI->getOperand(1).getReg();
2268 IdxRegKill =
MI->getOperand(1).isKill();
2270 bool PreservedBaseReg =
2271 preserveBaseRegister(
MI,
User.MI, DeadSize, CanDeleteLEA, BaseRegKill);
2281 if (
User.MI->getIterator() ==
User.MI->getParent()->begin())
2284 if (Shift->
getOpcode() != ARM::tLSLri ||
2298 if (
Load->getOpcode() != ARM::tLDRr)
2300 if (
Load->getOperand(1).getReg() != BaseReg ||
2301 Load->getOperand(2).getReg() != ShiftedIdxReg ||
2302 !
Load->getOperand(2).isKill())
2306 auto *
TRI = STI->getRegisterInfo();
2316 if (isPositionIndependentOrROPI) {
2318 if (
Add->getOpcode() != ARM::tADDrr ||
2319 Add->getOperand(2).getReg() != BaseReg ||
2320 Add->getOperand(3).getReg() !=
Load->getOperand(0).getReg() ||
2321 !
Add->getOperand(3).isKill())
2323 if (
Add->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2328 Add->eraseFromParent();
2331 if (
Load->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2339 CanDeleteLEA =
true;
2341 Load->eraseFromParent();
2347 unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
2349 Opc = ByteOk ? ARM::tTBB_JT : ARM::tTBH_JT;
2361 unsigned JTOpc = ByteOk ? ARM::JUMPTABLE_TBB : ARM::JUMPTABLE_TBH;
2372 User.MI->eraseFromParent();
2373 DeadSize += isThumb2 ? 4 : 2;
2380 User.IsSoImm =
false;
2381 User.KnownAlignment =
false;
2385 int CPEntryIdx = JumpTableEntryIndices[JTI];
2386 auto &CPEs = CPEntries[CPEntryIdx];
2388 find_if(CPEs, [&](CPEntry &
E) {
return E.CPEMI ==
User.CPEMI; });
2390 CPUsers.emplace_back(CPUser(NewJTMI,
User.CPEMI, 4,
false,
false));
2394 unsigned NewSize =
TII->getInstSizeInBytes(*NewJTMI);
2395 unsigned OrigSize =
TII->getInstSizeInBytes(*
MI);
2396 MI->eraseFromParent();
2398 int Delta = OrigSize - NewSize + DeadSize;
2400 BBUtils->adjustBBOffsetsAfter(
MBB);
2411bool ARMConstantIslands::reorderThumb2JumpTables() {
2412 bool MadeChange =
false;
2415 if (!MJTI)
return false;
2418 for (
unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) {
2422 unsigned JTOpIdx = NumOps - (
MI->isPredicable() ? 2 : 1);
2424 unsigned JTI = JTOP.getIndex();
2430 int JTNumber =
MI->getParent()->getNumber();
2431 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
2435 if (DTNumber < JTNumber) {
2439 adjustJTTargetBlockForward(JTI,
MBB,
MI->getParent());
2452 assert(isThumb2 &&
"BTI in Thumb1?");
2463 --BlockJumpTableRefCount[
MBB];
2464 ++BlockJumpTableRefCount[&NewBB];
2469 if (BlockJumpTableRefCount[&OldBB] > 0)
2474 return MI.isMetaInstruction();
2476 assert(BTIPos->getOpcode() == ARM::t2BTI &&
2477 "BasicBlock is mentioned in a jump table but does start with BTI");
2478 if (BTIPos->getOpcode() == ARM::t2BTI)
2479 BTIPos->eraseFromParent();
2501 if (!
B &&
Cond.empty() && BB != &MF->front() &&
2504 OldPrior->updateTerminator(BB);
2507 MF->RenumberBlocks();
2516 MF->insert(
MBBI, NewBB);
2535 MF->RenumberBlocks(NewBB);
2542 fixupBTI(JTI, *BB, *NewBB);
2551 return new ARMConstantIslands();
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator MBBI
static bool isThumb(const MCSubtargetInfo &STI)
static cl::opt< unsigned > CPMaxIteration("arm-constant-island-max-iteration", cl::Hidden, cl::init(30), cl::desc("The max number of iteration for converge"))
static bool isSimpleIndexCalc(MachineInstr &I, unsigned EntryReg, unsigned BaseReg)
static bool jumpTableFollowsTB(MachineInstr *JTMI, MachineInstr *CPEMI)
Returns whether CPEMI is the first instruction in the block immediately following JTMI (assumed to be...
static bool CompareMBBNumbers(const MachineBasicBlock *LHS, const MachineBasicBlock *RHS)
CompareMBBNumbers - Little predicate function to sort the WaterList by MBB ID.
static unsigned getUnconditionalBrDisp(int Opc)
getUnconditionalBrDisp - Returns the maximum displacement that can fit in the specific unconditional ...
static void RemoveDeadAddBetweenLEAAndJT(MachineInstr *LEAMI, MachineInstr *JumpMI, unsigned &DeadSize)
static bool isAlwaysIndirectTarget(const MachineBasicBlock &MBB)
static bool AlignBlocks(MachineFunction *MF, const ARMSubtarget *STI)
static cl::opt< bool > SynthesizeThumb1TBB("arm-synthesize-thumb-1-tbb", cl::Hidden, cl::init(true), cl::desc("Use compressed jump tables in Thumb-1 by synthesizing an " "equivalent to the TBB/TBH instructions"))
static cl::opt< bool > AdjustJumpTableBlocks("arm-adjust-jump-tables", cl::Hidden, cl::init(true), cl::desc("Adjust basic block layout to better use TB[BH]"))
#define ARM_CP_ISLANDS_OPT_NAME
static bool BBIsJumpedOver(MachineBasicBlock *MBB)
BBIsJumpedOver - Return true of the specified basic block's only predecessor unconditionally branches...
SmallVector< MachineOperand, 4 > Cond
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
return ToRemove size() > 0
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool branchTargetEnforcement() const
const ARMTargetLowering * getTargetLowering() const override
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
unsigned pred_size() const
bool isEHPad() const
Returns true if the block is a landing pad.
void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
Replace successor OLD with NEW and update probability info.
void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator_range< livein_iterator > liveins() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void push_back(MachineInstr *MI)
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void updateTerminator(MachineBasicBlock *PreviousLayoutSuccessor)
Update the terminator instructions in block to account for changes to block layout which may have bee...
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
succ_iterator succ_begin()
MachineBasicBlock * getFallThrough(bool JumpToFallThrough=false)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
unsigned succ_size() const
bool hasAddressTaken() const
Test whether this block is used as as something other than the target of a terminator,...
void setAlignment(Align A)
Set alignment of the basic block.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
pred_iterator pred_begin()
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< iterator > terminators()
reverse_iterator rbegin()
bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
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 '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
void moveAfter(MachineBasicBlock *NewBefore)
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
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)
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
iterator_range< mop_iterator > operands()
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
bool ReplaceMBBInJumpTable(unsigned Idx, MachineBasicBlock *Old, MachineBasicBlock *New)
ReplaceMBBInJumpTable - If Old is a target of the jump tables, update the jump table to branch to New...
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
void setIsKill(bool Val=true)
void setMBB(MachineBasicBlock *MBB)
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.
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...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
Value * getOperand(unsigned i) const
Iterator for intrusive lists based on ilist_node.
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCodes getOppositeCondition(CondCodes CC)
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstr * findCMPToFoldIntoCBZ(MachineInstr *Br, const TargetRegisterInfo *TRI)
Search backwards from a tBcc to find a tCMPi8 against 0, meaning we can convert them to a tCBZ or tCB...
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI)
Return true if Reg is defd between From and To.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
ARMCC::CondCodes getITInstrPredicate(const MachineInstr &MI, Register &PredReg)
getITInstrPredicate - Valid only in Thumb2 mode.
static bool isARMLowRegister(unsigned Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
auto reverse(ContainerTy &&C)
auto find_if_not(R &&Range, UnaryPredicate P)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
static bool isLoopStart(const MachineInstr &MI)
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
unsigned getKillRegState(bool B)
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
FunctionPass * createARMConstantIslandPass()
createARMConstantIslandPass - returns an instance of the constpool island pass.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
unsigned UnknownPadding(Align Alignment, unsigned KnownBits)
UnknownPadding - Return the worst case padding that could result from unknown offset bits.
APFloat neg(APFloat X)
Returns the negated value of the argument.
unsigned Log2(Align A)
Returns the log2 of the alignment.
static bool isSpeculationBarrierEndBBOpcode(int Opc)
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
BasicBlockInfo - Information about the offset and size of a single basic block.
unsigned internalKnownBits() const
Compute the number of known offset bits internally to this block.
unsigned postOffset(Align Alignment=Align(1)) const
Compute the offset immediately following this block.
unsigned Offset
Offset - Distance from the beginning of the function to the beginning of this basic block.
Pair of physical register and lane mask.
MachineJumpTableEntry - One jump table in the jump table info.
std::vector< MachineBasicBlock * > MBBs
MBBs - The vector of basic blocks from which to create the jump table.