274 InstrToIdMap InstrToId;
277 void initializeTables() {
279 calcInstrIds(&BB, InstrToId);
280 initializeCfgPaths();
281 initializeInterBlockDistances();
289 resetDistanceCache();
303 void calcInstrIds(
const MachineBasicBlock *BB,
304 InstrToIdMap &MutableInstrToId)
const {
307 MutableInstrToId[&
MI] =
Id;
314 InstrIdTy getInstrId(
const MachineInstr *
MI)
const {
315 auto It = InstrToId.find(
MI);
316 if (It != InstrToId.end())
321 auto &MutableInstrToId =
const_cast<InstrToIdMap &
>(InstrToId);
322 calcInstrIds(
MI->getParent(), MutableInstrToId);
323 return InstrToId.find(
MI)->second;
328 InstrIdTy getHeadLen(
const MachineInstr *
MI)
const {
335 InstrIdTy getTailLen(
const MachineInstr *
MI)
const {
342 InstrIdTy getDistance(
const MachineInstr *From,
343 const MachineInstr *To)
const {
345 return getInstrId(To) - getInstrId(From);
352 DenseMap<Register, SmallVector<const MachineOperand *>> RegUseMap;
356 auto I = RegUseMap.find(
Reg);
357 if (
I != RegUseMap.end())
362 for (
const MachineOperand &UseMO : MRI->use_nodbg_operands(
Reg)) {
363 if (!UseMO.isUndef())
364 Uses.push_back(&UseMO);
370 return !getRegisterUses(
Reg).empty();
379 std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
383 constexpr Path() : P(nullptr, nullptr) {}
384 constexpr Path(
const MachineBasicBlock *Src,
const MachineBasicBlock *Dst)
386 Path(
const StorageTy &Pair) : P(Pair) {}
388 constexpr operator const StorageTy &()
const {
return P; }
389 using DenseMapInfo = llvm::DenseMapInfo<StorageTy>;
391 const MachineBasicBlock *src()
const {
return P.first; }
392 const MachineBasicBlock *dst()
const {
return P.second; }
395 enum class EdgeKind { Back = -1, None = 0, Forward = 1 };
396 static constexpr StringRef toString(EdgeKind EK) {
397 if (EK == EdgeKind::Back)
399 if (EK == EdgeKind::Forward)
407 int ForwardReachable;
408 unsigned RelativeLoopDepth;
409 std::optional<NextUseDistance> ShortestDistance;
410 std::optional<NextUseDistance> ShortestUnweightedDistance;
414 : EK(EdgeKind::
None), Reachable(
false), ForwardReachable(-1),
415 RelativeLoopDepth(0), Size(0) {}
417 bool isBackedge()
const {
return EK == EdgeKind::Back; }
419 bool isForwardReachableSet()
const {
return 0 <= ForwardReachable; }
420 bool isForwardReachableUnset()
const {
return ForwardReachable < 0; }
421 bool isForwardReachable()
const {
return ForwardReachable == 1; }
422 bool isNotForwardReachable()
const {
return ForwardReachable == 0; }
424 void print(raw_ostream &OS)
const {
425 OS <<
"{ek=" <<
toString(EK) <<
" reach=" << Reachable
426 <<
" fwd-reach=" << ForwardReachable
427 <<
" loop-depth=" << RelativeLoopDepth <<
" size=" << Size;
428 if (ShortestDistance) {
429 OS <<
" shortest-dist=";
430 ShortestDistance->print(OS);
432 if (ShortestUnweightedDistance) {
433 OS <<
" shortest-unweighted-dist=";
434 ShortestUnweightedDistance->print(OS);
450 DenseMap<Path, PathInfo, Path::DenseMapInfo> Paths;
452 const PathInfo *maybePathInfoFor(
const MachineBasicBlock *From,
453 const MachineBasicBlock *To)
const {
454 auto I = Paths.find({From, To});
455 return I == Paths.end() ? nullptr : &
I->second;
458 PathInfo &getOrInitPathInfo(
const MachineBasicBlock *From,
459 const MachineBasicBlock *To)
const {
461 auto &MutablePaths = NonConstThis->Paths;
464 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
468 bool Reachable = calcIsReachable(
P.src(),
P.dst());
472 return NonConstThis->initializePathInfo(MutablePaths.at(
P),
P,
473 EdgeKind::None, Reachable);
476 const PathInfo &pathInfoFor(
const MachineBasicBlock *From,
477 const MachineBasicBlock *To)
const {
478 return getOrInitPathInfo(From, To);
485 PathInfo &initializePathInfo(PathInfo &Slot, Path
P, EdgeKind EK,
488 Slot.Reachable = Reachable;
489 Slot.ForwardReachable = EK == EdgeKind::None ? -1 : EK == EdgeKind::Forward;
490 Slot.RelativeLoopDepth =
491 Slot.Reachable ? calcRelativeLoopDepth(
P.src(),
P.dst()) : 0;
492 Slot.Size =
P.src() ==
P.dst() ? calcSize(
P.src()) : 0;
493 if (EK != EdgeKind::None)
494 Slot.ShortestUnweightedDistance = 0;
498 PathInfo &initializePathInfo(Path
P, EdgeKind EK,
bool Reachable)
const {
500 auto &MutablePaths = NonConstThis->Paths;
501 return NonConstThis->initializePathInfo(MutablePaths[
P],
P, EK, Reachable);
504 bool initializePathInfoForwardReachable(
const MachineBasicBlock *From,
505 const MachineBasicBlock *To,
507 PathInfo &
Slot = getOrInitPathInfo(From, To);
514 initializePathInfoShortestDistance(
const MachineBasicBlock *From,
515 const MachineBasicBlock *To,
516 NextUseDistance
Value)
const {
517 PathInfo &
Slot = getOrInitPathInfo(From, To);
524 initializePathInfoShortestUnweightedDistance(
const MachineBasicBlock *From,
525 const MachineBasicBlock *To,
526 NextUseDistance
Value)
const {
527 PathInfo &
Slot = getOrInitPathInfo(From, To);
528 assert(!
Slot.ShortestUnweightedDistance.has_value());
539 for (
const Path &
P : ReachablePaths)
540 initializePathInfo(
P, EdgeKind::None,
true);
541 for (
const Path &
P : UnreachablePaths)
542 initializePathInfo(
P, EdgeKind::None,
false);
548 for (
bool R : {
true,
false}) {
549 const auto &ToInit =
R ? ReachablePaths : UnreachablePaths;
550 for (
const Path &
P : ToInit) {
551 PathInfo &
Slot = getOrInitPathInfo(
P.src(),
P.dst());
552 assert(
Slot.isForwardReachableUnset() ||
Slot.ForwardReachable == R);
553 Slot.ForwardReachable =
R;
561 void initializeCfgPaths() {
564 enum VisitState { Undiscovered, Visiting, Finished };
565 DenseMap<const MachineBasicBlock *, VisitState> State;
568 State[&MF->front()] = Undiscovered;
570 while (!Work.
empty()) {
571 const MachineBasicBlock *Src = Work.
back();
572 VisitState &SrcState = State[Src];
577 if (SrcState == Visiting || SrcState == Finished) {
584 for (
const MachineBasicBlock *Dst : Src->successors()) {
585 const VisitState DstState = State.
lookup(Dst);
588 if (DstState == Undiscovered) {
589 EK = EdgeKind::Forward;
591 }
else if (DstState == Visiting) {
594 EK = EdgeKind::Forward;
599 initializePathInfo(
P, EK,
true);
610 static bool isStandAloneLoop(
const MachineLoop *
Loop) {
611 return Loop->getSubLoops().empty() &&
Loop->isOutermost();
614 static MachineLoop *findChildLoop(MachineLoop *
const Parent,
615 MachineLoop *Descendant) {
616 for (MachineLoop *L = Descendant;
L != Parent;
L =
L->getParentLoop()) {
617 if (
L->getParentLoop() == Parent)
626 static std::pair<MachineLoop *, unsigned>
627 findCommonParent(MachineLoop *
A,
const MachineLoop *
B) {
629 for (;
A !=
nullptr;
A =
A->getParentLoop(), ++
Depth) {
636 static const MachineBasicBlock *
637 getOutermostPreheader(
const MachineLoop *
Loop) {
638 return Loop ?
Loop->getOutermostLoop()->getLoopPreheader() :
nullptr;
641 static MachineBasicBlock *findChildPreheader(MachineLoop *
const Parent,
642 MachineLoop *Descendant) {
643 MachineLoop *ChildLoop = findChildLoop(Parent, Descendant);
647 static const MachineBasicBlock *
648 getIncomingBlockIfPhiUse(
const MachineInstr *
MI,
const MachineOperand *MO) {
657 InstrIdTy calcSize(
const MachineBasicBlock *BB)
const {
665 unsigned calcRelativeLoopDepth(
const MachineBasicBlock *From,
666 const MachineBasicBlock *To)
const {
667 MachineLoop *LoopFrom = MLI->getLoopFor(From);
668 MachineLoop *LoopTo = MLI->getLoopFor(To);
683 return findCommonParent(LoopFrom, LoopTo).second;
690 bool calcIsReachable(
const MachineBasicBlock *From,
691 const MachineBasicBlock *To,
692 bool ForwardOnly =
false)
const {
693 if (From == To && !MLI->getLoopFor(From))
696 if (!ForwardOnly && interBlockDistanceExists(From, To))
699 enum { VisitOp, PopOp };
700 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
702 DenseSet<const MachineBasicBlock *> Visited{From};
708 auto Finally = [&](
bool Reachable) {
713 IntermediatePath.
clear();
714 for (
const MachineBasicBlock *
MBB : Visited) {
721 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
723 initializePaths(IntermediatePath, Unreachable);
728 while (!Work.
empty()) {
739 if (Current->succ_empty())
742 if (Current != From) {
747 for (
const MachineBasicBlock *Succ : Current->successors()) {
748 if (ForwardOnly && isBackedge(Current, Succ))
754 if (
auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
755 if (CachedReachable.value())
757 Visited.insert(Succ);
761 if (Visited.insert(Succ).second)
780 struct InterBlockDistance {
781 NextUseDistance Weighted;
782 NextUseDistance Unweighted;
783 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
784 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
785 : Weighted(
W), Unweighted(UW) {}
786 bool operator==(
const InterBlockDistance &
Other)
const {
787 return Weighted ==
Other.Weighted && Unweighted ==
Other.Unweighted;
789 bool operator!=(
const InterBlockDistance &
Other)
const {
790 return !(*
this ==
Other);
793 void print(raw_ostream &OS)
const {
797 Unweighted.print(OS);
806 using InterBlockDistanceMap =
807 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
808 InterBlockDistanceMap InterBlockDistances;
810 void initializeInterBlockDistances() {
811 InterBlockDistanceMap Distances;
820 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
821 InterBlockDistanceMap::mapped_type Curr;
822 Curr.reserve(Prev.size());
827 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
831 unsigned SuccNum = Succ->getNumber();
832 const unsigned UnweightedSize{getSize(Succ)};
834 for (
const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
837 if (DestBlockNum == MBBNum)
840 const MachineBasicBlock *DestMBB =
841 MF->getBlockNumbered(DestBlockNum);
843 const NextUseDistance UnweightedDist{UnweightedSize +
844 DestDist.Unweighted};
846 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
848 const NextUseDistance WeightedDist =
854 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
856 InterBlockDistance &
Slot =
I->second;
858 Slot.Unweighted =
min(
Slot.Unweighted, UnweightedDist);
863 Distances[MBBNum] = std::move(Curr);
867 InterBlockDistances = std::move(Distances);
871 const InterBlockDistance *
872 getInterBlockDistanceMapValue(
const MachineBasicBlock *From,
873 const MachineBasicBlock *To)
const {
874 auto I = InterBlockDistances.find(From->
getNumber());
875 if (
I == InterBlockDistances.end())
877 const InterBlockDistanceMap::mapped_type &FromSlot =
I->second;
879 return J == FromSlot.end() ? nullptr : &J->second;
882 bool interBlockDistanceExists(
const MachineBasicBlock *From,
883 const MachineBasicBlock *To)
const {
884 return getInterBlockDistanceMapValue(From, To);
887 NextUseDistance getInterBlockDistance(
const MachineBasicBlock *From,
888 const MachineBasicBlock *To,
889 bool Unweighted)
const {
891 assert(From != To &&
"The basic blocks should be different.");
895 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
898 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
902 return Unweighted ? BD->Unweighted : BD->Weighted;
906 getWeightedInterBlockDistance(
const MachineBasicBlock *From,
907 const MachineBasicBlock *To)
const {
908 return getInterBlockDistance(From, To,
false);
912 getUnweightedInterBlockDistance(
const MachineBasicBlock *From,
913 const MachineBasicBlock *To)
const {
914 return getInterBlockDistance(From, To,
true);
921 InstrIdTy getSize(
const MachineBasicBlock *BB)
const {
922 return pathInfoFor(BB, BB).Size;
925 bool isReachable(
const MachineBasicBlock *From,
926 const MachineBasicBlock *To)
const {
927 return pathInfoFor(From, To).Reachable;
930 bool isReachableOrSame(
const MachineBasicBlock *From,
931 const MachineBasicBlock *To)
const {
932 return From == To || pathInfoFor(From, To).Reachable;
935 bool isForwardReachable(
const MachineBasicBlock *From,
936 const MachineBasicBlock *To)
const {
937 const PathInfo &PI = pathInfoFor(From, To);
938 if (PI.isForwardReachableSet())
939 return PI.isForwardReachable();
941 return initializePathInfoForwardReachable(
943 PI.Reachable && calcIsReachable(From, To,
true));
948 std::optional<bool> isMaybeReachable(
const MachineBasicBlock *From,
949 const MachineBasicBlock *To,
950 bool ForwardOnly)
const {
951 const PathInfo *PI = maybePathInfoFor(From, To);
956 if (PI->isForwardReachable())
959 if (PI->isNotForwardReachable())
963 return PI->Reachable;
966 bool isBackedge(
const MachineBasicBlock *From,
967 const MachineBasicBlock *To)
const {
968 return pathInfoFor(From, To).isBackedge();
973 bool instrsAreInOrder(
const MachineInstr *
A,
const MachineInstr *
B)
const {
974 assert(
A->getParent() ==
B->getParent() &&
975 "instructions must be in the same basic block!");
976 if (
A ==
B || getInstrId(
A) < getInstrId(
B))
982 for (
auto &
PHI :
A->getParent()->phis()) {
991 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
992 const MachineBasicBlock *To)
const {
993 std::optional<NextUseDistance> MaybeD =
994 pathInfoFor(From, To).ShortestDistance;
995 if (MaybeD.has_value())
996 return MaybeD.value();
998 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
999 return initializePathInfoShortestDistance(From, To, Dist);
1002 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
1003 const MachineBasicBlock *To)
const {
1004 std::optional<NextUseDistance> MaybeD =
1005 pathInfoFor(From, To).ShortestUnweightedDistance;
1006 if (MaybeD.has_value())
1007 return MaybeD.value();
1009 return initializePathInfoShortestUnweightedDistance(
1010 From, To, getUnweightedInterBlockDistance(From, To));
1018 struct MBBDistPair {
1019 NextUseDistance Distance;
1020 const MachineBasicBlock *MBB;
1021 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1022 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
1023 : Distance(
D), MBB(
B) {}
1025 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
1026 MBBDistPair &operator+=(NextUseDistance
D) {
1031 void print(raw_ostream &OS)
const {
1052 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1053 const MachineLoop *CurLoop)
const {
1058 for (MachineBasicBlock *LMBB : Latches) {
1062 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1063 if (Dst <
LD.Distance) {
1073 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1074 const MachineLoop *CurLoop)
const {
1079 for (MachineBasicBlock *LMBB : Latches) {
1083 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1084 if (Dst <
LD.Distance) {
1093 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1094 const MachineLoop *CurLoop)
const {
1096 MLI->getExitEdges(*CurLoop, ExitEdges);
1099 for (
auto [Exit, Dest] : ExitEdges) {
1103 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1104 if (Dst <
LD.Distance) {
1115 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1116 MachineLoop *CurLoop)
const {
1117 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1121 return {getSize(CurMBB), CurMBB};
1123 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1124 MBBDistPair
LD{0,
nullptr};
1126 LD += getSize(LoopHeader);
1128 if (CurMBB != LoopHeader)
1129 LD += getShortestPath(LoopHeader, CurMBB);
1134 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1136 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1137 LD += getSize(CurMBB);
1139 if (
LD.MBB != LoopHeader)
1140 LD += getSize(
LD.MBB);
1147 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1148 MachineLoop *OuterLoop)
const {
1149 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1151 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1153 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1155 if (OuterLoop == CurLoop)
1159 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1161 MBBDistPair
LD{0,
nullptr};
1162 LD += getSize(ParentHdr);
1163 LD += getShortestPath(ParentHdr, CurHdr);
1164 LD += CurLD.Distance.applyLoopWeight();
1165 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1166 LD += getSize(
LD.MBB);
1168 CurLoop = ParentLoop;
1177 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1178 MachineLoop *CurLoop)
const {
1179 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1180 LD.Distance =
LD.Distance.applyLoopWeight();
1186 MBBDistPair calcWeightedDistanceThroughLoop(
1187 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1188 const MachineLoop *ParentLoop =
nullptr)
const {
1190 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1192 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1201 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1202 const MachineInstr *
UseMI,
1203 const MachineBasicBlock *UseMBB)
const {
1204 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1210 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1211 MachineLoop *CurLoop,
1212 MachineLoop *UseLoop)
const {
1215 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1216 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1217 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1221 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1222 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1223 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1224 MachineLoop *UseLoop)
const {
1225 return appendDistanceToUse(
1226 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1231 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1232 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1233 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1236 if (isStandAloneLoop(CurLoop))
1237 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1240 if (!OutermostLoop->
contains(UseLoop)) {
1246 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1252 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1253 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1255 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1256 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1261 if (CurLoop == OutermostLoop)
1264 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1269 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1270 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1271 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1272 MachineLoop *UseLoop)
const {
1273 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1274 CurMBB, CurLoop, UseMBB, UseLoop),
1279 bool machineOperandCoveredBy(
const MachineOperand &MO,
1280 LaneBitmask LaneMask)
const {
1281 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1282 return (Mask & LaneMask) ==
Mask;
1287 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1288 const MachineInstr *CurMI,
1289 const MachineInstr *
UseMI)
const {
1293 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1301 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1309 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1312 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1313 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1314 if (RegMO.
getReg() == LiveReg &&
1315 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1316 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1327 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1328 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1329 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1330 assert(UseLoop &&
"There is no backedge.");
1331 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1332 "Unexpected loop configuration");
1334 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1335 MBBDistPair InnerLoopLD =
1336 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1337 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1339 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1344 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1345 const MachineBasicBlock *CurMBB,
1346 MachineLoop *CurLoop,
1347 const MachineInstr *
UseMI)
const {
1349 InstrIdTy CurTailLen = getTailLen(CurMI);
1350 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1351 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1352 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1353 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1354 NextUseDistance Dst =
1355 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1357 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1367 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1368 const MachineInstr *ToMI)
const {
1369 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1370 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1372 if (FromMBB == ToMBB) {
1373 NextUseDistance RV = getDistance(FromMI, ToMI);
1374 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1378 InstrIdTy FromTailLen = getTailLen(FromMI);
1379 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1380 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1381 assert(Dst.isReachable() &&
1382 "calcShortestDistance called for instructions in non-reachable"
1384 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1385 assert(RV >= 0 &&
"unexpected negative distance");
1394 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1395 const MachineInstr *ToMI)
const {
1396 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1397 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1399 if (FromMBB == ToMBB)
1400 return getDistance(FromMI, ToMI);
1402 InstrIdTy FromTailLen = getTailLen(FromMI);
1403 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1404 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1405 assert(Dst.isReachable() &&
1406 "calcShortestUnweightedDistance called for instructions in"
1407 " non-reachable basic blocks!");
1408 return FromTailLen + Dst + ToHeadLen;
1423 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1424 const MachineInstr &CurMI,
1425 const MachineOperand *UseMO)
const {
1427 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1429 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1430 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1432 if (Cfg.PreciseUseModeling) {
1434 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1435 UseMI = &PhiUseEdge->back();
1436 UseMBB = PhiUseEdge;
1437 UseLoop = MLI->getLoopFor(PhiUseEdge);
1441 enum class LoopConfig {
1449 auto [LpCfg, PreHdr, CommonParent] = [&]()
1450 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1452 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1455 return {CurMBB == UseMBB ? LoopConfig::Same
1456 : LoopConfig::CurContainsUse,
1457 findChildPreheader(CurLoop, UseLoop),
nullptr};
1460 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1462 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1463 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1465 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1471 if (!Cfg.PromoteToPreheader) {
1473 case LoopConfig::NoCur:
1474 case LoopConfig::Same:
1475 case LoopConfig::CurContainsUse:
1478 case LoopConfig::UseContainsCur: {
1479 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1480 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1481 UseMI, UseMBB, UseLoop);
1485 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1487 case LoopConfig::Siblings:
1488 case LoopConfig::Unrelated:
1489 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1490 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1499 UseMI = &PreHdr->back();
1501 UseLoop = CommonParent;
1505 case LoopConfig::NoCur:
1507 (sizeOf(*
UseMI) ? 0 : 1)};
1509 case LoopConfig::Same:
1510 case LoopConfig::CurContainsUse:
1511 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1513 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1517 case LoopConfig::UseContainsCur:
1518 case LoopConfig::Siblings:
1520 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1522 case LoopConfig::Unrelated:
1523 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1524 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1535 bool isUseReachablePrecise(
const MachineInstr &
MI,
1536 const MachineBasicBlock *
MBB,
1537 const MachineOperand *UseMO,
1538 const MachineInstr *
UseMI,
1539 const MachineBasicBlock *UseMBB)
const {
1542 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1547 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1548 if (!isReachableOrSame(
MBB, PhiUseEdge))
1553 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1555 if (
MBB == UseMBB) {
1559 if (instrsAreInOrder(&
MI,
UseMI))
1564 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1565 return UseLoop && !UseLoop->
contains(DefMBB);
1569 return instrsAreInOrder(
DefMI, &
MI);
1571 MachineLoop *
Loop = MLI->getLoopFor(
MBB);
1575 MachineLoop *TopLoop =
Loop->getOutermostLoop();
1576 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1577 !isForwardReachable(UseMBB,
MBB);
1584 void printPaths(raw_ostream &OS)
const {
1585 OS <<
"\n---------------- Paths --------------- {\n";
1586 for (
const auto &[
P, PI] : Paths) {
1597 void printInterBlockDistances(raw_ostream &OS)
const {
1598 using MBBPair = std::pair<unsigned, unsigned>;
1599 using Elem = std::pair<NextUseDistance, MBBPair>;
1600 std::vector<Elem> SortedDistances;
1602 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1603 for (
const auto &[ToNum, Dist] : Dsts) {
1604 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1607 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1608 if (
A.first !=
B.first)
1609 return A.first <
B.first;
1611 if (
A.second.first !=
B.second.first)
1612 return A.second.first <
B.second.first;
1614 return A.second.second <
B.second.second;
1617 OS <<
"\n--------- InterBlockDistances -------- {\n";
1618 for (
const Elem &
E : SortedDistances) {
1620 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1628 printInterBlockDistances(
dbgs());
1639 struct LiveRegToUseMapElem {
1642 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1643 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1644 : Use(
U), MIDependent(MIDep) {}
1646 void print(raw_ostream &OS)
const {
1648 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1659 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1660 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1662 const MachineInstr *CachedDistancesMI =
nullptr;
1663 LiveRegToUseMap CachedDistances;
1664 LiveRegToUseMap PendingCachedDistances;
1665 unsigned DistanceCacheHits = 0;
1666 unsigned DistanceCacheMisses = 0;
1668 void resetDistanceCache() {
1669 CachedDistancesMI =
nullptr;
1670 CachedDistances.clear();
1671 DistanceCacheHits = 0;
1672 DistanceCacheMisses = 0;
1675 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1676 if (CachedDistancesMI &&
1677 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1678 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1679 CachedDistancesMI =
nullptr;
1680 CachedDistances.clear();
1684 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1685 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1686 if (!CacheElem.MIDependent)
1689 const LiveRegUse &
U = CacheElem.Use;
1692 if (
U.Dist < LastDelta)
1695 const MachineInstr *
UseMI =
U.Use->getParent();
1703 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1704 !instrsAreInOrder(
UseMI, &
MI);
1707 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1708 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1709 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1710 if (!DistanceCacheEnabled)
1711 return {
nullptr,
nullptr};
1713 ++DistanceCacheMisses;
1714 auto I = CachedDistances.find(
Reg);
1715 if (
I == CachedDistances.end())
1716 return {
nullptr,
nullptr};
1717 const LaneBitmaskToUseMap &RegSlot =
I->second;
1718 if (RegSlot.empty())
1719 return {
nullptr,
nullptr};
1721 auto J = RegSlot.find(LaneMask);
1722 if (J == RegSlot.end())
1723 return {
nullptr,
nullptr};
1725 const LiveRegToUseMapElem &MaskSlot = J->second;
1726 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1727 return {
nullptr,
nullptr};
1729 --DistanceCacheMisses;
1730 ++DistanceCacheHits;
1731 return {&RegSlot, &MaskSlot};
1734 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1735 LiveRegUse U,
bool MIDependent) {
1736 if (!DistanceCacheEnabled)
1739 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1740 LaneBitmaskToUseMap &RegSlot =
I->second;
1741 RegSlot.try_emplace(Mask, U, MIDependent);
1744 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1745 if (!DistanceCacheEnabled)
1748 CachedDistancesMI = &
MI;
1749 CachedDistances = std::move(PendingCachedDistances);
1750 PendingCachedDistances.clear();
1754 void printDistanceCache(raw_ostream &OS)
const {
1755 OS <<
"\n----------- Distance Cache ----------- {\n";
1756 OS <<
" CachedAt: ";
1757 if (CachedDistancesMI)
1758 OS << *CachedDistancesMI;
1762 constexpr size_t RegNameWidth = 20;
1763 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1765 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1767 for (
const auto &[Mask, Elem] : ByMask) {
1769 raw_string_ostream KOS(
RegName);
1770 if (Mask == AllLanes) {
1773 SmallVector<unsigned> Indexes;
1774 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1775 if (Indexes.
size() == 1)
1785 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1791 printDistanceCache(
dbgs());
1801 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1802 SubRegIndexesForRegClass;
1803 void collectSubRegUsesByMask(
1804 const SmallVectorImpl<const MachineOperand *> &
Uses,
1805 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1806 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1812 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1815 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1818 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1819 const MachineOperand *MO =
Uses[
I];
1820 auto [SubRegMIDep, Dist] = Distances[
I];
1821 const LiveRegUse LRU{MO, Dist};
1823 ArrayRef<unsigned> Indexes;
1828 Indexes = RCSubRegIndexes;
1831 for (
unsigned Idx : Indexes) {
1832 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1833 if (
Mask.all() || Mask == LiveRegLaneMask)
1836 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1837 if (updateClosest(SlotU, LRU))
1838 SlotMIDep = SubRegMIDep;
1844 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1845 LaneBitmask LiveRegLaneMask,
1846 const MachineInstr *
MI,
1847 InstrIdTy LastDelta,
1848 LaneBitmaskToUseMap &UseByMask) {
1850 for (
const auto &KV : CachedMap) {
1851 LaneBitmask SubregLaneMask = KV.first;
1852 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1855 const LiveRegToUseMapElem &SubregE = KV.second;
1856 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1859 const bool MIDep = SubregE.MIDependent;
1860 LiveRegUse
U = SubregE.Use;
1862 U.Dist -= LastDelta;
1864 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1865 if (updateClosest(SlotU, U))
1872 void updateFurthestSubReg(
1873 const MachineInstr &
MI,
const LiveRegUse &U,
1874 const LaneBitmaskToUseMap &UseByMask,
1875 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1876 LiveRegUse &FurthestSubreg) {
1878 if (UseByMask.empty()) {
1879 updateFurthest(FurthestSubreg, U);
1883 for (
const auto &KV : UseByMask) {
1884 const LiveRegUse &SubregU = KV.second.Use;
1885 const bool SubregMIDep = KV.second.MIDependent;
1889 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1891 updateFurthest(FurthestSubreg, SubregU);
1896 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1897 SmallSet<Register, 4> MIDefs;
1899 for (
const MachineOperand &MO :
MI.all_defs()) {
1912 LiveRegUse *FurthestSubreg =
nullptr,
1914 *RelevantUses =
nullptr) {
1919 LaneBitmaskToUseMap UseByMask;
1921 maybeClearCachedLiveRegUses(
MI);
1922 const InstrIdTy LastDelta =
1923 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1936 bool MIDependent =
false;
1937 auto [CacheMap, CacheElem] =
1938 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1939 if (CacheMap && CacheElem) {
1940 MIDependent = CacheElem->MIDependent;
1943 U.Dist -= LastDelta;
1951 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
1952 U = LiveRegUse{NextUse, Dist};
1957 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
1959 updateFurthest(Furthest, U);
1961 if (!FurthestSubreg)
1965 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
1968 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
1970 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1972 updateCachedLiveRegUses(
MI);
1991 for (
const auto &KV : Paths) {
1992 const Path &
P = KV.first;
1993 const PathInfo &PI = KV.second;
1997 printMBBNameAttr(J,
"src", *
P.src(), MST);
1998 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
2000 if (PI.ShortestDistance.has_value()) {
2002 PI.ShortestDistance.value().toJsonValue());
2004 J.
attribute(
"shortest-distance",
nullptr);
2007 if (PI.ShortestUnweightedDistance.has_value()) {
2008 J.
attribute(
"shortest-unweighted-distance",
2009 PI.ShortestUnweightedDistance.value().toJsonValue());
2011 J.
attribute(
"shortest-unweighted-distance",
nullptr);
2014 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
2016 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2054 nullptr,
nullptr,
nullptr);