16 #define DEBUG_TYPE "arm-cp-islands"
39 STATISTIC(NumCPEs,
"Number of constpool entries");
40 STATISTIC(NumSplit,
"Number of uncond branches inserted");
41 STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
42 STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
43 STATISTIC(NumTBs,
"Number of table branches generated");
44 STATISTIC(NumT2CPShrunk,
"Number of Thumb2 constantpool instructions shrunk");
45 STATISTIC(NumT2BrShrunk,
"Number of Thumb2 immediate branches shrunk");
46 STATISTIC(NumCBZ,
"Number of CBZ / CBNZ formed");
47 STATISTIC(NumJTMoved,
"Number of jump table destination blocks moved");
48 STATISTIC(NumJTInserted,
"Number of jump table intermediate blocks inserted");
53 cl::desc(
"Adjust basic block layout to better use TB[BH]"));
58 cl::desc(
"Align constant islands in code"));
66 static inline unsigned UnknownPadding(
unsigned LogAlign,
unsigned KnownBits) {
67 if (KnownBits < LogAlign)
68 return (1u << LogAlign) - (1u << KnownBits);
87 struct BasicBlockInfo {
120 BasicBlockInfo() : Offset(0), Size(0), KnownBits(0), Unalign(0),
126 unsigned internalKnownBits()
const {
127 unsigned Bits = Unalign ? Unalign : KnownBits;
130 if (Size & ((1u << Bits) - 1))
138 unsigned postOffset(
unsigned LogAlign = 0)
const {
139 unsigned PO = Offset + Size;
140 unsigned LA = std::max(
unsigned(PostAlign), LogAlign);
152 unsigned postKnownBits(
unsigned LogAlign = 0)
const {
153 return std::max(std::max(
unsigned(PostAlign), LogAlign),
154 internalKnownBits());
158 std::vector<BasicBlockInfo> BBInfo;
163 std::vector<MachineBasicBlock*> WaterList;
169 typedef std::vector<MachineBasicBlock*>::iterator water_iterator;
194 bool neg,
bool soimm)
195 :
MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm),
196 KnownAlignment(
false) {
197 HighWaterMark = CPEMI->getParent();
202 unsigned getMaxDisp()
const {
203 return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
209 std::vector<CPUser> CPUsers;
218 CPEntry(
MachineInstr *cpemi,
unsigned cpi,
unsigned rc = 0)
219 : CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
227 std::vector<std::vector<CPEntry> > CPEntries;
235 unsigned MaxDisp : 31;
238 ImmBranch(
MachineInstr *mi,
unsigned maxdisp,
bool cond,
int ubr)
239 :
MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
244 std::vector<ImmBranch> ImmBranches;
271 virtual const char *getPassName()
const {
272 return "ARM constant island placement and branch shortening pass";
276 void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
277 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
279 void scanFunctionJumpTables();
280 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
284 bool decrementCPEReferenceCount(
unsigned CPI,
MachineInstr* CPEMI);
285 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
286 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
287 water_iterator &WaterIter);
288 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
290 bool handleConstantPoolUser(
unsigned CPUserIndex);
292 bool removeUnusedCPEntries();
295 bool DoDump =
false);
297 CPUser &U,
unsigned &Growth);
299 bool fixupImmediateBr(ImmBranch &Br);
300 bool fixupConditionalBr(ImmBranch &Br);
301 bool fixupUnconditionalBr(ImmBranch &Br);
302 bool undoLRSpillRestore();
304 bool optimizeThumb2Instructions();
305 bool optimizeThumb2Branches();
306 bool reorderThumb2JumpTables();
307 bool optimizeThumb2JumpTables();
313 unsigned getUserOffset(CPUser&)
const;
317 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
318 unsigned Disp,
bool NegativeOK,
bool IsSoImm =
false);
319 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
321 return isOffsetInRange(UserOffset, TrialOffset,
322 U.getMaxDisp(), U.NegOk, U.IsSoImm);
335 assert(!MBBId || BBInfo[MBBId - 1].postOffset() <= BBInfo[MBBId].Offset);
337 DEBUG(
dbgs() <<
"Verifying " << CPUsers.size() <<
" CP users.\n");
338 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i) {
339 CPUser &U = CPUsers[i];
340 unsigned UserOffset = getUserOffset(U);
343 if (isCPEntryInRange(U.MI, UserOffset, U.CPEMI, U.getMaxDisp()+2, U.NegOk,
357 void ARMConstantIslands::dumpBBs() {
359 for (
unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
360 const BasicBlockInfo &BBI = BBInfo[J];
361 dbgs() <<
format(
"%08x BB#%u\t", BBI.Offset, J)
362 <<
" kb=" <<
unsigned(BBI.KnownBits)
364 <<
" pa=" <<
unsigned(BBI.PostAlign)
365 <<
format(
" size=%#x\n", BBInfo[J].Size);
373 return new ARMConstantIslands();
380 DEBUG(
dbgs() <<
"***** ARMConstantIslands: "
381 << MCP->getConstants().size() <<
" CP entries, aligned to "
382 << MCP->getConstantPoolAlignment() <<
" bytes *****\n");
388 isThumb = AFI->isThumbFunction();
389 isThumb1 = AFI->isThumb1OnlyFunction();
390 isThumb2 = AFI->isThumb2Function();
395 MF->getRegInfo().invalidateLiveness();
399 MF->RenumberBlocks();
403 bool MadeChange =
false;
405 scanFunctionJumpTables();
406 MadeChange |= reorderThumb2JumpTables();
408 T2JumpTables.clear();
410 MF->RenumberBlocks();
418 MF->ensureAlignment(2);
422 std::vector<MachineInstr*> CPEMIs;
424 doInitialPlacement(CPEMIs);
427 AFI->initPICLabelUId(CPEMIs.size());
432 initializeFunctionInfo(CPEMIs);
438 MadeChange |= removeUnusedCPEntries();
442 unsigned NoCPIters = 0, NoBRIters = 0;
444 DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
445 bool CPChange =
false;
446 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
447 CPChange |= handleConstantPoolUser(i);
448 if (CPChange && ++NoCPIters > 30)
454 NewWaterList.clear();
456 DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
457 bool BRChange =
false;
458 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
459 BRChange |= fixupImmediateBr(ImmBranches[i]);
460 if (BRChange && ++NoBRIters > 30)
464 if (!CPChange && !BRChange)
470 if (isThumb2 && !STI->prefers32BitThumb())
471 MadeChange |= optimizeThumb2Instructions();
478 if (isThumb && !HasFarJump && AFI->isLRSpilledForFarJump())
479 MadeChange |= undoLRSpillRestore();
482 for (
unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
483 for (
unsigned j = 0, je = CPEntries[i].size(); j != je; ++j) {
484 const CPEntry & CPE = CPEntries[i][j];
485 AFI->recordCPEClone(i, CPE.CPI);
497 T2JumpTables.clear();
505 ARMConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
511 unsigned MaxAlign =
Log2_32(MCP->getConstantPoolAlignment());
529 const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants();
531 const DataLayout &
TD = *MF->getTarget().getDataLayout();
532 for (
unsigned i = 0, e = CPs.
size(); i != e; ++i) {
534 assert(Size >= 4 &&
"Too small constant pool entry");
535 unsigned Align = CPs[i].getAlignment();
539 assert((Size % Align) == 0 &&
"CP Entry not multiple of 4 bytes!");
542 unsigned LogAlign =
Log2_32(Align);
547 CPEMIs.push_back(CPEMI);
551 for (
unsigned a = LogAlign + 1; a <= MaxAlign; ++a)
552 if (InsPoint[a] == InsAt)
556 std::vector<CPEntry> CPEs;
557 CPEs.push_back(CPEntry(CPEMI, i));
558 CPEntries.push_back(CPEs);
560 DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
561 << Size <<
", align = " << Align <<
'\n');
586 ARMConstantIslands::CPEntry
587 *ARMConstantIslands::findConstPoolEntry(
unsigned CPI,
589 std::vector<CPEntry> &CPEs = CPEntries[CPI];
592 for (
unsigned i = 0, e = CPEs.size(); i != e; ++i) {
593 if (CPEs[i].CPEMI == CPEMI)
601 unsigned ARMConstantIslands::getCPELogAlign(
const MachineInstr *CPEMI) {
602 assert(CPEMI && CPEMI->
getOpcode() == ARM::CONSTPOOL_ENTRY);
609 assert(CPI < MCP->getConstants().size() &&
"Invalid constant pool index.");
610 unsigned Align = MCP->getConstants()[CPI].getAlignment();
618 void ARMConstantIslands::scanFunctionJumpTables() {
625 if (
I->isBranch() &&
I->getOpcode() == ARM::t2BR_JT)
633 void ARMConstantIslands::
634 initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
636 BBInfo.resize(MF->getNumBlockIDs());
647 BBInfo.front().KnownBits = MF->getAlignment();
650 adjustBBOffsetsAfter(MF->begin());
664 if (
I->isDebugValue())
667 int Opc =
I->getOpcode();
677 T2JumpTables.push_back(
I);
710 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
711 ImmBranches.push_back(ImmBranch(
I, MaxOffs, isCond, UOpc));
714 if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET)
715 PushPopMIs.push_back(
I);
717 if (Opc == ARM::CONSTPOOL_ENTRY)
721 for (
unsigned op = 0, e =
I->getNumOperands(); op != e; ++op)
722 if (
I->getOperand(op).isCPI()) {
730 bool IsSoImm =
false;
747 case ARM::t2LEApcrel:
778 unsigned CPI =
I->getOperand(op).getIndex();
780 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
781 CPUsers.push_back(CPUser(
I, CPEMI, MaxOffs, NegOk, IsSoImm));
784 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
785 assert(CPE &&
"Cannot find a corresponding CPEntry!");
799 BasicBlockInfo &BBI = BBInfo[MBB->
getNumber()];
806 BBI.Size += TII->GetInstSizeInBytes(
I);
809 if (
I->isInlineAsm())
810 BBI.Unalign = isThumb ? 1 : 2;
812 else if (isThumb && mayOptimizeThumb2Instruction(
I))
826 unsigned ARMConstantIslands::getOffsetOf(
MachineInstr *
MI)
const {
832 unsigned Offset = BBInfo[MBB->
getNumber()].Offset;
836 assert(
I != MBB->
end() &&
"Didn't find MI in its own basic block?");
837 Offset += TII->GetInstSizeInBytes(
I);
858 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
863 std::lower_bound(WaterList.begin(), WaterList.end(), NewBB,
865 WaterList.insert(IP, NewBB);
888 unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
905 MF->RenumberBlocks(NewBB);
909 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
916 std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB,
919 if (WaterBB == OrigBB)
922 WaterList.insert(IP, OrigBB);
923 NewWaterList.insert(OrigBB);
930 computeBlockSize(OrigBB);
934 computeBlockSize(NewBB);
937 adjustBBOffsetsAfter(OrigBB);
945 unsigned ARMConstantIslands::getUserOffset(CPUser &U)
const {
946 unsigned UserOffset = getOffsetOf(U.MI);
947 const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];
948 unsigned KnownBits = BBI.internalKnownBits();
951 UserOffset += (isThumb ? 4 : 8);
955 U.KnownAlignment = (KnownBits >= 2);
960 if (isThumb && U.KnownAlignment)
972 bool ARMConstantIslands::isOffsetInRange(
unsigned UserOffset,
973 unsigned TrialOffset,
unsigned MaxDisp,
974 bool NegativeOK,
bool IsSoImm) {
975 if (UserOffset <= TrialOffset) {
977 if (TrialOffset - UserOffset <= MaxDisp)
980 }
else if (NegativeOK) {
981 if (UserOffset - TrialOffset <= MaxDisp)
992 bool ARMConstantIslands::isWaterInRange(
unsigned UserOffset,
995 unsigned CPELogAlign = getCPELogAlign(U.CPEMI);
996 unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset(CPELogAlign);
997 unsigned NextBlockOffset, NextBlockAlignment;
999 if (++NextBlock == MF->end()) {
1000 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
1001 NextBlockAlignment = 0;
1003 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
1004 NextBlockAlignment = NextBlock->getAlignment();
1006 unsigned Size = U.CPEMI->getOperand(2).getImm();
1007 unsigned CPEEnd = CPEOffset + Size;
1012 if (CPEEnd > NextBlockOffset) {
1013 Growth = CPEEnd - NextBlockOffset;
1021 if (CPEOffset < UserOffset)
1022 UserOffset += Growth +
UnknownPadding(MF->getAlignment(), CPELogAlign);
1027 return isOffsetInRange(UserOffset, CPEOffset, U);
1032 bool ARMConstantIslands::isCPEntryInRange(
MachineInstr *MI,
unsigned UserOffset,
1034 bool NegOk,
bool DoDump) {
1035 unsigned CPEOffset = getOffsetOf(CPEMI);
1040 const BasicBlockInfo &BBI = BBInfo[Block];
1042 <<
" max delta=" << MaxDisp
1043 <<
format(
" insn address=%#x", UserOffset)
1044 <<
" in BB#" << Block <<
": "
1045 <<
format(
"%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI
1046 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
1047 int(CPEOffset-UserOffset));
1051 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
1073 for(
unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
1076 unsigned LogAlign = MF->getBlockNumbered(i)->getAlignment();
1077 unsigned Offset = BBInfo[i - 1].postOffset(LogAlign);
1078 unsigned KnownBits = BBInfo[i - 1].postKnownBits(LogAlign);
1083 if (i > BBNum + 2 &&
1084 BBInfo[i].Offset == Offset &&
1085 BBInfo[i].KnownBits == KnownBits)
1088 BBInfo[i].Offset = Offset;
1089 BBInfo[i].KnownBits = KnownBits;
1098 bool ARMConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
1101 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1102 assert(CPE &&
"Unexpected!");
1103 if (--CPE->RefCount == 0) {
1104 removeDeadCPEMI(CPEMI);
1118 int ARMConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset)
1124 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
1132 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1133 for (
unsigned i = 0, e = CPEs.size(); i != e; ++i) {
1135 if (CPEs[i].CPEMI == CPEMI)
1138 if (CPEs[i].CPEMI == NULL)
1140 if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(),
1142 DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#"
1143 << CPEs[i].CPI <<
"\n");
1145 U.CPEMI = CPEs[i].CPEMI;
1156 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1167 return ((1<<10)-1)*2;
1169 return ((1<<23)-1)*2;
1174 return ((1<<23)-1)*4;
1185 bool ARMConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1186 water_iterator &WaterIter) {
1187 if (WaterList.empty())
1190 unsigned BestGrowth = ~0u;
1191 for (water_iterator IP =
prior(WaterList.end()), B = WaterList.begin();;
1203 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1204 (WaterBB->
getNumber() < U.HighWaterMark->getNumber() ||
1205 NewWaterList.count(WaterBB)) && Growth < BestGrowth) {
1207 BestGrowth = Growth;
1210 <<
" Growth=" << Growth <<
'\n');
1213 if (BestGrowth == 0)
1219 return BestGrowth != ~0u;
1229 void ARMConstantIslands::createNewWater(
unsigned CPUserIndex,
1230 unsigned UserOffset,
1232 CPUser &U = CPUsers[CPUserIndex];
1235 unsigned CPELogAlign = getCPELogAlign(CPEMI);
1237 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1245 unsigned Delta = isThumb1 ? 2 : 4;
1247 unsigned CPEOffset = UserBBI.postOffset(CPELogAlign) + Delta;
1249 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1251 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1258 int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) :
ARM::B;
1265 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1266 MaxDisp,
false, UncondBr));
1267 BBInfo[UserMBB->
getNumber()].Size += Delta;
1268 adjustBBOffsetsAfter(UserMBB);
1288 unsigned LogAlign = MF->getAlignment();
1289 assert(LogAlign >= CPELogAlign &&
"Over-aligned constant pool entry");
1290 unsigned KnownBits = UserBBI.internalKnownBits();
1292 unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;
1299 BaseInsertOffset -= 4;
1302 <<
" la=" << LogAlign
1303 <<
" kb=" << KnownBits
1304 <<
" up=" << UPad <<
'\n');
1310 if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {
1311 BaseInsertOffset = UserBBI.postOffset() - UPad - 8;
1312 DEBUG(
dbgs() <<
format(
"Move inside block: %#x\n", BaseInsertOffset));
1314 unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
1318 unsigned CPUIndex = CPUserIndex+1;
1319 unsigned NumCPUsers = CPUsers.size();
1321 for (
unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI);
1322 Offset < BaseInsertOffset;
1323 Offset += TII->GetInstSizeInBytes(MI),
1325 assert(MI != UserMBB->
end() &&
"Fell off end of block");
1326 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
1327 CPUser &U = CPUsers[CPUIndex];
1328 if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
1330 BaseInsertOffset -= 1u << LogAlign;
1331 EndInsertOffset -= 1u << LogAlign;
1337 EndInsertOffset += U.CPEMI->getOperand(2).getImm();
1342 if (MI->getOpcode() == ARM::t2IT)
1350 unsigned PredReg = 0;
1355 NewMBB = splitBlockBeforeInstr(MI);
1362 bool ARMConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex) {
1363 CPUser &U = CPUsers[CPUserIndex];
1369 unsigned UserOffset = getUserOffset(U);
1373 int result = findInRangeCPEntry(U, UserOffset);
1374 if (result==1)
return false;
1375 else if (result==2)
return true;
1379 unsigned ID = AFI->createPICLabelUId();
1385 if (findAvailableWater(U, UserOffset, IP)) {
1386 DEBUG(
dbgs() <<
"Found water in range\n");
1392 if (NewWaterList.erase(WaterBB))
1393 NewWaterList.
insert(NewIsland);
1401 createNewWater(CPUserIndex, UserOffset, NewMBB);
1409 IP = std::find(WaterList.begin(), WaterList.end(), WaterBB);
1410 if (IP != WaterList.end())
1411 NewWaterList.erase(WaterBB);
1414 NewWaterList.insert(NewIsland);
1421 if (IP != WaterList.end())
1422 WaterList.erase(IP);
1425 MF->insert(NewMBB, NewIsland);
1428 updateForInsertedWaterBlock(NewIsland);
1431 decrementCPEReferenceCount(CPI, CPEMI);
1435 U.HighWaterMark = NewIsland;
1438 CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
1445 BBInfo[NewIsland->
getNumber()].Size += Size;
1455 DEBUG(
dbgs() <<
" Moved CPE to #" << ID <<
" CPI=" << CPI
1463 void ARMConstantIslands::removeDeadCPEMI(
MachineInstr *CPEMI) {
1467 BBInfo[CPEBB->
getNumber()].Size -= Size;
1469 if (CPEBB->
empty()) {
1478 adjustBBOffsetsAfter(CPEBB);
1488 bool ARMConstantIslands::removeUnusedCPEntries() {
1489 unsigned MadeChange =
false;
1490 for (
unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
1491 std::vector<CPEntry> &CPEs = CPEntries[i];
1492 for (
unsigned j = 0, ee = CPEs.size(); j != ee; ++j) {
1493 if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) {
1494 removeDeadCPEMI(CPEs[j].CPEMI);
1495 CPEs[j].CPEMI = NULL;
1507 unsigned PCAdj = isThumb ? 4 : 8;
1508 unsigned BrOffset = getOffsetOf(MI) + PCAdj;
1509 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1513 <<
" max delta=" << MaxDisp
1514 <<
" from " << getOffsetOf(MI) <<
" to " << DestOffset
1515 <<
" offset " << int(DestOffset-BrOffset) <<
"\t" << *
MI);
1517 if (BrOffset <= DestOffset) {
1519 if (DestOffset-BrOffset <= MaxDisp)
1522 if (BrOffset-DestOffset <= MaxDisp)
1530 bool ARMConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1535 if (isBBInRange(MI, DestBB, Br.MaxDisp))
1539 return fixupUnconditionalBr(Br);
1540 return fixupConditionalBr(Br);
1548 ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1555 Br.MaxDisp = (1 << 21) * 2;
1556 MI->
setDesc(TII->get(ARM::tBfar));
1558 adjustBBOffsetsAfter(MBB);
1562 DEBUG(
dbgs() <<
" Changed B to long jump " << *MI);
1571 ARMConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1605 if (isBBInRange(MI, NewDest, Br.MaxDisp)) {
1606 DEBUG(
dbgs() <<
" Invert Bcc condition and swap its destination with "
1617 splitBlockBeforeInstr(MI);
1620 int delta = TII->GetInstSizeInBytes(&MBB->
back());
1628 <<
" also invert condition and change dest. to BB#"
1635 Br.MI = &MBB->
back();
1636 BBInfo[MBB->
getNumber()].Size += TII->GetInstSizeInBytes(&MBB->
back());
1642 BBInfo[MBB->
getNumber()].Size += TII->GetInstSizeInBytes(&MBB->
back());
1644 ImmBranches.push_back(ImmBranch(&MBB->
back(), MaxDisp,
false, Br.UncondBr));
1649 adjustBBOffsetsAfter(MBB);
1656 bool ARMConstantIslands::undoLRSpillRestore() {
1657 bool MadeChange =
false;
1658 for (
unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
1678 ARMConstantIslands::mayOptimizeThumb2Instruction(
const MachineInstr *MI)
const {
1681 case ARM::t2LEApcrel:
1694 bool ARMConstantIslands::optimizeThumb2Instructions() {
1695 bool MadeChange =
false;
1698 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i) {
1699 CPUser &U = CPUsers[i];
1700 unsigned Opcode = U.MI->getOpcode();
1701 unsigned NewOpc = 0;
1706 case ARM::t2LEApcrel:
1708 NewOpc = ARM::tLEApcrel;
1715 NewOpc = ARM::tLDRpci;
1725 unsigned UserOffset = getUserOffset(U);
1726 unsigned MaxOffs = ((1 <<
Bits) - 1) * Scale;
1729 if (!U.KnownAlignment)
1733 if (isCPEntryInRange(U.MI, UserOffset, U.CPEMI, MaxOffs,
false,
true)) {
1735 U.MI->setDesc(TII->get(NewOpc));
1738 adjustBBOffsetsAfter(MBB);
1744 MadeChange |= optimizeThumb2Branches();
1745 MadeChange |= optimizeThumb2JumpTables();
1749 bool ARMConstantIslands::optimizeThumb2Branches() {
1750 bool MadeChange =
false;
1752 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
1753 ImmBranch &Br = ImmBranches[i];
1754 unsigned Opcode = Br.MI->getOpcode();
1755 unsigned NewOpc = 0;
1773 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
1775 if (isBBInRange(Br.MI, DestBB, MaxOffs)) {
1776 DEBUG(
dbgs() <<
"Shrink branch: " << *Br.MI);
1777 Br.MI->setDesc(TII->get(NewOpc));
1780 adjustBBOffsetsAfter(MBB);
1786 Opcode = Br.MI->getOpcode();
1787 if (Opcode != ARM::tBcc)
1792 if (!Br.MI->killsRegister(ARM::CPSR))
1796 unsigned PredReg = 0;
1801 NewOpc = ARM::tCBNZ;
1807 unsigned BrOffset = getOffsetOf(Br.MI) + 4 - 2;
1808 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1809 if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) {
1811 if (CmpMI != Br.MI->getParent()->begin()) {
1813 if (CmpMI->getOpcode() == ARM::tCMPi8) {
1814 unsigned Reg = CmpMI->getOperand(0).getReg();
1817 CmpMI->getOperand(1).getImm() == 0 &&
1820 DEBUG(
dbgs() <<
"Fold: " << *CmpMI <<
" and: " << *Br.MI);
1822 BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc))
1823 .addReg(Reg).
addMBB(DestBB,Br.MI->getOperand(0).getTargetFlags());
1825 Br.MI->eraseFromParent();
1828 adjustBBOffsetsAfter(MBB);
1842 bool ARMConstantIslands::optimizeThumb2JumpTables() {
1843 bool MadeChange =
false;
1848 if (MJTI == 0)
return false;
1850 const std::vector<MachineJumpTableEntry> &JT = MJTI->
getJumpTables();
1851 for (
unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) {
1855 unsigned JTOpIdx = NumOps - (MI->
isPredicable() ? 3 : 2);
1858 assert(JTI < JT.size());
1861 bool HalfWordOk =
true;
1862 unsigned JTOffset = getOffsetOf(MI) + 4;
1863 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1864 for (
unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) {
1866 unsigned DstOffset = BBInfo[MBB->
getNumber()].Offset;
1869 if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2)
1871 unsigned TBHLimit = ((1<<16)-1)*2;
1872 if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit)
1874 if (!ByteOk && !HalfWordOk)
1878 if (ByteOk || HalfWordOk) {
1892 while (PrevI != B && !PrevI->definesRegister(BaseReg))
1897 if (!PrevI->definesRegister(BaseReg))
1905 for (
unsigned k = 0, eee = AddrMI->
getNumOperands(); k != eee; ++k) {
1923 for (--PrevI; PrevI != B && !PrevI->definesRegister(BaseReg); --PrevI)
1929 if ((LeaMI->
getOpcode() != ARM::tLEApcrelJT &&
1930 LeaMI->
getOpcode() != ARM::t2LEApcrelJT) ||
1937 DEBUG(
dbgs() <<
"Shrink JT: " << *MI <<
" addr: " << *AddrMI
1938 <<
" lea: " << *LeaMI);
1939 unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
1942 .addJumpTableIndex(JTI, JTOP.getTargetFlags())
1947 unsigned NewSize = TII->GetInstSizeInBytes(NewJTMI);
1948 unsigned OrigSize = TII->GetInstSizeInBytes(AddrMI);
1949 OrigSize += TII->GetInstSizeInBytes(LeaMI);
1950 OrigSize += TII->GetInstSizeInBytes(MI);
1956 int delta = OrigSize - NewSize;
1958 adjustBBOffsetsAfter(MBB);
1970 bool ARMConstantIslands::reorderThumb2JumpTables() {
1971 bool MadeChange =
false;
1974 if (MJTI == 0)
return false;
1976 const std::vector<MachineJumpTableEntry> &JT = MJTI->
getJumpTables();
1977 for (
unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) {
1981 unsigned JTOpIdx = NumOps - (MI->
isPredicable() ? 3 : 2);
1983 unsigned JTI = JTOP.getIndex();
1984 assert(JTI < JT.size());
1990 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1991 for (
unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) {
1995 if (DTNumber < JTNumber) {
1999 adjustJTTargetBlockForward(MBB, MI->
getParent());
2023 bool B = TII->AnalyzeBranch(*BB, TBB, FBB, Cond);
2028 if (!B && Cond.
empty() && BB != MF->
begin() &&
2029 !TII->AnalyzeBranch(*OldPrior, TBB, FBB, CondPrior)) {
2031 OldPrior->updateTerminator();
2034 MF->RenumberBlocks();
2048 assert (isThumb2 &&
"Adjusting for TB[BH] but not in Thumb2?");
2053 MF->RenumberBlocks(NewBB);
unsigned succ_size() const
const MachineFunction * getParent() const
The machine constant pool.
MachineBasicBlock * getMBB() const
bool isPredicable(QueryType Type=AllInBundle) const
const MCInstrDesc & getDesc() const
void moveAfter(MachineBasicBlock *NewBefore)
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
void setAlignment(unsigned Align)
bool ReplaceMBBInJumpTable(unsigned Idx, MachineBasicBlock *Old, MachineBasicBlock *New)
ARMCC::CondCodes getITInstrPredicate(const MachineInstr *MI, unsigned &PredReg)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
static bool CompareMBBNumbers(const MachineBasicBlock *LHS, const MachineBasicBlock *RHS)
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const HexagonInstrInfo * TII
#define llvm_unreachable(msg)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
std::vector< MachineBasicBlock * >::iterator succ_iterator
ID
LLVM Calling Convention Representation.
const MachineInstrBuilder & addImm(int64_t Val) const
unsigned getNumOperands() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
format_object1< T > format(const char *Fmt, const T &Val)
FunctionPass * createARMConstantIslandPass()
static bool BBHasFallthrough(MachineBasicBlock *MBB)
void transferSuccessors(MachineBasicBlock *fromMBB)
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
enable_if_c< std::numeric_limits< T >::is_integer &&!std::numeric_limits< T >::is_signed, std::size_t >::type countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
void RenumberBlocks(MachineBasicBlock *MBBFrom=0)
STATISTIC(NumCPEs,"Number of constpool entries")
unsigned getKillRegState(bool B)
const BasicBlock * getBasicBlock() const
const MachineBasicBlock * getParent() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg)
const MachineOperand & getOperand(unsigned i) const
static cl::opt< bool > AlignConstantIslands("arm-align-constant-islands", cl::Hidden, cl::init(true), cl::desc("Align constant islands in code"))
void ensureAlignment(unsigned A)
ensureAlignment - Make sure the function is at least 1 << A bytes aligned.
void setMBB(MachineBasicBlock *MBB)
unsigned getNumExplicitOperands() const
ItTy next(ItTy it, Dist n)
static bool BBIsJumpedOver(MachineBasicBlock *MBB)
void setImm(int64_t immVal)
static unsigned UnknownPadding(unsigned LogAlign, unsigned KnownBits)
MachineConstantPool * getConstantPool()
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
succ_iterator succ_begin()
void removeSuccessor(MachineBasicBlock *succ)
pred_iterator pred_begin()
void setDesc(const MCInstrDesc &tid)
uint64_t getTypeAllocSize(Type *Ty) const
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]"))
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
unsigned Log2_32(uint32_t Value)
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, MDNode *InlinedAt=0)
static bool isARMLowRegister(unsigned Reg)
static CondCodes getOppositeCondition(CondCodes CC)
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned char TargetFlags=0) const
void push_back(MachineInstr *MI)
instr_iterator insert(instr_iterator I, MachineInstr *M)
static unsigned getUnconditionalBrDisp(int Opc)
unsigned getReg() const
getReg - Returns the register number.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction. Note that variadic (isVari...
uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align)
BasicBlockListType::iterator iterator
ItTy prior(ItTy it, Dist n)
bool isPowerOf2_32(uint32_t Value)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
void addSuccessor(MachineBasicBlock *succ, uint32_t weight=0)
unsigned pred_size() const
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
DebugLoc getDebugLoc() const
unsigned getAlignment() const