38#include "llvm/Config/llvm-config.h"
57#define DEBUG_TYPE "mips-constant-islands"
60STATISTIC(NumSplit,
"Number of uncond branches inserted");
61STATISTIC(NumCBrFixed,
"Number of cond branches fixed");
62STATISTIC(NumUBrFixed,
"Number of uncond branches fixed");
67 cl::desc(
"Align constant islands in code"));
72 "mips-constant-islands-small-offset",
74 cl::desc(
"Make small offsets be this amount for testing purposes"),
80 "mips-constant-islands-no-load-relaxation",
82 cl::desc(
"Don't relax loads to long loads - for testing purposes"),
86 switch (
MI->getOpcode()) {
95 case Mips::BeqzRxImm16:
96 case Mips::BeqzRxImmX16:
97 case Mips::BnezRxImm16:
98 case Mips::BnezRxImmX16:
108 return Mips::BimmX16;
111 return Mips::BteqzX16;
114 return Mips::BtnezX16;
117 case Mips::BeqzRxImm16:
118 case Mips::BeqzRxImmX16:
119 return Mips::BeqzRxImmX16;
120 case Mips::BnezRxImm16:
121 case Mips::BnezRxImmX16:
122 return Mips::BnezRxImmX16;
132 unsigned Bits, Scale;
142 case Mips::BeqzRxImm16:
146 case Mips::BeqzRxImmX16:
150 case Mips::BnezRxImm16:
154 case Mips::BnezRxImmX16:
177 unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
201 struct BasicBlockInfo {
220 BasicBlockInfo() =
default;
222 unsigned postOffset()
const {
return Offset + Size; }
225 std::vector<BasicBlockInfo> BBInfo;
230 std::vector<MachineBasicBlock*> WaterList;
234 SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
236 using water_iterator = std::vector<MachineBasicBlock *>::iterator;
253 MachineBasicBlock *HighWaterMark;
257 unsigned LongFormMaxDisp;
259 unsigned LongFormOpcode;
264 CPUser(MachineInstr *mi, MachineInstr *cpemi,
unsigned maxdisp,
266 unsigned longformmaxdisp,
unsigned longformopcode)
267 : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
268 LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
270 HighWaterMark = CPEMI->getParent();
274 unsigned getMaxDisp()
const {
280 void setMaxDisp(
unsigned val) {
284 unsigned getLongFormMaxDisp()
const {
285 return LongFormMaxDisp;
288 unsigned getLongFormOpcode()
const {
289 return LongFormOpcode;
295 std::vector<CPUser> CPUsers;
305 CPEntry(MachineInstr *cpemi,
unsigned cpi,
unsigned rc = 0)
306 : CPEMI(cpemi), CPI(cpi), RefCount(
rc) {}
314 std::vector<std::vector<CPEntry>> CPEntries;
322 unsigned MaxDisp : 31;
327 ImmBranch(MachineInstr *mi,
unsigned maxdisp,
bool cond,
int ubr)
328 : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
333 std::vector<ImmBranch> ImmBranches;
339 const MipsSubtarget *STI =
nullptr;
340 const Mips16InstrInfo *TII;
341 MipsFunctionInfo *MFI;
342 MachineFunction *MF =
nullptr;
343 MachineConstantPool *MCP =
nullptr;
345 unsigned PICLabelUId;
346 bool PrescannedForConstants =
false;
348 void initPICLabelUId(
unsigned UId) {
352 unsigned createPICLabelUId() {
353 return PICLabelUId++;
359 MipsConstantIslands() : MachineFunctionPass(ID) {}
361 StringRef getPassName()
const override {
return "Mips Constant Islands"; }
363 bool runOnMachineFunction(MachineFunction &
F)
override;
365 MachineFunctionProperties getRequiredProperties()
const override {
366 return MachineFunctionProperties().setNoVRegs();
369 void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
370 CPEntry *findConstPoolEntry(
unsigned CPI,
const MachineInstr *CPEMI);
371 Align getCPEAlign(
const MachineInstr &CPEMI);
372 void initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs);
373 unsigned getOffsetOf(MachineInstr *
MI)
const;
374 unsigned getUserOffset(CPUser&)
const;
377 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
378 unsigned Disp,
bool NegativeOK);
379 bool isOffsetInRange(
unsigned UserOffset,
unsigned TrialOffset,
382 void computeBlockSize(MachineBasicBlock *
MBB);
383 MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &
MI);
384 void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
385 void adjustBBOffsetsAfter(MachineBasicBlock *BB);
386 bool decrementCPEReferenceCount(
unsigned CPI, MachineInstr* CPEMI);
387 int findInRangeCPEntry(CPUser& U,
unsigned UserOffset);
388 int findLongFormInRangeCPEntry(CPUser& U,
unsigned UserOffset);
389 bool findAvailableWater(CPUser&U,
unsigned UserOffset,
390 water_iterator &WaterIter);
391 void createNewWater(
unsigned CPUserIndex,
unsigned UserOffset,
392 MachineBasicBlock *&NewMBB);
393 bool handleConstantPoolUser(
unsigned CPUserIndex);
394 void removeDeadCPEMI(MachineInstr *CPEMI);
395 bool removeUnusedCPEntries();
396 bool isCPEntryInRange(MachineInstr *
MI,
unsigned UserOffset,
397 MachineInstr *CPEMI,
unsigned Disp,
bool NegOk,
398 bool DoDump =
false);
399 bool isWaterInRange(
unsigned UserOffset, MachineBasicBlock *Water,
400 CPUser &U,
unsigned &Growth);
401 bool isBBInRange(MachineInstr *
MI, MachineBasicBlock *BB,
unsigned Disp);
402 bool fixupImmediateBr(ImmBranch &Br);
403 bool fixupConditionalBr(ImmBranch &Br);
404 bool fixupUnconditionalBr(ImmBranch &Br);
406 void prescanForConstants();
411char MipsConstantIslands::ID = 0;
413bool MipsConstantIslands::isOffsetInRange
414 (
unsigned UserOffset,
unsigned TrialOffset,
416 return isOffsetInRange(UserOffset, TrialOffset,
417 U.getMaxDisp(),
U.NegOk);
420#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
423 for (
unsigned J = 0,
E = BBInfo.size(); J !=
E; ++J) {
424 const BasicBlockInfo &BBI = BBInfo[J];
431bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
443 MFI = MF->
getInfo<MipsFunctionInfo>();
450 if (!PrescannedForConstants) prescanForConstants();
460 bool MadeChange =
false;
464 std::vector<MachineInstr*> CPEMIs;
466 doInitialPlacement(CPEMIs);
469 initPICLabelUId(CPEMIs.size());
474 initializeFunctionInfo(CPEMIs);
479 MadeChange |= removeUnusedCPEntries();
483 unsigned NoCPIters = 0, NoBRIters = 0;
486 LLVM_DEBUG(
dbgs() <<
"Beginning CP iteration #" << NoCPIters <<
'\n');
487 bool CPChange =
false;
488 for (
unsigned i = 0, e = CPUsers.size(); i != e; ++i)
489 CPChange |= handleConstantPoolUser(i);
490 if (CPChange && ++NoCPIters > 30)
496 NewWaterList.
clear();
498 LLVM_DEBUG(
dbgs() <<
"Beginning BR iteration #" << NoBRIters <<
'\n');
499 bool BRChange =
false;
500 for (
unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
501 BRChange |= fixupImmediateBr(ImmBranches[i]);
502 if (BRChange && ++NoBRIters > 30)
505 if (!CPChange && !BRChange)
523MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
548 const std::vector<MachineConstantPoolEntry> &CPs = MCP->
getConstants();
551 for (
unsigned i = 0, e = CPs.size(); i != e; ++i) {
552 unsigned Size = CPs[i].getSizeInBytes(TD);
553 assert(
Size >= 4 &&
"Too small constant pool entry");
554 Align Alignment = CPs[i].getAlign();
560 unsigned LogAlign =
Log2(Alignment);
563 MachineInstr *CPEMI =
567 CPEMIs.push_back(CPEMI);
571 for (
unsigned a = LogAlign + 1; a <=
Log2(MaxAlign); ++a)
572 if (InsPoint[a] == InsAt)
575 CPEntries.emplace_back(1, CPEntry(CPEMI, i));
577 LLVM_DEBUG(
dbgs() <<
"Moved CPI#" << i <<
" to end of function, size = "
578 <<
Size <<
", align = " << Alignment.
value() <<
'\n');
589 if (std::next(
MBBI) ==
MBB->getParent()->end())
598MipsConstantIslands::CPEntry
599*MipsConstantIslands::findConstPoolEntry(
unsigned CPI,
600 const MachineInstr *CPEMI) {
601 std::vector<CPEntry> &CPEs = CPEntries[CPI];
604 for (CPEntry &CPE : CPEs) {
605 if (CPE.CPEMI == CPEMI)
613Align MipsConstantIslands::getCPEAlign(
const MachineInstr &CPEMI) {
621 assert(CPI < MCP->getConstants().
size() &&
"Invalid constant pool index.");
628void MipsConstantIslands::
629initializeFunctionInfo(
const std::vector<MachineInstr*> &CPEMIs) {
637 for (MachineBasicBlock &
MBB : *MF)
638 computeBlockSize(&
MBB);
641 adjustBBOffsetsAfter(&MF->front());
644 for (MachineBasicBlock &
MBB : *MF) {
648 WaterList.push_back(&
MBB);
649 for (MachineInstr &
MI :
MBB) {
650 if (
MI.isDebugInstr())
653 int Opc =
MI.getOpcode();
672 case Mips::BeqzRxImm16:
678 case Mips::BeqzRxImmX16:
684 case Mips::BnezRxImm16:
690 case Mips::BnezRxImmX16:
722 unsigned MaxOffs = ((1 << (
Bits-1))-1) * Scale;
723 ImmBranches.push_back(ImmBranch(&
MI, MaxOffs, isCond, UOpc));
726 if (
Opc == Mips::CONSTPOOL_ENTRY)
730 for (
const MachineOperand &MO :
MI.operands())
739 unsigned LongFormBits = 0;
740 unsigned LongFormScale = 0;
741 unsigned LongFormOpcode = 0;
745 case Mips::LwRxPcTcp16:
748 LongFormOpcode = Mips::LwRxPcTcpX16;
752 case Mips::LwRxPcTcpX16:
759 unsigned CPI = MO.getIndex();
760 MachineInstr *CPEMI = CPEMIs[CPI];
761 unsigned MaxOffs = ((1 <<
Bits)-1) * Scale;
762 unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
763 CPUsers.push_back(CPUser(&
MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
767 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
768 assert(CPE &&
"Cannot find a corresponding CPEntry!");
781void MipsConstantIslands::computeBlockSize(MachineBasicBlock *
MBB) {
785 for (
const MachineInstr &
MI : *
MBB)
792unsigned MipsConstantIslands::getOffsetOf(MachineInstr *
MI)
const {
793 MachineBasicBlock *
MBB =
MI->getParent();
802 assert(
I !=
MBB->
end() &&
"Didn't find MI in its own basic block?");
812 return LHS->getNumber() <
RHS->getNumber();
818void MipsConstantIslands::updateForInsertedWaterBlock
819 (MachineBasicBlock *NewBB) {
825 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
830 WaterList.insert(IP, NewBB);
833unsigned MipsConstantIslands::getUserOffset(CPUser &U)
const {
834 return getOffsetOf(
U.MI);
841MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &
MI) {
842 MachineBasicBlock *OrigBB =
MI.getParent();
845 MachineBasicBlock *NewBB =
848 MF->insert(
MBBI, NewBB);
869 MF->RenumberBlocks(NewBB);
873 BBInfo.insert(BBInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
880 MachineBasicBlock* WaterBB = *IP;
881 if (WaterBB == OrigBB)
882 WaterList.insert(std::next(IP), NewBB);
884 WaterList.insert(IP, OrigBB);
885 NewWaterList.
insert(OrigBB);
892 computeBlockSize(OrigBB);
896 computeBlockSize(NewBB);
899 adjustBBOffsetsAfter(OrigBB);
907bool MipsConstantIslands::isOffsetInRange(
unsigned UserOffset,
908 unsigned TrialOffset,
unsigned MaxDisp,
910 if (UserOffset <= TrialOffset) {
912 if (TrialOffset - UserOffset <= MaxDisp)
914 }
else if (NegativeOK) {
915 if (UserOffset - TrialOffset <= MaxDisp)
925bool MipsConstantIslands::isWaterInRange(
unsigned UserOffset,
926 MachineBasicBlock* Water, CPUser &U,
928 unsigned CPEOffset = BBInfo[Water->
getNumber()].postOffset();
929 unsigned NextBlockOffset;
930 Align NextBlockAlignment;
932 if (NextBlock == MF->end()) {
933 NextBlockOffset = BBInfo[Water->
getNumber()].postOffset();
934 NextBlockAlignment =
Align(1);
936 NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
937 NextBlockAlignment = NextBlock->getAlignment();
939 unsigned Size =
U.CPEMI->getOperand(2).getImm();
940 unsigned CPEEnd = CPEOffset +
Size;
945 if (CPEEnd > NextBlockOffset) {
946 Growth = CPEEnd - NextBlockOffset;
954 if (CPEOffset < UserOffset)
955 UserOffset += Growth;
960 return isOffsetInRange(UserOffset, CPEOffset, U);
965bool MipsConstantIslands::isCPEntryInRange
966 (MachineInstr *
MI,
unsigned UserOffset,
967 MachineInstr *CPEMI,
unsigned MaxDisp,
968 bool NegOk,
bool DoDump) {
969 unsigned CPEOffset = getOffsetOf(CPEMI);
973 unsigned Block =
MI->getParent()->getNumber();
974 const BasicBlockInfo &BBI = BBInfo[
Block];
976 <<
" max delta=" << MaxDisp
977 <<
format(
" insn address=%#x", UserOffset) <<
" in "
980 <<
format(
"CPE address=%#x offset=%+d: ", CPEOffset,
981 int(CPEOffset - UserOffset));
985 return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
992 if (
MBB->pred_size() != 1 ||
MBB->succ_size() != 1)
1003void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
1005 for(
unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
1008 unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
1009 BBInfo[i].Offset =
Offset;
1017bool MipsConstantIslands::decrementCPEReferenceCount(
unsigned CPI,
1018 MachineInstr *CPEMI) {
1020 CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
1021 assert(CPE &&
"Unexpected!");
1022 if (--CPE->RefCount == 0) {
1023 removeDeadCPEMI(CPEMI);
1024 CPE->CPEMI =
nullptr;
1037int MipsConstantIslands::findInRangeCPEntry(CPUser& U,
unsigned UserOffset)
1039 MachineInstr *UserMI =
U.MI;
1040 MachineInstr *CPEMI =
U.CPEMI;
1043 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
U.getMaxDisp(),
U.NegOk,
1051 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1052 for (CPEntry &CPE : CPEs) {
1054 if (CPE.CPEMI == CPEMI)
1057 if (CPE.CPEMI ==
nullptr)
1059 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getMaxDisp(),
1061 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1064 U.CPEMI = CPE.CPEMI;
1066 for (MachineOperand &MO : UserMI->
operands())
1068 MO.setIndex(CPE.CPI);
1075 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1089int MipsConstantIslands::findLongFormInRangeCPEntry
1090 (CPUser& U,
unsigned UserOffset)
1092 MachineInstr *UserMI =
U.MI;
1093 MachineInstr *CPEMI =
U.CPEMI;
1096 if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
1097 U.getLongFormMaxDisp(),
U.NegOk,
1101 U.setMaxDisp(
U.getLongFormMaxDisp());
1107 std::vector<CPEntry> &CPEs = CPEntries[CPI];
1108 for (CPEntry &CPE : CPEs) {
1110 if (CPE.CPEMI == CPEMI)
1113 if (CPE.CPEMI ==
nullptr)
1115 if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI,
U.getLongFormMaxDisp(),
1117 LLVM_DEBUG(
dbgs() <<
"Replacing CPE#" << CPI <<
" with CPE#" << CPE.CPI
1120 U.CPEMI = CPE.CPEMI;
1122 for (MachineOperand &MO : UserMI->
operands())
1124 MO.setIndex(CPE.CPI);
1131 return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
1142 return ((1<<10)-1)*2;
1144 return ((1<<16)-1)*2;
1148 return ((1<<16)-1)*2;
1159bool MipsConstantIslands::findAvailableWater(CPUser &U,
unsigned UserOffset,
1160 water_iterator &WaterIter) {
1161 if (WaterList.empty())
1164 unsigned BestGrowth = ~0
u;
1165 for (water_iterator IP = std::prev(WaterList.end()),
B = WaterList.begin();;
1167 MachineBasicBlock* WaterBB = *IP;
1177 if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
1178 (WaterBB->
getNumber() <
U.HighWaterMark->getNumber() ||
1179 NewWaterList.
count(WaterBB)) && Growth < BestGrowth) {
1181 BestGrowth = Growth;
1184 <<
" Growth=" << Growth <<
'\n');
1187 if (BestGrowth == 0)
1193 return BestGrowth != ~0
u;
1203void MipsConstantIslands::createNewWater(
unsigned CPUserIndex,
1204 unsigned UserOffset,
1205 MachineBasicBlock *&NewMBB) {
1206 CPUser &
U = CPUsers[CPUserIndex];
1207 MachineInstr *UserMI =
U.MI;
1208 MachineInstr *CPEMI =
U.CPEMI;
1209 MachineBasicBlock *UserMBB = UserMI->
getParent();
1210 const BasicBlockInfo &UserBBI = BBInfo[UserMBB->
getNumber()];
1218 unsigned CPEOffset = UserBBI.
postOffset() + Delta;
1220 if (isOffsetInRange(UserOffset, CPEOffset, U)) {
1222 <<
format(
", expected CPE offset %#x\n", CPEOffset));
1229 int UncondBr = Mips::Bimm16;
1232 ImmBranches.push_back(ImmBranch(&UserMBB->
back(),
1233 MaxDisp,
false, UncondBr));
1234 BBInfo[UserMBB->
getNumber()].Size += Delta;
1235 adjustBBOffsetsAfter(UserMBB);
1246 unsigned BaseInsertOffset = UserOffset +
U.getMaxDisp();
1253 BaseInsertOffset -= 4;
1256 <<
" la=" <<
Log2(Align) <<
'\n');
1262 if (BaseInsertOffset + 8 >= UserBBI.
postOffset()) {
1266 unsigned EndInsertOffset = BaseInsertOffset + 4 +
1270 unsigned CPUIndex = CPUserIndex+1;
1271 unsigned NumCPUsers = CPUsers.size();
1273 for (
unsigned Offset = UserOffset +
TII->getInstSizeInBytes(*UserMI);
1274 Offset < BaseInsertOffset;
1276 assert(
MI != UserMBB->
end() &&
"Fell off end of block");
1277 if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].
MI ==
MI) {
1278 CPUser &
U = CPUsers[CPUIndex];
1279 if (!isOffsetInRange(
Offset, EndInsertOffset, U)) {
1281 BaseInsertOffset -=
Align.value();
1282 EndInsertOffset -=
Align.value();
1288 EndInsertOffset +=
U.CPEMI->getOperand(2).getImm();
1293 NewMBB = splitBlockBeforeInstr(*--
MI);
1300bool MipsConstantIslands::handleConstantPoolUser(
unsigned CPUserIndex) {
1301 CPUser &
U = CPUsers[CPUserIndex];
1302 MachineInstr *UserMI =
U.MI;
1303 MachineInstr *CPEMI =
U.CPEMI;
1307 unsigned UserOffset = getUserOffset(U);
1311 int result = findInRangeCPEntry(U, UserOffset);
1312 if (result==1)
return false;
1313 else if (result==2)
return true;
1316 MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
1317 MachineBasicBlock *NewMBB;
1319 if (findAvailableWater(U, UserOffset, IP)) {
1321 MachineBasicBlock *WaterBB = *IP;
1326 if (NewWaterList.
erase(WaterBB))
1327 NewWaterList.
insert(NewIsland);
1336 result = findLongFormInRangeCPEntry(U, UserOffset);
1337 if (result != 0)
return true;
1340 createNewWater(CPUserIndex, UserOffset, NewMBB);
1347 MachineBasicBlock *WaterBB = &*--NewMBB->
getIterator();
1349 if (IP != WaterList.end())
1350 NewWaterList.
erase(WaterBB);
1353 NewWaterList.
insert(NewIsland);
1360 if (IP != WaterList.end())
1361 WaterList.erase(IP);
1367 updateForInsertedWaterBlock(NewIsland);
1370 decrementCPEReferenceCount(CPI, CPEMI);
1374 unsigned ID = createPICLabelUId();
1378 U.HighWaterMark = NewIsland;
1381 CPEntries[CPI].push_back(CPEntry(
U.CPEMI,
ID, 1));
1389 adjustBBOffsetsAfter(&*--NewIsland->
getIterator());
1392 for (MachineOperand &MO : UserMI->
operands())
1399 dbgs() <<
" Moved CPE to #" <<
ID <<
" CPI=" << CPI
1407void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
1408 MachineBasicBlock *CPEBB = CPEMI->
getParent();
1413 if (CPEBB->
empty()) {
1423 adjustBBOffsetsAfter(CPEBB);
1433bool MipsConstantIslands::removeUnusedCPEntries() {
1434 unsigned MadeChange =
false;
1435 for (std::vector<CPEntry> &CPEs : CPEntries) {
1436 for (CPEntry &CPE : CPEs) {
1437 if (CPE.RefCount == 0 && CPE.CPEMI) {
1438 removeDeadCPEMI(CPE.CPEMI);
1439 CPE.CPEMI =
nullptr;
1449bool MipsConstantIslands::isBBInRange
1450 (MachineInstr *
MI,MachineBasicBlock *DestBB,
unsigned MaxDisp) {
1452 unsigned BrOffset = getOffsetOf(
MI) + PCAdj;
1453 unsigned DestOffset = BBInfo[DestBB->
getNumber()].Offset;
1457 <<
" max delta=" << MaxDisp <<
" from " << getOffsetOf(
MI)
1458 <<
" to " << DestOffset <<
" offset "
1459 <<
int(DestOffset - BrOffset) <<
"\t" << *
MI);
1461 if (BrOffset <= DestOffset) {
1463 if (DestOffset-BrOffset <= MaxDisp)
1466 if (BrOffset-DestOffset <= MaxDisp)
1474bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) {
1475 MachineInstr *
MI = Br.MI;
1477 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1480 if (isBBInRange(
MI, DestBB, Br.MaxDisp))
1484 return fixupUnconditionalBr(Br);
1485 return fixupConditionalBr(Br);
1493MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
1494 MachineInstr *
MI = Br.MI;
1495 MachineBasicBlock *
MBB =
MI->getParent();
1496 MachineBasicBlock *DestBB =
MI->getOperand(0).getMBB();
1498 unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2;
1499 if (isBBInRange(
MI, DestBB, BimmX16MaxDisp)) {
1500 Br.MaxDisp = BimmX16MaxDisp;
1501 MI->setDesc(
TII->get(Mips::BimmX16));
1516 Br.MaxDisp = ((1<<24)-1) * 2;
1517 MI->setDesc(
TII->get(Mips::JalB16));
1520 adjustBBOffsetsAfter(
MBB);
1533MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
1534 MachineInstr *
MI = Br.MI;
1536 MachineBasicBlock *DestBB =
MI->getOperand(TargetOperand).getMBB();
1537 unsigned Opcode =
MI->getOpcode();
1542 if (isBBInRange(
MI, DestBB, LongFormMaxOff)) {
1543 Br.MaxDisp = LongFormMaxOff;
1544 MI->setDesc(
TII->get(LongFormOpcode));
1559 MachineBasicBlock *
MBB =
MI->getParent();
1560 MachineInstr *BMI = &
MBB->
back();
1562 unsigned OppositeBranchOpcode =
TII->getOppositeBranchOpc(Opcode);
1576 MachineBasicBlock *NewDest =
1578 if (isBBInRange(
MI, NewDest, Br.MaxDisp)) {
1580 dbgs() <<
" Invert Bcc condition and swap its destination with "
1582 MI->setDesc(
TII->get(OppositeBranchOpcode));
1584 MI->getOperand(TargetOperand).setMBB(NewDest);
1591 splitBlockBeforeInstr(*
MI);
1594 int delta =
TII->getInstSizeInBytes(
MBB->
back());
1602 <<
" also invert condition and change dest. to "
1607 if (
MI->getNumExplicitOperands() == 2) {
1609 .
addReg(
MI->getOperand(0).getReg())
1620 ImmBranches.push_back(ImmBranch(&
MBB->
back(), MaxDisp,
false, Br.UncondBr));
1623 BBInfo[
MI->getParent()->getNumber()].Size -=
TII->getInstSizeInBytes(*
MI);
1624 MI->eraseFromParent();
1625 adjustBBOffsetsAfter(
MBB);
1629void MipsConstantIslands::prescanForConstants() {
1630 for (MachineBasicBlock &
B : *MF) {
1631 for (MachineInstr &
MI :
B) {
1632 switch (
MI.getDesc().getOpcode()) {
1633 case Mips::LwConstant32: {
1634 PrescannedForConstants =
true;
1637 MachineOperand &
Literal =
MI.getOperand(1);
1641 Type *
Int32Ty = Type::getInt32Ty(MF->getFunction().getContext());
1644 MI.getOperand(2).ChangeToImmediate(index);
1646 MI.setDesc(
TII->get(Mips::LwRxPcTcp16));
1647 MI.removeOperand(1);
1648 MI.removeOperand(1);
1662 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< 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 cl::opt< bool > NoLoadRelaxation("mips-constant-islands-no-load-relaxation", cl::init(false), cl::desc("Don't relax loads to long loads - for testing purposes"), cl::Hidden)
static cl::opt< int > ConstantIslandsSmallOffset("mips-constant-islands-small-offset", cl::init(0), cl::desc("Make small offsets be this amount for testing purposes"), cl::Hidden)
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
static cl::opt< bool > AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), cl::desc("Align constant islands in code"))
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)
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.
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & 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.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
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.
static bool useConstantIslands()
const MipsInstrInfo * getInstrInfo() const override
bool inMips16Mode() 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
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.
uint64_t value() const
This is a hole in the type system and should not be abused.
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.