39#include "llvm/Config/llvm-config.h"
58#define DEBUG_TYPE "arm-cp-islands"
60#define ARM_CP_ISLANDS_OPT_NAME \
61 "ARM constant island placement and branch shortening pass"
63STATISTIC(NumSplit,
"Number of uncond branches inserted");
64STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
65STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
66STATISTIC(NumTBs,
"Number of table branches generated");
67STATISTIC(NumT2CPShrunk,
"Number of Thumb2 constantpool instructions shrunk");
68STATISTIC(NumT2BrShrunk,
"Number of Thumb2 immediate branches shrunk");
70STATISTIC(NumJTMoved,
"Number of jump table destination blocks moved");
71STATISTIC(NumJTInserted,
"Number of jump table intermediate blocks inserted");
72STATISTIC(NumLEInserted,
"Number of LE backwards branches inserted");
76 cl::desc(
"Adjust basic block layout to better use TB[BH]"));
80 cl::desc(
"The max number of iteration for converge"));
84 cl::desc(
"Use compressed jump tables in Thumb-1 by synthesizing an "
85 "equivalent to the TBB/TBH instructions"));
101 std::unique_ptr<ARMBasicBlockUtils> BBUtils =
nullptr;
106 std::vector<MachineBasicBlock*> WaterList;
112 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
133 bool KnownAlignment =
false;
136 bool neg,
bool soimm)
137 :
MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(
neg), IsSoImm(soimm) {
144 unsigned getMaxDisp()
const {
145 return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
151 std::vector<CPUser> CPUsers;
161 CPEntry(MachineInstr *cpemi,
unsigned cpi,
unsigned rc = 0)
162 : CPEMI(cpemi), CPI(cpi), RefCount(
rc) {}
174 std::vector<std::vector<CPEntry>> CPEntries;
178 DenseMap<int, int> JumpTableEntryIndices;
182 DenseMap<int, int> JumpTableUserIndices;
190 unsigned MaxDisp : 31;
195 ImmBranch(MachineInstr *mi,
unsigned maxdisp,
bool cond,
unsigned ubr)
196 : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
200 std::vector<ImmBranch> ImmBranches;
203 SmallVector<MachineInstr*, 4> PushPopMIs;
206 SmallVector<MachineInstr*, 4> T2JumpTables;
209 MachineConstantPool *MCP;
210 const ARMBaseInstrInfo *TII;
211 const ARMSubtarget *STI;
212 ARMFunctionInfo *AFI;
213 MachineDominatorTree *DT =
nullptr;
217 bool isPositionIndependentOrROPI;
222 ARMConstantIslands() : MachineFunctionPass(ID) {}
224 bool runOnMachineFunction(MachineFunction &MF)
override;
226 void getAnalysisUsage(AnalysisUsage &AU)
const override {
231 MachineFunctionProperties getRequiredProperties()
const override {
232 return MachineFunctionProperties().setNoVRegs();
235 StringRef getPassName()
const override {
240 void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
241 void doInitialJumpTablePlacement(std::vector<MachineInstr *> &CPEMIs);
243 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
244 Align getCPEAlign(
const MachineInstr *CPEMI);
245 void scanFunctionJumpTables();
246 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
247 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *
MI);
248 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
249 bool decrementCPEReferenceCount(
unsigned CPI, MachineInstr* CPEMI);
250 unsigned getCombinedIndex(
const MachineInstr *CPEMI);
251 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
252 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
253 water_iterator &WaterIter,
bool CloserWater);
254 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
255 MachineBasicBlock *&NewMBB);
256 bool handleConstantPoolUser(
unsigned CPUserIndex,
bool CloserWater);
257 void removeDeadCPEMI(MachineInstr *CPEMI);
258 bool removeUnusedCPEntries();
259 bool isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
260 MachineInstr *CPEMI,
unsigned Disp,
bool NegOk,
261 bool DoDump =
false);
262 bool isWaterInRange(
unsigned UserOffset, MachineBasicBlock *Water,
263 CPUser &U,
unsigned &Growth);
264 bool fixupImmediateBr(ImmBranch &Br);
265 bool fixupConditionalBr(ImmBranch &Br);
266 bool fixupUnconditionalBr(ImmBranch &Br);
267 bool optimizeThumb2Instructions();
268 bool optimizeThumb2Branches();
269 bool reorderThumb2JumpTables();
270 bool preserveBaseRegister(MachineInstr *JumpMI, MachineInstr *LEAMI,
271 unsigned &DeadSize,
bool &CanDeleteLEA,
273 bool optimizeThumb2JumpTables();
274 MachineBasicBlock *adjustJTTargetBlockForward(
unsigned JTI,
275 MachineBasicBlock *BB,
276 MachineBasicBlock *JTBB);
278 unsigned getUserOffset(CPUser&)
const;
282 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
283 unsigned Disp,
bool NegativeOK,
bool IsSoImm =
false);
284 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
286 return isOffsetInRange(UserOffset, TrialOffset,
287 U.getMaxDisp(),
U.NegOk,
U.IsSoImm);
293char ARMConstantIslands::ID = 0;
296void ARMConstantIslands::verify() {
300 const MachineBasicBlock &
RHS) {
301 return BBInfo[
LHS.getNumber()].postOffset() <
302 BBInfo[
RHS.getNumber()].postOffset();
304 LLVM_DEBUG(
dbgs() <<
"Verifying " << CPUsers.size() <<
" CP users.\n");
305 for (CPUser &U : CPUsers) {
306 unsigned UserOffset = getUserOffset(U);
309 if (isCPEntryInRange(
U.MI, UserOffset,
U.CPEMI,
U.getMaxDisp()+2,
U.NegOk,
322#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
327 for (
unsigned J = 0,
E = BBInfo.
size(); J !=
E; ++J) {
328 const BasicBlockInfo &BBI = BBInfo[J];
347 const Align Alignment = TLI->getPrefLoopAlignment();
352 bool PrevCanFallthough =
true;
353 for (
auto &
MBB : *MF) {
354 if (!PrevCanFallthough) {
356 MBB.setAlignment(Alignment);
359 PrevCanFallthough =
MBB.canFallThrough();
365 if (
MI.getOpcode() == ARM::t2B &&
366 MI.getOperand(0).getMBB() ==
MBB.getNextNode())
369 MI.getOpcode() == ARM::t2LoopEndDec) {
370 PrevCanFallthough =
true;
382bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
385 BBUtils = std::make_unique<ARMBasicBlockUtils>(mf);
388 << MCP->
getConstants().size() <<
" CP entries, aligned to "
393 isPositionIndependentOrROPI =
395 AFI = MF->
getInfo<ARMFunctionInfo>();
396 DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
405 if (STI->hardenSlsRetBr())
411 DT->updateBlockNumbers();
415 bool MadeChange =
false;
417 scanFunctionJumpTables();
418 MadeChange |= reorderThumb2JumpTables();
420 T2JumpTables.
clear();
423 DT->updateBlockNumbers();
431 std::vector<MachineInstr*> CPEMIs;
433 doInitialConstPlacement(CPEMIs);
436 doInitialJumpTablePlacement(CPEMIs);
444 initializeFunctionInfo(CPEMIs);
450 if (!T2JumpTables.
empty())
454 MadeChange |= removeUnusedCPEntries();
458 unsigned NoCPIters = 0, NoBRIters = 0;
460 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
461 bool CPChange =
false;
462 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
466 CPChange |= handleConstantPoolUser(i, NoCPIters >=
CPMaxIteration / 2);
473 NewWaterList.
clear();
475 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
476 bool BRChange =
false;
477 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
479 BRChange |= fixupImmediateBr(ImmBranches[i]);
481 if (BRChange && ++NoBRIters > 30)
485 if (!CPChange && !BRChange)
491 if (isThumb2 && !STI->prefers32BitThumb())
492 MadeChange |= optimizeThumb2Instructions();
495 if (
isThumb && STI->hasV8MBaselineOps())
496 MadeChange |= optimizeThumb2Branches();
499 if (GenerateTBB && !STI->genExecuteOnly())
500 MadeChange |= optimizeThumb2JumpTables();
506 for (
unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
507 for (
unsigned j = 0, je = CPEntries[i].
size();
j != je; ++
j) {
508 const CPEntry & CPE = CPEntries[i][
j];
509 if (CPE.CPEMI && CPE.CPEMI->getOperand(1).isCPI())
520 JumpTableEntryIndices.
clear();
521 JumpTableUserIndices.
clear();
524 T2JumpTables.
clear();
532ARMConstantIslands::doInitialConstPlacement(std::vector<MachineInstr*> &CPEMIs) {
539 const unsigned MaxLogAlign =
Log2(MaxAlign);
547 Align FuncAlign = MaxAlign;
549 FuncAlign =
Align(4);
561 const std::vector<MachineConstantPoolEntry> &CPs = MCP->
getConstants();
564 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
565 unsigned Size = CPs[i].getSizeInBytes(TD);
566 Align Alignment = CPs[i].getAlign();
572 unsigned LogAlign =
Log2(Alignment);
574 MachineInstr *CPEMI =
577 CPEMIs.push_back(CPEMI);
581 for (
unsigned a = LogAlign + 1; a <= MaxLogAlign; ++a)
582 if (InsPoint[a] == InsAt)
586 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
588 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
589 <<
Size <<
", align = " << Alignment.
value() <<
'\n');
599void ARMConstantIslands::doInitialJumpTablePlacement(
600 std::vector<MachineInstr *> &CPEMIs) {
601 unsigned i = CPEntries.size();
603 const std::vector<MachineJumpTableEntry> &
JT = MJTI->getJumpTables();
609 MachineBasicBlock *LastCorrectlyNumberedBB =
nullptr;
610 for (MachineBasicBlock &
MBB : *MF) {
622 switch (
MI->getOpcode()) {
628 case ARM::BR_JTm_i12:
633 assert(!MF->getInfo<ARMFunctionInfo>()->branchTargetEnforcement() &&
634 "Branch protection must not be enabled for Arm or Thumb1 modes");
635 JTOpcode = ARM::JUMPTABLE_ADDRS;
638 JTOpcode = ARM::JUMPTABLE_INSTS;
642 JTOpcode = ARM::JUMPTABLE_TBB;
646 JTOpcode = ARM::JUMPTABLE_TBH;
650 unsigned NumOps =
MI->getDesc().getNumOperands();
651 MachineOperand JTOp =
652 MI->getOperand(
NumOps - (
MI->isPredicable() ? 2 : 1));
654 unsigned Size =
JT[JTI].MBBs.size() *
sizeof(uint32_t);
655 MachineBasicBlock *JumpTableBB = MF->CreateMachineBasicBlock();
657 MachineInstr *CPEMI =
BuildMI(*JumpTableBB, JumpTableBB->
begin(),
662 CPEMIs.push_back(CPEMI);
663 CPEntries.emplace_back(1, CPEntry(CPEMI, JTI));
664 JumpTableEntryIndices.
insert(std::make_pair(JTI, CPEntries.size() - 1));
665 if (!LastCorrectlyNumberedBB)
666 LastCorrectlyNumberedBB = &
MBB;
670 if (LastCorrectlyNumberedBB) {
671 MF->RenumberBlocks(LastCorrectlyNumberedBB);
672 DT->updateBlockNumbers();
678bool ARMConstantIslands::BBHasFallthrough(MachineBasicBlock *
MBB) {
685 MachineBasicBlock *NextBB = &*std::next(
MBBI);
691 MachineBasicBlock *
TBB, *FBB;
694 return TooDifficult || FBB ==
nullptr;
699ARMConstantIslands::CPEntry *
700ARMConstantIslands::findConstPoolEntry(
unsigned CPI,
701 const MachineInstr *CPEMI) {
702 std::vector<CPEntry> &CPEs = CPEntries[CPI];
705 for (CPEntry &CPE : CPEs)
706 if (CPE.CPEMI == CPEMI)
713Align ARMConstantIslands::getCPEAlign(
const MachineInstr *CPEMI) {
715 case ARM::CONSTPOOL_ENTRY:
717 case ARM::JUMPTABLE_TBB:
719 case ARM::JUMPTABLE_TBH:
721 case ARM::JUMPTABLE_INSTS:
723 case ARM::JUMPTABLE_ADDRS:
729 unsigned CPI = getCombinedIndex(CPEMI);
730 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
737void ARMConstantIslands::scanFunctionJumpTables() {
738 for (MachineBasicBlock &
MBB : *MF) {
739 for (MachineInstr &
I :
MBB)
741 (
I.getOpcode() == ARM::t2BR_JT ||
I.getOpcode() == ARM::tBR_JTr))
749void ARMConstantIslands::
750initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
752 BBUtils->computeAllBlockSizes();
756 BBInfo.
front().KnownBits =
Log2(MF->getAlignment());
759 BBUtils->adjustBBOffsetsAfter(&MF->front());
762 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
763 bool InlineJumpTables =
767 for (MachineBasicBlock &
MBB : *MF) {
771 WaterList.push_back(&
MBB);
773 for (MachineInstr &
I :
MBB) {
774 if (
I.isDebugInstr())
777 unsigned Opc =
I.getOpcode();
788 if (InlineJumpTables)
822 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
823 ImmBranches.push_back(ImmBranch(&
I, MaxOffs, isCond, UOpc));
826 if (
Opc == ARM::tPUSH ||
Opc == ARM::tPOP_RET)
829 if (
Opc == ARM::CONSTPOOL_ENTRY ||
Opc == ARM::JUMPTABLE_ADDRS ||
830 Opc == ARM::JUMPTABLE_INSTS ||
Opc == ARM::JUMPTABLE_TBB ||
831 Opc == ARM::JUMPTABLE_TBH)
835 for (
unsigned op = 0, e =
I.getNumOperands();
op != e; ++
op)
836 if (
I.getOperand(
op).isCPI() ||
837 (
I.getOperand(
op).isJTI() && InlineJumpTables)) {
845 bool IsSoImm =
false;
853 case ARM::LEApcrelJT: {
861 unsigned CPI =
I.getOperand(
op).getIndex();
862 assert(CPI < CPEMIs.size());
863 MachineInstr *CPEMI = CPEMIs[CPI];
864 const Align CPEAlign = getCPEAlign(CPEMI);
865 const unsigned LogCPEAlign =
Log2(CPEAlign);
866 if (LogCPEAlign >= 2)
874 case ARM::t2LEApcrel:
875 case ARM::t2LEApcrelJT:
880 case ARM::tLEApcrelJT:
890 case ARM::t2LDRSHpci:
892 case ARM::t2LDRSBpci:
916 unsigned CPI =
I.getOperand(
op).getIndex();
917 if (
I.getOperand(
op).isJTI()) {
918 JumpTableUserIndices.
insert(std::make_pair(CPI, CPUsers.size()));
919 CPI = JumpTableEntryIndices[CPI];
922 MachineInstr *CPEMI = CPEMIs[CPI];
923 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
924 CPUsers.push_back(CPUser(&
I, CPEMI, MaxOffs, NegOk, IsSoImm));
927 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
928 assert(CPE &&
"Cannot find a corresponding CPEntry!");
943 return LHS->getNumber() <
RHS->getNumber();
949void ARMConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
952 DT->updateBlockNumbers();
956 BBUtils->insert(NewBB->
getNumber(), BasicBlockInfo());
961 WaterList.insert(IP, NewBB);
967MachineBasicBlock *ARMConstantIslands::splitBlockBeforeInstr(MachineInstr *
MI) {
968 MachineBasicBlock *OrigBB =
MI->getParent();
971 LivePhysRegs LRs(*MF->getSubtarget().getRegisterInfo());
972 LRs.addLiveOuts(*OrigBB);
975 LRs.stepBackward(LiveMI);
978 MachineBasicBlock *NewBB =
981 MF->insert(
MBBI, NewBB);
990 unsigned Opc =
isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) :
ARM::
B;
1006 MachineRegisterInfo &
MRI = MF->getRegInfo();
1008 if (!
MRI.isReserved(L))
1014 MF->RenumberBlocks(NewBB);
1015 DT->updateBlockNumbers();
1019 BBUtils->insert(NewBB->
getNumber(), BasicBlockInfo());
1026 MachineBasicBlock* WaterBB = *IP;
1027 if (WaterBB == OrigBB)
1028 WaterList.insert(std::next(IP), NewBB);
1030 WaterList.insert(IP, OrigBB);
1031 NewWaterList.
insert(OrigBB);
1038 BBUtils->computeBlockSize(OrigBB);
1042 BBUtils->computeBlockSize(NewBB);
1045 BBUtils->adjustBBOffsetsAfter(OrigBB);
1053unsigned ARMConstantIslands::getUserOffset(CPUser &U)
const {
1054 unsigned UserOffset = BBUtils->getOffsetOf(
U.MI);
1056 SmallVectorImpl<BasicBlockInfo> &BBInfo = BBUtils->getBBInfo();
1057 const BasicBlockInfo &BBI = BBInfo[
U.MI->getParent()->getNumber()];
1061 UserOffset += (
isThumb ? 4 : 8);
1065 U.KnownAlignment = (KnownBits >= 2);
1082bool ARMConstantIslands::isOffsetInRange(
unsigned UserOffset,
1083 unsigned TrialOffset,
unsigned MaxDisp,
1084 bool NegativeOK,
bool IsSoImm) {
1085 if (UserOffset <= TrialOffset) {
1087 if (TrialOffset - UserOffset <= MaxDisp)
1090 }
else if (NegativeOK) {
1091 if (UserOffset - TrialOffset <= MaxDisp)
1102bool ARMConstantIslands::isWaterInRange(
unsigned UserOffset,
1103 MachineBasicBlock* Water, CPUser &U,
1106 const Align CPEAlign = getCPEAlign(
U.CPEMI);
1107 const unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset(CPEAlign);
1108 unsigned NextBlockOffset;
1109 Align NextBlockAlignment;
1111 if (++NextBlock == MF->end()) {
1112 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
1114 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
1115 NextBlockAlignment = NextBlock->getAlignment();
1117 unsigned Size =
U.CPEMI->getOperand(2).getImm();
1118 unsigned CPEEnd = CPEOffset +
Size;
1123 if (CPEEnd > NextBlockOffset) {
1124 Growth = CPEEnd - NextBlockOffset;
1132 if (CPEOffset < UserOffset)
1138 return isOffsetInRange(UserOffset, CPEOffset, U);
1143bool ARMConstantIslands::isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
1144 MachineInstr *CPEMI,
unsigned MaxDisp,
1145 bool NegOk,
bool DoDump) {
1146 unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
1151 unsigned Block =
MI->getParent()->getNumber();
1152 const BasicBlockInfo &BBI = BBInfo[
Block];
1154 <<
" max delta=" << MaxDisp
1155 <<
format(
" insn address=%#x", UserOffset) <<
" in "
1158 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
1159 int(CPEOffset - UserOffset));
1163 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
1170 if (
MBB->pred_size() != 1 ||
MBB->succ_size() != 1)
1187bool ARMConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
1188 MachineInstr *CPEMI) {
1190 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1191 assert(CPE &&
"Unexpected!");
1192 if (--CPE->RefCount == 0) {
1193 removeDeadCPEMI(CPEMI);
1194 CPE->CPEMI =
nullptr;
1201unsigned ARMConstantIslands::getCombinedIndex(
const MachineInstr *CPEMI) {
1214int ARMConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset) {
1215 MachineInstr *UserMI =
U.MI;
1216 MachineInstr *CPEMI =
U.CPEMI;
1219 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
U.getMaxDisp(),
U.NegOk,
1226 unsigned CPI = getCombinedIndex(CPEMI);
1227 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1228 for (CPEntry &CPE : CPEs) {
1230 if (CPE.CPEMI == CPEMI)
1233 if (CPE.CPEMI ==
nullptr)
1235 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getMaxDisp(),
1237 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1240 U.CPEMI = CPE.CPEMI;
1242 for (MachineOperand &MO : UserMI->
operands())
1244 MO.setIndex(CPE.CPI);
1251 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1262 return ((1<<10)-1)*2;
1264 return ((1<<23)-1)*2;
1269 return ((1<<23)-1)*4;
1280bool ARMConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1281 water_iterator &WaterIter,
1283 if (WaterList.empty())
1286 unsigned BestGrowth = ~0
u;
1297 MachineBasicBlock *UserBB =
U.MI->getParent();
1299 const Align CPEAlign = getCPEAlign(
U.CPEMI);
1300 unsigned MinNoSplitDisp = BBInfo[UserBB->
getNumber()].postOffset(CPEAlign);
1301 if (CloserWater && MinNoSplitDisp >
U.getMaxDisp() / 2)
1303 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1305 MachineBasicBlock* WaterBB = *IP;
1317 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1318 (WaterBB->
getNumber() <
U.HighWaterMark->getNumber() ||
1319 NewWaterList.
count(WaterBB) || WaterBB ==
U.MI->getParent()) &&
1320 Growth < BestGrowth) {
1322 BestGrowth = Growth;
1325 <<
" Growth=" << Growth <<
'\n');
1327 if (CloserWater && WaterBB ==
U.MI->getParent())
1331 if (!CloserWater && BestGrowth == 0)
1337 return BestGrowth != ~0
u;
1347void ARMConstantIslands::createNewWater(
unsigned CPUserIndex,
1348 unsigned UserOffset,
1349 MachineBasicBlock *&NewMBB) {
1350 CPUser &
U = CPUsers[CPUserIndex];
1351 MachineInstr *UserMI =
U.MI;
1352 MachineInstr *CPEMI =
U.CPEMI;
1353 const Align CPEAlign = getCPEAlign(CPEMI);
1354 MachineBasicBlock *UserMBB = UserMI->
getParent();
1356 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1364 unsigned Delta = isThumb1 ? 2 : 4;
1366 unsigned CPEOffset = UserBBI.
postOffset(CPEAlign) + Delta;
1368 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1370 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1377 int UncondBr =
isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) :
ARM::
B;
1385 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1386 MaxDisp,
false, UncondBr));
1387 BBUtils->computeBlockSize(UserMBB);
1388 BBUtils->adjustBBOffsetsAfter(UserMBB);
1409 assert(Align >= CPEAlign &&
"Over-aligned constant pool entry");
1412 unsigned BaseInsertOffset = UserOffset +
U.getMaxDisp() - UPad;
1419 BaseInsertOffset -= 4;
1422 <<
" la=" <<
Log2(Align) <<
" kb=" << KnownBits
1423 <<
" up=" << UPad <<
'\n');
1429 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1435 UserOffset +
TII->getInstSizeInBytes(*UserMI) + 1);
1450 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1451 I->getOpcode() != ARM::t2IT &&
1453 Offset +=
TII->getInstSizeInBytes(*
I),
I = std::next(
I)) {
1455 std::max(BaseInsertOffset,
Offset +
TII->getInstSizeInBytes(*
I) + 1);
1456 assert(
I != UserMBB->
end() &&
"Fell off end of block");
1460 unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
1464 unsigned CPUIndex = CPUserIndex+1;
1465 unsigned NumCPUsers = CPUsers.size();
1466 MachineInstr *LastIT =
nullptr;
1467 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1468 Offset < BaseInsertOffset;
1470 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1471 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI == &*
MI) {
1472 CPUser &
U = CPUsers[CPUIndex];
1473 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1475 BaseInsertOffset -=
Align.value();
1476 EndInsertOffset -=
Align.value();
1482 EndInsertOffset +=
U.CPEMI->getOperand(2).getImm();
1487 if (
MI->getOpcode() == ARM::t2IT)
1512 assert(
MI->getOpcode() == ARM::t2MOVi16 &&
1522 NewMBB = splitBlockBeforeInstr(&*
MI);
1529bool ARMConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex,
1531 CPUser &
U = CPUsers[CPUserIndex];
1532 MachineInstr *UserMI =
U.MI;
1533 MachineInstr *CPEMI =
U.CPEMI;
1534 unsigned CPI = getCombinedIndex(CPEMI);
1537 unsigned UserOffset = getUserOffset(U);
1541 int result = findInRangeCPEntry(U, UserOffset);
1542 if (result==1)
return false;
1543 else if (result==2)
return true;
1550 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1551 MachineBasicBlock *NewMBB;
1553 if (findAvailableWater(U, UserOffset, IP, CloserWater)) {
1555 MachineBasicBlock *WaterBB = *IP;
1560 if (NewWaterList.
erase(WaterBB))
1561 NewWaterList.
insert(NewIsland);
1568 createNewWater(CPUserIndex, UserOffset, NewMBB);
1575 MachineBasicBlock *WaterBB = &*--NewMBB->
getIterator();
1576 IP =
find(WaterList, WaterBB);
1577 if (IP != WaterList.end())
1578 NewWaterList.
erase(WaterBB);
1581 NewWaterList.
insert(NewIsland);
1594 if (IP != WaterList.end())
1595 WaterList.erase(IP);
1601 updateForInsertedWaterBlock(NewIsland);
1605 U.HighWaterMark = NewIsland;
1610 CPEntries[CPI].push_back(CPEntry(
U.CPEMI,
ID, 1));
1614 decrementCPEReferenceCount(CPI, CPEMI);
1620 BBUtils->adjustBBSize(NewIsland,
Size);
1621 BBUtils->adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1624 for (MachineOperand &MO : UserMI->
operands())
1631 dbgs() <<
" Moved CPE to #" <<
ID <<
" CPI=" << CPI
1632 <<
format(
" offset=%#x\n",
1633 BBUtils->getBBInfo()[NewIsland->
getNumber()].Offset));
1640void ARMConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1641 MachineBasicBlock *CPEBB = CPEMI->
getParent();
1645 BBUtils->adjustBBSize(CPEBB, -
Size);
1647 if (CPEBB->
empty()) {
1657 BBUtils->adjustBBOffsetsAfter(CPEBB);
1667bool ARMConstantIslands::removeUnusedCPEntries() {
1668 unsigned MadeChange =
false;
1669 for (std::vector<CPEntry> &CPEs : CPEntries) {
1670 for (CPEntry &CPE : CPEs) {
1671 if (CPE.RefCount == 0 && CPE.CPEMI) {
1672 removeDeadCPEMI(CPE.CPEMI);
1673 CPE.CPEMI =
nullptr;
1684bool ARMConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1685 MachineInstr *
MI = Br.MI;
1686 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1689 if (BBUtils->isBBInRange(
MI, DestBB, Br.MaxDisp))
1693 return fixupUnconditionalBr(Br);
1694 return fixupConditionalBr(Br);
1702ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1703 MachineInstr *
MI = Br.MI;
1704 MachineBasicBlock *
MBB =
MI->getParent();
1712 Br.MaxDisp = (1 << 21) * 2;
1713 MI->setDesc(
TII->get(ARM::tBfar));
1716 BBUtils->adjustBBOffsetsAfter(
MBB);
1728ARMConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1729 MachineInstr *
MI = Br.MI;
1730 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1746 MachineBasicBlock *
MBB =
MI->getParent();
1747 MachineInstr *BMI = &
MBB->
back();
1762 if (BBUtils->isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1764 dbgs() <<
" Invert Bcc condition and swap its destination with "
1767 MI->getOperand(0).setMBB(NewDest);
1768 MI->getOperand(1).setImm(CC);
1775 splitBlockBeforeInstr(
MI);
1778 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1779 BBUtils->adjustBBSize(
MBB, -delta);
1792 <<
" also invert condition and change dest. to "
1800 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1807 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1809 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1812 BBUtils->adjustBBSize(
MI->getParent(), -
TII->getInstSizeInBytes(*
MI));
1813 MI->eraseFromParent();
1814 BBUtils->adjustBBOffsetsAfter(
MBB);
1818bool ARMConstantIslands::optimizeThumb2Instructions() {
1819 bool MadeChange =
false;
1822 for (CPUser &U : CPUsers) {
1823 unsigned Opcode =
U.MI->getOpcode();
1824 unsigned NewOpc = 0;
1829 case ARM::t2LEApcrel:
1831 NewOpc = ARM::tLEApcrel;
1838 NewOpc = ARM::tLDRpci;
1848 unsigned UserOffset = getUserOffset(U);
1849 unsigned MaxOffs = ((1 <<
Bits) - 1) * Scale;
1852 if (!
U.KnownAlignment)
1856 if (isCPEntryInRange(
U.MI, UserOffset,
U.CPEMI, MaxOffs,
false,
true)) {
1858 U.MI->setDesc(
TII->get(NewOpc));
1859 MachineBasicBlock *
MBB =
U.MI->getParent();
1860 BBUtils->adjustBBSize(
MBB, -2);
1861 BBUtils->adjustBBOffsetsAfter(
MBB);
1871bool ARMConstantIslands::optimizeThumb2Branches() {
1873 auto TryShrinkBranch = [
this](ImmBranch &Br) {
1874 unsigned Opcode = Br.MI->getOpcode();
1875 unsigned NewOpc = 0;
1892 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
1893 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1894 if (BBUtils->isBBInRange(Br.MI, DestBB, MaxOffs)) {
1896 Br.MI->setDesc(
TII->get(NewOpc));
1897 MachineBasicBlock *
MBB = Br.MI->getParent();
1898 BBUtils->adjustBBSize(
MBB, -2);
1899 BBUtils->adjustBBOffsetsAfter(
MBB);
1908 MachineInstr*
MI =
nullptr;
1909 unsigned NewOpc = 0;
1912 auto FindCmpForCBZ = [
this](ImmBranch &Br, ImmCompare &ImmCmp,
1913 MachineBasicBlock *DestBB) {
1914 ImmCmp.MI =
nullptr;
1919 if (!Br.MI->killsRegister(ARM::CPSR,
nullptr))
1923 unsigned NewOpc = 0;
1928 NewOpc = ARM::tCBNZ;
1934 unsigned BrOffset = BBUtils->getOffsetOf(Br.MI) + 4 - 2;
1936 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1937 if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
1943 if (!CmpMI || CmpMI->
getOpcode() != ARM::tCMPi8)
1947 ImmCmp.NewOpc = NewOpc;
1951 auto TryConvertToLE = [
this](ImmBranch &Br, ImmCompare &
Cmp) {
1952 if (Br.MI->getOpcode() != ARM::t2Bcc || !STI->hasLOB() ||
1956 MachineBasicBlock *
MBB = Br.MI->getParent();
1957 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1958 if (BBUtils->getOffsetOf(
MBB) < BBUtils->getOffsetOf(DestBB) ||
1959 !BBUtils->isBBInRange(Br.MI, DestBB, 4094))
1962 if (!DT->dominates(DestBB,
MBB))
1967 Cmp.NewOpc =
Cmp.NewOpc == ARM::tCBZ ? ARM::tCBNZ : ARM::tCBZ;
1969 MachineInstrBuilder MIB =
BuildMI(*
MBB, Br.MI, Br.MI->getDebugLoc(),
1970 TII->get(ARM::t2LE));
1972 MIB.
add(Br.MI->getOperand(0));
1973 Br.MI->eraseFromParent();
1979 bool MadeChange =
false;
1986 for (ImmBranch &Br :
reverse(ImmBranches)) {
1987 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1988 MachineBasicBlock *
MBB = Br.MI->getParent();
1989 MachineBasicBlock *ExitBB = &
MBB->
back() == Br.MI ?
1994 if (FindCmpForCBZ(Br, Cmp, ExitBB) && TryConvertToLE(Br, Cmp)) {
1998 FindCmpForCBZ(Br, Cmp, DestBB);
1999 MadeChange |= TryShrinkBranch(Br);
2002 unsigned Opcode = Br.MI->getOpcode();
2003 if ((Opcode != ARM::tBcc && Opcode != ARM::t2LE) || !
Cmp.NewOpc)
2012 bool RegKilled =
false;
2015 if (KillMI->killsRegister(
Reg,
TRI)) {
2016 KillMI->clearRegisterKills(
Reg,
TRI);
2020 }
while (KillMI !=
Cmp.MI);
2024 MachineInstr *NewBR =
2028 .
addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags());
2030 Cmp.MI->eraseFromParent();
2032 if (Br.MI->getOpcode() == ARM::tBcc) {
2033 Br.MI->eraseFromParent();
2035 BBUtils->adjustBBSize(
MBB, -2);
2042 MachineInstr *LastMI = &
MBB->
back();
2046 BBUtils->adjustBBOffsetsAfter(
MBB);
2056 if (
I.getOpcode() != ARM::t2ADDrs)
2059 if (
I.getOperand(0).getReg() != EntryReg)
2062 if (
I.getOperand(1).getReg() != BaseReg)
2075bool ARMConstantIslands::preserveBaseRegister(MachineInstr *JumpMI,
2076 MachineInstr *LEAMI,
2079 bool &BaseRegKill) {
2102 CanDeleteLEA =
true;
2103 BaseRegKill =
false;
2104 MachineInstr *RemovableAdd =
nullptr;
2106 for (++
I; &*
I != JumpMI; ++
I) {
2112 for (
const MachineOperand &MO :
I->operands()) {
2113 if (!MO.isReg() || !MO.getReg())
2115 if (MO.isDef() && MO.getReg() == BaseReg)
2117 if (MO.isUse() && MO.getReg() == BaseReg) {
2118 BaseRegKill = BaseRegKill || MO.isKill();
2119 CanDeleteLEA =
false;
2129 for (++
I; &*
I != JumpMI; ++
I) {
2130 for (
const MachineOperand &MO :
I->operands()) {
2131 if (!MO.isReg() || !MO.getReg())
2133 if (MO.isDef() && MO.getReg() == BaseReg)
2135 if (MO.isUse() && MO.getReg() == EntryReg)
2136 RemovableAdd =
nullptr;
2142 DeadSize += isThumb2 ? 4 : 2;
2143 }
else if (BaseReg == EntryReg) {
2164 return MBB != MF->
end() && !
MBB->empty() && &*
MBB->begin() == CPEMI;
2169 unsigned &DeadSize) {
2178 for (++
I; &*
I != JumpMI; ++
I) {
2179 if (
I->getOpcode() == ARM::t2ADDrs &&
I->getOperand(0).getReg() == EntryReg)
2188 for (++J; &*J != JumpMI; ++J) {
2190 if (!MO.isReg() || !MO.getReg())
2192 if (MO.isDef() && MO.getReg() == EntryReg)
2194 if (MO.isUse() && MO.getReg() == EntryReg)
2206bool ARMConstantIslands::optimizeThumb2JumpTables() {
2207 bool MadeChange =
false;
2211 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
2212 if (!MJTI)
return false;
2215 for (MachineInstr *
MI : T2JumpTables) {
2216 const MCInstrDesc &MCID =
MI->getDesc();
2218 unsigned JTOpIdx =
NumOps - (
MI->isPredicable() ? 2 : 1);
2219 MachineOperand JTOP =
MI->getOperand(JTOpIdx);
2224 bool HalfWordOk =
true;
2225 unsigned JTOffset = BBUtils->getOffsetOf(
MI) + 4;
2226 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
2228 for (MachineBasicBlock *
MBB : JTBBs) {
2232 if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2)
2234 unsigned TBHLimit = ((1<<16)-1)*2;
2235 if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit)
2237 if (!ByteOk && !HalfWordOk)
2241 if (!ByteOk && !HalfWordOk)
2244 CPUser &
User = CPUsers[JumpTableUserIndices[JTI]];
2245 MachineBasicBlock *
MBB =
MI->getParent();
2246 if (!
MI->getOperand(0).isKill())
2249 unsigned DeadSize = 0;
2250 bool CanDeleteLEA =
false;
2251 bool BaseRegKill =
false;
2253 unsigned IdxReg = ~0
U;
2254 bool IdxRegKill =
true;
2256 IdxReg =
MI->getOperand(1).getReg();
2257 IdxRegKill =
MI->getOperand(1).isKill();
2259 bool PreservedBaseReg =
2260 preserveBaseRegister(
MI,
User.MI, DeadSize, CanDeleteLEA, BaseRegKill);
2270 MachineBasicBlock *UserMBB =
User.MI->getParent();
2272 if (Shift == UserMBB->
begin())
2276 if (Shift->getOpcode() != ARM::tLSLri ||
2277 Shift->getOperand(3).getImm() != 2 ||
2278 !Shift->getOperand(2).isKill())
2280 IdxReg = Shift->getOperand(2).getReg();
2281 Register ShiftedIdxReg = Shift->getOperand(0).getReg();
2289 MachineInstr *
Load =
User.MI->getNextNode();
2290 if (
Load->getOpcode() != ARM::tLDRr)
2292 if (
Load->getOperand(1).getReg() != BaseReg ||
2293 Load->getOperand(2).getReg() != ShiftedIdxReg ||
2294 !
Load->getOperand(2).isKill())
2308 if (isPositionIndependentOrROPI) {
2309 MachineInstr *
Add =
Load->getNextNode();
2310 if (
Add->getOpcode() != ARM::tADDrr ||
2311 Add->getOperand(2).getReg() != BaseReg ||
2312 Add->getOperand(3).getReg() !=
Load->getOperand(0).getReg() ||
2313 !
Add->getOperand(3).isKill())
2315 if (
Add->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2320 Add->eraseFromParent();
2323 if (
Load->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2331 CanDeleteLEA =
true;
2332 Shift->eraseFromParent();
2333 Load->eraseFromParent();
2338 MachineInstr *CPEMI =
User.CPEMI;
2339 unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
2341 Opc = ByteOk ? ARM::tTBB_JT : ARM::tTBH_JT;
2344 MachineInstr *NewJTMI =
2353 unsigned JTOpc = ByteOk ? ARM::JUMPTABLE_TBB : ARM::JUMPTABLE_TBH;
2364 User.MI->eraseFromParent();
2365 DeadSize += isThumb2 ? 4 : 2;
2372 User.IsSoImm =
false;
2373 User.KnownAlignment =
false;
2377 int CPEntryIdx = JumpTableEntryIndices[JTI];
2378 auto &CPEs = CPEntries[CPEntryIdx];
2380 find_if(CPEs, [&](CPEntry &
E) {
return E.CPEMI ==
User.CPEMI; });
2382 CPUsers.emplace_back(CPUser(NewJTMI,
User.CPEMI, 4,
false,
false));
2386 unsigned NewSize =
TII->getInstSizeInBytes(*NewJTMI);
2387 unsigned OrigSize =
TII->getInstSizeInBytes(*
MI);
2388 MI->eraseFromParent();
2390 int Delta = OrigSize - NewSize + DeadSize;
2392 BBUtils->adjustBBOffsetsAfter(
MBB);
2403bool ARMConstantIslands::reorderThumb2JumpTables() {
2404 bool MadeChange =
false;
2406 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
2407 if (!MJTI)
return false;
2410 for (MachineInstr *
MI : T2JumpTables) {
2411 const MCInstrDesc &MCID =
MI->getDesc();
2413 unsigned JTOpIdx =
NumOps - (
MI->isPredicable() ? 2 : 1);
2414 MachineOperand JTOP =
MI->getOperand(JTOpIdx);
2421 int JTNumber =
MI->getParent()->getNumber();
2422 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
2423 for (MachineBasicBlock *
MBB : JTBBs) {
2426 if (DTNumber < JTNumber) {
2429 MachineBasicBlock *NewBB =
2430 adjustJTTargetBlockForward(JTI,
MBB,
MI->getParent());
2441MachineBasicBlock *ARMConstantIslands::adjustJTTargetBlockForward(
2442 unsigned JTI, MachineBasicBlock *BB, MachineBasicBlock *JTBB) {
2447 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
2460 if (!
B &&
Cond.empty() && BB != &MF->front() &&
2463 OldPrior->updateTerminator(BB);
2466 MF->RenumberBlocks();
2467 DT->updateBlockNumbers();
2473 MachineBasicBlock *NewBB =
2476 MF->insert(
MBBI, NewBB);
2479 for (
const MachineBasicBlock::RegisterMaskPair &RegMaskPair : BB->
liveins())
2495 MF->RenumberBlocks(NewBB);
2496 DT->updateBlockNumbers();
2509 return new ARMConstantIslands();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 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...
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
#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
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
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 ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
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)
bool isThumb2Function() const
void initPICLabelUId(unsigned UId)
unsigned createPICLabelUId()
bool isThumb1OnlyFunction() const
bool isThumbFunction() const
void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx)
const ARMBaseInstrInfo * getInstrInfo() const override
bool isTargetWindows() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
AnalysisUsage & addRequired()
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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....
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...
LLVM_ABI void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
Replace successor OLD with NEW and update probability info.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
iterator_range< livein_iterator > liveins() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void updateTerminator(MachineBasicBlock *PreviousLayoutSuccessor)
Update the terminator instructions in block to account for changes to block layout which may have bee...
void setAlignment(Align A)
Set alignment of the basic block.
LLVM_ABI void dump() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI 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.
reverse_iterator rbegin()
LLVM_ABI 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
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
Align getConstantPoolAlign() const
Return the alignment required by the whole constant pool, of which the first element must be aligned.
const std::vector< MachineConstantPoolEntry > & getConstants() const
bool isEmpty() const
isEmpty - Return true if this constant pool contains no constants.
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
void ensureAlignment(Align A)
ensureAlignment - Make sure the function is at least A bytes aligned.
void push_back(MachineBasicBlock *MBB)
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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 MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
BasicBlockListType::const_iterator const_iterator
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.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI 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...
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
JTEntryKind getEntryKind() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setIsKill(bool Val=true)
void setMBB(MachineBasicBlock *MBB)
unsigned getTargetFlags() const
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
bool isPositionIndependent() const
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
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.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
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.
SmallVectorImpl< BasicBlockInfo > BBInfoVector
unsigned Log2(Align A)
Returns the log2 of the alignment.
static bool isSpeculationBarrierEndBBOpcode(int Opc)
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.
LLVM_ABI 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.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Align PostAlign
PostAlign - When > 1, the block terminator contains a .align directive, so the end of the block is al...
uint8_t KnownBits
KnownBits - The number of low bits in Offset that are known to be exact.
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.
uint8_t Unalign
Unalign - When non-zero, the block contains instructions (inline asm) of unknown size.
unsigned Offset
Offset - Distance from the beginning of the function to the beginning of this basic block.