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");
109 bool runOnMachineFunction(MachineFunction &MF)
override;
111 StringRef getPassName()
const override {
return "Hexagon Hardware Loops"; }
113 void getAnalysisUsage(AnalysisUsage &AU)
const override {
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) {
176 bool findInductionRegister(MachineLoop *L,
Register &
Reg,
177 int64_t &IVBump, MachineInstr *&IVOp)
const;
180 Comparison::Kind getComparisonKind(
unsigned CondOpc,
181 MachineOperand *InitialValue,
182 const MachineOperand *Endvalue,
183 int64_t IVBump)
const;
188 CountValue *getLoopTripCount(MachineLoop *L,
189 SmallVectorImpl<MachineInstr *> &OldInsts);
198 CountValue *computeCount(MachineLoop *Loop,
const MachineOperand *Start,
199 const MachineOperand *End,
Register IVReg,
200 int64_t IVBump, Comparison::Kind Cmp)
const;
204 bool isInvalidLoopOperation(
const MachineInstr *
MI,
205 bool IsInnerHWLoop)
const;
209 bool containsInvalidInstruction(MachineLoop *L,
bool IsInnerHWLoop)
const;
213 bool convertToHardwareLoop(MachineLoop *L,
bool &L0used,
bool &L1used);
217 SmallVectorImpl<MachineInstr *> &DeadPhis)
const;
220 void removeIfDead(MachineInstr *
MI);
226 bool orderBumpCompare(MachineInstr *BumpI, MachineInstr *CmpI);
231 bool isLoopFeeder(MachineLoop *L, MachineBasicBlock *
A, MachineInstr *
MI,
232 const MachineOperand *MO,
233 LoopFeederMap &LoopFeederPhi)
const;
237 bool phiMayWrapOrUnderflow(MachineInstr *Phi,
const MachineOperand *EndVal,
238 MachineBasicBlock *
MBB, MachineLoop *L,
239 LoopFeederMap &LoopFeederPhi)
const;
243 bool loopCountMayWrapOrUnderFlow(
const MachineOperand *InitVal,
244 const MachineOperand *EndVal,
245 MachineBasicBlock *
MBB, MachineLoop *L,
246 LoopFeederMap &LoopFeederPhi)
const;
251 bool checkForImmediate(
const MachineOperand &MO, int64_t &Val)
const;
254 bool isImmediate(
const MachineOperand &MO)
const {
256 return checkForImmediate(MO, V);
260 int64_t getImmediate(
const MachineOperand &MO)
const {
262 if (!checkForImmediate(MO, V))
270 void setImmediate(MachineOperand &MO, int64_t Val);
291 bool fixupInductionVariable(MachineLoop *L);
295 MachineBasicBlock *createPreheaderForLoop(MachineLoop *L);
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;
354 void print(raw_ostream &OS,
const TargetRegisterInfo *
TRI =
nullptr)
const {
356 if (isImm()) { OS << Contents.ImmVal; }
363 "Hexagon Hardware Loops",
false,
false)
370 return new HexagonHardwareLoops();
374 LLVM_DEBUG(
dbgs() <<
"********* Hexagon Hardware Loops *********\n");
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,
402 MachineBasicBlock *Header =
L->getHeader();
403 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
404 MachineBasicBlock *Latch =
L->getLoopLatch();
405 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
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) {
425 MachineInstr *
Phi = &*
I;
430 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
431 if (
Phi->getOperand(i+1).getMBB() != Latch)
435 MachineInstr *DI =
MRI->getVRegDef(PhiOpReg);
443 if (
MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
445 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
452 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
458 unsigned PredPos, PredRegFlags;
462 MachineInstr *PredI =
MRI->getVRegDef(PredR);
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,
505 MachineOperand *InitialValue,
506 const MachineOperand *EndValue,
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,
563 SmallVectorImpl<MachineInstr *> &OldInsts) {
564 MachineBasicBlock *TopMBB =
L->getTopBlock();
567 "Loop must have more than one incoming edge!");
568 MachineBasicBlock *Backedge = *PI++;
571 MachineBasicBlock *Incoming = *PI++;
577 if (
L->contains(Incoming)) {
578 if (
L->contains(Backedge))
581 }
else if (!
L->contains(Backedge))
587 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
594 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
598 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
600 MachineOperand *InitialValue =
nullptr;
601 MachineInstr *IV_Phi =
MRI->getVRegDef(IVReg);
602 MachineBasicBlock *Latch =
L->getLoopLatch();
603 for (
unsigned i = 1, n = IV_Phi->
getNumOperands(); i < n; i += 2) {
605 if (
MBB == Preheader)
607 else if (
MBB == Latch)
614 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
619 MachineBasicBlock *Header =
L->getHeader();
623 assert (TB &&
"Exit block without a branch?");
624 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
625 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
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;
648 MachineInstr *CondI =
MRI->getVRegDef(PredReg);
652 int64_t
Mask = 0, ImmValue = 0;
668 Comparison::Kind
Cmp;
669 bool isSwapped =
false;
670 const MachineOperand &Op1 = CondI->
getOperand(1);
671 const MachineOperand &Op2 = CondI->
getOperand(2);
672 const MachineOperand *EndValue =
nullptr;
686 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
690 Cmp = Comparison::getNegatedComparison(Cmp);
692 Cmp = Comparison::getSwappedComparison(Cmp);
694 if (InitialValue->
isReg()) {
696 MachineBasicBlock *DefBB =
MRI->getVRegDef(R)->getParent();
699 if (!checkForImmediate(*InitialValue, V))
704 if (EndValue->
isReg()) {
706 MachineBasicBlock *DefBB =
MRI->getVRegDef(R)->getParent();
709 if (!checkForImmediate(*EndValue, V))
715 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
722CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop,
723 const MachineOperand *Start,
724 const MachineOperand *End,
727 Comparison::Kind Cmp)
const {
734 if (Cmp == Comparison::EQ)
739 if (
Start->isReg()) {
740 const MachineInstr *StartValInstr =
MRI->getVRegDef(
Start->getReg());
741 if (StartValInstr && (StartValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
742 StartValInstr->
getOpcode() == Hexagon::A2_tfrpi))
746 const MachineInstr *EndValInstr =
MRI->getVRegDef(End->
getReg());
747 if (EndValInstr && (EndValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
748 EndValInstr->
getOpcode() == Hexagon::A2_tfrpi))
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;
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.");
814 uint64_t
Count = Dist1;
816 if (
Count > 0xFFFFFFFFULL)
819 return new CountValue(CountValue::CV_Immediate,
Count);
831 MachineBasicBlock *PH = MLI->findLoopPreheader(Loop,
SpecPreheader);
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();
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();
899 const TargetRegisterClass *RC =
MRI->getRegClass(R);
902 if (!SR && RC == &Hexagon::DoubleRegsRegClass)
904 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
911 if (
Start->isImm() && StartV == 0) {
915 const MCInstrDesc &SubD = RegToReg ?
TII->get(Hexagon::A2_sub) :
916 (RegToImm ?
TII->get(Hexagon::A2_subri) :
917 TII->get(Hexagon::A2_addi));
918 if (RegToReg || RegToImm) {
920 MachineInstrBuilder SubIB =
934 const MachineInstr *EndValInstr =
MRI->getVRegDef(End->
getReg());
935 if (EndValInstr->
getOpcode() == Hexagon::A2_addi &&
941 MachineInstrBuilder SubIB =
961 MCInstrDesc
const &AddD =
TII->get(Hexagon::A2_addi);
979 unsigned Shift =
Log2_32(IVBump);
983 const MCInstrDesc &LsrD =
TII->get(Hexagon::S2_lsr_i_r);
992 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
994 unsigned MuxSR = CountSR;
998 if (!(
Start->isImm() && StartV == 0 && Comparison::isUnsigned(Cmp) &&
1000 (CmpLess || CmpGreater)) {
1004 Register DistCheckR =
MRI->createVirtualRegister(PredRC);
1005 const MCInstrDesc &DistCheckD =
TII->get(Hexagon::C2_cmpgti);
1006 BuildMI(*PH, InsertPos,
DL, DistCheckD, DistCheckR)
1007 .
addReg(DistR, 0, DistSR)
1008 .
addImm((CmpLess) ? 0 : -1);
1013 MuxR =
MRI->createVirtualRegister(IntRC);
1015 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxir);
1018 .
addReg(CountR, 0, CountSR)
1021 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxri);
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 {
1060 for (MachineBasicBlock *
MBB :
L->getBlocks()) {
1061 for (
const MachineInstr &
MI : *
MBB) {
1062 if (isInvalidLoopOperation(&
MI, IsInnerHWLoop)) {
1076bool HexagonHardwareLoops::isDead(
const MachineInstr *
MI,
1077 SmallVectorImpl<MachineInstr *> &DeadPhis)
const {
1079 for (
const MachineOperand &MO :
MI->operands()) {
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())
1097 MachineInstr *OnePhi =
I->getParent();
1098 for (
const MachineOperand &OPO : OnePhi->
operands()) {
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);
1107 MachineOperand &
Use = *J;
1108 MachineInstr *
UseMI =
Use.getParent();
1122void HexagonHardwareLoops::removeIfDead(MachineInstr *
MI) {
1132 for (
const MachineOperand &MO :
MI->operands()) {
1138 for (MachineOperand &MO :
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?");
1169 bool L0Used =
false;
1170 bool L1Used =
false;
1173 for (MachineLoop *
I : *L) {
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))
1217 MachineBasicBlock *LastMBB =
L->findLoopControlBlock();
1223 if (LastI == LastMBB->
end())
1227 if (!fixupInductionVariable(L))
1232 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
1234 Preheader = createPreheaderForLoop(L);
1241 SmallVector<MachineInstr*, 2> OldInsts;
1243 CountValue *TripCount = getLoopTripCount(L, OldInsts);
1248 if (TripCount->isReg()) {
1251 MachineInstr *TCDef =
MRI->getVRegDef(TripCount->getReg());
1252 MachineBasicBlock *BBDef = TCDef->
getParent();
1258 MachineBasicBlock *TopBlock =
L->getTopBlock();
1259 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1260 MachineBasicBlock *LoopStart =
nullptr;
1261 if (ExitingBlock !=
L->getLoopLatch()) {
1262 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
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) {
1322 MachineBasicBlock *
BranchTarget = LastI->getOperand(1).getMBB();
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,
1355 MachineInstr *CmpI) {
1356 assert (BumpI != CmpI &&
"Bump and compare in the same instruction?");
1358 MachineBasicBlock *BB = BumpI->
getParent();
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) {
1374 MachineInstr *
In = &*
I;
1375 for (
unsigned i = 0, n =
In->getNumOperands(); i < n; ++i) {
1376 MachineOperand &MO =
In->getOperand(i);
1378 if (MO.
getReg() == PredR)
1389 assert (FoundBump &&
"Cannot determine instruction order");
1398bool HexagonHardwareLoops::isLoopFeeder(MachineLoop *L, MachineBasicBlock *
A,
1400 const MachineOperand *MO,
1401 LoopFeederMap &LoopFeederPhi)
const {
1402 if (LoopFeederPhi.find(MO->
getReg()) == LoopFeederPhi.end()) {
1409 LoopFeederPhi.insert(std::make_pair(MO->
getReg(), Def));
1418bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1419 MachineInstr *Phi,
const MachineOperand *EndVal, MachineBasicBlock *
MBB,
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(
1447 const MachineOperand *InitVal,
const MachineOperand *EndVal,
1448 MachineBasicBlock *
MBB, MachineLoop *L,
1449 LoopFeederMap &LoopFeederPhi)
const {
1451 if (!InitVal->
isReg())
1454 if (!EndVal->
isImm())
1460 if (checkForImmediate(*InitVal, Imm))
1461 return (EndVal->
getImm() == Imm);
1469 MachineInstr *
Def =
MRI->getVRegDef(
Reg);
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) {
1488 MachineInstr *
MI = &*
I;
1490 int64_t CmpMask = 0, CmpValue = 0;
1495 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
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 {
1546 MachineInstr *DI =
MRI->getVRegDef(R);
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: {
1566 const MachineOperand &S2 = DI->
getOperand(2);
1568 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S2, V2))
1570 TV = V2 | (
static_cast<uint64_t
>(V1) << 32);
1573 case TargetOpcode::REG_SEQUENCE: {
1575 const MachineOperand &S3 = DI->
getOperand(3);
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) {
1618 MachineInstr *DI =
MRI->getVRegDef(R);
1620 const TargetRegisterClass *RC =
MRI->getRegClass(R);
1628bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
1629 MachineBasicBlock *Header =
L->getHeader();
1630 MachineBasicBlock *Latch =
L->getLoopLatch();
1631 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
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) {
1652 MachineInstr *
Phi = &*
I;
1655 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
1656 if (
Phi->getOperand(i+1).getMBB() != Latch)
1660 MachineInstr *DI =
MRI->getVRegDef(PhiReg);
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())
1679 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1683 if (NotAnalyzed ||
Cond.empty())
1686 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1687 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
1696 TB = (LTB == Header) ? LTB : LFB;
1698 FB = (LTB == Header) ? LTB : LFB;
1720 unsigned CSz =
Cond.size();
1721 if (CSz != 1 && CSz != 2)
1728 MachineInstr *PredDef =
MRI->getVRegDef(
P);
1733 SmallSet<Register,2> CmpRegs;
1734 MachineOperand *CmpImmOp =
nullptr;
1740 for (MachineOperand &MO : PredDef->
operands()) {
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)) {
1783 MachineInstr *IndI =
nullptr;
1784 MachineInstr *nonIndI =
nullptr;
1785 MachineOperand *IndMO =
nullptr;
1786 MachineOperand *nonIndMO =
nullptr;
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)) ||
1848 MachineInstr *BumpI =
MRI->getVRegDef(
I->first);
1849 bool Order = orderBumpCompare(BumpI, PredDef);
1854 setImmediate(*CmpImmOp, CmpImm);
1855 for (MachineOperand &MO : PredDef->
operands()) {
1868MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop(
1870 if (MachineBasicBlock *TmpPH = MLI->findLoopPreheader(L,
SpecPreheader))
1875 MachineBasicBlock *Header =
L->getHeader();
1876 MachineBasicBlock *Latch =
L->getLoopLatch();
1877 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1878 MachineFunction *MF = Header->getParent();
1886 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1893 using MBBVector = std::vector<MachineBasicBlock *>;
1895 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1897 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1902 for (MachineBasicBlock *
PB : Preds) {
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) {
1919 MachineInstr *PN = &*
I;
1921 const MCInstrDesc &
PD =
TII->get(TargetOpcode::PHI);
1922 MachineInstr *NewPN = MF->CreateMachineInstr(PD,
DL);
1926 const TargetRegisterClass *RC =
MRI->getRegClass(PR);
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) {
1967 MachineInstr *PN = &*
I;
1970 if (MO.
getMBB() != Latch)
1984 for (MachineBasicBlock *
PB : Preds) {
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!");
2009 MachineLoop *ParentLoop =
L->getParentLoop();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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
Promote Memory to Register
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)
SmallVector< MachineBasicBlock *, 4 > MBBVector
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)
AnalysisUsage & addRequired()
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.
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
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.
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.
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)
CreateMachineInstr - Allocate a new MachineInstr.
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
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
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)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, true, true > use_instr_nodbg_iterator
use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk all uses of the specified r...
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,...
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
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.
void push_back(const T &Elt)
self_iterator getIterator()
#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.
@ 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< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
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()
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
@ Sub
Subtraction of integers.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.