40#include "llvm/Config/llvm-config.h"
59#define DEBUG_TYPE "mips-constant-islands"
62STATISTIC(NumSplit,
"Number of uncond branches inserted");
63STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
64STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
67 switch (
MI->getOpcode()) {
76 case Mips::BeqzRxImm16:
77 case Mips::BeqzRxImmX16:
78 case Mips::BnezRxImm16:
79 case Mips::BnezRxImmX16:
92 return Mips::BteqzX16;
95 return Mips::BtnezX16;
98 case Mips::BeqzRxImm16:
99 case Mips::BeqzRxImmX16:
100 return Mips::BeqzRxImmX16;
101 case Mips::BnezRxImm16:
102 case Mips::BnezRxImmX16:
103 return Mips::BnezRxImmX16;
113 unsigned Bits, Scale;
123 case Mips::BeqzRxImm16:
127 case Mips::BeqzRxImmX16:
131 case Mips::BnezRxImm16:
135 case Mips::BnezRxImmX16:
158 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
183 MipsConstantIslandLegacy() : MachineFunctionPass(ID) {}
185 StringRef getPassName()
const override {
return "Mips Constant Islands"; }
189 MachineFunctionProperties getRequiredProperties()
const override {
190 return MachineFunctionProperties().setNoVRegs();
194 class MipsConstantIslandImpl {
197 struct BasicBlockInfo {
216 BasicBlockInfo() =
default;
218 unsigned postOffset()
const {
return Offset + Size; }
221 std::vector<BasicBlockInfo> BBInfo;
226 std::vector<MachineBasicBlock*> WaterList;
230 SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
232 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
249 MachineBasicBlock *HighWaterMark;
253 unsigned LongFormMaxDisp;
255 unsigned LongFormOpcode;
260 CPUser(MachineInstr *mi, MachineInstr *cpemi,
unsigned maxdisp,
262 unsigned longformmaxdisp,
unsigned longformopcode)
263 : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
264 LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
266 HighWaterMark = CPEMI->getParent();
270 unsigned getMaxDisp()
const {
return MaxDisp; }
272 void setMaxDisp(
unsigned val) {
276 unsigned getLongFormMaxDisp()
const {
277 return LongFormMaxDisp;
280 unsigned getLongFormOpcode()
const {
281 return LongFormOpcode;
287 std::vector<CPUser> CPUsers;
297 CPEntry(MachineInstr *cpemi,
unsigned cpi,
unsigned rc = 0)
298 : CPEMI(cpemi), CPI(cpi), RefCount(
rc) {}
306 std::vector<std::vector<CPEntry>> CPEntries;
314 unsigned MaxDisp : 31;
319 ImmBranch(MachineInstr *mi,
unsigned maxdisp,
bool cond,
int ubr)
320 : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
325 std::vector<ImmBranch> ImmBranches;
331 const MipsSubtarget *STI =
nullptr;
332 const Mips16InstrInfo *TII;
333 MipsFunctionInfo *MFI;
335 MachineConstantPool *MCP =
nullptr;
337 unsigned PICLabelUId;
338 bool PrescannedForConstants =
false;
340 void initPICLabelUId(
unsigned UId) { PICLabelUId = UId; }
342 unsigned createPICLabelUId() {
return PICLabelUId++; }
344 void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
345 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
346 Align getCPEAlign(
const MachineInstr &CPEMI);
347 unsigned getMaxDisp(
const CPUser &U)
const {
348 int SmallOffset = STI->getCLOpts().constant_islands_small_offset;
349 return SmallOffset ? SmallOffset :
U.getMaxDisp();
351 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
352 unsigned getOffsetOf(MachineInstr *
MI)
const;
353 unsigned getUserOffset(CPUser&)
const;
356 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
357 unsigned Disp,
bool NegativeOK);
358 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
361 void computeBlockSize(MachineBasicBlock *
MBB);
362 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &
MI);
363 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
364 void adjustBBOffsetsAfter(MachineBasicBlock *BB);
365 bool decrementCPEReferenceCount(
unsigned CPI, MachineInstr* CPEMI);
366 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
367 int findLongFormInRangeCPEntry(CPUser& U,
unsigned UserOffset);
368 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
369 water_iterator &WaterIter);
370 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
371 MachineBasicBlock *&NewMBB);
372 bool handleConstantPoolUser(
unsigned CPUserIndex);
373 void removeDeadCPEMI(MachineInstr *CPEMI);
374 bool removeUnusedCPEntries();
375 bool isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
376 MachineInstr *CPEMI,
unsigned Disp,
bool NegOk,
377 bool DoDump =
false);
378 bool isWaterInRange(
unsigned UserOffset, MachineBasicBlock *Water,
379 CPUser &U,
unsigned &Growth);
380 bool isBBInRange(MachineInstr *
MI, MachineBasicBlock *BB,
unsigned Disp);
381 bool fixupImmediateBr(ImmBranch &Br);
382 bool fixupConditionalBr(ImmBranch &Br);
383 bool fixupUnconditionalBr(ImmBranch &Br);
385 void prescanForConstants();
393char MipsConstantIslandLegacy::ID = 0;
395bool MipsConstantIslandImpl::isOffsetInRange(
unsigned UserOffset,
396 unsigned TrialOffset,
398 return isOffsetInRange(UserOffset, TrialOffset, getMaxDisp(U),
U.NegOk);
401#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
404 for (
unsigned J = 0,
E = BBInfo.size(); J !=
E; ++J) {
405 const BasicBlockInfo &BBI = BBInfo[J];
412bool MipsConstantIslandImpl::runOnMachineFunction(
MachineFunction &mf) {
424 MFI = MF->
getInfo<MipsFunctionInfo>();
431 if (!PrescannedForConstants) prescanForConstants();
441 bool MadeChange =
false;
445 std::vector<MachineInstr*> CPEMIs;
447 doInitialPlacement(CPEMIs);
450 initPICLabelUId(CPEMIs.size());
455 initializeFunctionInfo(CPEMIs);
460 MadeChange |= removeUnusedCPEntries();
464 unsigned NoCPIters = 0, NoBRIters = 0;
467 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
468 bool CPChange =
false;
469 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
470 CPChange |= handleConstantPoolUser(i);
471 if (CPChange && ++NoCPIters > 30)
477 NewWaterList.
clear();
479 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
480 bool BRChange =
false;
481 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
482 BRChange |= fixupImmediateBr(ImmBranches[i]);
483 if (BRChange && ++NoBRIters > 30)
486 if (!CPChange && !BRChange)
503void MipsConstantIslandImpl::doInitialPlacement(
504 std::vector<MachineInstr *> &CPEMIs) {
531 const std::vector<MachineConstantPoolEntry> &CPs = MCP->
getConstants();
534 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
535 unsigned Size = CPs[i].getSizeInBytes(TD);
536 assert(
Size >= 4 &&
"Too small constant pool entry");
543 unsigned LogAlign =
Log2(Alignment);
546 MachineInstr *CPEMI =
550 CPEMIs.push_back(CPEMI);
554 for (
unsigned a = LogAlign + 1; a <=
Log2(MaxAlign); ++a)
555 if (InsPoint[a] == InsAt)
558 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
560 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
572 if (std::next(
MBBI) ==
MBB->getParent()->end())
581MipsConstantIslandImpl::CPEntry *
582MipsConstantIslandImpl::findConstPoolEntry(
unsigned CPI,
583 const MachineInstr *CPEMI) {
584 std::vector<CPEntry> &CPEs = CPEntries[CPI];
587 for (CPEntry &CPE : CPEs) {
588 if (CPE.CPEMI == CPEMI)
596Align MipsConstantIslandImpl::getCPEAlign(
const MachineInstr &CPEMI) {
600 if (!STI->
getCLOpts().align_constant_islands)
604 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
611void MipsConstantIslandImpl::initializeFunctionInfo(
612 const std::vector<MachineInstr *> &CPEMIs) {
620 for (MachineBasicBlock &
MBB : *MF)
621 computeBlockSize(&
MBB);
624 adjustBBOffsetsAfter(&MF->front());
627 for (MachineBasicBlock &
MBB : *MF) {
631 WaterList.push_back(&
MBB);
632 for (MachineInstr &
MI :
MBB) {
633 if (
MI.isDebugInstr())
636 int Opc =
MI.getOpcode();
655 case Mips::BeqzRxImm16:
661 case Mips::BeqzRxImmX16:
667 case Mips::BnezRxImm16:
673 case Mips::BnezRxImmX16:
705 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
706 ImmBranches.push_back(ImmBranch(&
MI, MaxOffs, isCond, UOpc));
709 if (
Opc == Mips::CONSTPOOL_ENTRY)
713 for (
const MachineOperand &MO :
MI.operands())
722 unsigned LongFormBits = 0;
723 unsigned LongFormScale = 0;
724 unsigned LongFormOpcode = 0;
728 case Mips::LwRxPcTcp16:
731 LongFormOpcode = Mips::LwRxPcTcpX16;
735 case Mips::LwRxPcTcpX16:
742 unsigned CPI = MO.getIndex();
743 MachineInstr *CPEMI = CPEMIs[CPI];
744 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
745 unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
746 CPUsers.push_back(CPUser(&
MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
750 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
751 assert(CPE &&
"Cannot find a corresponding CPEntry!");
764void MipsConstantIslandImpl::computeBlockSize(MachineBasicBlock *
MBB) {
768 for (
const MachineInstr &
MI : *
MBB)
775unsigned MipsConstantIslandImpl::getOffsetOf(MachineInstr *
MI)
const {
785 assert(
I !=
MBB->
end() &&
"Didn't find MI in its own basic block?");
795 return LHS->getNumber() <
RHS->getNumber();
801void MipsConstantIslandImpl::updateForInsertedWaterBlock(
802 MachineBasicBlock *NewBB) {
808 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
813 WaterList.insert(IP, NewBB);
816unsigned MipsConstantIslandImpl::getUserOffset(CPUser &U)
const {
817 return getOffsetOf(
U.MI);
824MipsConstantIslandImpl::splitBlockBeforeInstr(MachineInstr &
MI) {
825 MachineBasicBlock *OrigBB =
MI.getParent();
828 MachineBasicBlock *NewBB =
831 MF->insert(
MBBI, NewBB);
852 MF->RenumberBlocks(NewBB);
856 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
863 MachineBasicBlock* WaterBB = *IP;
864 if (WaterBB == OrigBB)
865 WaterList.insert(std::next(IP), NewBB);
867 WaterList.insert(IP, OrigBB);
868 NewWaterList.
insert(OrigBB);
875 computeBlockSize(OrigBB);
879 computeBlockSize(NewBB);
882 adjustBBOffsetsAfter(OrigBB);
890bool MipsConstantIslandImpl::isOffsetInRange(
unsigned UserOffset,
891 unsigned TrialOffset,
894 if (UserOffset <= TrialOffset) {
896 if (TrialOffset - UserOffset <= MaxDisp)
898 }
else if (NegativeOK) {
899 if (UserOffset - TrialOffset <= MaxDisp)
909bool MipsConstantIslandImpl::isWaterInRange(
unsigned UserOffset,
910 MachineBasicBlock *Water, CPUser &U,
912 unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset();
913 unsigned NextBlockOffset;
914 Align NextBlockAlignment;
916 if (NextBlock == MF->end()) {
917 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
918 NextBlockAlignment =
Align(1);
920 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
921 NextBlockAlignment = NextBlock->getAlignment();
923 unsigned Size =
U.CPEMI->getOperand(2).getImm();
924 unsigned CPEEnd = CPEOffset +
Size;
929 if (CPEEnd > NextBlockOffset) {
930 Growth = CPEEnd - NextBlockOffset;
938 if (CPEOffset < UserOffset)
939 UserOffset += Growth;
944 return isOffsetInRange(UserOffset, CPEOffset, U);
949bool MipsConstantIslandImpl::isCPEntryInRange(MachineInstr *
MI,
952 unsigned MaxDisp,
bool NegOk,
954 unsigned CPEOffset = getOffsetOf(CPEMI);
958 unsigned Block =
MI->getParent()->getNumber();
959 const BasicBlockInfo &BBI = BBInfo[
Block];
961 <<
" max delta=" << MaxDisp
962 <<
format(
" insn address=%#x", UserOffset) <<
" in "
965 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
966 int(CPEOffset - UserOffset));
970 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
977 if (
MBB->pred_size() != 1 ||
MBB->succ_size() != 1)
988void MipsConstantIslandImpl::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
990 for(
unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
993 unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
994 BBInfo[i].Offset =
Offset;
1002bool MipsConstantIslandImpl::decrementCPEReferenceCount(
unsigned CPI,
1003 MachineInstr *CPEMI) {
1005 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1006 assert(CPE &&
"Unexpected!");
1007 if (--CPE->RefCount == 0) {
1008 removeDeadCPEMI(CPEMI);
1009 CPE->CPEMI =
nullptr;
1022int MipsConstantIslandImpl::findInRangeCPEntry(CPUser &U,
unsigned UserOffset) {
1023 MachineInstr *UserMI =
U.MI;
1024 MachineInstr *CPEMI =
U.CPEMI;
1027 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, getMaxDisp(U),
U.NegOk,
1035 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1036 for (CPEntry &CPE : CPEs) {
1038 if (CPE.CPEMI == CPEMI)
1041 if (CPE.CPEMI ==
nullptr)
1043 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, getMaxDisp(U),
1045 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1048 U.CPEMI = CPE.CPEMI;
1050 for (MachineOperand &MO : UserMI->
operands())
1052 MO.setIndex(CPE.CPI);
1059 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1073int MipsConstantIslandImpl::findLongFormInRangeCPEntry(CPUser &U,
1074 unsigned UserOffset) {
1075 MachineInstr *UserMI =
U.MI;
1076 MachineInstr *CPEMI =
U.CPEMI;
1079 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
1080 U.getLongFormMaxDisp(),
U.NegOk,
1084 U.setMaxDisp(
U.getLongFormMaxDisp());
1090 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1091 for (CPEntry &CPE : CPEs) {
1093 if (CPE.CPEMI == CPEMI)
1096 if (CPE.CPEMI ==
nullptr)
1098 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getLongFormMaxDisp(),
1100 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1103 U.CPEMI = CPE.CPEMI;
1105 for (MachineOperand &MO : UserMI->
operands())
1107 MO.setIndex(CPE.CPI);
1114 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1125 return ((1<<10)-1)*2;
1127 return ((1<<16)-1)*2;
1131 return ((1<<16)-1)*2;
1142bool MipsConstantIslandImpl::findAvailableWater(CPUser &U,
unsigned UserOffset,
1143 water_iterator &WaterIter) {
1144 if (WaterList.empty())
1147 unsigned BestGrowth = ~0
u;
1148 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1150 MachineBasicBlock* WaterBB = *IP;
1160 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1161 (WaterBB->
getNumber() <
U.HighWaterMark->getNumber() ||
1162 NewWaterList.
count(WaterBB)) && Growth < BestGrowth) {
1164 BestGrowth = Growth;
1167 <<
" Growth=" << Growth <<
'\n');
1170 if (BestGrowth == 0)
1176 return BestGrowth != ~0
u;
1186void MipsConstantIslandImpl::createNewWater(
unsigned CPUserIndex,
1187 unsigned UserOffset,
1188 MachineBasicBlock *&NewMBB) {
1189 CPUser &
U = CPUsers[CPUserIndex];
1190 MachineInstr *UserMI =
U.MI;
1191 MachineInstr *CPEMI =
U.CPEMI;
1192 MachineBasicBlock *UserMBB = UserMI->
getParent();
1193 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1201 unsigned CPEOffset = UserBBI.
postOffset() + Delta;
1203 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1205 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1212 int UncondBr = Mips::Bimm16;
1215 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1216 MaxDisp,
false, UncondBr));
1217 BBInfo[UserMBB->
getNumber()].Size += Delta;
1218 adjustBBOffsetsAfter(UserMBB);
1229 unsigned BaseInsertOffset = UserOffset + getMaxDisp(U);
1236 BaseInsertOffset -= 4;
1239 <<
" la=" <<
Log2(Align) <<
'\n');
1245 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1249 unsigned EndInsertOffset = BaseInsertOffset + 4 +
1253 unsigned CPUIndex = CPUserIndex+1;
1254 unsigned NumCPUsers = CPUsers.size();
1256 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1257 Offset < BaseInsertOffset;
1259 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1260 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI ==
MI) {
1261 CPUser &
U = CPUsers[CPUIndex];
1262 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1264 BaseInsertOffset -=
Align.value();
1265 EndInsertOffset -=
Align.value();
1271 EndInsertOffset +=
U.CPEMI->getOperand(2).getImm();
1276 NewMBB = splitBlockBeforeInstr(*--
MI);
1283bool MipsConstantIslandImpl::handleConstantPoolUser(
unsigned CPUserIndex) {
1284 CPUser &
U = CPUsers[CPUserIndex];
1285 MachineInstr *UserMI =
U.MI;
1286 MachineInstr *CPEMI =
U.CPEMI;
1290 unsigned UserOffset = getUserOffset(U);
1294 int result = findInRangeCPEntry(U, UserOffset);
1295 if (result==1)
return false;
1296 else if (result==2)
return true;
1299 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1300 MachineBasicBlock *NewMBB;
1302 if (findAvailableWater(U, UserOffset, IP)) {
1304 MachineBasicBlock *WaterBB = *IP;
1309 if (NewWaterList.
erase(WaterBB))
1310 NewWaterList.
insert(NewIsland);
1318 if (!STI->
getCLOpts().constant_islands_no_load_relaxation) {
1319 result = findLongFormInRangeCPEntry(U, UserOffset);
1320 if (result != 0)
return true;
1323 createNewWater(CPUserIndex, UserOffset, NewMBB);
1330 MachineBasicBlock *WaterBB = &*--NewMBB->
getIterator();
1332 if (IP != WaterList.end())
1333 NewWaterList.
erase(WaterBB);
1336 NewWaterList.
insert(NewIsland);
1343 if (IP != WaterList.end())
1344 WaterList.erase(IP);
1350 updateForInsertedWaterBlock(NewIsland);
1353 decrementCPEReferenceCount(CPI, CPEMI);
1357 unsigned ID = createPICLabelUId();
1361 U.HighWaterMark = NewIsland;
1364 CPEntries[CPI].push_back(CPEntry(
U.CPEMI, ID, 1));
1372 adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1375 for (MachineOperand &MO : UserMI->
operands())
1382 dbgs() <<
" Moved CPE to #" << ID <<
" CPI=" << CPI
1390void MipsConstantIslandImpl::removeDeadCPEMI(MachineInstr *CPEMI) {
1391 MachineBasicBlock *CPEBB = CPEMI->
getParent();
1396 if (CPEBB->
empty()) {
1406 adjustBBOffsetsAfter(CPEBB);
1416bool MipsConstantIslandImpl::removeUnusedCPEntries() {
1417 unsigned MadeChange =
false;
1418 for (std::vector<CPEntry> &CPEs : CPEntries) {
1419 for (CPEntry &CPE : CPEs) {
1420 if (CPE.RefCount == 0 && CPE.CPEMI) {
1421 removeDeadCPEMI(CPE.CPEMI);
1422 CPE.CPEMI =
nullptr;
1432bool MipsConstantIslandImpl::isBBInRange(MachineInstr *
MI,
1433 MachineBasicBlock *DestBB,
1436 unsigned BrOffset = getOffsetOf(
MI) + PCAdj;
1437 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1441 <<
" max delta=" << MaxDisp <<
" from " << getOffsetOf(
MI)
1442 <<
" to " << DestOffset <<
" offset "
1443 <<
int(DestOffset - BrOffset) <<
"\t" << *
MI);
1445 if (BrOffset <= DestOffset) {
1447 if (DestOffset-BrOffset <= MaxDisp)
1450 if (BrOffset-DestOffset <= MaxDisp)
1458bool MipsConstantIslandImpl::fixupImmediateBr(ImmBranch &Br) {
1459 MachineInstr *
MI = Br.MI;
1461 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1464 if (isBBInRange(
MI, DestBB, Br.MaxDisp))
1468 return fixupUnconditionalBr(Br);
1469 return fixupConditionalBr(Br);
1476bool MipsConstantIslandImpl::fixupUnconditionalBr(ImmBranch &Br) {
1477 MachineInstr *
MI = Br.MI;
1479 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1481 unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2;
1482 if (isBBInRange(
MI, DestBB, BimmX16MaxDisp)) {
1483 Br.MaxDisp = BimmX16MaxDisp;
1484 MI->setDesc(
TII->get(Mips::BimmX16));
1499 Br.MaxDisp = ((1<<24)-1) * 2;
1500 MI->setDesc(
TII->get(Mips::JalB16));
1503 adjustBBOffsetsAfter(
MBB);
1515bool MipsConstantIslandImpl::fixupConditionalBr(ImmBranch &Br) {
1516 MachineInstr *
MI = Br.MI;
1518 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1519 unsigned Opcode =
MI->getOpcode();
1524 if (isBBInRange(
MI, DestBB, LongFormMaxOff)) {
1525 Br.MaxDisp = LongFormMaxOff;
1526 MI->setDesc(
TII->get(LongFormOpcode));
1542 MachineInstr *BMI = &
MBB->
back();
1544 unsigned OppositeBranchOpcode =
TII->getOppositeBranchOpc(Opcode);
1558 MachineBasicBlock *NewDest =
1560 if (isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1562 dbgs() <<
" Invert Bcc condition and swap its destination with "
1564 MI->setDesc(
TII->get(OppositeBranchOpcode));
1566 MI->getOperand(TargetOperand).setMBB(NewDest);
1573 splitBlockBeforeInstr(*
MI);
1576 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1584 <<
" also invert condition and change dest. to "
1589 if (
MI->getNumExplicitOperands() == 2) {
1591 .
addReg(
MI->getOperand(0).getReg())
1602 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1605 BBInfo[
MI->getParent()->getNumber()].Size -=
TII->getInstSizeInBytes(*
MI);
1606 MI->eraseFromParent();
1607 adjustBBOffsetsAfter(
MBB);
1611void MipsConstantIslandImpl::prescanForConstants() {
1612 for (MachineBasicBlock &
B : *MF) {
1613 for (MachineInstr &
MI :
B) {
1614 switch (
MI.getDesc().getOpcode()) {
1615 case Mips::LwConstant32: {
1616 PrescannedForConstants =
true;
1619 MachineOperand &
Literal =
MI.getOperand(1);
1623 Type *Int32Ty = Type::getInt32Ty(MF->getFunction().getContext());
1626 MI.getOperand(2).ChangeToImmediate(index);
1628 MI.setDesc(
TII->get(Mips::LwRxPcTcp16));
1629 MI.removeOperand(1);
1630 MI.removeOperand(1);
1644 return new MipsConstantIslandLegacy();
1647bool MipsConstantIslandLegacy::runOnMachineFunction(
MachineFunction &MF) {
1648 MipsConstantIslandImpl Impl;
1649 return Impl.runOnMachineFunction(MF);
1655 MipsConstantIslandImpl Impl;
1656 return Impl.runOnMachineFunction(MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 bool BBIsJumpedOver(MachineBasicBlock *MBB)
BBIsJumpedOver - Return true of the specified basic block's only predecessor unconditionally branches...
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 contains the declarations for the subclasses of Constant, which represent the different fla...
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static unsigned int longformBranchOpcode(unsigned int Opcode)
static unsigned int branchMaxOffsets(unsigned int Opcode)
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
static unsigned int branchTargetOperand(MachineInstr *MI)
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)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
FunctionPass class - This class is used to implement most global optimizations.
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
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.
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.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic 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
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.
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void ensureAlignment(Align A)
ensureAlignment - Make sure the function is at least A bytes aligned.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
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.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
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 & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateCPI(unsigned Idx, int Offset, unsigned TargetFlags=0)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const MipsInstrInfo * getInstrInfo() const override
bool inMips16Mode() const
const MipsOptions & getCLOpts() const
bool useConstantIslands() const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
self_iterator getIterator()
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This is an optimization pass for GlobalISel generic memory operations.
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.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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)
FunctionPass * createMipsConstantIslandLegacyPass()
Returns a pass that converts branches to long branches.
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...
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
APFloat neg(APFloat X)
Returns the negated value of the argument.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
unsigned Size
Size - Size of the basic block in bytes.
unsigned postOffset(Align Alignment=Align(1)) const
Compute the offset immediately following this block.
unsigned Offset
Offset - Distance from the beginning of the function to the beginning of this basic block.