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 PrevCanFallthrough =
true;
353 for (
auto &
MBB : *MF) {
354 if (!PrevCanFallthrough) {
356 MBB.setAlignment(Alignment);
359 PrevCanFallthrough =
MBB.canFallThrough();
365 if (
MI.getOpcode() == ARM::t2B &&
366 MI.getOperand(0).getMBB() ==
MBB.getNextNode())
369 MI.getOpcode() == ARM::t2LoopEndDec) {
370 PrevCanFallthrough =
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())
414 bool MadeChange =
false;
416 scanFunctionJumpTables();
417 MadeChange |= reorderThumb2JumpTables();
419 T2JumpTables.
clear();
429 std::vector<MachineInstr*> CPEMIs;
431 doInitialConstPlacement(CPEMIs);
434 doInitialJumpTablePlacement(CPEMIs);
442 initializeFunctionInfo(CPEMIs);
448 if (!T2JumpTables.
empty())
452 MadeChange |= removeUnusedCPEntries();
456 unsigned NoCPIters = 0, NoBRIters = 0;
458 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
459 bool CPChange =
false;
460 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
464 CPChange |= handleConstantPoolUser(i, NoCPIters >=
CPMaxIteration / 2);
471 NewWaterList.
clear();
473 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
474 bool BRChange =
false;
475 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
477 BRChange |= fixupImmediateBr(ImmBranches[i]);
479 if (BRChange && ++NoBRIters > 30)
483 if (!CPChange && !BRChange)
489 if (isThumb2 && !STI->prefers32BitThumb())
490 MadeChange |= optimizeThumb2Instructions();
493 if (
isThumb && STI->hasV8MBaselineOps())
494 MadeChange |= optimizeThumb2Branches();
497 if (GenerateTBB && !STI->genExecuteOnly())
498 MadeChange |= optimizeThumb2JumpTables();
504 for (
unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
505 for (
unsigned j = 0, je = CPEntries[i].
size();
j != je; ++
j) {
506 const CPEntry & CPE = CPEntries[i][
j];
507 if (CPE.CPEMI && CPE.CPEMI->getOperand(1).isCPI())
518 JumpTableEntryIndices.
clear();
519 JumpTableUserIndices.
clear();
522 T2JumpTables.
clear();
530ARMConstantIslands::doInitialConstPlacement(std::vector<MachineInstr*> &CPEMIs) {
537 const unsigned MaxLogAlign =
Log2(MaxAlign);
545 Align FuncAlign = MaxAlign;
547 FuncAlign =
Align(4);
559 const std::vector<MachineConstantPoolEntry> &CPs = MCP->
getConstants();
562 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
563 unsigned Size = CPs[i].getSizeInBytes(TD);
564 Align Alignment = CPs[i].getAlign();
570 unsigned LogAlign =
Log2(Alignment);
572 MachineInstr *CPEMI =
575 CPEMIs.push_back(CPEMI);
579 for (
unsigned a = LogAlign + 1; a <= MaxLogAlign; ++a)
580 if (InsPoint[a] == InsAt)
584 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
586 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
587 <<
Size <<
", align = " << Alignment.
value() <<
'\n');
597void ARMConstantIslands::doInitialJumpTablePlacement(
598 std::vector<MachineInstr *> &CPEMIs) {
599 unsigned i = CPEntries.size();
601 const std::vector<MachineJumpTableEntry> &JT = MJTI->
getJumpTables();
607 MachineBasicBlock *LastCorrectlyNumberedBB =
nullptr;
608 for (MachineBasicBlock &
MBB : *MF) {
620 switch (
MI->getOpcode()) {
626 case ARM::BR_JTm_i12:
631 assert(!MF->getInfo<ARMFunctionInfo>()->branchTargetEnforcement() &&
632 "Branch protection must not be enabled for Arm or Thumb1 modes");
633 JTOpcode = ARM::JUMPTABLE_ADDRS;
636 JTOpcode = ARM::JUMPTABLE_INSTS;
640 JTOpcode = ARM::JUMPTABLE_TBB;
644 JTOpcode = ARM::JUMPTABLE_TBH;
648 unsigned NumOps =
MI->getDesc().getNumOperands();
649 MachineOperand JTOp =
650 MI->getOperand(
NumOps - (
MI->isPredicable() ? 2 : 1));
652 unsigned Size = JT[JTI].MBBs.size() *
sizeof(uint32_t);
653 MachineBasicBlock *JumpTableBB = MF->CreateMachineBasicBlock();
655 MachineInstr *CPEMI =
BuildMI(*JumpTableBB, JumpTableBB->
begin(),
660 CPEMIs.push_back(CPEMI);
661 CPEntries.emplace_back(1, CPEntry(CPEMI, JTI));
662 JumpTableEntryIndices.
insert(std::make_pair(JTI, CPEntries.size() - 1));
663 if (!LastCorrectlyNumberedBB)
664 LastCorrectlyNumberedBB = &
MBB;
668 if (LastCorrectlyNumberedBB)
669 MF->RenumberBlocks(LastCorrectlyNumberedBB);
674bool ARMConstantIslands::BBHasFallthrough(MachineBasicBlock *
MBB) {
681 MachineBasicBlock *NextBB = &*std::next(
MBBI);
687 MachineBasicBlock *
TBB, *FBB;
690 return TooDifficult || FBB ==
nullptr;
695ARMConstantIslands::CPEntry *
696ARMConstantIslands::findConstPoolEntry(
unsigned CPI,
697 const MachineInstr *CPEMI) {
698 std::vector<CPEntry> &CPEs = CPEntries[CPI];
701 for (CPEntry &CPE : CPEs)
702 if (CPE.CPEMI == CPEMI)
709Align ARMConstantIslands::getCPEAlign(
const MachineInstr *CPEMI) {
711 case ARM::CONSTPOOL_ENTRY:
713 case ARM::JUMPTABLE_TBB:
715 case ARM::JUMPTABLE_TBH:
717 case ARM::JUMPTABLE_INSTS:
719 case ARM::JUMPTABLE_ADDRS:
725 unsigned CPI = getCombinedIndex(CPEMI);
726 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
733void ARMConstantIslands::scanFunctionJumpTables() {
734 for (MachineBasicBlock &
MBB : *MF) {
735 for (MachineInstr &
I :
MBB)
737 (
I.getOpcode() == ARM::t2BR_JT ||
I.getOpcode() == ARM::tBR_JTr))
745void ARMConstantIslands::
746initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
748 BBUtils->computeAllBlockSizes();
752 BBInfo.
front().KnownBits =
Log2(MF->getAlignment());
755 BBUtils->adjustBBOffsetsAfter(&MF->front());
758 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
759 bool InlineJumpTables =
763 for (MachineBasicBlock &
MBB : *MF) {
767 WaterList.push_back(&
MBB);
769 for (MachineInstr &
I :
MBB) {
770 if (
I.isDebugInstr())
773 unsigned Opc =
I.getOpcode();
784 if (InlineJumpTables)
818 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
819 ImmBranches.push_back(ImmBranch(&
I, MaxOffs, isCond, UOpc));
822 if (
Opc == ARM::tPUSH ||
Opc == ARM::tPOP_RET)
825 if (
Opc == ARM::CONSTPOOL_ENTRY ||
Opc == ARM::JUMPTABLE_ADDRS ||
826 Opc == ARM::JUMPTABLE_INSTS ||
Opc == ARM::JUMPTABLE_TBB ||
827 Opc == ARM::JUMPTABLE_TBH)
831 for (
unsigned op = 0, e =
I.getNumOperands();
op != e; ++
op)
832 if (
I.getOperand(
op).isCPI() ||
833 (
I.getOperand(
op).isJTI() && InlineJumpTables)) {
841 bool IsSoImm =
false;
849 case ARM::LEApcrelJT: {
857 unsigned CPI =
I.getOperand(
op).getIndex();
858 assert(CPI < CPEMIs.size());
859 MachineInstr *CPEMI = CPEMIs[CPI];
860 const Align CPEAlign = getCPEAlign(CPEMI);
861 const unsigned LogCPEAlign =
Log2(CPEAlign);
862 if (LogCPEAlign >= 2)
870 case ARM::t2LEApcrel:
871 case ARM::t2LEApcrelJT:
876 case ARM::tLEApcrelJT:
886 case ARM::t2LDRSHpci:
888 case ARM::t2LDRSBpci:
912 unsigned CPI =
I.getOperand(
op).getIndex();
913 if (
I.getOperand(
op).isJTI()) {
914 JumpTableUserIndices.
insert(std::make_pair(CPI, CPUsers.size()));
915 CPI = JumpTableEntryIndices[CPI];
918 MachineInstr *CPEMI = CPEMIs[CPI];
919 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
920 CPUsers.push_back(CPUser(&
I, CPEMI, MaxOffs, NegOk, IsSoImm));
923 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
924 assert(CPE &&
"Cannot find a corresponding CPEntry!");
939 return LHS->getNumber() <
RHS->getNumber();
945void ARMConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
951 BBUtils->insert(NewBB->
getNumber(), BasicBlockInfo());
956 WaterList.insert(IP, NewBB);
962MachineBasicBlock *ARMConstantIslands::splitBlockBeforeInstr(MachineInstr *
MI) {
963 MachineBasicBlock *OrigBB =
MI->getParent();
966 LivePhysRegs LRs(*MF->getSubtarget().getRegisterInfo());
967 LRs.addLiveOuts(*OrigBB);
970 LRs.stepBackward(LiveMI);
973 MachineBasicBlock *NewBB =
976 MF->insert(
MBBI, NewBB);
985 unsigned Opc =
isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) :
ARM::
B;
1001 MachineRegisterInfo &MRI = MF->getRegInfo();
1009 MF->RenumberBlocks(NewBB);
1013 BBUtils->insert(NewBB->
getNumber(), BasicBlockInfo());
1020 MachineBasicBlock* WaterBB = *IP;
1021 if (WaterBB == OrigBB)
1022 WaterList.insert(std::next(IP), NewBB);
1024 WaterList.insert(IP, OrigBB);
1025 NewWaterList.
insert(OrigBB);
1032 BBUtils->computeBlockSize(OrigBB);
1036 BBUtils->computeBlockSize(NewBB);
1039 BBUtils->adjustBBOffsetsAfter(OrigBB);
1047unsigned ARMConstantIslands::getUserOffset(CPUser &U)
const {
1048 unsigned UserOffset = BBUtils->getOffsetOf(
U.MI);
1050 SmallVectorImpl<BasicBlockInfo> &BBInfo = BBUtils->getBBInfo();
1051 const BasicBlockInfo &BBI = BBInfo[
U.MI->getParent()->getNumber()];
1055 UserOffset += (
isThumb ? 4 : 8);
1059 U.KnownAlignment = (KnownBits >= 2);
1076bool ARMConstantIslands::isOffsetInRange(
unsigned UserOffset,
1077 unsigned TrialOffset,
unsigned MaxDisp,
1078 bool NegativeOK,
bool IsSoImm) {
1079 if (UserOffset <= TrialOffset) {
1081 if (TrialOffset - UserOffset <= MaxDisp)
1084 }
else if (NegativeOK) {
1085 if (UserOffset - TrialOffset <= MaxDisp)
1096bool ARMConstantIslands::isWaterInRange(
unsigned UserOffset,
1097 MachineBasicBlock* Water, CPUser &U,
1100 const Align CPEAlign = getCPEAlign(
U.CPEMI);
1101 const unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset(CPEAlign);
1102 unsigned NextBlockOffset;
1103 Align NextBlockAlignment;
1105 if (++NextBlock == MF->end()) {
1106 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
1108 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
1109 NextBlockAlignment = NextBlock->getAlignment();
1111 unsigned Size =
U.CPEMI->getOperand(2).getImm();
1112 unsigned CPEEnd = CPEOffset +
Size;
1117 if (CPEEnd > NextBlockOffset) {
1118 Growth = CPEEnd - NextBlockOffset;
1126 if (CPEOffset < UserOffset)
1132 return isOffsetInRange(UserOffset, CPEOffset, U);
1137bool ARMConstantIslands::isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
1138 MachineInstr *CPEMI,
unsigned MaxDisp,
1139 bool NegOk,
bool DoDump) {
1140 unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
1145 unsigned Block =
MI->getParent()->getNumber();
1146 const BasicBlockInfo &BBI = BBInfo[
Block];
1148 <<
" max delta=" << MaxDisp
1149 <<
format(
" insn address=%#x", UserOffset) <<
" in "
1152 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
1153 int(CPEOffset - UserOffset));
1157 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
1164 if (
MBB->pred_size() != 1 ||
MBB->succ_size() != 1)
1181bool ARMConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
1182 MachineInstr *CPEMI) {
1184 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1185 assert(CPE &&
"Unexpected!");
1186 if (--CPE->RefCount == 0) {
1187 removeDeadCPEMI(CPEMI);
1188 CPE->CPEMI =
nullptr;
1195unsigned ARMConstantIslands::getCombinedIndex(
const MachineInstr *CPEMI) {
1208int ARMConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset) {
1209 MachineInstr *UserMI =
U.MI;
1210 MachineInstr *CPEMI =
U.CPEMI;
1213 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
U.getMaxDisp(),
U.NegOk,
1220 unsigned CPI = getCombinedIndex(CPEMI);
1221 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1222 for (CPEntry &CPE : CPEs) {
1224 if (CPE.CPEMI == CPEMI)
1227 if (CPE.CPEMI ==
nullptr)
1229 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getMaxDisp(),
1231 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1234 U.CPEMI = CPE.CPEMI;
1236 for (MachineOperand &MO : UserMI->
operands())
1238 MO.setIndex(CPE.CPI);
1245 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1256 return ((1<<10)-1)*2;
1258 return ((1<<23)-1)*2;
1263 return ((1<<23)-1)*4;
1274bool ARMConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1275 water_iterator &WaterIter,
1277 if (WaterList.empty())
1280 unsigned BestGrowth = ~0
u;
1291 MachineBasicBlock *UserBB =
U.MI->getParent();
1293 const Align CPEAlign = getCPEAlign(
U.CPEMI);
1294 unsigned MinNoSplitDisp = BBInfo[UserBB->
getNumber()].postOffset(CPEAlign);
1295 if (CloserWater && MinNoSplitDisp >
U.getMaxDisp() / 2)
1297 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1299 MachineBasicBlock* WaterBB = *IP;
1311 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1312 (WaterBB->
getNumber() <
U.HighWaterMark->getNumber() ||
1313 NewWaterList.
count(WaterBB) || WaterBB ==
U.MI->getParent()) &&
1314 Growth < BestGrowth) {
1316 BestGrowth = Growth;
1319 <<
" Growth=" << Growth <<
'\n');
1321 if (CloserWater && WaterBB ==
U.MI->getParent())
1325 if (!CloserWater && BestGrowth == 0)
1331 return BestGrowth != ~0
u;
1341void ARMConstantIslands::createNewWater(
unsigned CPUserIndex,
1342 unsigned UserOffset,
1343 MachineBasicBlock *&NewMBB) {
1344 CPUser &
U = CPUsers[CPUserIndex];
1345 MachineInstr *UserMI =
U.MI;
1346 MachineInstr *CPEMI =
U.CPEMI;
1347 const Align CPEAlign = getCPEAlign(CPEMI);
1348 MachineBasicBlock *UserMBB = UserMI->
getParent();
1350 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1358 unsigned Delta = isThumb1 ? 2 : 4;
1360 unsigned CPEOffset = UserBBI.
postOffset(CPEAlign) + Delta;
1362 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1364 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1371 int UncondBr =
isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) :
ARM::
B;
1379 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1380 MaxDisp,
false, UncondBr));
1381 BBUtils->computeBlockSize(UserMBB);
1382 BBUtils->adjustBBOffsetsAfter(UserMBB);
1403 assert(Align >= CPEAlign &&
"Over-aligned constant pool entry");
1406 unsigned BaseInsertOffset = UserOffset +
U.getMaxDisp() - UPad;
1413 BaseInsertOffset -= 4;
1416 <<
" la=" <<
Log2(Align) <<
" kb=" << KnownBits
1417 <<
" up=" << UPad <<
'\n');
1423 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1429 UserOffset +
TII->getInstSizeInBytes(*UserMI) + 1);
1444 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1445 I->getOpcode() != ARM::t2IT &&
1447 Offset +=
TII->getInstSizeInBytes(*
I),
I = std::next(
I)) {
1449 std::max(BaseInsertOffset,
Offset +
TII->getInstSizeInBytes(*
I) + 1);
1450 assert(
I != UserMBB->
end() &&
"Fell off end of block");
1454 unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
1458 unsigned CPUIndex = CPUserIndex+1;
1459 unsigned NumCPUsers = CPUsers.size();
1460 MachineInstr *LastIT =
nullptr;
1461 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1462 Offset < BaseInsertOffset;
1464 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1465 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI == &*
MI) {
1466 CPUser &
U = CPUsers[CPUIndex];
1467 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1469 BaseInsertOffset -=
Align.value();
1470 EndInsertOffset -=
Align.value();
1476 EndInsertOffset +=
U.CPEMI->getOperand(2).getImm();
1481 if (
MI->getOpcode() == ARM::t2IT)
1506 assert(
MI->getOpcode() == ARM::t2MOVi16 &&
1516 NewMBB = splitBlockBeforeInstr(&*
MI);
1523bool ARMConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex,
1525 CPUser &
U = CPUsers[CPUserIndex];
1526 MachineInstr *UserMI =
U.MI;
1527 MachineInstr *CPEMI =
U.CPEMI;
1528 unsigned CPI = getCombinedIndex(CPEMI);
1531 unsigned UserOffset = getUserOffset(U);
1535 int result = findInRangeCPEntry(U, UserOffset);
1536 if (result==1)
return false;
1537 else if (result==2)
return true;
1544 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1545 MachineBasicBlock *NewMBB;
1547 if (findAvailableWater(U, UserOffset, IP, CloserWater)) {
1549 MachineBasicBlock *WaterBB = *IP;
1554 if (NewWaterList.
erase(WaterBB))
1555 NewWaterList.
insert(NewIsland);
1562 createNewWater(CPUserIndex, UserOffset, NewMBB);
1569 MachineBasicBlock *WaterBB = &*--NewMBB->
getIterator();
1570 IP =
find(WaterList, WaterBB);
1571 if (IP != WaterList.end())
1572 NewWaterList.
erase(WaterBB);
1575 NewWaterList.
insert(NewIsland);
1588 if (IP != WaterList.end())
1589 WaterList.erase(IP);
1595 updateForInsertedWaterBlock(NewIsland);
1599 U.HighWaterMark = NewIsland;
1604 CPEntries[CPI].push_back(CPEntry(
U.CPEMI,
ID, 1));
1608 decrementCPEReferenceCount(CPI, CPEMI);
1614 BBUtils->adjustBBSize(NewIsland,
Size);
1615 BBUtils->adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1618 for (MachineOperand &MO : UserMI->
operands())
1625 dbgs() <<
" Moved CPE to #" <<
ID <<
" CPI=" << CPI
1626 <<
format(
" offset=%#x\n",
1627 BBUtils->getBBInfo()[NewIsland->
getNumber()].Offset));
1634void ARMConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1635 MachineBasicBlock *CPEBB = CPEMI->
getParent();
1639 BBUtils->adjustBBSize(CPEBB, -
Size);
1641 if (CPEBB->
empty()) {
1651 BBUtils->adjustBBOffsetsAfter(CPEBB);
1661bool ARMConstantIslands::removeUnusedCPEntries() {
1662 unsigned MadeChange =
false;
1663 for (std::vector<CPEntry> &CPEs : CPEntries) {
1664 for (CPEntry &CPE : CPEs) {
1665 if (CPE.RefCount == 0 && CPE.CPEMI) {
1666 removeDeadCPEMI(CPE.CPEMI);
1667 CPE.CPEMI =
nullptr;
1678bool ARMConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1679 MachineInstr *
MI = Br.MI;
1680 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1683 if (BBUtils->isBBInRange(
MI, DestBB, Br.MaxDisp))
1687 return fixupUnconditionalBr(Br);
1688 return fixupConditionalBr(Br);
1696ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1697 MachineInstr *
MI = Br.MI;
1698 MachineBasicBlock *
MBB =
MI->getParent();
1706 Br.MaxDisp = (1 << 21) * 2;
1707 MI->setDesc(
TII->get(ARM::tBfar));
1710 BBUtils->adjustBBOffsetsAfter(
MBB);
1722ARMConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1723 MachineInstr *
MI = Br.MI;
1724 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1740 MachineBasicBlock *
MBB =
MI->getParent();
1741 MachineInstr *BMI = &
MBB->
back();
1756 if (BBUtils->isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1758 dbgs() <<
" Invert Bcc condition and swap its destination with "
1761 MI->getOperand(0).setMBB(NewDest);
1762 MI->getOperand(1).setImm(CC);
1769 splitBlockBeforeInstr(
MI);
1772 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1773 BBUtils->adjustBBSize(
MBB, -delta);
1786 <<
" also invert condition and change dest. to "
1794 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1801 BBUtils->adjustBBSize(
MBB,
TII->getInstSizeInBytes(
MBB->
back()));
1803 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1806 BBUtils->adjustBBSize(
MI->getParent(), -
TII->getInstSizeInBytes(*
MI));
1807 MI->eraseFromParent();
1808 BBUtils->adjustBBOffsetsAfter(
MBB);
1812bool ARMConstantIslands::optimizeThumb2Instructions() {
1813 bool MadeChange =
false;
1816 for (CPUser &U : CPUsers) {
1817 unsigned Opcode =
U.MI->getOpcode();
1818 unsigned NewOpc = 0;
1823 case ARM::t2LEApcrel:
1825 NewOpc = ARM::tLEApcrel;
1832 NewOpc = ARM::tLDRpci;
1842 unsigned UserOffset = getUserOffset(U);
1843 unsigned MaxOffs = ((1 <<
Bits) - 1) * Scale;
1846 if (!
U.KnownAlignment)
1850 if (isCPEntryInRange(
U.MI, UserOffset,
U.CPEMI, MaxOffs,
false,
true)) {
1852 U.MI->setDesc(
TII->get(NewOpc));
1853 MachineBasicBlock *
MBB =
U.MI->getParent();
1854 BBUtils->adjustBBSize(
MBB, -2);
1855 BBUtils->adjustBBOffsetsAfter(
MBB);
1865bool ARMConstantIslands::optimizeThumb2Branches() {
1867 auto TryShrinkBranch = [
this](ImmBranch &Br) {
1868 unsigned Opcode = Br.MI->getOpcode();
1869 unsigned NewOpc = 0;
1886 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
1887 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1888 if (BBUtils->isBBInRange(Br.MI, DestBB, MaxOffs)) {
1890 Br.MI->setDesc(
TII->get(NewOpc));
1891 MachineBasicBlock *
MBB = Br.MI->getParent();
1892 BBUtils->adjustBBSize(
MBB, -2);
1893 BBUtils->adjustBBOffsetsAfter(
MBB);
1902 MachineInstr*
MI =
nullptr;
1903 unsigned NewOpc = 0;
1906 auto FindCmpForCBZ = [
this](ImmBranch &Br, ImmCompare &ImmCmp,
1907 MachineBasicBlock *DestBB) {
1908 ImmCmp.MI =
nullptr;
1913 if (!Br.MI->killsRegister(ARM::CPSR,
nullptr))
1917 unsigned NewOpc = 0;
1922 NewOpc = ARM::tCBNZ;
1928 unsigned BrOffset = BBUtils->getOffsetOf(Br.MI) + 4 - 2;
1930 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1931 if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
1937 if (!CmpMI || CmpMI->
getOpcode() != ARM::tCMPi8)
1941 ImmCmp.NewOpc = NewOpc;
1945 auto TryConvertToLE = [
this](ImmBranch &Br, ImmCompare &
Cmp) {
1946 if (Br.MI->getOpcode() != ARM::t2Bcc || !STI->hasLOB() ||
1950 MachineBasicBlock *
MBB = Br.MI->getParent();
1951 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1952 if (BBUtils->getOffsetOf(
MBB) < BBUtils->getOffsetOf(DestBB) ||
1953 !BBUtils->isBBInRange(Br.MI, DestBB, 4094))
1956 if (!DT->dominates(DestBB,
MBB))
1961 Cmp.NewOpc =
Cmp.NewOpc == ARM::tCBZ ? ARM::tCBNZ : ARM::tCBZ;
1963 MachineInstrBuilder MIB =
BuildMI(*
MBB, Br.MI, Br.MI->getDebugLoc(),
1964 TII->get(ARM::t2LE));
1966 MIB.
add(Br.MI->getOperand(0));
1967 Br.MI->eraseFromParent();
1973 bool MadeChange =
false;
1980 for (ImmBranch &Br :
reverse(ImmBranches)) {
1981 MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
1982 MachineBasicBlock *
MBB = Br.MI->getParent();
1983 MachineBasicBlock *ExitBB = &
MBB->
back() == Br.MI ?
1988 if (FindCmpForCBZ(Br, Cmp, ExitBB) && TryConvertToLE(Br, Cmp)) {
1992 FindCmpForCBZ(Br, Cmp, DestBB);
1993 MadeChange |= TryShrinkBranch(Br);
1996 unsigned Opcode = Br.MI->getOpcode();
1997 if ((Opcode != ARM::tBcc && Opcode != ARM::t2LE) || !
Cmp.NewOpc)
2006 bool RegKilled =
false;
2009 if (KillMI->killsRegister(
Reg,
TRI)) {
2010 KillMI->clearRegisterKills(
Reg,
TRI);
2014 }
while (KillMI !=
Cmp.MI);
2018 MachineInstr *NewBR =
2022 .
addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags());
2024 Cmp.MI->eraseFromParent();
2026 if (Br.MI->getOpcode() == ARM::tBcc) {
2027 Br.MI->eraseFromParent();
2029 BBUtils->adjustBBSize(
MBB, -2);
2036 MachineInstr *LastMI = &
MBB->
back();
2040 BBUtils->adjustBBOffsetsAfter(
MBB);
2050 if (
I.getOpcode() != ARM::t2ADDrs)
2053 if (
I.getOperand(0).getReg() != EntryReg)
2056 if (
I.getOperand(1).getReg() != BaseReg)
2069bool ARMConstantIslands::preserveBaseRegister(MachineInstr *JumpMI,
2070 MachineInstr *LEAMI,
2073 bool &BaseRegKill) {
2096 CanDeleteLEA =
true;
2097 BaseRegKill =
false;
2098 MachineInstr *RemovableAdd =
nullptr;
2100 for (++
I; &*
I != JumpMI; ++
I) {
2106 for (
const MachineOperand &MO :
I->operands()) {
2107 if (!MO.isReg() || !MO.getReg())
2109 if (MO.isDef() && MO.getReg() == BaseReg)
2111 if (MO.isUse() && MO.getReg() == BaseReg) {
2112 BaseRegKill = BaseRegKill || MO.isKill();
2113 CanDeleteLEA =
false;
2123 for (++
I; &*
I != JumpMI; ++
I) {
2124 for (
const MachineOperand &MO :
I->operands()) {
2125 if (!MO.isReg() || !MO.getReg())
2127 if (MO.isDef() && MO.getReg() == BaseReg)
2129 if (MO.isUse() && MO.getReg() == EntryReg)
2130 RemovableAdd =
nullptr;
2136 DeadSize += isThumb2 ? 4 : 2;
2137 }
else if (BaseReg == EntryReg) {
2158 return MBB != MF->
end() && !
MBB->empty() && &*
MBB->begin() == CPEMI;
2163 unsigned &DeadSize) {
2172 for (++
I; &*
I != JumpMI; ++
I) {
2173 if (
I->getOpcode() == ARM::t2ADDrs &&
I->getOperand(0).getReg() == EntryReg)
2182 for (++J; &*J != JumpMI; ++J) {
2184 if (!MO.isReg() || !MO.getReg())
2186 if (MO.isDef() && MO.getReg() == EntryReg)
2188 if (MO.isUse() && MO.getReg() == EntryReg)
2200bool ARMConstantIslands::optimizeThumb2JumpTables() {
2201 bool MadeChange =
false;
2205 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
2206 if (!MJTI)
return false;
2208 const std::vector<MachineJumpTableEntry> &JT = MJTI->
getJumpTables();
2209 for (MachineInstr *
MI : T2JumpTables) {
2210 const MCInstrDesc &MCID =
MI->getDesc();
2212 unsigned JTOpIdx =
NumOps - (
MI->isPredicable() ? 2 : 1);
2213 MachineOperand JTOP =
MI->getOperand(JTOpIdx);
2218 bool HalfWordOk =
true;
2219 unsigned JTOffset = BBUtils->getOffsetOf(
MI) + 4;
2220 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
2222 for (MachineBasicBlock *
MBB : JTBBs) {
2226 if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2)
2228 unsigned TBHLimit = ((1<<16)-1)*2;
2229 if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit)
2231 if (!ByteOk && !HalfWordOk)
2235 if (!ByteOk && !HalfWordOk)
2238 CPUser &
User = CPUsers[JumpTableUserIndices[JTI]];
2239 MachineBasicBlock *
MBB =
MI->getParent();
2240 if (!
MI->getOperand(0).isKill())
2243 unsigned DeadSize = 0;
2244 bool CanDeleteLEA =
false;
2245 bool BaseRegKill =
false;
2247 unsigned IdxReg = ~0
U;
2248 bool IdxRegKill =
true;
2250 IdxReg =
MI->getOperand(1).getReg();
2251 IdxRegKill =
MI->getOperand(1).isKill();
2253 bool PreservedBaseReg =
2254 preserveBaseRegister(
MI,
User.MI, DeadSize, CanDeleteLEA, BaseRegKill);
2264 MachineBasicBlock *UserMBB =
User.MI->getParent();
2266 if (Shift == UserMBB->
begin())
2270 if (Shift->getOpcode() != ARM::tLSLri ||
2271 Shift->getOperand(3).getImm() != 2 ||
2272 !Shift->getOperand(2).isKill())
2274 IdxReg = Shift->getOperand(2).getReg();
2275 Register ShiftedIdxReg = Shift->getOperand(0).getReg();
2283 MachineInstr *
Load =
User.MI->getNextNode();
2284 if (
Load->getOpcode() != ARM::tLDRr)
2286 if (
Load->getOperand(1).getReg() != BaseReg ||
2287 Load->getOperand(2).getReg() != ShiftedIdxReg ||
2288 !
Load->getOperand(2).isKill())
2302 if (isPositionIndependentOrROPI) {
2303 MachineInstr *
Add =
Load->getNextNode();
2304 if (
Add->getOpcode() != ARM::tADDrr ||
2305 Add->getOperand(2).getReg() != BaseReg ||
2306 Add->getOperand(3).getReg() !=
Load->getOperand(0).getReg() ||
2307 !
Add->getOperand(3).isKill())
2309 if (
Add->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2314 Add->eraseFromParent();
2317 if (
Load->getOperand(0).getReg() !=
MI->getOperand(0).getReg())
2325 CanDeleteLEA =
true;
2326 Shift->eraseFromParent();
2327 Load->eraseFromParent();
2332 MachineInstr *CPEMI =
User.CPEMI;
2333 unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
2335 Opc = ByteOk ? ARM::tTBB_JT : ARM::tTBH_JT;
2338 MachineInstr *NewJTMI =
2347 unsigned JTOpc = ByteOk ? ARM::JUMPTABLE_TBB : ARM::JUMPTABLE_TBH;
2358 User.MI->eraseFromParent();
2359 DeadSize += isThumb2 ? 4 : 2;
2366 User.IsSoImm =
false;
2367 User.KnownAlignment =
false;
2371 int CPEntryIdx = JumpTableEntryIndices[JTI];
2372 auto &CPEs = CPEntries[CPEntryIdx];
2374 find_if(CPEs, [&](CPEntry &
E) {
return E.CPEMI ==
User.CPEMI; });
2376 CPUsers.emplace_back(CPUser(NewJTMI,
User.CPEMI, 4,
false,
false));
2380 unsigned NewSize =
TII->getInstSizeInBytes(*NewJTMI);
2381 unsigned OrigSize =
TII->getInstSizeInBytes(*
MI);
2382 MI->eraseFromParent();
2384 int Delta = OrigSize - NewSize + DeadSize;
2386 BBUtils->adjustBBOffsetsAfter(
MBB);
2397bool ARMConstantIslands::reorderThumb2JumpTables() {
2398 bool MadeChange =
false;
2400 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
2401 if (!MJTI)
return false;
2403 const std::vector<MachineJumpTableEntry> &JT = MJTI->
getJumpTables();
2404 for (MachineInstr *
MI : T2JumpTables) {
2405 const MCInstrDesc &MCID =
MI->getDesc();
2407 unsigned JTOpIdx =
NumOps - (
MI->isPredicable() ? 2 : 1);
2408 MachineOperand JTOP =
MI->getOperand(JTOpIdx);
2415 int JTNumber =
MI->getParent()->getNumber();
2416 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
2417 for (MachineBasicBlock *
MBB : JTBBs) {
2420 if (DTNumber < JTNumber) {
2423 MachineBasicBlock *NewBB =
2424 adjustJTTargetBlockForward(JTI,
MBB,
MI->getParent());
2435MachineBasicBlock *ARMConstantIslands::adjustJTTargetBlockForward(
2436 unsigned JTI, MachineBasicBlock *BB, MachineBasicBlock *JTBB) {
2441 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
2454 if (!
B &&
Cond.empty() && BB != &MF->front() &&
2457 OldPrior->updateTerminator(BB);
2460 MF->RenumberBlocks();
2466 MachineBasicBlock *NewBB =
2469 MF->insert(
MBBI, NewBB);
2472 for (
const MachineBasicBlock::RegisterMaskPair &RegMaskPair : BB->
liveins())
2488 MF->RenumberBlocks(NewBB);
2501 return new ARMConstantIslands();
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
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.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
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.
constexpr RegState getKillRegState(bool B)
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...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
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...
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
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.