66#define DEBUG_TYPE "hwloops"
79 cl::desc(
"Add a preheader to a hardware loop if one doesn't exist"));
85 cl::desc(
"Allow speculation of preheader "
88STATISTIC(NumHWLoops,
"Number of loops converted to hardware loops");
120 using LoopFeederMap = std::map<Register, MachineInstr *>;
140 static Kind getSwappedComparison(Kind Cmp) {
141 assert ((!((Cmp & L) && (Cmp & G))) &&
"Malformed comparison operator");
142 if ((Cmp & L) || (Cmp & G))
143 return (Kind)(
Cmp ^ (
L|
G));
147 static Kind getNegatedComparison(Kind Cmp) {
148 if ((Cmp & L) || (Cmp & G))
149 return (Kind)((
Cmp ^ (
L |
G)) ^
EQ);
150 if ((Cmp & NE) || (
Cmp &
EQ))
151 return (Kind)(
Cmp ^ (
EQ |
NE));
156 return (Cmp & (L | G) && !(Cmp & U));
159 static bool isUnsigned(Kind Cmp) {
180 Comparison::Kind getComparisonKind(
unsigned CondOpc,
183 int64_t IVBump)
const;
200 int64_t IVBump, Comparison::Kind Cmp)
const;
205 bool IsInnerHWLoop)
const;
209 bool containsInvalidInstruction(
MachineLoop *L,
bool IsInnerHWLoop)
const;
213 bool convertToHardwareLoop(
MachineLoop *L,
bool &L0used,
bool &L1used);
233 LoopFeederMap &LoopFeederPhi)
const;
239 LoopFeederMap &LoopFeederPhi)
const;
246 LoopFeederMap &LoopFeederPhi)
const;
251 bool checkForImmediate(
const MachineOperand &MO, int64_t &Val)
const;
256 return checkForImmediate(MO, V);
262 if (!checkForImmediate(MO, V))
298 char HexagonHardwareLoops::ID = 0;
300 int HexagonHardwareLoops::Counter = 0;
308 enum CountValueType {
317 Values(
const Values&) =
default;
326 explicit CountValue(CountValueType t,
Register v,
unsigned u = 0) {
328 if (Kind == CV_Register) {
336 bool isReg()
const {
return Kind == CV_Register; }
337 bool isImm()
const {
return Kind == CV_Immediate; }
341 return Contents.R.Reg;
344 unsigned getSubReg()
const {
346 return Contents.R.Sub;
350 assert(isImm() &&
"Wrong CountValue accessor");
351 return Contents.ImmVal;
356 if (isImm()) {
OS << Contents.ImmVal; }
363 "Hexagon Hardware Loops",
false,
false)
370 return new HexagonHardwareLoops();
374 LLVM_DEBUG(
dbgs() <<
"********* Hexagon Hardware Loops *********\n");
378 bool Changed =
false;
380 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
382 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
388 if (L->isOutermost()) {
391 Changed |= convertToHardwareLoop(L, L0Used, L1Used);
397bool HexagonHardwareLoops::findInductionRegister(
MachineLoop *L,
406 if (!Header || !Preheader || !Latch || !ExitingBlock)
411 using RegisterBump = std::pair<Register, int64_t>;
417 using InductionMap = std::map<Register, RegisterBump>;
423 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
424 I != E &&
I->isPHI(); ++
I) {
430 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
431 if (
Phi->getOperand(i+1).getMBB() != Latch)
443 if (
MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
445 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
458 unsigned PredPos, PredRegFlags;
467 int64_t CmpImm = 0, CmpMask = 0;
478 InductionMap::iterator IndMapEnd = IndMap.end();
479 InductionMap::iterator
F = IndMapEnd;
481 InductionMap::iterator F1 = IndMap.find(CmpReg1);
486 InductionMap::iterator F2 = IndMap.find(CmpReg2);
487 if (F2 != IndMapEnd) {
496 Reg =
F->second.first;
497 IVBump =
F->second.second;
498 IVOp =
MRI->getVRegDef(
F->first);
503HexagonHardwareLoops::Comparison::Kind
504HexagonHardwareLoops::getComparisonKind(
unsigned CondOpc,
507 int64_t IVBump)
const {
508 Comparison::Kind
Cmp = (Comparison::Kind)0;
510 case Hexagon::C2_cmpeq:
511 case Hexagon::C2_cmpeqi:
512 case Hexagon::C2_cmpeqp:
513 Cmp = Comparison::EQ;
515 case Hexagon::C4_cmpneq:
516 case Hexagon::C4_cmpneqi:
517 Cmp = Comparison::NE;
519 case Hexagon::C2_cmplt:
520 Cmp = Comparison::LTs;
522 case Hexagon::C2_cmpltu:
523 Cmp = Comparison::LTu;
525 case Hexagon::C4_cmplte:
526 case Hexagon::C4_cmpltei:
527 Cmp = Comparison::LEs;
529 case Hexagon::C4_cmplteu:
530 case Hexagon::C4_cmplteui:
531 Cmp = Comparison::LEu;
533 case Hexagon::C2_cmpgt:
534 case Hexagon::C2_cmpgti:
535 case Hexagon::C2_cmpgtp:
536 Cmp = Comparison::GTs;
538 case Hexagon::C2_cmpgtu:
539 case Hexagon::C2_cmpgtui:
540 case Hexagon::C2_cmpgtup:
541 Cmp = Comparison::GTu;
543 case Hexagon::C2_cmpgei:
544 Cmp = Comparison::GEs;
546 case Hexagon::C2_cmpgeui:
547 Cmp = Comparison::GEs;
550 return (Comparison::Kind)0;
562CountValue *HexagonHardwareLoops::getLoopTripCount(
MachineLoop *L,
567 "Loop must have more than one incoming edge!");
578 if (
L->contains(Backedge))
581 }
else if (!
L->contains(Backedge))
594 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
603 for (
unsigned i = 1, n = IV_Phi->
getNumOperands(); i < n; i += 2) {
605 if (
MBB == Preheader)
607 else if (
MBB == Latch)
623 assert (TB &&
"Exit block without a branch?");
624 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
631 TB = (LTB == Header) ? LTB : LFB;
633 FB = (LTB == Header) ? LTB: LFB;
635 assert ((!FB || TB == Header || FB == Header) &&
"Branches not to header?");
636 if (!TB || (FB && TB != Header && FB != Header))
645 unsigned PredPos, PredRegFlags;
652 int64_t
Mask = 0, ImmValue = 0;
668 Comparison::Kind
Cmp;
669 bool isSwapped =
false;
686 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
690 Cmp = Comparison::getNegatedComparison(Cmp);
692 Cmp = Comparison::getSwappedComparison(Cmp);
694 if (InitialValue->
isReg()) {
699 if (!checkForImmediate(*InitialValue, V))
704 if (EndValue->
isReg()) {
709 if (!checkForImmediate(*EndValue, V))
715 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
727 Comparison::Kind Cmp)
const {
734 if (Cmp == Comparison::EQ)
739 if (Start->isReg()) {
741 if (StartValInstr && (StartValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
742 StartValInstr->
getOpcode() == Hexagon::A2_tfrpi))
747 if (EndValInstr && (EndValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
748 EndValInstr->
getOpcode() == Hexagon::A2_tfrpi))
752 if (!Start->isReg() && !Start->isImm())
754 if (!
End->isReg() && !
End->isImm())
757 bool CmpLess =
Cmp & Comparison::L;
758 bool CmpGreater =
Cmp & Comparison::G;
759 bool CmpHasEqual =
Cmp & Comparison::EQ;
762 if (CmpLess && IVBump < 0)
766 if (CmpGreater && IVBump > 0)
771 LoopFeederMap LoopFeederPhi;
780 if (Start->isImm() &&
End->isImm()) {
782 int64_t StartV = Start->getImm();
783 int64_t EndV =
End->getImm();
784 int64_t Dist = EndV - StartV;
788 bool Exact = (Dist % IVBump) == 0;
790 if (Cmp == Comparison::NE) {
793 if ((Dist < 0) ^ (IVBump < 0))
800 Dist = Dist > 0 ? Dist+1 : Dist-1;
806 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))
810 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump
811 : (-Dist + (-IVBump - 1)) / (-IVBump);
812 assert (Dist1 > 0 &&
"Fishy thing. Both operands have the same sign.");
816 if (Count > 0xFFFFFFFFULL)
819 return new CountValue(CountValue::CV_Immediate, Count);
832 assert (PH &&
"Should have a preheader by now");
835 if (InsertPos != PH->
end())
836 DL = InsertPos->getDebugLoc();
853 bool RegToImm = Start->isReg() &&
End->isImm();
854 bool RegToReg = Start->isReg() &&
End->isReg();
856 int64_t StartV = 0, EndV = 0;
858 StartV = Start->getImm();
860 EndV =
End->getImm();
875 else if (
End->isImm())
881 if (Cmp != Comparison::NE) {
883 StartV -= (IVBump-1);
884 else if (
End->isImm())
892 if (Start->isReg()) {
894 SR = Start->getSubReg();
897 SR =
End->getSubReg();
902 if (!SR && RC == &Hexagon::DoubleRegsRegClass)
911 if (Start->isImm() && StartV == 0) {
912 DistR =
End->getReg();
913 DistSR =
End->getSubReg();
916 (RegToImm ?
TII->get(Hexagon::A2_subri) :
917 TII->get(Hexagon::A2_addi));
918 if (RegToReg || RegToImm) {
925 .
addReg(Start->getReg(), 0, Start->getSubReg());
928 .
addReg(Start->getReg(), 0, Start->getSubReg());
935 if (EndValInstr->
getOpcode() == Hexagon::A2_addi &&
979 unsigned Shift =
Log2_32(IVBump);
994 unsigned MuxSR = CountSR;
998 if (!(Start->isImm() && StartV == 0 && Comparison::isUnsigned(Cmp) &&
1000 (CmpLess || CmpGreater)) {
1004 Register DistCheckR =
MRI->createVirtualRegister(PredRC);
1006 BuildMI(*PH, InsertPos,
DL, DistCheckD, DistCheckR)
1007 .
addReg(DistR, 0, DistSR)
1008 .
addImm((CmpLess) ? 0 : -1);
1013 MuxR =
MRI->createVirtualRegister(IntRC);
1018 .
addReg(CountR, 0, CountSR)
1025 .
addReg(CountR, 0, CountSR);
1030 return new CountValue(CountValue::CV_Register, MuxR, MuxSR);
1034bool HexagonHardwareLoops::isInvalidLoopOperation(
const MachineInstr *
MI,
1035 bool IsInnerHWLoop)
const {
1038 if (
MI->getDesc().isCall())
1042 using namespace Hexagon;
1044 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };
1045 static const Register Regs1[] = { LC1, SA1 };
1048 if (
MI->modifiesRegister(R,
TRI))
1056bool HexagonHardwareLoops::containsInvalidInstruction(
MachineLoop *L,
1057 bool IsInnerHWLoop)
const {
1062 if (isInvalidLoopOperation(&
MI, IsInnerHWLoop)) {
1084 if (
MRI->use_nodbg_empty(Reg))
1092 use_nodbg_iterator
I =
MRI->use_nodbg_begin(Reg);
1093 use_nodbg_iterator
End =
MRI->use_nodbg_end();
1094 if (std::next(
I) !=
End || !
I->getParent()->isPHI())
1099 if (!OPO.isReg() || !OPO.isDef())
1103 use_nodbg_iterator nextJ;
1104 for (use_nodbg_iterator J =
MRI->use_nodbg_begin(OPReg);
1105 J !=
End; J = nextJ) {
1106 nextJ = std::next(J);
1148 MI->eraseFromParent();
1149 for (
unsigned i = 0; i < DeadPhis.
size(); ++i)
1150 DeadPhis[i]->eraseFromParent();
1162bool HexagonHardwareLoops::convertToHardwareLoop(
MachineLoop *L,
1166 assert(
L->getHeader() &&
"Loop without a header?");
1168 bool Changed =
false;
1169 bool L0Used =
false;
1170 bool L1Used =
false;
1174 Changed |= convertToHardwareLoop(
I, RecL0used, RecL1used);
1175 L0Used |= RecL0used;
1176 L1Used |= RecL1used;
1180 if (Changed && L0Used && L1Used)
1190 unsigned IsInnerHWLoop = 1;
1193 LOOP_i = Hexagon::J2_loop1i;
1194 LOOP_r = Hexagon::J2_loop1r;
1195 ENDLOOP = Hexagon::ENDLOOP1;
1198 LOOP_i = Hexagon::J2_loop0i;
1199 LOOP_r = Hexagon::J2_loop0r;
1200 ENDLOOP = Hexagon::ENDLOOP0;
1214 if (containsInvalidInstruction(L, IsInnerHWLoop))
1223 if (LastI == LastMBB->
end())
1227 if (!fixupInductionVariable(L))
1234 Preheader = createPreheaderForLoop(L);
1243 CountValue *TripCount = getLoopTripCount(L, OldInsts);
1248 if (TripCount->isReg()) {
1261 if (ExitingBlock !=
L->getLoopLatch()) {
1268 if (
L->contains(TB))
1270 else if (
L->contains(FB))
1276 LoopStart = TopBlock;
1281 if (InsertPos != Preheader->
end())
1282 DL = InsertPos->getDebugLoc();
1284 if (TripCount->isReg()) {
1286 Register CountReg =
MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1287 BuildMI(*Preheader, InsertPos,
DL,
TII->get(TargetOpcode::COPY), CountReg)
1288 .
addReg(TripCount->getReg(), 0, TripCount->getSubReg());
1293 assert(TripCount->isImm() &&
"Expecting immediate value for trip count");
1297 int64_t CountImm = TripCount->getImm();
1299 Register CountReg =
MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1300 BuildMI(*Preheader, InsertPos,
DL,
TII->get(Hexagon::A2_tfrsi), CountReg)
1313 DebugLoc LastIDL = LastI->getDebugLoc();
1319 if (LastI->getOpcode() == Hexagon::J2_jumpt ||
1320 LastI->getOpcode() == Hexagon::J2_jumpf) {
1323 LastI = LastMBB->
erase(LastI);
1324 if (!
L->contains(BranchTarget)) {
1325 if (LastI != LastMBB->
end())
1326 LastI = LastMBB->
erase(LastI);
1332 LastMBB->
erase(LastI);
1338 for (
unsigned i = 0; i < OldInsts.
size(); ++i)
1339 removeIfDead(OldInsts[i]);
1354bool HexagonHardwareLoops::orderBumpCompare(
MachineInstr *BumpI,
1356 assert (BumpI != CmpI &&
"Bump and compare in the same instruction?");
1365 for (instr_iterator
I(BumpI), E = BB->
instr_end();
I != E; ++
I)
1371 bool FoundBump =
false;
1372 instr_iterator CmpIt = CmpI->
getIterator(), NextIt = std::next(CmpIt);
1373 for (instr_iterator
I = NextIt, E = BB->
instr_end();
I != E; ++
I) {
1375 for (
unsigned i = 0, n =
In->getNumOperands(); i < n; ++i) {
1378 if (MO.
getReg() == PredR)
1389 assert (FoundBump &&
"Cannot determine instruction order");
1401 LoopFeederMap &LoopFeederPhi)
const {
1402 if (LoopFeederPhi.find(MO->
getReg()) == LoopFeederPhi.end()) {
1409 LoopFeederPhi.insert(std::make_pair(MO->
getReg(), Def));
1418bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1420 MachineLoop *L, LoopFeederMap &LoopFeederPhi)
const {
1421 assert(
Phi->isPHI() &&
"Expecting a Phi.");
1424 for (
int i = 1, n =
Phi->getNumOperands(); i < n; i += 2)
1425 if (isLoopFeeder(L,
MBB, Phi, &(
Phi->getOperand(i)), LoopFeederPhi))
1426 if (loopCountMayWrapOrUnderFlow(&(
Phi->getOperand(i)), EndVal,
1427 Phi->getParent(), L, LoopFeederPhi))
1446bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(
1449 LoopFeederMap &LoopFeederPhi)
const {
1451 if (!InitVal->
isReg())
1454 if (!EndVal->
isImm())
1460 if (checkForImmediate(*InitVal, Imm))
1461 return (EndVal->
getImm() == Imm);
1466 if (!
Reg.isVirtual())
1475 if (
Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal,
Def->getParent(),
1478 if (
Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(
Def->getOperand(1)),
1479 EndVal,
Def->getParent(),
1487 E =
MRI->use_instr_nodbg_end();
I != E; ++
I) {
1490 int64_t CmpMask = 0, CmpValue = 0;
1500 Comparison::Kind
Cmp =
1501 getComparisonKind(
MI->getOpcode(),
nullptr,
nullptr, 0);
1505 Cmp = Comparison::getNegatedComparison(Cmp);
1506 if (CmpReg2 != 0 && CmpReg2 == Reg)
1507 Cmp = Comparison::getSwappedComparison(Cmp);
1510 if (Comparison::isSigned(Cmp))
1516 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)
1523 if (!
Def->isCopy() && !
Def->isPHI())
1529bool HexagonHardwareLoops::checkForImmediate(
const MachineOperand &MO,
1530 int64_t &Val)
const {
1549 case TargetOpcode::COPY:
1550 case Hexagon::A2_tfrsi:
1551 case Hexagon::A2_tfrpi:
1552 case Hexagon::CONST32:
1553 case Hexagon::CONST64:
1557 if (!checkForImmediate(DI->
getOperand(1), TV))
1560 case Hexagon::A2_combineii:
1561 case Hexagon::A4_combineir:
1562 case Hexagon::A4_combineii:
1563 case Hexagon::A4_combineri:
1564 case Hexagon::A2_combinew: {
1568 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S2, V2))
1570 TV = V2 | (
static_cast<uint64_t>(V1) << 32);
1573 case TargetOpcode::REG_SEQUENCE: {
1577 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S3, V3))
1581 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)
1582 TV = V1 | (V3 << 32);
1583 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)
1584 TV = V3 | (V1 << 32);
1597 case Hexagon::isub_lo:
1598 Val = TV & 0xFFFFFFFFULL;
1600 case Hexagon::isub_hi:
1601 Val = (TV >> 32) & 0xFFFFFFFFULL;
1610void HexagonHardwareLoops::setImmediate(
MachineOperand &MO, int64_t Val) {
1628bool HexagonHardwareLoops::fixupInductionVariable(
MachineLoop *L) {
1633 if (!(Header && Latch && ExitingBlock))
1638 using RegisterBump = std::pair<Register, int64_t>;
1639 using RegisterInduction = std::pair<Register, RegisterBump>;
1640 using RegisterInductionSet = std::set<RegisterInduction>;
1643 RegisterInductionSet IndRegs;
1650 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1651 I != E &&
I->isPHI(); ++
I) {
1655 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
1656 if (
Phi->getOperand(i+1).getMBB() != Latch)
1668 if (
MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
1670 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
1676 if (IndRegs.empty())
1683 if (NotAnalyzed ||
Cond.empty())
1686 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1696 TB = (LTB == Header) ? LTB : LFB;
1698 FB = (LTB == Header) ? LTB : LFB;
1720 unsigned CSz =
Cond.size();
1721 if (CSz != 1 && CSz != 2)
1747 if (!isImmediate(MO)) {
1756 }
else if (MO.
isImm()) {
1763 if (CmpRegs.
empty())
1767 for (RegisterInductionSet::iterator
I = IndRegs.begin(), E = IndRegs.end();
1772 if (CmpRegs.
count(
I->first))
1778 const RegisterBump &RB =
I->second;
1779 if (CmpRegs.
count(RB.first)) {
1788 for (
unsigned i = 1, n = PredDef->
getNumOperands(); i < n; ++i) {
1792 <<
") = " << *(
MRI->getVRegDef(
I->first)));
1796 IndI =
MRI->getVRegDef(
I->first);
1798 }
else if (MO.
isReg()) {
1800 <<
") = " << *(
MRI->getVRegDef(MO.
getReg())));
1808 if (IndI && nonIndI &&
1809 nonIndI->
getOpcode() == Hexagon::A2_addi &&
1812 bool Order = orderBumpCompare(IndI, PredDef);
1824 Comparison::Kind
Cmp =
1825 getComparisonKind(PredDef->
getOpcode(),
nullptr,
nullptr, 0);
1826 if (!Cmp || Comparison::isUnsigned(Cmp))
1832 int64_t CmpImm = getImmediate(*CmpImmOp);
1833 int64_t
V = RB.second;
1835 if (((V > 0) && (CmpImm >
INT64_MAX - V)) ||
1849 bool Order = orderBumpCompare(BumpI, PredDef);
1854 setImmediate(*CmpImmOp, CmpImm);
1886 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1893 using MBBVector = std::vector<MachineBasicBlock *>;
1895 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1909 MF->
insert(Header->getIterator(), NewPH);
1911 if (Header->pred_size() > 2) {
1917 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1918 I != E &&
I->isPHI(); ++
I) {
1949 if (PredB != Latch) {
1958 assert(Header->pred_size() == 2);
1965 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1966 I != E &&
I->isPHI(); ++
I) {
1970 if (MO.
getMBB() != Latch)
1989 assert (!NotAnalyzed &&
"Should be analyzable!");
1990 if (TB != Header && (Tmp2.
empty() || FB != Header))
1992 PB->ReplaceUsesOfBlockWith(Header, NewPH);
2000 (void)LatchNotAnalyzed;
2001 assert (!LatchNotAnalyzed &&
"Should be analyzable!");
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
static cl::opt< bool > HWCreatePreheader("hexagon-hwloop-preheader", cl::Hidden, cl::init(true), cl::desc("Add a preheader to a hardware loop if one doesn't exist"))
static cl::opt< bool > SpecPreheader("hwloop-spec-preheader", cl::Hidden, cl::desc("Allow speculation of preheader " "instructions"))
static cl::opt< std::string > PHFn("hexagon-hwloop-phfn", cl::Hidden, cl::init(""))
static cl::opt< int > HWLoopLimit("hexagon-max-hwloop", cl::Hidden, cl::init(-1))
Register const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
This file defines the SmallSet class.
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)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Base class for the actual dominator tree node.
DomTreeNodeBase * getIDom() const
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
FunctionPass class - This class is used to implement most global optimizations.
bool doesNotReturn(const MachineInstr &CallMI) const
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
bool getPredReg(ArrayRef< MachineOperand > Cond, Register &PredReg, unsigned &PredRegPos, unsigned &PredRegFlags) const
bool isValidOffset(unsigned Opcode, int Offset, const TargetRegisterInfo *TRI, bool Extend=true) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const override
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Insert branch code into the end of the specified MachineBasicBlock.
bool predOpcodeHasNot(ArrayRef< MachineOperand > Cond) const
bool isExtendable(const MachineInstr &MI) const
const HexagonInstrInfo * getInstrInfo() const override
const HexagonRegisterInfo * getRegisterInfo() const override
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
Represents a single loop in the control flow graph.
Describe properties that are true of each instruction in the target description file.
bool isAdd() const
Return true if the instruction is an add instruction.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator pred_iterator
Instructions::iterator instr_iterator
pred_iterator pred_begin()
instr_iterator instr_end()
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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 '...
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
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
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setMBB(MachineBasicBlock *MBB)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_iterator< true, false, true, true, false > use_nodbg_iterator
use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the specified register,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
@ PD
PD - Prefix code for packed double precision vector floating point operations performed in the SSE re...
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonHardwareLoops()
@ Sub
Subtraction of integers.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...