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");
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);
279 bool tryExtractPostIncInduction(MachineInstr *DI, MachineInstr *Phi,
281 int64_t &IVBump)
const;
302 bool fixupInductionVariable(MachineLoop *L);
306 MachineBasicBlock *createPreheaderForLoop(MachineLoop *L);
309 char HexagonHardwareLoops::ID = 0;
311 int HexagonHardwareLoops::Counter = 0;
319 enum CountValueType {
337 explicit CountValue(CountValueType t,
Register v,
unsigned u = 0) {
339 if (Kind == CV_Register) {
347 bool isReg()
const {
return Kind == CV_Register; }
348 bool isImm()
const {
return Kind == CV_Immediate; }
352 return Contents.R.Reg;
355 unsigned getSubReg()
const {
357 return Contents.R.Sub;
361 assert(isImm() &&
"Wrong CountValue accessor");
362 return Contents.ImmVal;
365 void print(raw_ostream &OS,
const TargetRegisterInfo *
TRI =
nullptr)
const {
367 if (isImm()) { OS << Contents.ImmVal; }
374 "Hexagon Hardware Loops",
false,
false)
381 return new HexagonHardwareLoops();
385 LLVM_DEBUG(
dbgs() <<
"********* Hexagon Hardware Loops *********\n");
391 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
393 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
398 MORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
401 if (L->isOutermost()) {
404 Changed |= convertToHardwareLoop(L, L0Used, L1Used);
410bool HexagonHardwareLoops::tryExtractPostIncInduction(MachineInstr *DI,
414 int64_t &IVBump)
const {
418 unsigned BasePos, OffsetPos;
428 const MachineOperand &BaseOp = DI->
getOperand(BasePos);
439bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L,
444 MachineBasicBlock *Header =
L->getHeader();
445 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
446 MachineBasicBlock *Latch =
L->getLoopLatch();
447 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
448 if (!Header || !Preheader || !Latch || !ExitingBlock)
453 using RegisterBump = std::pair<Register, int64_t>;
459 using InductionMap = std::map<Register, RegisterBump>;
465 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
466 I !=
E &&
I->isPHI(); ++
I) {
467 MachineInstr *
Phi = &*
I;
472 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
473 if (
Phi->getOperand(i+1).getMBB() != Latch)
485 if (MRI->
getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
487 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
492 if (tryExtractPostIncInduction(DI, Phi, PhiOpReg, IndReg, V))
493 IndMap.insert(std::make_pair(PhiOpReg, std::make_pair(IndReg, V)));
499 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
515 int64_t CmpImm = 0, CmpMask = 0;
526 InductionMap::iterator IndMapEnd = IndMap.end();
527 InductionMap::iterator
F = IndMapEnd;
529 InductionMap::iterator F1 = IndMap.find(CmpReg1);
534 InductionMap::iterator F2 = IndMap.find(CmpReg2);
535 if (F2 != IndMapEnd) {
544 Reg =
F->second.first;
545 IVBump =
F->second.second;
551HexagonHardwareLoops::Comparison::Kind
552HexagonHardwareLoops::getComparisonKind(
unsigned CondOpc,
553 MachineOperand *InitialValue,
554 const MachineOperand *EndValue,
555 int64_t IVBump)
const {
556 Comparison::Kind
Cmp = (Comparison::Kind)0;
558 case Hexagon::C2_cmpeq:
559 case Hexagon::C2_cmpeqi:
560 case Hexagon::C2_cmpeqp:
561 Cmp = Comparison::EQ;
563 case Hexagon::C4_cmpneq:
564 case Hexagon::C4_cmpneqi:
565 Cmp = Comparison::NE;
567 case Hexagon::C2_cmplt:
568 Cmp = Comparison::LTs;
570 case Hexagon::C2_cmpltu:
571 Cmp = Comparison::LTu;
573 case Hexagon::C4_cmplte:
574 case Hexagon::C4_cmpltei:
575 Cmp = Comparison::LEs;
577 case Hexagon::C4_cmplteu:
578 case Hexagon::C4_cmplteui:
579 Cmp = Comparison::LEu;
581 case Hexagon::C2_cmpgt:
582 case Hexagon::C2_cmpgti:
583 case Hexagon::C2_cmpgtp:
584 Cmp = Comparison::GTs;
586 case Hexagon::C2_cmpgtu:
587 case Hexagon::C2_cmpgtui:
588 case Hexagon::C2_cmpgtup:
589 Cmp = Comparison::GTu;
591 case Hexagon::C2_cmpgei:
592 Cmp = Comparison::GEs;
594 case Hexagon::C2_cmpgeui:
595 Cmp = Comparison::GEs;
598 return (Comparison::Kind)0;
610CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L,
611 SmallVectorImpl<MachineInstr *> &OldInsts) {
612 MachineBasicBlock *TopMBB =
L->getTopBlock();
615 "Loop must have more than one incoming edge!");
616 MachineBasicBlock *Backedge = *PI++;
619 MachineBasicBlock *Incoming = *PI++;
625 if (
L->contains(Incoming)) {
626 if (
L->contains(Backedge))
629 }
else if (!
L->contains(Backedge))
635 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
642 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
646 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
648 MachineOperand *InitialValue =
nullptr;
649 MachineInstr *IV_Phi = MRI->
getVRegDef(IVReg);
650 MachineBasicBlock *Latch =
L->getLoopLatch();
651 for (
unsigned i = 1, n = IV_Phi->
getNumOperands(); i < n; i += 2) {
653 if (
MBB == Preheader)
655 else if (
MBB == Latch)
662 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
667 MachineBasicBlock *Header =
L->getHeader();
671 assert (TB &&
"Exit block without a branch?");
672 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
673 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
679 TB = (LTB == Header) ? LTB : LFB;
681 FB = (LTB == Header) ? LTB: LFB;
683 assert ((!FB || TB == Header || FB == Header) &&
"Branches not to header?");
684 if (!TB || (FB && TB != Header && FB != Header))
697 MachineInstr *CondI = MRI->
getVRegDef(PredReg);
701 int64_t
Mask = 0, ImmValue = 0;
717 Comparison::Kind
Cmp;
718 bool isSwapped =
false;
719 const MachineOperand &Op1 = CondI->
getOperand(1);
720 const MachineOperand &Op2 = CondI->
getOperand(2);
721 const MachineOperand *EndValue =
nullptr;
735 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
739 Cmp = Comparison::getNegatedComparison(Cmp);
741 Cmp = Comparison::getSwappedComparison(Cmp);
743 if (InitialValue->
isReg()) {
748 if (!checkForImmediate(*InitialValue, V))
753 if (EndValue->
isReg()) {
758 if (!checkForImmediate(*EndValue, V))
764 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
771CountValue *HexagonHardwareLoops::computeCount(MachineLoop *
Loop,
772 const MachineOperand *Start,
773 const MachineOperand *End,
776 Comparison::Kind Cmp)
const {
783 if (Cmp == Comparison::EQ)
788 if (
Start->isReg()) {
790 if (StartValInstr && (StartValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
791 StartValInstr->
getOpcode() == Hexagon::A2_tfrpi))
796 if (EndValInstr && (EndValInstr->
getOpcode() == Hexagon::A2_tfrsi ||
797 EndValInstr->
getOpcode() == Hexagon::A2_tfrpi))
806 bool CmpLess =
Cmp & Comparison::L;
807 bool CmpGreater =
Cmp & Comparison::G;
808 bool CmpHasEqual =
Cmp & Comparison::EQ;
811 if (CmpLess && IVBump < 0)
815 if (CmpGreater && IVBump > 0)
820 LoopFeederMap LoopFeederPhi;
825 if (loopCountMayWrapOrUnderFlow(Start, End,
Loop->getLoopPreheader(),
Loop,
831 int64_t StartV =
Start->getImm();
832 int64_t EndV = End->
getImm();
833 int64_t Dist = EndV - StartV;
837 bool Exact = (Dist % IVBump) == 0;
839 if (Cmp == Comparison::NE) {
842 if ((Dist < 0) ^ (IVBump < 0))
849 Dist = Dist > 0 ? Dist+1 : Dist-1;
855 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))
859 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump
860 : (-Dist + (-IVBump - 1)) / (-IVBump);
861 assert (Dist1 > 0 &&
"Fishy thing. Both operands have the same sign.");
865 if (
Count > 0xFFFFFFFFULL)
868 return new CountValue(CountValue::CV_Immediate,
Count);
881 assert (PH &&
"Should have a preheader by now");
884 if (InsertPos != PH->
end())
885 DL = InsertPos->getDebugLoc();
902 bool RegToImm =
Start->isReg() && End->
isImm();
903 bool RegToReg =
Start->isReg() && End->
isReg();
905 int64_t StartV = 0, EndV = 0;
907 StartV =
Start->getImm();
924 else if (End->
isImm())
930 if (Cmp != Comparison::NE) {
932 StartV -= (IVBump-1);
933 else if (End->
isImm())
941 if (
Start->isReg()) {
943 SR =
Start->getSubReg();
951 if (!SR && RC == &Hexagon::DoubleRegsRegClass)
960 if (
Start->isImm() && StartV == 0) {
964 const MCInstrDesc &SubD = RegToReg ?
TII->get(Hexagon::A2_sub) :
965 (RegToImm ?
TII->get(Hexagon::A2_subri) :
966 TII->get(Hexagon::A2_addi));
967 if (RegToReg || RegToImm) {
969 MachineInstrBuilder SubIB =
983 if (EndValInstr->
getOpcode() == Hexagon::A2_addi &&
989 MachineInstrBuilder SubIB =
1008 MCInstrDesc
const &AddD =
TII->get(Hexagon::A2_addi);
1010 .
addReg(DistR, {}, DistSR)
1026 unsigned Shift =
Log2_32(IVBump);
1030 const MCInstrDesc &LsrD =
TII->get(Hexagon::S2_lsr_i_r);
1041 unsigned MuxSR = CountSR;
1045 if (!(
Start->isImm() && StartV == 0 && Comparison::isUnsigned(Cmp) &&
1047 (CmpLess || CmpGreater)) {
1052 const MCInstrDesc &DistCheckD =
TII->get(Hexagon::C2_cmpgti);
1053 BuildMI(*PH, InsertPos,
DL, DistCheckD, DistCheckR)
1054 .
addReg(DistR, {}, DistSR)
1055 .addImm((CmpLess) ? 0 : -1);
1062 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxir);
1065 .
addReg(CountR, {}, CountSR)
1068 const MCInstrDesc &MuxD =
TII->get(Hexagon::C2_muxri);
1072 .
addReg(CountR, {}, CountSR);
1077 return new CountValue(CountValue::CV_Register, MuxR, MuxSR);
1081bool HexagonHardwareLoops::isInvalidLoopOperation(
const MachineInstr *
MI,
1082 bool IsInnerHWLoop)
const {
1085 if (
MI->getDesc().isCall())
1089 using namespace Hexagon;
1091 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };
1092 static const Register Regs1[] = { LC1, SA1 };
1095 if (
MI->modifiesRegister(R,
TRI))
1103bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L,
1104 bool IsInnerHWLoop)
const {
1107 for (MachineBasicBlock *
MBB :
L->getBlocks()) {
1108 for (
const MachineInstr &
MI : *
MBB) {
1109 if (isInvalidLoopOperation(&
MI, IsInnerHWLoop)) {
1123bool HexagonHardwareLoops::isDead(
const MachineInstr *
MI,
1124 SmallVectorImpl<MachineInstr *> &DeadPhis)
const {
1126 for (
const MachineOperand &MO :
MI->operands()) {
1141 if (std::next(
I) != End || !
I->getParent()->isPHI())
1145 for (
const MachineOperand &OPO : OnePhi->
operands()) {
1146 if (!OPO.isReg() || !OPO.isDef())
1150 use_nodbg_iterator nextJ;
1152 J != End; J = nextJ) {
1153 nextJ = std::next(J);
1154 MachineOperand &
Use = *J;
1155 MachineInstr *
UseMI =
Use.getParent();
1169void HexagonHardwareLoops::removeIfDead(MachineInstr *
MI) {
1179 for (
const MachineOperand &MO :
MI->operands()) {
1185 for (MachineOperand &MO :
1195 MI->eraseFromParent();
1196 for (
unsigned i = 0; i < DeadPhis.
size(); ++i)
1197 DeadPhis[i]->eraseFromParent();
1209bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L,
1213 assert(
L->getHeader() &&
"Loop without a header?");
1216 bool L0Used =
false;
1217 bool L1Used =
false;
1220 for (MachineLoop *
I : *L) {
1221 Changed |= convertToHardwareLoop(
I, RecL0used, RecL1used);
1222 L0Used |= RecL0used;
1223 L1Used |= RecL1used;
1227 if (
Changed && L0Used && L1Used)
1237 unsigned IsInnerHWLoop = 1;
1240 LOOP_i = Hexagon::J2_loop1i;
1241 LOOP_r = Hexagon::J2_loop1r;
1242 ENDLOOP = Hexagon::ENDLOOP1;
1245 LOOP_i = Hexagon::J2_loop0i;
1246 LOOP_r = Hexagon::J2_loop0r;
1247 ENDLOOP = Hexagon::ENDLOOP0;
1261 if (containsInvalidInstruction(L, IsInnerHWLoop)) {
1263 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"InvalidInstruction",
1264 L->getStartLoc(),
L->getHeader())
1265 <<
"loop contains an instruction that prevents hardware loop "
1266 "generation (e.g. a call or hardware loop register definition)";
1271 MachineBasicBlock *LastMBB =
L->findLoopControlBlock();
1275 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"MultipleExits",
1276 L->getStartLoc(),
L->getHeader())
1277 <<
"loop has multiple exits and cannot be converted to a "
1284 if (LastI == LastMBB->
end())
1288 if (!fixupInductionVariable(L)) {
1290 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"InductionVariable",
1291 L->getStartLoc(),
L->getHeader())
1292 <<
"could not identify or fix up the induction variable";
1299 MachineBasicBlock *Preheader = MLI->findLoopPreheader(L,
SpecPreheader);
1301 Preheader = createPreheaderForLoop(L);
1308 SmallVector<MachineInstr*, 2> OldInsts;
1313 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
"TripCount",
1314 L->getStartLoc(),
L->getHeader())
1315 <<
"trip count of the loop could not be computed";
1321 if (TripCount->isReg()) {
1324 MachineInstr *TCDef = MRI->
getVRegDef(TripCount->getReg());
1325 MachineBasicBlock *BBDef = TCDef->
getParent();
1326 if (!MDT->
dominates(BBDef, Preheader)) {
1328 return MachineOptimizationRemarkMissed(
DEBUG_TYPE,
1329 "TripCountNotDominating",
1330 L->getStartLoc(),
L->getHeader())
1331 <<
"trip count register is not available in the loop preheader";
1338 MachineBasicBlock *TopBlock =
L->getTopBlock();
1339 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1340 MachineBasicBlock *LoopStart =
nullptr;
1341 if (ExitingBlock !=
L->getLoopLatch()) {
1342 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1348 if (
L->contains(TB))
1350 else if (
L->contains(FB))
1356 LoopStart = TopBlock;
1361 if (InsertPos != Preheader->
end())
1362 DL = InsertPos->getDebugLoc();
1364 if (TripCount->isReg()) {
1367 BuildMI(*Preheader, InsertPos,
DL,
TII->get(TargetOpcode::COPY), CountReg)
1368 .
addReg(TripCount->getReg(), {}, TripCount->getSubReg());
1373 assert(TripCount->isImm() &&
"Expecting immediate value for trip count");
1377 int64_t CountImm = TripCount->getImm();
1380 BuildMI(*Preheader, InsertPos,
DL,
TII->get(Hexagon::A2_tfrsi), CountReg)
1393 DebugLoc LastIDL = LastI->getDebugLoc();
1399 if (LastI->getOpcode() == Hexagon::J2_jumpt ||
1400 LastI->getOpcode() == Hexagon::J2_jumpf) {
1402 MachineBasicBlock *
BranchTarget = LastI->getOperand(1).getMBB();
1403 LastI = LastMBB->
erase(LastI);
1404 if (!
L->contains(BranchTarget)) {
1405 if (LastI != LastMBB->
end())
1406 LastI = LastMBB->
erase(LastI);
1412 LastMBB->
erase(LastI);
1418 for (
unsigned i = 0; i < OldInsts.
size(); ++i)
1419 removeIfDead(OldInsts[i]);
1424 return MachineOptimizationRemark(
DEBUG_TYPE,
"HardwareLoop",
1425 L->getStartLoc(),
L->getHeader())
1426 <<
"converted loop to hardware loop";
1440bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI,
1441 MachineInstr *CmpI) {
1442 assert (BumpI != CmpI &&
"Bump and compare in the same instruction?");
1444 MachineBasicBlock *BB = BumpI->
getParent();
1457 bool FoundBump =
false;
1458 instr_iterator CmpIt = CmpI->
getIterator(), NextIt = std::next(CmpIt);
1459 for (instr_iterator
I = NextIt,
E = BB->
instr_end();
I !=
E; ++
I) {
1460 MachineInstr *
In = &*
I;
1461 for (
unsigned i = 0, n =
In->getNumOperands(); i < n; ++i) {
1462 MachineOperand &MO =
In->getOperand(i);
1464 if (MO.
getReg() == PredR)
1475 assert (FoundBump &&
"Cannot determine instruction order");
1484bool HexagonHardwareLoops::isLoopFeeder(MachineLoop *L, MachineBasicBlock *
A,
1486 const MachineOperand *MO,
1487 LoopFeederMap &LoopFeederPhi)
const {
1488 if (LoopFeederPhi.find(MO->
getReg()) == LoopFeederPhi.end()) {
1495 LoopFeederPhi.
insert(std::make_pair(MO->
getReg(), Def));
1504bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1505 MachineInstr *Phi,
const MachineOperand *EndVal, MachineBasicBlock *
MBB,
1506 MachineLoop *L, LoopFeederMap &LoopFeederPhi)
const {
1507 assert(
Phi->isPHI() &&
"Expecting a Phi.");
1510 for (
int i = 1, n =
Phi->getNumOperands(); i < n; i += 2)
1511 if (isLoopFeeder(L,
MBB, Phi, &(
Phi->getOperand(i)), LoopFeederPhi))
1512 if (loopCountMayWrapOrUnderFlow(&(
Phi->getOperand(i)), EndVal,
1513 Phi->getParent(), L, LoopFeederPhi))
1532bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(
1533 const MachineOperand *InitVal,
const MachineOperand *EndVal,
1534 MachineBasicBlock *
MBB, MachineLoop *L,
1535 LoopFeederMap &LoopFeederPhi)
const {
1537 if (!InitVal->
isReg())
1540 if (!EndVal->
isImm())
1546 if (checkForImmediate(*InitVal,
Imm))
1561 if (
Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal,
Def->getParent(),
1564 if (
Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(
Def->getOperand(1)),
1565 EndVal,
Def->getParent(),
1574 MachineInstr *
MI = &*
I;
1576 int64_t CmpMask = 0, CmpValue = 0;
1581 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
1586 Comparison::Kind
Cmp =
1587 getComparisonKind(
MI->getOpcode(),
nullptr,
nullptr, 0);
1591 Cmp = Comparison::getNegatedComparison(Cmp);
1592 if (CmpReg2 != 0 && CmpReg2 ==
Reg)
1593 Cmp = Comparison::getSwappedComparison(Cmp);
1596 if (Comparison::isSigned(Cmp))
1602 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)
1609 if (!
Def->isCopy() && !
Def->isPHI())
1615bool HexagonHardwareLoops::checkForImmediate(
const MachineOperand &MO,
1616 int64_t &Val)
const {
1635 case TargetOpcode::COPY:
1636 case Hexagon::A2_tfrsi:
1637 case Hexagon::A2_tfrpi:
1638 case Hexagon::CONST32:
1639 case Hexagon::CONST64:
1643 if (!checkForImmediate(DI->
getOperand(1), TV))
1646 case Hexagon::A2_combineii:
1647 case Hexagon::A4_combineir:
1648 case Hexagon::A4_combineii:
1649 case Hexagon::A4_combineri:
1650 case Hexagon::A2_combinew: {
1652 const MachineOperand &S2 = DI->
getOperand(2);
1654 if (!checkForImmediate(
S1,
V1) || !checkForImmediate(S2, V2))
1659 case TargetOpcode::REG_SEQUENCE: {
1661 const MachineOperand &S3 = DI->
getOperand(3);
1663 if (!checkForImmediate(
S1,
V1) || !checkForImmediate(S3,
V3))
1667 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)
1668 TV =
V1 | (
V3 << 32);
1669 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)
1670 TV =
V3 | (
V1 << 32);
1683 case Hexagon::isub_lo:
1684 Val = TV & 0xFFFFFFFFULL;
1686 case Hexagon::isub_hi:
1687 Val = (TV >> 32) & 0xFFFFFFFFULL;
1696void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) {
1714bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
1715 MachineBasicBlock *Header =
L->getHeader();
1716 MachineBasicBlock *Latch =
L->getLoopLatch();
1717 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1719 if (!(Header && Latch && ExitingBlock))
1724 using RegisterBump = std::pair<Register, int64_t>;
1725 using RegisterInduction = std::pair<Register, RegisterBump>;
1726 using RegisterInductionSet = std::set<RegisterInduction>;
1729 RegisterInductionSet IndRegs;
1736 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
1737 I !=
E &&
I->isPHI(); ++
I) {
1738 MachineInstr *
Phi = &*
I;
1741 for (
unsigned i = 1, n =
Phi->getNumOperands(); i < n; i += 2) {
1742 if (
Phi->getOperand(i+1).getMBB() != Latch)
1754 if (MRI->
getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
1756 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
1761 if (tryExtractPostIncInduction(DI, Phi, PhiReg, IndReg, V))
1762 IndRegs.insert(std::make_pair(PhiReg, std::make_pair(IndReg, V)));
1767 if (IndRegs.empty())
1770 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1777 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1778 MachineBasicBlock *LTB =
nullptr, *LFB =
nullptr;
1787 TB = (LTB == Header) ? LTB : LFB;
1789 FB = (LTB == Header) ? LTB : LFB;
1812 if (CSz != 1 && CSz != 2)
1824 SmallSet<Register,2> CmpRegs;
1825 MachineOperand *CmpImmOp =
nullptr;
1831 for (MachineOperand &MO : PredDef->
operands()) {
1838 if (!isImmediate(MO)) {
1847 }
else if (MO.
isImm()) {
1854 if (CmpRegs.
empty())
1858 for (RegisterInductionSet::iterator
I = IndRegs.begin(),
E = IndRegs.end();
1863 if (CmpRegs.
count(
I->first))
1869 const RegisterBump &RB =
I->second;
1870 if (CmpRegs.
count(RB.first)) {
1874 MachineInstr *IndI =
nullptr;
1875 MachineInstr *nonIndI =
nullptr;
1876 MachineOperand *IndMO =
nullptr;
1877 MachineOperand *nonIndMO =
nullptr;
1879 for (
unsigned i = 1, n = PredDef->
getNumOperands(); i < n; ++i) {
1889 }
else if (MO.
isReg()) {
1899 if (IndI && nonIndI &&
1900 nonIndI->
getOpcode() == Hexagon::A2_addi &&
1903 bool Order = orderBumpCompare(IndI, PredDef);
1915 Comparison::Kind
Cmp =
1916 getComparisonKind(PredDef->
getOpcode(),
nullptr,
nullptr, 0);
1917 if (!Cmp || Comparison::isUnsigned(Cmp))
1923 int64_t CmpImm = getImmediate(*CmpImmOp);
1924 int64_t
V = RB.second;
1926 if (((V > 0) && (CmpImm >
INT64_MAX - V)) ||
1940 bool Order = orderBumpCompare(BumpI, PredDef);
1945 setImmediate(*CmpImmOp, CmpImm);
1946 for (MachineOperand &MO : PredDef->
operands()) {
1959MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop(
1961 if (MachineBasicBlock *TmpPH = MLI->findLoopPreheader(L,
SpecPreheader))
1966 MachineBasicBlock *Header =
L->getHeader();
1967 MachineBasicBlock *Latch =
L->getLoopLatch();
1968 MachineBasicBlock *ExitingBlock =
L->findLoopControlBlock();
1977 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1984 using MBBVector = std::vector<MachineBasicBlock *>;
1986 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1988 MachineBasicBlock *
TB =
nullptr, *FB =
nullptr;
1993 for (MachineBasicBlock *
PB : Preds) {
2000 MF->
insert(Header->getIterator(), NewPH);
2002 if (Header->pred_size() > 2) {
2008 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
2009 I !=
E &&
I->isPHI(); ++
I) {
2010 MachineInstr *PN = &*
I;
2012 const MCInstrDesc &
PD =
TII->get(TargetOpcode::PHI);
2013 MachineInstr *NewPN = MF->CreateMachineInstr(PD,
DL);
2040 if (PredB != Latch) {
2049 assert(Header->pred_size() == 2);
2056 for (instr_iterator
I = Header->instr_begin(),
E = Header->instr_end();
2057 I !=
E &&
I->isPHI(); ++
I) {
2058 MachineInstr *PN = &*
I;
2061 if (MO.
getMBB() != Latch)
2075 for (MachineBasicBlock *
PB : Preds) {
2080 assert (!NotAnalyzed &&
"Should be analyzable!");
2081 if (TB != Header && (Tmp2.
empty() || FB != Header))
2083 PB->ReplaceUsesOfBlockWith(Header, NewPH);
2091 (void)LatchNotAnalyzed;
2092 assert (!LatchNotAnalyzed &&
"Should be analyzable!");
2100 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 isPostIncWithImmOffset(const MachineInstr &MI) 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 getPredReg(ArrayRef< MachineOperand > Cond, Register &PredReg, unsigned &PredRegPos, RegState &PredRegFlags) const
bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
For instructions with a base and offset, return the position of the base register and offset operands...
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.
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.
LLVM_ABI unsigned findTiedOperandIdx(unsigned OpIdx) const
Given the index of a tied register operand, find the operand it is tied to.
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 LLVM_READONLY 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.
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
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.
@ 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.
RelativeUniformCounterPtr Values
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()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.