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 {
660 Size -=
static_cast<InstrIdTy
>(
666 unsigned calcRelativeLoopDepth(
const MachineBasicBlock *From,
667 const MachineBasicBlock *To)
const {
668 MachineLoop *LoopFrom = MLI->getLoopFor(From);
669 MachineLoop *LoopTo = MLI->getLoopFor(To);
684 return findCommonParent(LoopFrom, LoopTo).second;
691 bool calcIsReachable(
const MachineBasicBlock *From,
692 const MachineBasicBlock *To,
693 bool ForwardOnly =
false)
const {
694 if (From == To && !MLI->getLoopFor(From))
697 if (!ForwardOnly && interBlockDistanceExists(From, To))
700 enum { VisitOp, PopOp };
701 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
703 DenseSet<const MachineBasicBlock *> Visited{From};
709 auto Finally = [&](
bool Reachable) {
714 IntermediatePath.
clear();
715 for (
const MachineBasicBlock *
MBB : Visited) {
722 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
724 initializePaths(IntermediatePath, Unreachable);
729 while (!Work.
empty()) {
740 if (Current->succ_empty())
743 if (Current != From) {
748 for (
const MachineBasicBlock *Succ : Current->successors()) {
749 if (ForwardOnly && isBackedge(Current, Succ))
755 if (
auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
756 if (CachedReachable.value())
758 Visited.insert(Succ);
762 if (Visited.insert(Succ).second)
781 struct InterBlockDistance {
782 NextUseDistance Weighted;
783 NextUseDistance Unweighted;
784 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
785 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
786 : Weighted(
W), Unweighted(UW) {}
787 bool operator==(
const InterBlockDistance &
Other)
const {
788 return Weighted ==
Other.Weighted && Unweighted ==
Other.Unweighted;
790 bool operator!=(
const InterBlockDistance &
Other)
const {
791 return !(*
this ==
Other);
794 void print(raw_ostream &OS)
const {
798 Unweighted.print(OS);
807 using InterBlockDistanceMap =
808 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
809 InterBlockDistanceMap InterBlockDistances;
811 void initializeInterBlockDistances() {
812 InterBlockDistanceMap Distances;
821 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
822 InterBlockDistanceMap::mapped_type Curr;
823 Curr.reserve(Prev.size());
828 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
832 unsigned SuccNum = Succ->getNumber();
833 const unsigned UnweightedSize{getSize(Succ)};
835 for (
const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
838 if (DestBlockNum == MBBNum)
841 const MachineBasicBlock *DestMBB =
842 MF->getBlockNumbered(DestBlockNum);
844 const NextUseDistance UnweightedDist{UnweightedSize +
845 DestDist.Unweighted};
847 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
849 const NextUseDistance WeightedDist =
855 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
857 InterBlockDistance &
Slot =
I->second;
859 Slot.Unweighted =
min(
Slot.Unweighted, UnweightedDist);
864 Distances[MBBNum] = std::move(Curr);
868 InterBlockDistances = std::move(Distances);
872 const InterBlockDistance *
873 getInterBlockDistanceMapValue(
const MachineBasicBlock *From,
874 const MachineBasicBlock *To)
const {
875 auto I = InterBlockDistances.find(From->
getNumber());
876 if (
I == InterBlockDistances.end())
878 const InterBlockDistanceMap::mapped_type &FromSlot =
I->second;
880 return J == FromSlot.end() ? nullptr : &J->second;
883 bool interBlockDistanceExists(
const MachineBasicBlock *From,
884 const MachineBasicBlock *To)
const {
885 return getInterBlockDistanceMapValue(From, To);
888 NextUseDistance getInterBlockDistance(
const MachineBasicBlock *From,
889 const MachineBasicBlock *To,
890 bool Unweighted)
const {
892 assert(From != To &&
"The basic blocks should be different.");
896 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
899 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
903 return Unweighted ? BD->Unweighted : BD->Weighted;
907 getWeightedInterBlockDistance(
const MachineBasicBlock *From,
908 const MachineBasicBlock *To)
const {
909 return getInterBlockDistance(From, To,
false);
913 getUnweightedInterBlockDistance(
const MachineBasicBlock *From,
914 const MachineBasicBlock *To)
const {
915 return getInterBlockDistance(From, To,
true);
922 InstrIdTy getSize(
const MachineBasicBlock *BB)
const {
923 return pathInfoFor(BB, BB).Size;
926 bool isReachable(
const MachineBasicBlock *From,
927 const MachineBasicBlock *To)
const {
928 return pathInfoFor(From, To).Reachable;
931 bool isReachableOrSame(
const MachineBasicBlock *From,
932 const MachineBasicBlock *To)
const {
933 return From == To || pathInfoFor(From, To).Reachable;
936 bool isForwardReachable(
const MachineBasicBlock *From,
937 const MachineBasicBlock *To)
const {
938 const PathInfo &PI = pathInfoFor(From, To);
939 if (PI.isForwardReachableSet())
940 return PI.isForwardReachable();
942 return initializePathInfoForwardReachable(
944 PI.Reachable && calcIsReachable(From, To,
true));
949 std::optional<bool> isMaybeReachable(
const MachineBasicBlock *From,
950 const MachineBasicBlock *To,
951 bool ForwardOnly)
const {
952 const PathInfo *PI = maybePathInfoFor(From, To);
957 if (PI->isForwardReachable())
960 if (PI->isNotForwardReachable())
964 return PI->Reachable;
967 bool isBackedge(
const MachineBasicBlock *From,
968 const MachineBasicBlock *To)
const {
969 return pathInfoFor(From, To).isBackedge();
974 bool instrsAreInOrder(
const MachineInstr *
A,
const MachineInstr *
B)
const {
975 assert(
A->getParent() ==
B->getParent() &&
976 "instructions must be in the same basic block!");
977 if (
A ==
B || getInstrId(
A) < getInstrId(
B))
983 for (
auto &
PHI :
A->getParent()->phis()) {
992 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
993 const MachineBasicBlock *To)
const {
994 std::optional<NextUseDistance> MaybeD =
995 pathInfoFor(From, To).ShortestDistance;
996 if (MaybeD.has_value())
997 return MaybeD.value();
999 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1000 return initializePathInfoShortestDistance(From, To, Dist);
1003 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
1004 const MachineBasicBlock *To)
const {
1005 std::optional<NextUseDistance> MaybeD =
1006 pathInfoFor(From, To).ShortestUnweightedDistance;
1007 if (MaybeD.has_value())
1008 return MaybeD.value();
1010 return initializePathInfoShortestUnweightedDistance(
1011 From, To, getUnweightedInterBlockDistance(From, To));
1019 struct MBBDistPair {
1020 NextUseDistance Distance;
1021 const MachineBasicBlock *MBB;
1022 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1023 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
1024 : Distance(
D), MBB(
B) {}
1026 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
1027 MBBDistPair &operator+=(NextUseDistance
D) {
1032 void print(raw_ostream &OS)
const {
1053 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1054 const MachineLoop *CurLoop)
const {
1059 for (MachineBasicBlock *LMBB : Latches) {
1063 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1064 if (Dst <
LD.Distance) {
1074 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1075 const MachineLoop *CurLoop)
const {
1080 for (MachineBasicBlock *LMBB : Latches) {
1084 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1085 if (Dst <
LD.Distance) {
1094 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1095 const MachineLoop *CurLoop)
const {
1097 MLI->getExitEdges(*CurLoop, ExitEdges);
1100 for (
auto [Exit, Dest] : ExitEdges) {
1104 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1105 if (Dst <
LD.Distance) {
1116 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1117 MachineLoop *CurLoop)
const {
1118 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1122 return {getSize(CurMBB), CurMBB};
1124 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1125 MBBDistPair
LD{0,
nullptr};
1127 LD += getSize(LoopHeader);
1129 if (CurMBB != LoopHeader)
1130 LD += getShortestPath(LoopHeader, CurMBB);
1135 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1137 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1138 LD += getSize(CurMBB);
1140 if (
LD.MBB != LoopHeader)
1141 LD += getSize(
LD.MBB);
1148 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1149 MachineLoop *OuterLoop)
const {
1150 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1152 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1154 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1156 if (OuterLoop == CurLoop)
1160 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1162 MBBDistPair
LD{0,
nullptr};
1163 LD += getSize(ParentHdr);
1164 LD += getShortestPath(ParentHdr, CurHdr);
1165 LD += CurLD.Distance.applyLoopWeight();
1166 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1167 LD += getSize(
LD.MBB);
1169 CurLoop = ParentLoop;
1178 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1179 MachineLoop *CurLoop)
const {
1180 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1181 LD.Distance =
LD.Distance.applyLoopWeight();
1187 MBBDistPair calcWeightedDistanceThroughLoop(
1188 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1189 const MachineLoop *ParentLoop =
nullptr)
const {
1191 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1193 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1202 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1203 const MachineInstr *
UseMI,
1204 const MachineBasicBlock *UseMBB)
const {
1205 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1211 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1212 MachineLoop *CurLoop,
1213 MachineLoop *UseLoop)
const {
1216 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1217 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1218 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1222 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1223 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1224 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1225 MachineLoop *UseLoop)
const {
1226 return appendDistanceToUse(
1227 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1232 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1233 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1234 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1237 if (isStandAloneLoop(CurLoop))
1238 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1241 if (!OutermostLoop->
contains(UseLoop)) {
1247 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1253 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1254 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1256 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1257 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1262 if (CurLoop == OutermostLoop)
1265 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1270 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1271 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1272 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1273 MachineLoop *UseLoop)
const {
1274 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1275 CurMBB, CurLoop, UseMBB, UseLoop),
1280 bool machineOperandCoveredBy(
const MachineOperand &MO,
1281 LaneBitmask LaneMask)
const {
1282 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1283 return (Mask & LaneMask) ==
Mask;
1288 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1289 const MachineInstr *CurMI,
1290 const MachineInstr *
UseMI)
const {
1294 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1302 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1310 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1313 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1314 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1315 if (RegMO.
getReg() == LiveReg &&
1316 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1317 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1328 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1329 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1330 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1331 assert(UseLoop &&
"There is no backedge.");
1332 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1333 "Unexpected loop configuration");
1335 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1336 MBBDistPair InnerLoopLD =
1337 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1338 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1340 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1345 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1346 const MachineBasicBlock *CurMBB,
1347 MachineLoop *CurLoop,
1348 const MachineInstr *
UseMI)
const {
1350 InstrIdTy CurTailLen = getTailLen(CurMI);
1351 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1352 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1353 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1354 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1355 NextUseDistance Dst =
1356 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1358 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1368 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1369 const MachineInstr *ToMI)
const {
1370 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1371 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1373 if (FromMBB == ToMBB) {
1374 NextUseDistance RV = getDistance(FromMI, ToMI);
1375 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1379 InstrIdTy FromTailLen = getTailLen(FromMI);
1380 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1381 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1382 assert(Dst.isReachable() &&
1383 "calcShortestDistance called for instructions in non-reachable"
1385 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1386 assert(RV >= 0 &&
"unexpected negative distance");
1395 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1396 const MachineInstr *ToMI)
const {
1397 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1398 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1400 if (FromMBB == ToMBB)
1401 return getDistance(FromMI, ToMI);
1403 InstrIdTy FromTailLen = getTailLen(FromMI);
1404 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1405 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1406 assert(Dst.isReachable() &&
1407 "calcShortestUnweightedDistance called for instructions in"
1408 " non-reachable basic blocks!");
1409 return FromTailLen + Dst + ToHeadLen;
1424 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1425 const MachineInstr &CurMI,
1426 const MachineOperand *UseMO)
const {
1428 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1430 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1431 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1433 if (Cfg.PreciseUseModeling) {
1435 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1436 UseMI = &PhiUseEdge->back();
1437 UseMBB = PhiUseEdge;
1438 UseLoop = MLI->getLoopFor(PhiUseEdge);
1442 enum class LoopConfig {
1450 auto [LpCfg, PreHdr, CommonParent] = [&]()
1451 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1453 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1456 return {CurMBB == UseMBB ? LoopConfig::Same
1457 : LoopConfig::CurContainsUse,
1458 findChildPreheader(CurLoop, UseLoop),
nullptr};
1461 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1463 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1464 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1466 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1472 if (!Cfg.PromoteToPreheader) {
1474 case LoopConfig::NoCur:
1475 case LoopConfig::Same:
1476 case LoopConfig::CurContainsUse:
1479 case LoopConfig::UseContainsCur: {
1480 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1481 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1482 UseMI, UseMBB, UseLoop);
1486 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1488 case LoopConfig::Siblings:
1489 case LoopConfig::Unrelated:
1490 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1491 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1500 UseMI = &PreHdr->back();
1502 UseLoop = CommonParent;
1506 case LoopConfig::NoCur:
1508 (sizeOf(*
UseMI) ? 0 : 1)};
1510 case LoopConfig::Same:
1511 case LoopConfig::CurContainsUse:
1512 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1514 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1518 case LoopConfig::UseContainsCur:
1519 case LoopConfig::Siblings:
1521 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1523 case LoopConfig::Unrelated:
1524 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1525 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1536 bool isUseReachablePrecise(
const MachineInstr &
MI,
1537 const MachineBasicBlock *
MBB,
1538 const MachineOperand *UseMO,
1539 const MachineInstr *
UseMI,
1540 const MachineBasicBlock *UseMBB)
const {
1543 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1548 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1549 if (!isReachableOrSame(
MBB, PhiUseEdge))
1554 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1556 if (
MBB == UseMBB) {
1560 if (instrsAreInOrder(&
MI,
UseMI))
1565 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1566 return UseLoop && !UseLoop->
contains(DefMBB);
1570 return instrsAreInOrder(
DefMI, &
MI);
1572 MachineLoop *
Loop = MLI->getLoopFor(
MBB);
1576 MachineLoop *TopLoop =
Loop->getOutermostLoop();
1577 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1578 !isForwardReachable(UseMBB,
MBB);
1585 void printPaths(raw_ostream &OS)
const {
1586 OS <<
"\n---------------- Paths --------------- {\n";
1587 for (
const auto &[
P, PI] : Paths) {
1598 void printInterBlockDistances(raw_ostream &OS)
const {
1599 using MBBPair = std::pair<unsigned, unsigned>;
1600 using Elem = std::pair<NextUseDistance, MBBPair>;
1601 std::vector<Elem> SortedDistances;
1603 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1604 for (
const auto &[ToNum, Dist] : Dsts) {
1605 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1608 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1609 if (
A.first !=
B.first)
1610 return A.first <
B.first;
1612 if (
A.second.first !=
B.second.first)
1613 return A.second.first <
B.second.first;
1615 return A.second.second <
B.second.second;
1618 OS <<
"\n--------- InterBlockDistances -------- {\n";
1619 for (
const Elem &
E : SortedDistances) {
1621 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1629 printInterBlockDistances(
dbgs());
1640 struct LiveRegToUseMapElem {
1643 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1644 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1645 : Use(
U), MIDependent(MIDep) {}
1647 void print(raw_ostream &OS)
const {
1649 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1660 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1661 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1663 const MachineInstr *CachedDistancesMI =
nullptr;
1664 LiveRegToUseMap CachedDistances;
1665 LiveRegToUseMap PendingCachedDistances;
1666 unsigned DistanceCacheHits = 0;
1667 unsigned DistanceCacheMisses = 0;
1669 void resetDistanceCache() {
1670 CachedDistancesMI =
nullptr;
1671 CachedDistances.clear();
1672 DistanceCacheHits = 0;
1673 DistanceCacheMisses = 0;
1676 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1677 if (CachedDistancesMI &&
1678 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1679 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1680 CachedDistancesMI =
nullptr;
1681 CachedDistances.clear();
1685 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1686 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1687 if (!CacheElem.MIDependent)
1690 const LiveRegUse &
U = CacheElem.Use;
1693 if (
U.Dist < LastDelta)
1696 const MachineInstr *
UseMI =
U.Use->getParent();
1704 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1705 !instrsAreInOrder(
UseMI, &
MI);
1708 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1709 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1710 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1711 if (!DistanceCacheEnabled)
1712 return {
nullptr,
nullptr};
1714 ++DistanceCacheMisses;
1715 auto I = CachedDistances.find(
Reg);
1716 if (
I == CachedDistances.end())
1717 return {
nullptr,
nullptr};
1718 const LaneBitmaskToUseMap &RegSlot =
I->second;
1719 if (RegSlot.empty())
1720 return {
nullptr,
nullptr};
1722 auto J = RegSlot.find(LaneMask);
1723 if (J == RegSlot.end())
1724 return {
nullptr,
nullptr};
1726 const LiveRegToUseMapElem &MaskSlot = J->second;
1727 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1728 return {
nullptr,
nullptr};
1730 --DistanceCacheMisses;
1731 ++DistanceCacheHits;
1732 return {&RegSlot, &MaskSlot};
1735 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1736 LiveRegUse U,
bool MIDependent) {
1737 if (!DistanceCacheEnabled)
1740 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1741 LaneBitmaskToUseMap &RegSlot =
I->second;
1742 RegSlot.try_emplace(Mask, U, MIDependent);
1745 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1746 if (!DistanceCacheEnabled)
1749 CachedDistancesMI = &
MI;
1750 CachedDistances = std::move(PendingCachedDistances);
1751 PendingCachedDistances.clear();
1755 void printDistanceCache(raw_ostream &OS)
const {
1756 OS <<
"\n----------- Distance Cache ----------- {\n";
1757 OS <<
" CachedAt: ";
1758 if (CachedDistancesMI)
1759 OS << *CachedDistancesMI;
1763 constexpr size_t RegNameWidth = 20;
1764 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1766 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1768 for (
const auto &[Mask, Elem] : ByMask) {
1770 raw_string_ostream KOS(
RegName);
1771 if (Mask == AllLanes) {
1774 SmallVector<unsigned> Indexes;
1775 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1776 if (Indexes.
size() == 1)
1786 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1792 printDistanceCache(
dbgs());
1802 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1803 SubRegIndexesForRegClass;
1804 void collectSubRegUsesByMask(
1805 const SmallVectorImpl<const MachineOperand *> &
Uses,
1806 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1807 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1813 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1816 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1819 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1820 const MachineOperand *MO =
Uses[
I];
1821 auto [SubRegMIDep, Dist] = Distances[
I];
1822 const LiveRegUse LRU{MO, Dist};
1824 ArrayRef<unsigned> Indexes;
1829 Indexes = RCSubRegIndexes;
1832 for (
unsigned Idx : Indexes) {
1833 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1834 if (
Mask.all() || Mask == LiveRegLaneMask)
1837 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1838 if (updateClosest(SlotU, LRU))
1839 SlotMIDep = SubRegMIDep;
1845 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1846 LaneBitmask LiveRegLaneMask,
1847 const MachineInstr *
MI,
1848 InstrIdTy LastDelta,
1849 LaneBitmaskToUseMap &UseByMask) {
1851 for (
const auto &KV : CachedMap) {
1852 LaneBitmask SubregLaneMask = KV.first;
1853 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1856 const LiveRegToUseMapElem &SubregE = KV.second;
1857 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1860 const bool MIDep = SubregE.MIDependent;
1861 LiveRegUse
U = SubregE.Use;
1863 U.Dist -= LastDelta;
1865 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1866 if (updateClosest(SlotU, U))
1873 void updateFurthestSubReg(
1874 const MachineInstr &
MI,
const LiveRegUse &U,
1875 const LaneBitmaskToUseMap &UseByMask,
1876 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1877 LiveRegUse &FurthestSubreg) {
1879 if (UseByMask.empty()) {
1880 updateFurthest(FurthestSubreg, U);
1884 for (
const auto &KV : UseByMask) {
1885 const LiveRegUse &SubregU = KV.second.Use;
1886 const bool SubregMIDep = KV.second.MIDependent;
1890 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1892 updateFurthest(FurthestSubreg, SubregU);
1897 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1898 SmallSet<Register, 4> MIDefs;
1900 for (
const MachineOperand &MO :
MI.all_defs()) {
1913 LiveRegUse *FurthestSubreg =
nullptr,
1915 *RelevantUses =
nullptr) {
1920 LaneBitmaskToUseMap UseByMask;
1922 maybeClearCachedLiveRegUses(
MI);
1923 const InstrIdTy LastDelta =
1924 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1937 bool MIDependent =
false;
1938 auto [CacheMap, CacheElem] =
1939 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1940 if (CacheMap && CacheElem) {
1941 MIDependent = CacheElem->MIDependent;
1944 U.Dist -= LastDelta;
1952 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
1953 U = LiveRegUse{NextUse, Dist};
1958 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
1960 updateFurthest(Furthest, U);
1962 if (!FurthestSubreg)
1966 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
1969 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
1971 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1973 updateCachedLiveRegUses(
MI);
1992 for (
const auto &KV : Paths) {
1993 const Path &
P = KV.first;
1994 const PathInfo &PI = KV.second;
1998 printMBBNameAttr(J,
"src", *
P.src(), MST);
1999 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
2001 if (PI.ShortestDistance.has_value()) {
2003 PI.ShortestDistance.value().toJsonValue());
2005 J.
attribute(
"shortest-distance",
nullptr);
2008 if (PI.ShortestUnweightedDistance.has_value()) {
2009 J.
attribute(
"shortest-unweighted-distance",
2010 PI.ShortestUnweightedDistance.value().toJsonValue());
2012 J.
attribute(
"shortest-unweighted-distance",
nullptr);
2015 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
2017 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2055 nullptr,
nullptr,
nullptr);