67#define DEBUG_TYPE "hwloops"
80 cl::desc(
"Add a preheader to a hardware loop if one doesn't exist"));
86 cl::desc(
"Allow speculation of preheader "
89STATISTIC(NumHWLoops,
"Number of loops converted to hardware loops");
111 bool runOnMachineFunction(MachineFunction &MF)
override;
113 StringRef getPassName()
const override {
return "Hexagon Hardware Loops"; }
115 void getAnalysisUsage(AnalysisUsage &AU)
const override {
118 AU.
addRequired<MachineOptimizationRemarkEmitterPass>();
123 using LoopFeederMap = std::map<Register, MachineInstr *>;
143 static Kind getSwappedComparison(Kind Cmp) {
144 assert ((!((Cmp & L) && (Cmp & G))) &&
"Malformed comparison operator");
145 if ((Cmp & L) || (Cmp & G))
146 return (Kind)(
Cmp ^ (L|G));
150 static Kind getNegatedComparison(Kind Cmp) {
151 if ((Cmp & L) || (Cmp & G))
152 return (Kind)((
Cmp ^ (L | G)) ^ EQ);
153 if ((Cmp & NE) || (Cmp & EQ))
154 return (Kind)(
Cmp ^ (EQ | NE));
159 return (Cmp & (L | G) && !(Cmp & U));
162 static bool isUnsigned(Kind Cmp) {
179 bool findInductionRegister(MachineLoop *L,
Register &
Reg,
180 int64_t &IVBump, MachineInstr *&IVOp)
const;
183 Comparison::Kind getComparisonKind(
unsigned CondOpc,
184 MachineOperand *InitialValue,
185 const MachineOperand *Endvalue,
186 int64_t IVBump)
const;
192 SmallVectorImpl<MachineInstr *> &OldInsts);
201 CountValue *computeCount(MachineLoop *Loop,
const MachineOperand *Start,
202 const MachineOperand *End,
Register IVReg,
203 int64_t IVBump, Comparison::Kind Cmp)
const;
207 bool isInvalidLoopOperation(
const MachineInstr *
MI,
208 bool IsInnerHWLoop)
const;
212 bool containsInvalidInstruction(MachineLoop *L,
bool IsInnerHWLoop)
const;
216 bool convertToHardwareLoop(MachineLoop *L,
bool &L0used,
bool &L1used);
220 SmallVectorImpl<MachineInstr *> &DeadPhis)
const;
223 void removeIfDead(MachineInstr *
MI);
229 bool orderBumpCompare(MachineInstr *BumpI, MachineInstr *CmpI);
234 bool isLoopFeeder(MachineLoop *L, MachineBasicBlock *
A, MachineInstr *
MI,
235 const MachineOperand *MO,
236 LoopFeederMap &LoopFeederPhi)
const;
240 bool phiMayWrapOrUnderflow(MachineInstr *Phi,
const MachineOperand *EndVal,
241 MachineBasicBlock *
MBB, MachineLoop *L,
242 LoopFeederMap &LoopFeederPhi)
const;
246 bool loopCountMayWrapOrUnderFlow(
const MachineOperand *InitVal,
247 const MachineOperand *EndVal,
248 MachineBasicBlock *
MBB, MachineLoop *L,
249 LoopFeederMap &LoopFeederPhi)
const;
254 bool checkForImmediate(
const MachineOperand &MO, int64_t &Val)
const;
257 bool isImmediate(
const MachineOperand &MO)
const {
259 return checkForImmediate(MO, V);
263 int64_t getImmediate(
const MachineOperand &MO)
const {
265 if (!checkForImmediate(MO, V))
273 void setImmediate(MachineOperand &MO, int64_t Val);
294 bool fixupInductionVariable(MachineLoop *L);
298 MachineBasicBlock *createPreheaderForLoop(MachineLoop *L);
301 char HexagonHardwareLoops::ID = 0;
303 int HexagonHardwareLoops::Counter = 0;
311 enum CountValueType {
320 Values(
const Values&) =
default;
329 explicit CountValue(CountValueType t,
Register v,
unsigned u = 0) {
331 if (Kind == CV_Register) {
339 bool isReg()
const {
return Kind == CV_Register; }
340 bool isImm()
const {
return Kind == CV_Immediate; }
344 return Contents.R.Reg;
347 unsigned getSubReg()
const {
349 return Contents.R.Sub;
353 assert(isImm() &&
"Wrong CountValue accessor");
354 return Contents.ImmVal;
357 void print(raw_ostream &OS,
const TargetRegisterInfo *
TRI =
nullptr)
const {
359 if (isImm()) { OS << Contents.ImmVal; }
366 "Hexagon Hardware Loops",
false,
false)
373 return new HexagonHardwareLoops();
377 LLVM_DEBUG(
dbgs() <<
"********* Hexagon Hardware Loops *********\n");
383 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
385 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
390 MORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
393 if (L->isOutermost()) {
396 Changed |= convertToHardwareLoop(L, L0Used, L1Used);
402bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L,
407 MachineBasicBlock *Header =
L->getHeader();
408 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
409 MachineBasicBlock *Latch =
L->getLoopLatch();
410 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
411 if (!Header || !Preheader || !Latch || !ExitingBlock)
416 using RegisterBump = std::pair<Register, int64_t>;
422 using InductionMap = std::map<Register, RegisterBump>;
428 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
429 I !=
E &&
I->isPHI(); ++
I) {
430 MachineInstr *
Phi = &*
I;
435 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
436 if (
Phi->getOperand(i+1).getMBB() != Latch)
448 if (MRI->
getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
450 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
457 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
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;
509HexagonHardwareLoops::Comparison::Kind
510HexagonHardwareLoops::getComparisonKind(
unsigned CondOpc,
511 MachineOperand *InitialValue,
512 const MachineOperand *EndValue,
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,
569 SmallVectorImpl<MachineInstr *> &OldInsts) {
570 MachineBasicBlock *TopMBB =
L->getTopBlock();
573 "Loop must have more than one incoming edge!");
574 MachineBasicBlock *Backedge = *PI++;
577 MachineBasicBlock *Incoming = *PI++;
583 if (
L->contains(Incoming)) {
584 if (
L->contains(Backedge))
587 }
else if (!
L->contains(Backedge))
593 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
600 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
604 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
606 MachineOperand *InitialValue =
nullptr;
607 MachineInstr *IV_Phi = MRI->
getVRegDef(IVReg);
608 MachineBasicBlock *Latch =
L->getLoopLatch();
609 for (
unsigned i = 1, n = IV_Phi->
getNumOperands(); i < n; i += 2) {
611 if (
MBB == Preheader)
613 else if (
MBB == Latch)
620 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
625 MachineBasicBlock *Header =
L->getHeader();
629 assert (TB &&
"Exit block without a branch?");
630 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
631 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
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))
655 MachineInstr *CondI = MRI->
getVRegDef(PredReg);
659 int64_t
Mask = 0, ImmValue = 0;
675 Comparison::Kind
Cmp;
676 bool isSwapped =
false;
677 const MachineOperand &Op1 = CondI->
getOperand(1);
678 const MachineOperand &Op2 = CondI->
getOperand(2);
679 const MachineOperand *EndValue =
nullptr;
693 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
697 Cmp = Comparison::getNegatedComparison(Cmp);
699 Cmp = Comparison::getSwappedComparison(Cmp);
701 if (InitialValue->
isReg()) {
706 if (!checkForImmediate(*InitialValue, V))
711 if (EndValue->
isReg()) {
716 if (!checkForImmediate(*EndValue, V))
722 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
729CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop,
730 const MachineOperand *Start,
731 const MachineOperand *End,
734 Comparison::Kind Cmp)
const {
741 if (Cmp == Comparison::EQ)
746 if (
Start->isReg()) {
748 if (StartValInstr && (StartValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
749 StartValInstr->
getOpcode() == Hexagon::A2_tfrpi))
754 if (EndValInstr && (EndValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
755 EndValInstr->
getOpcode() == Hexagon::A2_tfrpi))
764 bool CmpLess =
Cmp & Comparison::L;
765 bool CmpGreater =
Cmp & Comparison::G;
766 bool CmpHasEqual =
Cmp & Comparison::EQ;
769 if (CmpLess && IVBump < 0)
773 if (CmpGreater && IVBump > 0)
778 LoopFeederMap LoopFeederPhi;
789 int64_t StartV =
Start->getImm();
790 int64_t EndV = End->
getImm();
791 int64_t Dist = EndV - StartV;
795 bool Exact = (Dist % IVBump) == 0;
797 if (Cmp == Comparison::NE) {
800 if ((Dist < 0) ^ (IVBump < 0))
807 Dist = Dist > 0 ? Dist+1 : Dist-1;
813 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))
817 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump
818 : (-Dist + (-IVBump - 1)) / (-IVBump);
819 assert (Dist1 > 0 &&
"Fishy thing. Both operands have the same sign.");
821 uint64_t
Count = Dist1;
823 if (
Count > 0xFFFFFFFFULL)
826 return new CountValue(CountValue::CV_Immediate,
Count);
838 MachineBasicBlock *PH = MLI->findLoopPreheader(Loop,
SpecPreheader);
839 assert (PH &&
"Should have a preheader by now");
842 if (InsertPos != PH->
end())
843 DL = InsertPos->getDebugLoc();
860 bool RegToImm =
Start->isReg() && End->
isImm();
861 bool RegToReg =
Start->isReg() && End->
isReg();
863 int64_t StartV = 0, EndV = 0;
865 StartV =
Start->getImm();
882 else if (End->
isImm())
888 if (Cmp != Comparison::NE) {
890 StartV -= (IVBump-1);
891 else if (End->
isImm())
899 if (
Start->isReg()) {
901 SR =
Start->getSubReg();
906 const TargetRegisterClass *RC = MRI->
getRegClass(R);
909 if (!SR && RC == &Hexagon::DoubleRegsRegClass)
911 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
918 if (
Start->isImm() && StartV == 0) {
922 const MCInstrDesc &SubD = RegToReg ?
TII->get(Hexagon::A2_sub) :
923 (RegToImm ?
TII->get(Hexagon::A2_subri) :
924 TII->get(Hexagon::A2_addi));
925 if (RegToReg || RegToImm) {
927 MachineInstrBuilder SubIB =
941 if (EndValInstr->
getOpcode() == Hexagon::A2_addi &&
947 MachineInstrBuilder SubIB =
966 MCInstrDesc
const &AddD =
TII->get(Hexagon::A2_addi);
968 .
addReg(DistR, {}, DistSR)
984 unsigned Shift =
Log2_32(IVBump);
988 const MCInstrDesc &LsrD =
TII->get(Hexagon::S2_lsr_i_r);
997 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
999 unsigned MuxSR = CountSR;
1003 if (!(
Start->isImm() && StartV == 0 && Comparison::isUnsigned(Cmp) &&
1005 (CmpLess || CmpGreater)) {
1010 const MCInstrDesc &DistCheckD =
TII->get(Hexagon::C2_cmpgti);
1011 BuildMI(*PH, InsertPos,
DL, DistCheckD, DistCheckR)
1012 .
addReg(DistR, {}, DistSR)
1013 .addImm((CmpLess) ? 0 : -1);
1020 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxir);
1023 .
addReg(CountR, {}, CountSR)
1026 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxri);
1030 .
addReg(CountR, {}, CountSR);
1035 return new CountValue(CountValue::CV_Register, MuxR, MuxSR);
1039bool HexagonHardwareLoops::isInvalidLoopOperation(
const MachineInstr *
MI,
1040 bool IsInnerHWLoop)
const {
1043 if (
MI->getDesc().isCall())
1047 using namespace Hexagon;
1049 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };
1050 static const Register Regs1[] = { LC1, SA1 };
1053 if (
MI->modifiesRegister(R,
TRI))
1061bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L,
1062 bool IsInnerHWLoop)
const {
1065 for (MachineBasicBlock *
MBB :
L->getBlocks()) {
1066 for (
const MachineInstr &
MI : *
MBB) {
1067 if (isInvalidLoopOperation(&
MI, IsInnerHWLoop)) {
1081bool HexagonHardwareLoops::isDead(
const MachineInstr *
MI,
1082 SmallVectorImpl<MachineInstr *> &DeadPhis)
const {
1084 for (
const MachineOperand &MO :
MI->operands()) {
1099 if (std::next(
I) != End || !
I->getParent()->isPHI())
1103 for (
const MachineOperand &OPO : OnePhi->
operands()) {
1104 if (!OPO.isReg() || !OPO.isDef())
1108 use_nodbg_iterator nextJ;
1110 J != End; J = nextJ) {
1111 nextJ = std::next(J);
1112 MachineOperand &
Use = *J;
1113 MachineInstr *
UseMI =
Use.getParent();
1127void HexagonHardwareLoops::removeIfDead(MachineInstr *
MI) {
1137 for (
const MachineOperand &MO :
MI->operands()) {
1143 for (MachineOperand &MO :
1153 MI->eraseFromParent();
1154 for (
unsigned i = 0; i < DeadPhis.
size(); ++i)
1155 DeadPhis[i]->eraseFromParent();
1167bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L,
1171 assert(
L->getHeader() &&
"Loop without a header?");
1174 bool L0Used =
false;
1175 bool L1Used =
false;
1178 for (MachineLoop *
I : *L) {
1179 Changed |= convertToHardwareLoop(
I, RecL0used, RecL1used);
1180 L0Used |= RecL0used;
1181 L1Used |= RecL1used;
1185 if (
Changed && L0Used && L1Used)
1195 unsigned IsInnerHWLoop = 1;
1198 LOOP_i = Hexagon::J2_loop1i;
1199 LOOP_r = Hexagon::J2_loop1r;
1200 ENDLOOP = Hexagon::ENDLOOP1;
1203 LOOP_i = Hexagon::J2_loop0i;
1204 LOOP_r = Hexagon::J2_loop0r;
1205 ENDLOOP = Hexagon::ENDLOOP0;
1219 if (containsInvalidInstruction(L, IsInnerHWLoop)) {
1221 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"InvalidInstruction",
1222 L->getStartLoc(),
L->getHeader())
1223 <<
"loop contains an instruction that prevents hardware loop "
1224 "generation (e.g. a call or hardware loop register definition)";
1229 MachineBasicBlock *LastMBB =
L->findLoopControlBlock();
1233 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"MultipleExits",
1234 L->getStartLoc(),
L->getHeader())
1235 <<
"loop has multiple exits and cannot be converted to a "
1242 if (LastI == LastMBB->
end())
1246 if (!fixupInductionVariable(L)) {
1248 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"InductionVariable",
1249 L->getStartLoc(),
L->getHeader())
1250 <<
"could not identify or fix up the induction variable";
1257 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
1259 Preheader = createPreheaderForLoop(L);
1266 SmallVector<MachineInstr*, 2> OldInsts;
1271 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"TripCount",
1272 L->getStartLoc(),
L->getHeader())
1273 <<
"trip count of the loop could not be computed";
1279 if (TripCount->isReg()) {
1282 MachineInstr *TCDef = MRI->
getVRegDef(TripCount->getReg());
1283 MachineBasicBlock *BBDef = TCDef->
getParent();
1284 if (!MDT->
dominates(BBDef, Preheader)) {
1286 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
1287 "TripCountNotDominating",
1288 L->getStartLoc(),
L->getHeader())
1289 <<
"trip count register is not available in the loop preheader";
1296 MachineBasicBlock *TopBlock =
L->getTopBlock();
1297 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1298 MachineBasicBlock *LoopStart =
nullptr;
1299 if (ExitingBlock !=
L->getLoopLatch()) {
1300 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1306 if (
L->contains(TB))
1308 else if (
L->contains(FB))
1314 LoopStart = TopBlock;
1319 if (InsertPos != Preheader->
end())
1320 DL = InsertPos->getDebugLoc();
1322 if (TripCount->isReg()) {
1325 BuildMI(*Preheader, InsertPos,
DL,
TII->get(TargetOpcode::COPY), CountReg)
1326 .
addReg(TripCount->getReg(), {}, TripCount->getSubReg());
1331 assert(TripCount->isImm() &&
"Expecting immediate value for trip count");
1335 int64_t CountImm = TripCount->getImm();
1338 BuildMI(*Preheader, InsertPos,
DL,
TII->get(Hexagon::A2_tfrsi), CountReg)
1351 DebugLoc LastIDL = LastI->getDebugLoc();
1357 if (LastI->getOpcode() == Hexagon::J2_jumpt ||
1358 LastI->getOpcode() == Hexagon::J2_jumpf) {
1360 MachineBasicBlock *
BranchTarget = LastI->getOperand(1).getMBB();
1361 LastI = LastMBB->
erase(LastI);
1362 if (!
L->contains(BranchTarget)) {
1363 if (LastI != LastMBB->
end())
1364 LastI = LastMBB->
erase(LastI);
1370 LastMBB->
erase(LastI);
1376 for (
unsigned i = 0; i < OldInsts.
size(); ++i)
1377 removeIfDead(OldInsts[i]);
1382 return MachineOptimizationRemark(
DEBUG_TYPE,
"HardwareLoop",
1383 L->getStartLoc(),
L->getHeader())
1384 <<
"converted loop to hardware loop";
1398bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI,
1399 MachineInstr *CmpI) {
1400 assert (BumpI != CmpI &&
"Bump and compare in the same instruction?");
1402 MachineBasicBlock *BB = BumpI->
getParent();
1415 bool FoundBump =
false;
1416 instr_iterator CmpIt = CmpI->
getIterator(), NextIt = std::next(CmpIt);
1417 for (instr_iterator
I = NextIt,
E = BB->
instr_end();
I !=
E; ++
I) {
1418 MachineInstr *
In = &*
I;
1419 for (
unsigned i = 0, n =
In->getNumOperands(); i < n; ++i) {
1420 MachineOperand &MO =
In->getOperand(i);
1422 if (MO.
getReg() == PredR)
1433 assert (FoundBump &&
"Cannot determine instruction order");
1442bool HexagonHardwareLoops::isLoopFeeder(MachineLoop *L, MachineBasicBlock *
A,
1444 const MachineOperand *MO,
1445 LoopFeederMap &LoopFeederPhi)
const {
1446 if (LoopFeederPhi.find(MO->
getReg()) == LoopFeederPhi.end()) {
1453 LoopFeederPhi.
insert(std::make_pair(MO->
getReg(), Def));
1462bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1463 MachineInstr *Phi,
const MachineOperand *EndVal, MachineBasicBlock *
MBB,
1464 MachineLoop *L, LoopFeederMap &LoopFeederPhi)
const {
1465 assert(
Phi->isPHI() &&
"Expecting a Phi.");
1468 for (
int i = 1, n =
Phi->getNumOperands(); i < n; i += 2)
1469 if (isLoopFeeder(L,
MBB, Phi, &(
Phi->getOperand(i)), LoopFeederPhi))
1470 if (loopCountMayWrapOrUnderFlow(&(
Phi->getOperand(i)), EndVal,
1471 Phi->getParent(), L, LoopFeederPhi))
1490bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(
1491 const MachineOperand *InitVal,
const MachineOperand *EndVal,
1492 MachineBasicBlock *
MBB, MachineLoop *L,
1493 LoopFeederMap &LoopFeederPhi)
const {
1495 if (!InitVal->
isReg())
1498 if (!EndVal->
isImm())
1504 if (checkForImmediate(*InitVal, Imm))
1505 return (EndVal->
getImm() == Imm);
1519 if (
Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal,
Def->getParent(),
1522 if (
Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(
Def->getOperand(1)),
1523 EndVal,
Def->getParent(),
1532 MachineInstr *
MI = &*
I;
1534 int64_t CmpMask = 0, CmpValue = 0;
1539 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
1544 Comparison::Kind
Cmp =
1545 getComparisonKind(
MI->getOpcode(),
nullptr,
nullptr, 0);
1549 Cmp = Comparison::getNegatedComparison(Cmp);
1550 if (CmpReg2 != 0 && CmpReg2 ==
Reg)
1551 Cmp = Comparison::getSwappedComparison(Cmp);
1554 if (Comparison::isSigned(Cmp))
1560 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)
1567 if (!
Def->isCopy() && !
Def->isPHI())
1573bool HexagonHardwareLoops::checkForImmediate(
const MachineOperand &MO,
1574 int64_t &Val)
const {
1593 case TargetOpcode::COPY:
1594 case Hexagon::A2_tfrsi:
1595 case Hexagon::A2_tfrpi:
1596 case Hexagon::CONST32:
1597 case Hexagon::CONST64:
1601 if (!checkForImmediate(DI->
getOperand(1), TV))
1604 case Hexagon::A2_combineii:
1605 case Hexagon::A4_combineir:
1606 case Hexagon::A4_combineii:
1607 case Hexagon::A4_combineri:
1608 case Hexagon::A2_combinew: {
1610 const MachineOperand &S2 = DI->
getOperand(2);
1612 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S2, V2))
1614 TV = V2 | (
static_cast<uint64_t
>(V1) << 32);
1617 case TargetOpcode::REG_SEQUENCE: {
1619 const MachineOperand &S3 = DI->
getOperand(3);
1621 if (!checkForImmediate(
S1, V1) || !checkForImmediate(S3, V3))
1625 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)
1626 TV = V1 | (V3 << 32);
1627 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)
1628 TV = V3 | (V1 << 32);
1641 case Hexagon::isub_lo:
1642 Val = TV & 0xFFFFFFFFULL;
1644 case Hexagon::isub_hi:
1645 Val = (TV >> 32) & 0xFFFFFFFFULL;
1654void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) {
1664 const TargetRegisterClass *RC = MRI->
getRegClass(R);
1672bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
1673 MachineBasicBlock *Header =
L->getHeader();
1674 MachineBasicBlock *Latch =
L->getLoopLatch();
1675 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1677 if (!(Header && Latch && ExitingBlock))
1682 using RegisterBump = std::pair<Register, int64_t>;
1683 using RegisterInduction = std::pair<Register, RegisterBump>;
1684 using RegisterInductionSet = std::set<RegisterInduction>;
1687 RegisterInductionSet IndRegs;
1694 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
1695 I !=
E &&
I->isPHI(); ++
I) {
1696 MachineInstr *
Phi = &*
I;
1699 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
1700 if (
Phi->getOperand(i+1).getMBB() != Latch)
1712 if (MRI->
getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
1714 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
1720 if (IndRegs.empty())
1723 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1727 if (NotAnalyzed ||
Cond.empty())
1730 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1731 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
1740 TB = (LTB == Header) ? LTB : LFB;
1742 FB = (LTB == Header) ? LTB : LFB;
1764 unsigned CSz =
Cond.size();
1765 if (CSz != 1 && CSz != 2)
1777 SmallSet<Register,2> CmpRegs;
1778 MachineOperand *CmpImmOp =
nullptr;
1784 for (MachineOperand &MO : PredDef->
operands()) {
1791 if (!isImmediate(MO)) {
1800 }
else if (MO.
isImm()) {
1807 if (CmpRegs.
empty())
1811 for (RegisterInductionSet::iterator
I = IndRegs.begin(),
E = IndRegs.end();
1816 if (CmpRegs.
count(
I->first))
1822 const RegisterBump &RB =
I->second;
1823 if (CmpRegs.
count(RB.first)) {
1827 MachineInstr *IndI =
nullptr;
1828 MachineInstr *nonIndI =
nullptr;
1829 MachineOperand *IndMO =
nullptr;
1830 MachineOperand *nonIndMO =
nullptr;
1832 for (
unsigned i = 1, n = PredDef->
getNumOperands(); i < n; ++i) {
1842 }
else if (MO.
isReg()) {
1852 if (IndI && nonIndI &&
1853 nonIndI->
getOpcode() == Hexagon::A2_addi &&
1856 bool Order = orderBumpCompare(IndI, PredDef);
1868 Comparison::Kind
Cmp =
1869 getComparisonKind(PredDef->
getOpcode(),
nullptr,
nullptr, 0);
1870 if (!Cmp || Comparison::isUnsigned(Cmp))
1876 int64_t CmpImm = getImmediate(*CmpImmOp);
1877 int64_t
V = RB.second;
1879 if (((V > 0) && (CmpImm >
INT64_MAX - V)) ||
1893 bool Order = orderBumpCompare(BumpI, PredDef);
1898 setImmediate(*CmpImmOp, CmpImm);
1899 for (MachineOperand &MO : PredDef->
operands()) {
1912MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop(
1914 if (MachineBasicBlock *TmpPH = MLI->findLoopPreheader(L,
SpecPreheader))
1919 MachineBasicBlock *Header =
L->getHeader();
1920 MachineBasicBlock *Latch =
L->getLoopLatch();
1921 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1922 MachineFunction *MF = Header->getParent();
1930 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1937 using MBBVector = std::vector<MachineBasicBlock *>;
1939 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1941 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1946 for (MachineBasicBlock *
PB : Preds) {
1953 MF->
insert(Header->getIterator(), NewPH);
1955 if (Header->pred_size() > 2) {
1961 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
1962 I !=
E &&
I->isPHI(); ++
I) {
1963 MachineInstr *PN = &*
I;
1965 const MCInstrDesc &
PD =
TII->get(TargetOpcode::PHI);
1966 MachineInstr *NewPN = MF->CreateMachineInstr(PD,
DL);
1970 const TargetRegisterClass *RC = MRI->
getRegClass(PR);
1993 if (PredB != Latch) {
2002 assert(Header->pred_size() == 2);
2009 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
2010 I !=
E &&
I->isPHI(); ++
I) {
2011 MachineInstr *PN = &*
I;
2014 if (MO.
getMBB() != Latch)
2028 for (MachineBasicBlock *
PB : Preds) {
2033 assert (!NotAnalyzed &&
"Should be analyzable!");
2034 if (TB != Header && (Tmp2.
empty() || FB != Header))
2036 PB->ReplaceUsesOfBlockWith(Header, NewPH);
2044 (void)LatchNotAnalyzed;
2045 assert (!LatchNotAnalyzed &&
"Should be analyzable!");
2053 MachineLoop *ParentLoop =
L->getParentLoop();
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 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 MCRegister 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
static unsigned getLoopTripCount(const Loop *L, ScalarEvolution &SE)
Get the assumed loop trip count for the loop L.
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 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 getPredReg(ArrayRef< MachineOperand > Cond, Register &PredReg, unsigned &PredRegPos, RegState &PredRegFlags) 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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & 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.
LLVM_ABI void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
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,...
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
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...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
static use_nodbg_iterator use_nodbg_end()
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
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,...
iterator_range< use_iterator > use_operands(Register Reg) const
static use_instr_nodbg_iterator use_instr_nodbg_end()
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.
RegState
Flags to represent properties of register accesses.
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.