65#define DEBUG_TYPE "hwloops"
78 cl::desc(
"Add a preheader to a hardware loop if one doesn't exist"));
84 cl::desc(
"Allow speculation of preheader "
87STATISTIC(NumHWLoops,
"Number of loops converted to hardware loops");
126 using LoopFeederMap = std::map<Register, MachineInstr *>;
146 static Kind getSwappedComparison(Kind Cmp) {
147 assert ((!((Cmp & L) && (Cmp & G))) &&
"Malformed comparison operator");
148 if ((Cmp & L) || (Cmp & G))
149 return (Kind)(
Cmp ^ (
L|
G));
153 static Kind getNegatedComparison(Kind Cmp) {
154 if ((Cmp & L) || (Cmp & G))
155 return (Kind)((
Cmp ^ (
L |
G)) ^
EQ);
156 if ((Cmp & NE) || (
Cmp &
EQ))
157 return (Kind)(
Cmp ^ (
EQ |
NE));
162 return (Cmp & (L | G) && !(Cmp & U));
165 static bool isUnsigned(Kind Cmp) {
186 Comparison::Kind getComparisonKind(
unsigned CondOpc,
189 int64_t IVBump)
const;
206 int64_t IVBump, Comparison::Kind Cmp)
const;
211 bool IsInnerHWLoop)
const;
215 bool containsInvalidInstruction(
MachineLoop *L,
bool IsInnerHWLoop)
const;
219 bool convertToHardwareLoop(
MachineLoop *L,
bool &L0used,
bool &L1used);
239 LoopFeederMap &LoopFeederPhi)
const;
245 LoopFeederMap &LoopFeederPhi)
const;
252 LoopFeederMap &LoopFeederPhi)
const;
257 bool checkForImmediate(
const MachineOperand &MO, int64_t &Val)
const;
262 return checkForImmediate(MO, V);
268 if (!checkForImmediate(MO, V))
304 char HexagonHardwareLoops::ID = 0;
306 int HexagonHardwareLoops::Counter = 0;
314 enum CountValueType {
323 Values(
const Values&) =
default;
332 explicit CountValue(CountValueType t,
Register v,
unsigned u = 0) {
334 if (Kind == CV_Register) {
342 bool isReg()
const {
return Kind == CV_Register; }
343 bool isImm()
const {
return Kind == CV_Immediate; }
347 return Contents.R.Reg;
350 unsigned getSubReg()
const {
352 return Contents.R.Sub;
355 unsigned getImm()
const {
357 return Contents.ImmVal;
362 if (
isImm()) {
OS << Contents.ImmVal; }
369 "Hexagon Hardware Loops",
false,
false)
376 return new HexagonHardwareLoops();
380 LLVM_DEBUG(
dbgs() <<
"********* Hexagon Hardware Loops *********\n");
384 bool Changed =
false;
386 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
388 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
394 if (L->isOutermost()) {
397 Changed |= convertToHardwareLoop(L, L0Used, L1Used);
403bool HexagonHardwareLoops::findInductionRegister(
MachineLoop *L,
412 if (!Header || !Preheader || !Latch || !ExitingBlock)
417 using RegisterBump = std::pair<Register, int64_t>;
423 using InductionMap = std::map<Register, RegisterBump>;
429 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
430 I != E &&
I->isPHI(); ++
I) {
436 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
437 if (
Phi->getOperand(i+1).getMBB() != Latch)
449 if (
MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
451 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
464 unsigned PredPos, PredRegFlags;
473 int64_t CmpImm = 0, CmpMask = 0;
484 InductionMap::iterator IndMapEnd = IndMap.end();
485 InductionMap::iterator
F = IndMapEnd;
487 InductionMap::iterator F1 = IndMap.find(CmpReg1);
492 InductionMap::iterator F2 = IndMap.find(CmpReg2);
493 if (F2 != IndMapEnd) {
502 Reg =
F->second.first;
503 IVBump =
F->second.second;
504 IVOp =
MRI->getVRegDef(
F->first);
509HexagonHardwareLoops::Comparison::Kind
510HexagonHardwareLoops::getComparisonKind(
unsigned CondOpc,
513 int64_t IVBump)
const {
514 Comparison::Kind
Cmp = (Comparison::Kind)0;
516 case Hexagon::C2_cmpeq:
517 case Hexagon::C2_cmpeqi:
518 case Hexagon::C2_cmpeqp:
519 Cmp = Comparison::EQ;
521 case Hexagon::C4_cmpneq:
522 case Hexagon::C4_cmpneqi:
523 Cmp = Comparison::NE;
525 case Hexagon::C2_cmplt:
526 Cmp = Comparison::LTs;
528 case Hexagon::C2_cmpltu:
529 Cmp = Comparison::LTu;
531 case Hexagon::C4_cmplte:
532 case Hexagon::C4_cmpltei:
533 Cmp = Comparison::LEs;
535 case Hexagon::C4_cmplteu:
536 case Hexagon::C4_cmplteui:
537 Cmp = Comparison::LEu;
539 case Hexagon::C2_cmpgt:
540 case Hexagon::C2_cmpgti:
541 case Hexagon::C2_cmpgtp:
542 Cmp = Comparison::GTs;
544 case Hexagon::C2_cmpgtu:
545 case Hexagon::C2_cmpgtui:
546 case Hexagon::C2_cmpgtup:
547 Cmp = Comparison::GTu;
549 case Hexagon::C2_cmpgei:
550 Cmp = Comparison::GEs;
552 case Hexagon::C2_cmpgeui:
553 Cmp = Comparison::GEs;
556 return (Comparison::Kind)0;
568CountValue *HexagonHardwareLoops::getLoopTripCount(
MachineLoop *L,
573 "Loop must have more than one incoming edge!");
584 if (
L->contains(Backedge))
587 }
else if (!
L->contains(Backedge))
600 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
609 for (
unsigned i = 1, n = IV_Phi->
getNumOperands(); i < n; i += 2) {
611 if (
MBB == Preheader)
613 else if (
MBB == Latch)
629 assert (TB &&
"Exit block without a branch?");
630 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
637 TB = (LTB == Header) ? LTB : LFB;
639 FB = (LTB == Header) ? LTB: LFB;
641 assert ((!FB || TB == Header || FB == Header) &&
"Branches not to header?");
642 if (!TB || (FB && TB != Header && FB != Header))
651 unsigned PredPos, PredRegFlags;
658 int64_t
Mask = 0, ImmValue = 0;
674 Comparison::Kind
Cmp;
675 bool isSwapped =
false;
692 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
696 Cmp = Comparison::getNegatedComparison(Cmp);
698 Cmp = Comparison::getSwappedComparison(Cmp);
700 if (InitialValue->
isReg()) {
705 if (!checkForImmediate(*InitialValue, V))
710 if (EndValue->
isReg()) {
715 if (!checkForImmediate(*EndValue, V))
721 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
733 Comparison::Kind Cmp)
const {
735 if (Cmp == Comparison::EQ)
740 if (Start->isReg()) {
742 if (StartValInstr && (StartValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
743 StartValInstr->
getOpcode() == Hexagon::A2_tfrpi))
748 if (EndValInstr && (EndValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
749 EndValInstr->
getOpcode() == Hexagon::A2_tfrpi))
753 if (!Start->isReg() && !Start->isImm())
755 if (!
End->isReg() && !
End->isImm())
758 bool CmpLess =
Cmp & Comparison::L;
759 bool CmpGreater =
Cmp & Comparison::G;
760 bool CmpHasEqual =
Cmp & Comparison::EQ;
763 if (CmpLess && IVBump < 0)
767 if (CmpGreater && IVBump > 0)
772 LoopFeederMap LoopFeederPhi;
781 if (Start->isImm() &&
End->isImm()) {
783 int64_t StartV = Start->getImm();
784 int64_t EndV =
End->getImm();
785 int64_t Dist = EndV - StartV;
789 bool Exact = (Dist % IVBump) == 0;
791 if (Cmp == Comparison::NE) {
794 if ((Dist < 0) ^ (IVBump < 0))
801 Dist = Dist > 0 ? Dist+1 : Dist-1;
807 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))
811 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump
812 : (-Dist + (-IVBump - 1)) / (-IVBump);
813 assert (Dist1 > 0 &&
"Fishy thing. Both operands have the same sign.");
817 if (Count > 0xFFFFFFFFULL)
820 return new CountValue(CountValue::CV_Immediate, Count);
833 assert (PH &&
"Should have a preheader by now");
836 if (InsertPos != PH->
end())
837 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);
992 return new CountValue(CountValue::CV_Register, CountR, CountSR);
996bool HexagonHardwareLoops::isInvalidLoopOperation(
const MachineInstr *
MI,
997 bool IsInnerHWLoop)
const {
1000 if (
MI->getDesc().isCall())
1004 using namespace Hexagon;
1006 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };
1007 static const Register Regs1[] = { LC1, SA1 };
1010 if (
MI->modifiesRegister(R,
TRI))
1018bool HexagonHardwareLoops::containsInvalidInstruction(
MachineLoop *L,
1019 bool IsInnerHWLoop)
const {
1024 if (isInvalidLoopOperation(&
MI, IsInnerHWLoop)) {
1046 if (
MRI->use_nodbg_empty(Reg))
1054 use_nodbg_iterator
I =
MRI->use_nodbg_begin(Reg);
1055 use_nodbg_iterator
End =
MRI->use_nodbg_end();
1056 if (std::next(
I) !=
End || !
I->getParent()->isPHI())
1061 if (!OPO.isReg() || !OPO.isDef())
1065 use_nodbg_iterator nextJ;
1066 for (use_nodbg_iterator J =
MRI->use_nodbg_begin(OPReg);
1067 J !=
End; J = nextJ) {
1068 nextJ = std::next(J);
1110 MI->eraseFromParent();
1111 for (
unsigned i = 0; i < DeadPhis.
size(); ++i)
1112 DeadPhis[i]->eraseFromParent();
1124bool HexagonHardwareLoops::convertToHardwareLoop(
MachineLoop *L,
1128 assert(
L->getHeader() &&
"Loop without a header?");
1130 bool Changed =
false;
1131 bool L0Used =
false;
1132 bool L1Used =
false;
1136 Changed |= convertToHardwareLoop(
I, RecL0used, RecL1used);
1137 L0Used |= RecL0used;
1138 L1Used |= RecL1used;
1142 if (Changed && L0Used && L1Used)
1152 unsigned IsInnerHWLoop = 1;
1155 LOOP_i = Hexagon::J2_loop1i;
1156 LOOP_r = Hexagon::J2_loop1r;
1157 ENDLOOP = Hexagon::ENDLOOP1;
1160 LOOP_i = Hexagon::J2_loop0i;
1161 LOOP_r = Hexagon::J2_loop0r;
1162 ENDLOOP = Hexagon::ENDLOOP0;
1176 if (containsInvalidInstruction(L, IsInnerHWLoop))
1185 if (LastI == LastMBB->
end())
1189 if (!fixupInductionVariable(L))
1196 Preheader = createPreheaderForLoop(L);
1205 CountValue *TripCount = getLoopTripCount(L, OldInsts);
1210 if (TripCount->isReg()) {
1223 if (ExitingBlock !=
L->getLoopLatch()) {
1230 if (
L->contains(TB))
1232 else if (
L->contains(FB))
1238 LoopStart = TopBlock;
1243 if (InsertPos != Preheader->
end())
1244 DL = InsertPos->getDebugLoc();
1246 if (TripCount->isReg()) {
1248 Register CountReg =
MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1249 BuildMI(*Preheader, InsertPos,
DL,
TII->get(TargetOpcode::COPY), CountReg)
1250 .
addReg(TripCount->getReg(), 0, TripCount->getSubReg());
1255 assert(TripCount->isImm() &&
"Expecting immediate value for trip count");
1259 int64_t CountImm = TripCount->getImm();
1261 Register CountReg =
MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1262 BuildMI(*Preheader, InsertPos,
DL,
TII->get(Hexagon::A2_tfrsi), CountReg)
1275 DebugLoc LastIDL = LastI->getDebugLoc();
1281 if (LastI->getOpcode() == Hexagon::J2_jumpt ||
1282 LastI->getOpcode() == Hexagon::J2_jumpf) {
1285 LastI = LastMBB->
erase(LastI);
1286 if (!
L->contains(BranchTarget)) {
1287 if (LastI != LastMBB->
end())
1288 LastI = LastMBB->
erase(LastI);
1294 LastMBB->
erase(LastI);
1300 for (
unsigned i = 0; i < OldInsts.
size(); ++i)
1301 removeIfDead(OldInsts[i]);
1316bool HexagonHardwareLoops::orderBumpCompare(
MachineInstr *BumpI,
1318 assert (BumpI != CmpI &&
"Bump and compare in the same instruction?");
1327 for (instr_iterator
I(BumpI), E = BB->
instr_end();
I != E; ++
I)
1333 bool FoundBump =
false;
1334 instr_iterator CmpIt = CmpI->
getIterator(), NextIt = std::next(CmpIt);
1335 for (instr_iterator
I = NextIt, E = BB->
instr_end();
I != E; ++
I) {
1337 for (
unsigned i = 0, n =
In->getNumOperands(); i < n; ++i) {
1340 if (MO.
getReg() == PredR)
1351 assert (FoundBump &&
"Cannot determine instruction order");
1363 LoopFeederMap &LoopFeederPhi)
const {
1364 if (LoopFeederPhi.find(MO->
getReg()) == LoopFeederPhi.end()) {
1371 LoopFeederPhi.insert(std::make_pair(MO->
getReg(), Def));
1380bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1382 MachineLoop *L, LoopFeederMap &LoopFeederPhi)
const {
1383 assert(
Phi->isPHI() &&
"Expecting a Phi.");
1386 for (
int i = 1, n =
Phi->getNumOperands(); i < n; i += 2)
1387 if (isLoopFeeder(L,
MBB, Phi, &(
Phi->getOperand(i)), LoopFeederPhi))
1388 if (loopCountMayWrapOrUnderFlow(&(
Phi->getOperand(i)), EndVal,
1389 Phi->getParent(), L, LoopFeederPhi))
1408bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(
1411 LoopFeederMap &LoopFeederPhi)
const {
1413 if (!InitVal->
isReg())
1416 if (!EndVal->
isImm())
1422 if (checkForImmediate(*InitVal, Imm))
1423 return (EndVal->
getImm() == Imm);
1428 if (!
Reg.isVirtual())
1437 if (
Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal,
Def->getParent(),
1440 if (
Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(
Def->getOperand(1)),
1441 EndVal,
Def->getParent(),
1449 E =
MRI->use_instr_nodbg_end();
I != E; ++
I) {
1452 int64_t CmpMask = 0, CmpValue = 0;
1462 Comparison::Kind
Cmp =
1463 getComparisonKind(
MI->getOpcode(),
nullptr,
nullptr, 0);
1467 Cmp = Comparison::getNegatedComparison(Cmp);
1468 if (CmpReg2 != 0 && CmpReg2 == Reg)
1469 Cmp = Comparison::getSwappedComparison(Cmp);
1472 if (Comparison::isSigned(Cmp))
1478 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)
1485 if (!
Def->isCopy() && !
Def->isPHI())
1491bool HexagonHardwareLoops::checkForImmediate(
const MachineOperand &MO,
1492 int64_t &Val)
const {
1511 case TargetOpcode::COPY:
1512 case Hexagon::A2_tfrsi:
1513 case Hexagon::A2_tfrpi:
1514 case Hexagon::CONST32:
1515 case Hexagon::CONST64:
1519 if (!checkForImmediate(DI->
getOperand(1), TV))
1522 case Hexagon::A2_combineii:
1523 case Hexagon::A4_combineir:
1524 case Hexagon::A4_combineii:
1525 case Hexagon::A4_combineri:
1526 case Hexagon::A2_combinew: {
1530 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S2, V2))
1535 case TargetOpcode::REG_SEQUENCE: {
1539 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S3, V3))
1543 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)
1544 TV = V1 | (V3 << 32);
1545 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)
1546 TV = V3 | (V1 << 32);
1559 case Hexagon::isub_lo:
1560 Val = TV & 0xFFFFFFFFULL;
1562 case Hexagon::isub_hi:
1563 Val = (TV >> 32) & 0xFFFFFFFFULL;
1572void HexagonHardwareLoops::setImmediate(
MachineOperand &MO, int64_t Val) {
1590bool HexagonHardwareLoops::fixupInductionVariable(
MachineLoop *L) {
1595 if (!(Header && Latch && ExitingBlock))
1600 using RegisterBump = std::pair<Register, int64_t>;
1601 using RegisterInduction = std::pair<Register, RegisterBump>;
1602 using RegisterInductionSet = std::set<RegisterInduction>;
1605 RegisterInductionSet IndRegs;
1612 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1613 I != E &&
I->isPHI(); ++
I) {
1617 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
1618 if (
Phi->getOperand(i+1).getMBB() != Latch)
1630 if (
MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
1632 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
1638 if (IndRegs.empty())
1645 if (NotAnalyzed ||
Cond.empty())
1648 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1658 TB = (LTB == Header) ? LTB : LFB;
1660 FB = (LTB == Header) ? LTB : LFB;
1682 unsigned CSz =
Cond.size();
1683 if (CSz != 1 && CSz != 2)
1709 if (!isImmediate(MO)) {
1718 }
else if (MO.
isImm()) {
1725 if (CmpRegs.
empty())
1729 for (RegisterInductionSet::iterator
I = IndRegs.begin(), E = IndRegs.end();
1734 if (CmpRegs.
count(
I->first))
1740 const RegisterBump &RB =
I->second;
1741 if (CmpRegs.
count(RB.first)) {
1750 for (
unsigned i = 1, n = PredDef->
getNumOperands(); i < n; ++i) {
1754 <<
") = " << *(
MRI->getVRegDef(
I->first)));
1758 IndI =
MRI->getVRegDef(
I->first);
1760 }
else if (MO.
isReg()) {
1762 <<
") = " << *(
MRI->getVRegDef(MO.
getReg())));
1770 if (IndI && nonIndI &&
1771 nonIndI->
getOpcode() == Hexagon::A2_addi &&
1774 bool Order = orderBumpCompare(IndI, PredDef);
1786 Comparison::Kind
Cmp =
1787 getComparisonKind(PredDef->
getOpcode(),
nullptr,
nullptr, 0);
1788 if (!Cmp || Comparison::isUnsigned(Cmp))
1794 int64_t CmpImm = getImmediate(*CmpImmOp);
1795 int64_t
V = RB.second;
1797 if (((V > 0) && (CmpImm >
INT64_MAX - V)) ||
1811 bool Order = orderBumpCompare(BumpI, PredDef);
1816 setImmediate(*CmpImmOp, CmpImm);
1848 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1855 using MBBVector = std::vector<MachineBasicBlock *>;
1857 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1871 MF->
insert(Header->getIterator(), NewPH);
1873 if (Header->pred_size() > 2) {
1879 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1880 I != E &&
I->isPHI(); ++
I) {
1911 if (PredB != Latch) {
1920 assert(Header->pred_size() == 2);
1927 for (instr_iterator
I = Header->instr_begin(), E = Header->instr_end();
1928 I != E &&
I->isPHI(); ++
I) {
1932 if (MO.
getMBB() != Latch)
1951 assert (!NotAnalyzed &&
"Should be analyzable!");
1952 if (TB != Header && (Tmp2.
empty() || FB != Header))
1954 PB->ReplaceUsesOfBlockWith(Header, NewPH);
1962 (void)LatchNotAnalyzed;
1963 assert (!LatchNotAnalyzed &&
"Should be analyzable!");
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
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))
unsigned 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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
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.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
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()
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.
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.
iterator_range< mop_iterator > operands()
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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
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, false > use_nodbg_iterator
use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the specified register,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
FunctionPass * createHexagonHardwareLoops()
void initializeHexagonHardwareLoopsPass(PassRegistry &)
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.
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...