38#include "llvm/Config/llvm-config.h"
56#define DEBUG_TYPE "mips-constant-islands"
59STATISTIC(NumSplit,
"Number of uncond branches inserted");
60STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
61STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
64 switch (
MI->getOpcode()) {
73 case Mips::BeqzRxImm16:
74 case Mips::BeqzRxImmX16:
75 case Mips::BnezRxImm16:
76 case Mips::BnezRxImmX16:
89 return Mips::BteqzX16;
92 return Mips::BtnezX16;
95 case Mips::BeqzRxImm16:
96 case Mips::BeqzRxImmX16:
97 return Mips::BeqzRxImmX16;
98 case Mips::BnezRxImm16:
99 case Mips::BnezRxImmX16:
100 return Mips::BnezRxImmX16;
110 unsigned Bits, Scale;
120 case Mips::BeqzRxImm16:
124 case Mips::BeqzRxImmX16:
128 case Mips::BnezRxImm16:
132 case Mips::BnezRxImmX16:
155 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
179 struct BasicBlockInfo {
198 BasicBlockInfo() =
default;
200 unsigned postOffset()
const {
return Offset + Size; }
203 std::vector<BasicBlockInfo> BBInfo;
208 std::vector<MachineBasicBlock*> WaterList;
212 SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
214 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
231 MachineBasicBlock *HighWaterMark;
235 unsigned LongFormMaxDisp;
237 unsigned LongFormOpcode;
242 CPUser(MachineInstr *mi, MachineInstr *cpemi,
unsigned maxdisp,
244 unsigned longformmaxdisp,
unsigned longformopcode)
245 : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
246 LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
248 HighWaterMark = CPEMI->getParent();
252 unsigned getMaxDisp()
const {
return MaxDisp; }
254 void setMaxDisp(
unsigned val) {
258 unsigned getLongFormMaxDisp()
const {
259 return LongFormMaxDisp;
262 unsigned getLongFormOpcode()
const {
263 return LongFormOpcode;
269 std::vector<CPUser> CPUsers;
279 CPEntry(MachineInstr *cpemi,
unsigned cpi,
unsigned rc = 0)
280 : CPEMI(cpemi), CPI(cpi), RefCount(
rc) {}
288 std::vector<std::vector<CPEntry>> CPEntries;
296 unsigned MaxDisp : 31;
301 ImmBranch(MachineInstr *mi,
unsigned maxdisp,
bool cond,
int ubr)
302 : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
307 std::vector<ImmBranch> ImmBranches;
313 const MipsSubtarget *STI =
nullptr;
314 const Mips16InstrInfo *TII;
315 MipsFunctionInfo *MFI;
317 MachineConstantPool *MCP =
nullptr;
319 unsigned PICLabelUId;
320 bool PrescannedForConstants =
false;
322 void initPICLabelUId(
unsigned UId) {
326 unsigned createPICLabelUId() {
327 return PICLabelUId++;
333 MipsConstantIslands() : MachineFunctionPass(ID) {}
335 StringRef getPassName()
const override {
return "Mips Constant Islands"; }
339 MachineFunctionProperties getRequiredProperties()
const override {
340 return MachineFunctionProperties().setNoVRegs();
343 void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
344 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
345 Align getCPEAlign(
const MachineInstr &CPEMI);
346 unsigned getMaxDisp(
const CPUser &U)
const {
347 int SmallOffset = STI->getCLOpts().constant_islands_small_offset;
348 return SmallOffset ? SmallOffset :
U.getMaxDisp();
350 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
351 unsigned getOffsetOf(MachineInstr *
MI)
const;
352 unsigned getUserOffset(CPUser&)
const;
355 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
356 unsigned Disp,
bool NegativeOK);
357 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
360 void computeBlockSize(MachineBasicBlock *
MBB);
361 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &
MI);
362 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
363 void adjustBBOffsetsAfter(MachineBasicBlock *BB);
364 bool decrementCPEReferenceCount(
unsigned CPI, MachineInstr* CPEMI);
365 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
366 int findLongFormInRangeCPEntry(CPUser& U,
unsigned UserOffset);
367 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
368 water_iterator &WaterIter);
369 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
370 MachineBasicBlock *&NewMBB);
371 bool handleConstantPoolUser(
unsigned CPUserIndex);
372 void removeDeadCPEMI(MachineInstr *CPEMI);
373 bool removeUnusedCPEntries();
374 bool isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
375 MachineInstr *CPEMI,
unsigned Disp,
bool NegOk,
376 bool DoDump =
false);
377 bool isWaterInRange(
unsigned UserOffset, MachineBasicBlock *Water,
378 CPUser &U,
unsigned &Growth);
379 bool isBBInRange(MachineInstr *
MI, MachineBasicBlock *BB,
unsigned Disp);
380 bool fixupImmediateBr(ImmBranch &Br);
381 bool fixupConditionalBr(ImmBranch &Br);
382 bool fixupUnconditionalBr(ImmBranch &Br);
384 void prescanForConstants();
389char MipsConstantIslands::ID = 0;
391bool MipsConstantIslands::isOffsetInRange
392 (
unsigned UserOffset,
unsigned TrialOffset,
394 return isOffsetInRange(UserOffset, TrialOffset, getMaxDisp(U),
U.NegOk);
397#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
400 for (
unsigned J = 0,
E = BBInfo.size(); J !=
E; ++J) {
401 const BasicBlockInfo &BBI = BBInfo[J];
420 MFI = MF->
getInfo<MipsFunctionInfo>();
427 if (!PrescannedForConstants) prescanForConstants();
437 bool MadeChange =
false;
441 std::vector<MachineInstr*> CPEMIs;
443 doInitialPlacement(CPEMIs);
446 initPICLabelUId(CPEMIs.size());
451 initializeFunctionInfo(CPEMIs);
456 MadeChange |= removeUnusedCPEntries();
460 unsigned NoCPIters = 0, NoBRIters = 0;
463 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
464 bool CPChange =
false;
465 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
466 CPChange |= handleConstantPoolUser(i);
467 if (CPChange && ++NoCPIters > 30)
473 NewWaterList.
clear();
475 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
476 bool BRChange =
false;
477 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
478 BRChange |= fixupImmediateBr(ImmBranches[i]);
479 if (BRChange && ++NoBRIters > 30)
482 if (!CPChange && !BRChange)
500MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
527 const std::vector<MachineConstantPoolEntry> &CPs = MCP->
getConstants();
530 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
531 unsigned Size = CPs[i].getSizeInBytes(TD);
532 assert(
Size >= 4 &&
"Too small constant pool entry");
539 unsigned LogAlign =
Log2(Alignment);
542 MachineInstr *CPEMI =
546 CPEMIs.push_back(CPEMI);
550 for (
unsigned a = LogAlign + 1; a <=
Log2(MaxAlign); ++a)
551 if (InsPoint[a] == InsAt)
554 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
556 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
568 if (std::next(
MBBI) ==
MBB->getParent()->end())
577MipsConstantIslands::CPEntry
578*MipsConstantIslands::findConstPoolEntry(
unsigned CPI,
579 const MachineInstr *CPEMI) {
580 std::vector<CPEntry> &CPEs = CPEntries[CPI];
583 for (CPEntry &CPE : CPEs) {
584 if (CPE.CPEMI == CPEMI)
592Align MipsConstantIslands::getCPEAlign(
const MachineInstr &CPEMI) {
596 if (!STI->
getCLOpts().align_constant_islands)
600 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
607void MipsConstantIslands::
608initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
616 for (MachineBasicBlock &
MBB : *MF)
617 computeBlockSize(&
MBB);
620 adjustBBOffsetsAfter(&MF->front());
623 for (MachineBasicBlock &
MBB : *MF) {
627 WaterList.push_back(&
MBB);
628 for (MachineInstr &
MI :
MBB) {
629 if (
MI.isDebugInstr())
632 int Opc =
MI.getOpcode();
651 case Mips::BeqzRxImm16:
657 case Mips::BeqzRxImmX16:
663 case Mips::BnezRxImm16:
669 case Mips::BnezRxImmX16:
701 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
702 ImmBranches.push_back(ImmBranch(&
MI, MaxOffs, isCond, UOpc));
705 if (
Opc == Mips::CONSTPOOL_ENTRY)
709 for (
const MachineOperand &MO :
MI.operands())
718 unsigned LongFormBits = 0;
719 unsigned LongFormScale = 0;
720 unsigned LongFormOpcode = 0;
724 case Mips::LwRxPcTcp16:
727 LongFormOpcode = Mips::LwRxPcTcpX16;
731 case Mips::LwRxPcTcpX16:
738 unsigned CPI = MO.getIndex();
739 MachineInstr *CPEMI = CPEMIs[CPI];
740 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
741 unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
742 CPUsers.push_back(CPUser(&
MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
746 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
747 assert(CPE &&
"Cannot find a corresponding CPEntry!");
760void MipsConstantIslands::computeBlockSize(MachineBasicBlock *
MBB) {
764 for (
const MachineInstr &
MI : *
MBB)
771unsigned MipsConstantIslands::getOffsetOf(MachineInstr *
MI)
const {
781 assert(
I !=
MBB->
end() &&
"Didn't find MI in its own basic block?");
791 return LHS->getNumber() <
RHS->getNumber();
797void MipsConstantIslands::updateForInsertedWaterBlock
798 (MachineBasicBlock *NewBB) {
804 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
809 WaterList.insert(IP, NewBB);
812unsigned MipsConstantIslands::getUserOffset(CPUser &U)
const {
813 return getOffsetOf(
U.MI);
820MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &
MI) {
821 MachineBasicBlock *OrigBB =
MI.getParent();
824 MachineBasicBlock *NewBB =
827 MF->insert(
MBBI, NewBB);
848 MF->RenumberBlocks(NewBB);
852 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
859 MachineBasicBlock* WaterBB = *IP;
860 if (WaterBB == OrigBB)
861 WaterList.insert(std::next(IP), NewBB);
863 WaterList.insert(IP, OrigBB);
864 NewWaterList.
insert(OrigBB);
871 computeBlockSize(OrigBB);
875 computeBlockSize(NewBB);
878 adjustBBOffsetsAfter(OrigBB);
886bool MipsConstantIslands::isOffsetInRange(
unsigned UserOffset,
887 unsigned TrialOffset,
unsigned MaxDisp,
889 if (UserOffset <= TrialOffset) {
891 if (TrialOffset - UserOffset <= MaxDisp)
893 }
else if (NegativeOK) {
894 if (UserOffset - TrialOffset <= MaxDisp)
904bool MipsConstantIslands::isWaterInRange(
unsigned UserOffset,
905 MachineBasicBlock* Water, CPUser &U,
907 unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset();
908 unsigned NextBlockOffset;
909 Align NextBlockAlignment;
911 if (NextBlock == MF->end()) {
912 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
913 NextBlockAlignment =
Align(1);
915 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
916 NextBlockAlignment = NextBlock->getAlignment();
918 unsigned Size =
U.CPEMI->getOperand(2).getImm();
919 unsigned CPEEnd = CPEOffset +
Size;
924 if (CPEEnd > NextBlockOffset) {
925 Growth = CPEEnd - NextBlockOffset;
933 if (CPEOffset < UserOffset)
934 UserOffset += Growth;
939 return isOffsetInRange(UserOffset, CPEOffset, U);
944bool MipsConstantIslands::isCPEntryInRange
945 (MachineInstr *
MI,
unsigned UserOffset,
946 MachineInstr *CPEMI,
unsigned MaxDisp,
947 bool NegOk,
bool DoDump) {
948 unsigned CPEOffset = getOffsetOf(CPEMI);
952 unsigned Block =
MI->getParent()->getNumber();
953 const BasicBlockInfo &BBI = BBInfo[
Block];
955 <<
" max delta=" << MaxDisp
956 <<
format(
" insn address=%#x", UserOffset) <<
" in "
959 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
960 int(CPEOffset - UserOffset));
964 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
971 if (
MBB->pred_size() != 1 ||
MBB->succ_size() != 1)
982void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
984 for(
unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
987 unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
988 BBInfo[i].Offset =
Offset;
996bool MipsConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
997 MachineInstr *CPEMI) {
999 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1000 assert(CPE &&
"Unexpected!");
1001 if (--CPE->RefCount == 0) {
1002 removeDeadCPEMI(CPEMI);
1003 CPE->CPEMI =
nullptr;
1016int MipsConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset)
1018 MachineInstr *UserMI =
U.MI;
1019 MachineInstr *CPEMI =
U.CPEMI;
1022 if (isCPEntryInRange(UserMI, UserOffset, CPEMI, getMaxDisp(U),
U.NegOk,
1030 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1031 for (CPEntry &CPE : CPEs) {
1033 if (CPE.CPEMI == CPEMI)
1036 if (CPE.CPEMI ==
nullptr)
1038 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, getMaxDisp(U),
1040 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1043 U.CPEMI = CPE.CPEMI;
1045 for (MachineOperand &MO : UserMI->
operands())
1047 MO.setIndex(CPE.CPI);
1054 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1068int MipsConstantIslands::findLongFormInRangeCPEntry
1069 (CPUser& U,
unsigned UserOffset)
1071 MachineInstr *UserMI =
U.MI;
1072 MachineInstr *CPEMI =
U.CPEMI;
1075 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
1076 U.getLongFormMaxDisp(),
U.NegOk,
1080 U.setMaxDisp(
U.getLongFormMaxDisp());
1086 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1087 for (CPEntry &CPE : CPEs) {
1089 if (CPE.CPEMI == CPEMI)
1092 if (CPE.CPEMI ==
nullptr)
1094 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getLongFormMaxDisp(),
1096 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1099 U.CPEMI = CPE.CPEMI;
1101 for (MachineOperand &MO : UserMI->
operands())
1103 MO.setIndex(CPE.CPI);
1110 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1121 return ((1<<10)-1)*2;
1123 return ((1<<16)-1)*2;
1127 return ((1<<16)-1)*2;
1138bool MipsConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1139 water_iterator &WaterIter) {
1140 if (WaterList.empty())
1143 unsigned BestGrowth = ~0
u;
1144 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1146 MachineBasicBlock* WaterBB = *IP;
1156 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1157 (WaterBB->
getNumber() <
U.HighWaterMark->getNumber() ||
1158 NewWaterList.
count(WaterBB)) && Growth < BestGrowth) {
1160 BestGrowth = Growth;
1163 <<
" Growth=" << Growth <<
'\n');
1166 if (BestGrowth == 0)
1172 return BestGrowth != ~0
u;
1182void MipsConstantIslands::createNewWater(
unsigned CPUserIndex,
1183 unsigned UserOffset,
1184 MachineBasicBlock *&NewMBB) {
1185 CPUser &
U = CPUsers[CPUserIndex];
1186 MachineInstr *UserMI =
U.MI;
1187 MachineInstr *CPEMI =
U.CPEMI;
1188 MachineBasicBlock *UserMBB = UserMI->
getParent();
1189 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1197 unsigned CPEOffset = UserBBI.
postOffset() + Delta;
1199 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1201 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1208 int UncondBr = Mips::Bimm16;
1211 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1212 MaxDisp,
false, UncondBr));
1213 BBInfo[UserMBB->
getNumber()].Size += Delta;
1214 adjustBBOffsetsAfter(UserMBB);
1225 unsigned BaseInsertOffset = UserOffset + getMaxDisp(U);
1232 BaseInsertOffset -= 4;
1235 <<
" la=" <<
Log2(Align) <<
'\n');
1241 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1245 unsigned EndInsertOffset = BaseInsertOffset + 4 +
1249 unsigned CPUIndex = CPUserIndex+1;
1250 unsigned NumCPUsers = CPUsers.size();
1252 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1253 Offset < BaseInsertOffset;
1255 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1256 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI ==
MI) {
1257 CPUser &
U = CPUsers[CPUIndex];
1258 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1260 BaseInsertOffset -=
Align.value();
1261 EndInsertOffset -=
Align.value();
1267 EndInsertOffset +=
U.CPEMI->getOperand(2).getImm();
1272 NewMBB = splitBlockBeforeInstr(*--
MI);
1279bool MipsConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex) {
1280 CPUser &
U = CPUsers[CPUserIndex];
1281 MachineInstr *UserMI =
U.MI;
1282 MachineInstr *CPEMI =
U.CPEMI;
1286 unsigned UserOffset = getUserOffset(U);
1290 int result = findInRangeCPEntry(U, UserOffset);
1291 if (result==1)
return false;
1292 else if (result==2)
return true;
1295 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1296 MachineBasicBlock *NewMBB;
1298 if (findAvailableWater(U, UserOffset, IP)) {
1300 MachineBasicBlock *WaterBB = *IP;
1305 if (NewWaterList.
erase(WaterBB))
1306 NewWaterList.
insert(NewIsland);
1314 if (!STI->
getCLOpts().constant_islands_no_load_relaxation) {
1315 result = findLongFormInRangeCPEntry(U, UserOffset);
1316 if (result != 0)
return true;
1319 createNewWater(CPUserIndex, UserOffset, NewMBB);
1326 MachineBasicBlock *WaterBB = &*--NewMBB->
getIterator();
1328 if (IP != WaterList.end())
1329 NewWaterList.
erase(WaterBB);
1332 NewWaterList.
insert(NewIsland);
1339 if (IP != WaterList.end())
1340 WaterList.erase(IP);
1346 updateForInsertedWaterBlock(NewIsland);
1349 decrementCPEReferenceCount(CPI, CPEMI);
1353 unsigned ID = createPICLabelUId();
1357 U.HighWaterMark = NewIsland;
1360 CPEntries[CPI].push_back(CPEntry(
U.CPEMI, ID, 1));
1368 adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1371 for (MachineOperand &MO : UserMI->
operands())
1378 dbgs() <<
" Moved CPE to #" << ID <<
" CPI=" << CPI
1386void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1387 MachineBasicBlock *CPEBB = CPEMI->
getParent();
1392 if (CPEBB->
empty()) {
1402 adjustBBOffsetsAfter(CPEBB);
1412bool MipsConstantIslands::removeUnusedCPEntries() {
1413 unsigned MadeChange =
false;
1414 for (std::vector<CPEntry> &CPEs : CPEntries) {
1415 for (CPEntry &CPE : CPEs) {
1416 if (CPE.RefCount == 0 && CPE.CPEMI) {
1417 removeDeadCPEMI(CPE.CPEMI);
1418 CPE.CPEMI =
nullptr;
1428bool MipsConstantIslands::isBBInRange
1429 (MachineInstr *
MI,MachineBasicBlock *DestBB,
unsigned MaxDisp) {
1431 unsigned BrOffset = getOffsetOf(
MI) + PCAdj;
1432 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1436 <<
" max delta=" << MaxDisp <<
" from " << getOffsetOf(
MI)
1437 <<
" to " << DestOffset <<
" offset "
1438 <<
int(DestOffset - BrOffset) <<
"\t" << *
MI);
1440 if (BrOffset <= DestOffset) {
1442 if (DestOffset-BrOffset <= MaxDisp)
1445 if (BrOffset-DestOffset <= MaxDisp)
1453bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1454 MachineInstr *
MI = Br.MI;
1456 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1459 if (isBBInRange(
MI, DestBB, Br.MaxDisp))
1463 return fixupUnconditionalBr(Br);
1464 return fixupConditionalBr(Br);
1472MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1473 MachineInstr *
MI = Br.MI;
1475 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1477 unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2;
1478 if (isBBInRange(
MI, DestBB, BimmX16MaxDisp)) {
1479 Br.MaxDisp = BimmX16MaxDisp;
1480 MI->setDesc(
TII->get(Mips::BimmX16));
1495 Br.MaxDisp = ((1<<24)-1) * 2;
1496 MI->setDesc(
TII->get(Mips::JalB16));
1499 adjustBBOffsetsAfter(
MBB);
1512MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1513 MachineInstr *
MI = Br.MI;
1515 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1516 unsigned Opcode =
MI->getOpcode();
1521 if (isBBInRange(
MI, DestBB, LongFormMaxOff)) {
1522 Br.MaxDisp = LongFormMaxOff;
1523 MI->setDesc(
TII->get(LongFormOpcode));
1539 MachineInstr *BMI = &
MBB->
back();
1541 unsigned OppositeBranchOpcode =
TII->getOppositeBranchOpc(Opcode);
1555 MachineBasicBlock *NewDest =
1557 if (isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1559 dbgs() <<
" Invert Bcc condition and swap its destination with "
1561 MI->setDesc(
TII->get(OppositeBranchOpcode));
1563 MI->getOperand(TargetOperand).setMBB(NewDest);
1570 splitBlockBeforeInstr(*
MI);
1573 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1581 <<
" also invert condition and change dest. to "
1586 if (
MI->getNumExplicitOperands() == 2) {
1588 .
addReg(
MI->getOperand(0).getReg())
1599 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1602 BBInfo[
MI->getParent()->getNumber()].Size -=
TII->getInstSizeInBytes(*
MI);
1603 MI->eraseFromParent();
1604 adjustBBOffsetsAfter(
MBB);
1608void MipsConstantIslands::prescanForConstants() {
1609 for (MachineBasicBlock &
B : *MF) {
1610 for (MachineInstr &
MI :
B) {
1611 switch (
MI.getDesc().getOpcode()) {
1612 case Mips::LwConstant32: {
1613 PrescannedForConstants =
true;
1616 MachineOperand &
Literal =
MI.getOperand(1);
1620 Type *Int32Ty = Type::getInt32Ty(MF->getFunction().getContext());
1623 MI.getOperand(2).ChangeToImmediate(index);
1625 MI.setDesc(
TII->get(Mips::LwRxPcTcp16));
1626 MI.removeOperand(1);
1627 MI.removeOperand(1);
1641 return new MipsConstantIslands();
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.
const MipsInstrInfo * getInstrInfo() const override
bool inMips16Mode() const
const MipsOptions & getCLOpts() const
bool useConstantIslands() const
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()
#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.
FunctionPass * createMipsConstantIslandPass()
Returns a pass that converts branches to long branches.
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)
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.