278 InstrToIdMap InstrToId;
281 void initializeTables() {
283 calcInstrIds(&BB, InstrToId);
284 initializeCfgPaths();
285 initializeInterBlockDistances();
293 resetDistanceCache();
307 void calcInstrIds(
const MachineBasicBlock *BB,
308 InstrToIdMap &MutableInstrToId)
const {
311 MutableInstrToId[&
MI] =
Id;
318 InstrIdTy getInstrId(
const MachineInstr *
MI)
const {
319 auto It = InstrToId.find(
MI);
320 if (It != InstrToId.end())
325 auto &MutableInstrToId =
const_cast<InstrToIdMap &
>(InstrToId);
326 calcInstrIds(
MI->getParent(), MutableInstrToId);
327 return InstrToId.find(
MI)->second;
332 InstrIdTy getHeadLen(
const MachineInstr *
MI)
const {
339 InstrIdTy getTailLen(
const MachineInstr *
MI)
const {
346 InstrIdTy getDistance(
const MachineInstr *From,
347 const MachineInstr *To)
const {
349 return getInstrId(To) - getInstrId(From);
356 DenseMap<Register, SmallVector<const MachineOperand *>> RegUseMap;
360 auto I = RegUseMap.find(
Reg);
361 if (
I != RegUseMap.end())
366 for (
const MachineOperand &UseMO : MRI->use_nodbg_operands(
Reg)) {
367 if (!UseMO.isUndef())
368 Uses.push_back(&UseMO);
374 return !getRegisterUses(
Reg).empty();
383 std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
387 constexpr Path() : P(nullptr, nullptr) {}
388 constexpr Path(
const MachineBasicBlock *Src,
const MachineBasicBlock *Dst)
390 Path(
const StorageTy &Pair) : P(Pair) {}
392 constexpr operator const StorageTy &()
const {
return P; }
393 using DenseMapInfo = llvm::DenseMapInfo<StorageTy>;
395 const MachineBasicBlock *src()
const {
return P.first; }
396 const MachineBasicBlock *dst()
const {
return P.second; }
399 enum class EdgeKind { Back = -1, None = 0, Forward = 1 };
400 static constexpr StringRef toString(EdgeKind EK) {
401 if (EK == EdgeKind::Back)
403 if (EK == EdgeKind::Forward)
411 int ForwardReachable;
412 unsigned RelativeLoopDepth;
413 std::optional<NextUseDistance> ShortestDistance;
414 std::optional<NextUseDistance> ShortestUnweightedDistance;
418 : EK(EdgeKind::
None), Reachable(
false), ForwardReachable(-1),
419 RelativeLoopDepth(0), Size(0) {}
421 bool isBackedge()
const {
return EK == EdgeKind::Back; }
423 bool isForwardReachableSet()
const {
return 0 <= ForwardReachable; }
424 bool isForwardReachableUnset()
const {
return ForwardReachable < 0; }
425 bool isForwardReachable()
const {
return ForwardReachable == 1; }
426 bool isNotForwardReachable()
const {
return ForwardReachable == 0; }
428 void print(raw_ostream &OS)
const {
429 OS <<
"{ek=" <<
toString(EK) <<
" reach=" << Reachable
430 <<
" fwd-reach=" << ForwardReachable
431 <<
" loop-depth=" << RelativeLoopDepth <<
" size=" << Size;
432 if (ShortestDistance) {
433 OS <<
" shortest-dist=";
434 ShortestDistance->print(OS);
436 if (ShortestUnweightedDistance) {
437 OS <<
" shortest-unweighted-dist=";
438 ShortestUnweightedDistance->print(OS);
454 DenseMap<Path, PathInfo, Path::DenseMapInfo> Paths;
456 const PathInfo *maybePathInfoFor(
const MachineBasicBlock *From,
457 const MachineBasicBlock *To)
const {
458 auto I = Paths.find({From, To});
459 return I == Paths.end() ? nullptr : &
I->second;
462 PathInfo &getOrInitPathInfo(
const MachineBasicBlock *From,
463 const MachineBasicBlock *To)
const {
465 auto &MutablePaths = NonConstThis->Paths;
468 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
472 bool Reachable = calcIsReachable(
P.src(),
P.dst());
476 return NonConstThis->initializePathInfo(MutablePaths.at(
P),
P,
477 EdgeKind::None, Reachable);
480 const PathInfo &pathInfoFor(
const MachineBasicBlock *From,
481 const MachineBasicBlock *To)
const {
482 return getOrInitPathInfo(From, To);
489 PathInfo &initializePathInfo(PathInfo &Slot, Path
P, EdgeKind EK,
492 Slot.Reachable = Reachable;
493 Slot.ForwardReachable = EK == EdgeKind::None ? -1 : EK == EdgeKind::Forward;
494 Slot.RelativeLoopDepth =
495 Slot.Reachable ? calcRelativeLoopDepth(
P.src(),
P.dst()) : 0;
496 Slot.Size =
P.src() ==
P.dst() ? calcSize(
P.src()) : 0;
497 if (EK != EdgeKind::None)
498 Slot.ShortestUnweightedDistance = 0;
502 PathInfo &initializePathInfo(Path
P, EdgeKind EK,
bool Reachable)
const {
504 auto &MutablePaths = NonConstThis->Paths;
505 return NonConstThis->initializePathInfo(MutablePaths[
P],
P, EK, Reachable);
508 std::pair<PathInfo *, bool> maybeInitializePathInfo(Path
P, EdgeKind EK,
509 bool Reachable)
const {
511 auto &MutablePaths = NonConstThis->Paths;
512 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
514 NonConstThis->initializePathInfo(
I->second,
P, EK, Reachable);
518 bool initializePathInfoForwardReachable(
const MachineBasicBlock *From,
519 const MachineBasicBlock *To,
521 PathInfo &
Slot = getOrInitPathInfo(From, To);
528 initializePathInfoShortestDistance(
const MachineBasicBlock *From,
529 const MachineBasicBlock *To,
530 NextUseDistance
Value)
const {
531 PathInfo &
Slot = getOrInitPathInfo(From, To);
538 initializePathInfoShortestUnweightedDistance(
const MachineBasicBlock *From,
539 const MachineBasicBlock *To,
540 NextUseDistance
Value)
const {
541 PathInfo &
Slot = getOrInitPathInfo(From, To);
542 assert(!
Slot.ShortestUnweightedDistance.has_value());
553 for (
const Path &
P : ReachablePaths)
554 initializePathInfo(
P, EdgeKind::None,
true);
555 for (
const Path &
P : UnreachablePaths)
556 initializePathInfo(
P, EdgeKind::None,
false);
562 for (
bool R : {
true,
false}) {
563 const auto &ToInit =
R ? ReachablePaths : UnreachablePaths;
564 for (
const Path &
P : ToInit) {
565 PathInfo &
Slot = getOrInitPathInfo(
P.src(),
P.dst());
566 assert(
Slot.isForwardReachableUnset() ||
Slot.ForwardReachable == R);
567 Slot.ForwardReachable =
R;
575 void initializeCfgPaths() {
578 enum VisitState { Undiscovered, Visiting, Finished };
579 DenseMap<const MachineBasicBlock *, VisitState> State;
582 State[&MF->front()] = Undiscovered;
584 while (!Work.
empty()) {
585 const MachineBasicBlock *Src = Work.
back();
586 VisitState &SrcState = State[Src];
591 if (SrcState == Visiting || SrcState == Finished) {
598 for (
const MachineBasicBlock *Dst : Src->successors()) {
599 const VisitState DstState = State.
lookup(Dst);
602 if (DstState == Undiscovered) {
603 EK = EdgeKind::Forward;
605 }
else if (DstState == Visiting) {
608 EK = EdgeKind::Forward;
613 initializePathInfo(
P, EK,
true);
624 static bool isStandAloneLoop(
const MachineLoop *
Loop) {
625 return Loop->getSubLoops().empty() &&
Loop->isOutermost();
628 static MachineLoop *findChildLoop(MachineLoop *
const Parent,
629 MachineLoop *Descendant) {
630 for (MachineLoop *L = Descendant;
L != Parent;
L =
L->getParentLoop()) {
631 if (
L->getParentLoop() == Parent)
640 static std::pair<MachineLoop *, unsigned>
641 findCommonParent(MachineLoop *
A,
const MachineLoop *
B) {
643 for (;
A !=
nullptr;
A =
A->getParentLoop(), ++
Depth) {
650 static const MachineBasicBlock *
651 getOutermostPreheader(
const MachineLoop *
Loop) {
652 return Loop ?
Loop->getOutermostLoop()->getLoopPreheader() :
nullptr;
655 static MachineBasicBlock *findChildPreheader(MachineLoop *
const Parent,
656 MachineLoop *Descendant) {
657 MachineLoop *ChildLoop = findChildLoop(Parent, Descendant);
661 static const MachineBasicBlock *
662 getIncomingBlockIfPhiUse(
const MachineInstr *
MI,
const MachineOperand *MO) {
671 InstrIdTy calcSize(
const MachineBasicBlock *BB)
const {
678 NextUseDistance calcWeightedSize(
const MachineBasicBlock *From,
679 const MachineBasicBlock *To)
const {
681 getRelativeLoopDepth(From, To));
685 unsigned calcRelativeLoopDepth(
const MachineBasicBlock *From,
686 const MachineBasicBlock *To)
const {
687 MachineLoop *LoopFrom = MLI->getLoopFor(From);
688 MachineLoop *LoopTo = MLI->getLoopFor(To);
703 return findCommonParent(LoopFrom, LoopTo).second;
710 bool calcIsReachable(
const MachineBasicBlock *From,
711 const MachineBasicBlock *To,
712 bool ForwardOnly =
false)
const {
713 if (From == To && !MLI->getLoopFor(From))
716 if (!ForwardOnly && interBlockDistanceExists(From, To))
719 enum { VisitOp, PopOp };
720 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
722 DenseSet<const MachineBasicBlock *> Visited{From};
728 auto Finally = [&](
bool Reachable) {
733 IntermediatePath.
clear();
734 for (
const MachineBasicBlock *
MBB : Visited) {
741 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
743 initializePaths(IntermediatePath, Unreachable);
748 while (!Work.
empty()) {
759 if (Current->succ_empty())
762 if (Current != From) {
767 for (
const MachineBasicBlock *Succ : Current->successors()) {
768 if (ForwardOnly && isBackedge(Current, Succ))
774 if (
auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
775 if (CachedReachable.value())
777 Visited.insert(Succ);
781 if (Visited.insert(Succ).second)
800 struct InterBlockDistance {
801 NextUseDistance Weighted;
802 NextUseDistance Unweighted;
803 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
804 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
805 : Weighted(
W), Unweighted(UW) {}
806 bool operator==(
const InterBlockDistance &
Other)
const {
807 return Weighted ==
Other.Weighted && Unweighted ==
Other.Unweighted;
809 bool operator!=(
const InterBlockDistance &
Other)
const {
810 return !(*
this ==
Other);
813 void print(raw_ostream &OS)
const {
817 Unweighted.print(OS);
826 using InterBlockDistanceMap =
827 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
828 InterBlockDistanceMap InterBlockDistances;
830 void initializeInterBlockDistances() {
831 InterBlockDistanceMap Distances;
840 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
841 InterBlockDistanceMap::mapped_type Curr;
842 Curr.reserve(Prev.size());
847 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
851 unsigned SuccNum = Succ->getNumber();
852 const unsigned UnweightedSize{getSize(Succ)};
854 for (
const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
857 if (DestBlockNum == MBBNum)
860 const MachineBasicBlock *DestMBB =
861 MF->getBlockNumbered(DestBlockNum);
863 const NextUseDistance UnweightedDist{UnweightedSize +
864 DestDist.Unweighted};
866 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
868 const NextUseDistance WeightedDist =
874 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
876 InterBlockDistance &
Slot =
I->second;
878 Slot.Unweighted =
min(
Slot.Unweighted, UnweightedDist);
883 Distances[MBBNum] = std::move(Curr);
887 InterBlockDistances = std::move(Distances);
891 const InterBlockDistance *
892 getInterBlockDistanceMapValue(
const MachineBasicBlock *From,
893 const MachineBasicBlock *To)
const {
894 auto I = InterBlockDistances.find(From->
getNumber());
895 if (
I == InterBlockDistances.end())
897 const InterBlockDistanceMap::mapped_type &FromSlot =
I->second;
899 return J == FromSlot.end() ? nullptr : &J->second;
902 bool interBlockDistanceExists(
const MachineBasicBlock *From,
903 const MachineBasicBlock *To)
const {
904 return getInterBlockDistanceMapValue(From, To);
907 NextUseDistance getInterBlockDistance(
const MachineBasicBlock *From,
908 const MachineBasicBlock *To,
909 bool Unweighted)
const {
911 assert(From != To &&
"The basic blocks should be different.");
915 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
918 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
922 return Unweighted ? BD->Unweighted : BD->Weighted;
926 getWeightedInterBlockDistance(
const MachineBasicBlock *From,
927 const MachineBasicBlock *To)
const {
928 return getInterBlockDistance(From, To,
false);
932 getUnweightedInterBlockDistance(
const MachineBasicBlock *From,
933 const MachineBasicBlock *To)
const {
934 return getInterBlockDistance(From, To,
true);
941 InstrIdTy getSize(
const MachineBasicBlock *BB)
const {
942 return pathInfoFor(BB, BB).Size;
945 bool isReachable(
const MachineBasicBlock *From,
946 const MachineBasicBlock *To)
const {
947 return pathInfoFor(From, To).Reachable;
950 bool isReachableOrSame(
const MachineBasicBlock *From,
951 const MachineBasicBlock *To)
const {
952 return From == To || pathInfoFor(From, To).Reachable;
955 bool isForwardReachable(
const MachineBasicBlock *From,
956 const MachineBasicBlock *To)
const {
957 const PathInfo &PI = pathInfoFor(From, To);
958 if (PI.isForwardReachableSet())
959 return PI.isForwardReachable();
961 return initializePathInfoForwardReachable(
963 PI.Reachable && calcIsReachable(From, To,
true));
968 std::optional<bool> isMaybeReachable(
const MachineBasicBlock *From,
969 const MachineBasicBlock *To,
970 bool ForwardOnly)
const {
971 const PathInfo *PI = maybePathInfoFor(From, To);
976 if (PI->isForwardReachable())
979 if (PI->isNotForwardReachable())
983 return PI->Reachable;
986 bool isBackedge(
const MachineBasicBlock *From,
987 const MachineBasicBlock *To)
const {
988 return pathInfoFor(From, To).isBackedge();
993 bool instrsAreInOrder(
const MachineInstr *
A,
const MachineInstr *
B)
const {
994 assert(
A->getParent() ==
B->getParent() &&
995 "instructions must be in the same basic block!");
996 if (
A ==
B || getInstrId(
A) < getInstrId(
B))
1002 for (
auto &
PHI :
A->getParent()->phis()) {
1011 unsigned getRelativeLoopDepth(
const MachineBasicBlock *From,
1012 const MachineBasicBlock *To)
const {
1013 return pathInfoFor(From, To).RelativeLoopDepth;
1016 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
1017 const MachineBasicBlock *To)
const {
1018 std::optional<NextUseDistance> MaybeD =
1019 pathInfoFor(From, To).ShortestDistance;
1020 if (MaybeD.has_value())
1021 return MaybeD.value();
1023 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1024 return initializePathInfoShortestDistance(From, To, Dist);
1027 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
1028 const MachineBasicBlock *To)
const {
1029 std::optional<NextUseDistance> MaybeD =
1030 pathInfoFor(From, To).ShortestUnweightedDistance;
1031 if (MaybeD.has_value())
1032 return MaybeD.value();
1034 return initializePathInfoShortestUnweightedDistance(
1035 From, To, getUnweightedInterBlockDistance(From, To));
1043 struct MBBDistPair {
1044 NextUseDistance Distance;
1045 const MachineBasicBlock *MBB;
1046 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1047 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
1048 : Distance(
D), MBB(
B) {}
1050 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
1051 MBBDistPair &operator+=(NextUseDistance
D) {
1056 void print(raw_ostream &OS)
const {
1077 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1078 const MachineLoop *CurLoop)
const {
1083 for (MachineBasicBlock *LMBB : Latches) {
1087 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1088 if (Dst <
LD.Distance) {
1098 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1099 const MachineLoop *CurLoop)
const {
1104 for (MachineBasicBlock *LMBB : Latches) {
1108 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1109 if (Dst <
LD.Distance) {
1118 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1119 const MachineLoop *CurLoop)
const {
1121 MLI->getExitEdges(*CurLoop, ExitEdges);
1124 for (
auto [Exit, Dest] : ExitEdges) {
1128 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1129 if (Dst <
LD.Distance) {
1140 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1141 MachineLoop *CurLoop)
const {
1142 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1146 return {getSize(CurMBB), CurMBB};
1148 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1149 MBBDistPair
LD{0,
nullptr};
1151 LD += getSize(LoopHeader);
1153 if (CurMBB != LoopHeader)
1154 LD += getShortestPath(LoopHeader, CurMBB);
1159 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1161 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1162 LD += getSize(CurMBB);
1164 if (
LD.MBB != LoopHeader)
1165 LD += getSize(
LD.MBB);
1172 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1173 MachineLoop *OuterLoop)
const {
1174 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1176 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1178 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1180 if (OuterLoop == CurLoop)
1184 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1186 MBBDistPair
LD{0,
nullptr};
1187 LD += getSize(ParentHdr);
1188 LD += getShortestPath(ParentHdr, CurHdr);
1189 LD += CurLD.Distance.applyLoopWeight();
1190 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1191 LD += getSize(
LD.MBB);
1193 CurLoop = ParentLoop;
1202 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1203 MachineLoop *CurLoop)
const {
1204 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1205 LD.Distance =
LD.Distance.applyLoopWeight();
1211 MBBDistPair calcWeightedDistanceThroughLoop(
1212 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1213 const MachineLoop *ParentLoop =
nullptr)
const {
1215 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1217 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1226 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1227 const MachineInstr *
UseMI,
1228 const MachineBasicBlock *UseMBB)
const {
1229 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1235 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1236 MachineLoop *CurLoop,
1237 MachineLoop *UseLoop)
const {
1240 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1241 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1242 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1246 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1247 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1248 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1249 MachineLoop *UseLoop)
const {
1250 return appendDistanceToUse(
1251 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1256 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1257 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1258 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1261 if (isStandAloneLoop(CurLoop))
1262 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1265 if (!OutermostLoop->
contains(UseLoop)) {
1271 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1277 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1278 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1280 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1281 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1286 if (CurLoop == OutermostLoop)
1289 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1294 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1295 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1296 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1297 MachineLoop *UseLoop)
const {
1298 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1299 CurMBB, CurLoop, UseMBB, UseLoop),
1304 bool machineOperandCoveredBy(
const MachineOperand &MO,
1305 LaneBitmask LaneMask)
const {
1306 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1307 return (Mask & LaneMask) ==
Mask;
1312 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1313 const MachineInstr *CurMI,
1314 const MachineInstr *
UseMI)
const {
1318 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1326 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1334 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1337 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1338 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1339 if (RegMO.
getReg() == LiveReg &&
1340 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1341 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1352 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1353 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1354 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1355 assert(UseLoop &&
"There is no backedge.");
1356 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1357 "Unexpected loop configuration");
1359 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1360 MBBDistPair InnerLoopLD =
1361 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1362 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1364 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1369 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1370 const MachineBasicBlock *CurMBB,
1371 MachineLoop *CurLoop,
1372 const MachineInstr *
UseMI)
const {
1374 InstrIdTy CurTailLen = getTailLen(CurMI);
1375 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1376 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1377 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1378 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1379 NextUseDistance Dst =
1380 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1382 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1392 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1393 const MachineInstr *ToMI)
const {
1394 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1395 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1397 if (FromMBB == ToMBB) {
1398 NextUseDistance RV = getDistance(FromMI, ToMI);
1399 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1403 InstrIdTy FromTailLen = getTailLen(FromMI);
1404 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1405 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1406 assert(Dst.isReachable() &&
1407 "calcShortestDistance called for instructions in non-reachable"
1409 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1410 assert(RV >= 0 &&
"unexpected negative distance");
1419 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1420 const MachineInstr *ToMI)
const {
1421 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1422 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1424 if (FromMBB == ToMBB)
1425 return getDistance(FromMI, ToMI);
1427 InstrIdTy FromTailLen = getTailLen(FromMI);
1428 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1429 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1430 assert(Dst.isReachable() &&
1431 "calcShortestUnweightedDistance called for instructions in"
1432 " non-reachable basic blocks!");
1433 return FromTailLen + Dst + ToHeadLen;
1448 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1449 const MachineInstr &CurMI,
1450 const MachineOperand *UseMO)
const {
1452 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1454 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1455 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1457 if (Cfg.PreciseUseModeling) {
1459 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1460 UseMI = &PhiUseEdge->back();
1461 UseMBB = PhiUseEdge;
1462 UseLoop = MLI->getLoopFor(PhiUseEdge);
1466 enum class LoopConfig {
1474 auto [LpCfg, PreHdr, CommonParent] = [&]()
1475 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1477 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1480 return {CurMBB == UseMBB ? LoopConfig::Same
1481 : LoopConfig::CurContainsUse,
1482 findChildPreheader(CurLoop, UseLoop),
nullptr};
1485 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1487 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1488 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1490 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1496 if (!Cfg.PromoteToPreheader) {
1498 case LoopConfig::NoCur:
1499 case LoopConfig::Same:
1500 case LoopConfig::CurContainsUse:
1503 case LoopConfig::UseContainsCur: {
1504 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1505 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1506 UseMI, UseMBB, UseLoop);
1510 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1512 case LoopConfig::Siblings:
1513 case LoopConfig::Unrelated:
1514 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1515 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1524 UseMI = &PreHdr->back();
1526 UseLoop = CommonParent;
1530 case LoopConfig::NoCur:
1532 (sizeOf(*
UseMI) ? 0 : 1)};
1534 case LoopConfig::Same:
1535 case LoopConfig::CurContainsUse:
1536 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1538 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1542 case LoopConfig::UseContainsCur:
1543 case LoopConfig::Siblings:
1545 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1547 case LoopConfig::Unrelated:
1548 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1549 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1560 bool isUseReachablePrecise(
const MachineInstr &
MI,
1561 const MachineBasicBlock *
MBB,
1562 const MachineOperand *UseMO,
1563 const MachineInstr *
UseMI,
1564 const MachineBasicBlock *UseMBB)
const {
1567 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1572 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1573 if (!isReachableOrSame(
MBB, PhiUseEdge))
1578 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1580 if (
MBB == UseMBB) {
1584 if (instrsAreInOrder(&
MI,
UseMI))
1589 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1590 return UseLoop && !UseLoop->
contains(DefMBB);
1594 return instrsAreInOrder(
DefMI, &
MI);
1596 MachineLoop *
Loop = MLI->getLoopFor(
MBB);
1600 MachineLoop *TopLoop =
Loop->getOutermostLoop();
1601 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1602 !isForwardReachable(UseMBB,
MBB);
1611 void populatePathTable() {
1612 for (
const MachineBasicBlock &MBB1 : *MF) {
1613 for (
const MachineBasicBlock &MBB2 : *MF) {
1616 getShortestPath(&MBB1, &MBB2);
1621 void printPaths(raw_ostream &OS)
const {
1622 OS <<
"\n---------------- Paths --------------- {\n";
1623 for (
const auto &[
P, PI] : Paths) {
1635 void dumpShortestPaths()
const {
1636 for (
const auto &
P : Paths) {
1637 const MachineBasicBlock *From =
P.first.src();
1638 const MachineBasicBlock *To =
P.first.dst();
1639 std::optional<NextUseDistance> Dist =
P.second.ShortestDistance;
1642 << Dist.value_or(-1).fmt() <<
"\n";
1646 void printInterBlockDistances(raw_ostream &OS)
const {
1647 using MBBPair = std::pair<unsigned, unsigned>;
1648 using Elem = std::pair<NextUseDistance, MBBPair>;
1649 std::vector<Elem> SortedDistances;
1651 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1652 for (
const auto &[ToNum, Dist] : Dsts) {
1653 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1656 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1657 if (
A.first !=
B.first)
1658 return A.first <
B.first;
1660 if (
A.second.first !=
B.second.first)
1661 return A.second.first <
B.second.first;
1663 return A.second.second <
B.second.second;
1666 OS <<
"\n--------- InterBlockDistances -------- {\n";
1667 for (
const Elem &
E : SortedDistances) {
1669 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1677 printInterBlockDistances(
dbgs());
1688 struct LiveRegToUseMapElem {
1691 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1692 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1693 : Use(
U), MIDependent(MIDep) {}
1695 void print(raw_ostream &OS)
const {
1697 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1708 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1709 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1711 const MachineInstr *CachedDistancesMI =
nullptr;
1712 LiveRegToUseMap CachedDistances;
1713 LiveRegToUseMap PendingCachedDistances;
1714 unsigned DistanceCacheHits = 0;
1715 unsigned DistanceCacheMisses = 0;
1717 void resetDistanceCache() {
1718 CachedDistancesMI =
nullptr;
1719 CachedDistances.clear();
1720 DistanceCacheHits = 0;
1721 DistanceCacheMisses = 0;
1724 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1725 if (CachedDistancesMI &&
1726 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1727 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1728 CachedDistancesMI =
nullptr;
1729 CachedDistances.clear();
1733 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1734 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1735 if (!CacheElem.MIDependent)
1738 const LiveRegUse &
U = CacheElem.Use;
1741 if (
U.Dist < LastDelta)
1744 const MachineInstr *
UseMI =
U.Use->getParent();
1752 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1753 !instrsAreInOrder(
UseMI, &
MI);
1756 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1757 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1758 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1759 if (!DistanceCacheEnabled)
1760 return {
nullptr,
nullptr};
1762 ++DistanceCacheMisses;
1763 auto I = CachedDistances.find(
Reg);
1764 if (
I == CachedDistances.end())
1765 return {
nullptr,
nullptr};
1766 const LaneBitmaskToUseMap &RegSlot =
I->second;
1767 if (RegSlot.empty())
1768 return {
nullptr,
nullptr};
1770 auto J = RegSlot.find(LaneMask);
1771 if (J == RegSlot.end())
1772 return {
nullptr,
nullptr};
1774 const LiveRegToUseMapElem &MaskSlot = J->second;
1775 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1776 return {
nullptr,
nullptr};
1778 --DistanceCacheMisses;
1779 ++DistanceCacheHits;
1780 return {&RegSlot, &MaskSlot};
1783 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1784 LiveRegUse U,
bool MIDependent) {
1785 if (!DistanceCacheEnabled)
1788 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1789 LaneBitmaskToUseMap &RegSlot =
I->second;
1790 RegSlot.try_emplace(Mask, U, MIDependent);
1793 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1794 if (!DistanceCacheEnabled)
1797 CachedDistancesMI = &
MI;
1798 CachedDistances = std::move(PendingCachedDistances);
1799 PendingCachedDistances.clear();
1803 void printDistanceCache(raw_ostream &OS)
const {
1804 OS <<
"\n----------- Distance Cache ----------- {\n";
1805 OS <<
" CachedAt: ";
1806 if (CachedDistancesMI)
1807 OS << *CachedDistancesMI;
1811 constexpr size_t RegNameWidth = 20;
1812 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1814 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1816 for (
const auto &[Mask, Elem] : ByMask) {
1818 raw_string_ostream KOS(
RegName);
1819 if (Mask == AllLanes) {
1822 SmallVector<unsigned> Indexes;
1823 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1824 if (Indexes.
size() == 1)
1834 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1840 printDistanceCache(
dbgs());
1850 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1851 SubRegIndexesForRegClass;
1852 void collectSubRegUsesByMask(
1853 const SmallVectorImpl<const MachineOperand *> &
Uses,
1854 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1855 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1861 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1864 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1867 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1868 const MachineOperand *MO =
Uses[
I];
1869 auto [SubRegMIDep, Dist] = Distances[
I];
1870 const LiveRegUse LRU{MO, Dist};
1872 ArrayRef<unsigned> Indexes;
1877 Indexes = RCSubRegIndexes;
1880 for (
unsigned Idx : Indexes) {
1881 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1882 if (
Mask.all() || Mask == LiveRegLaneMask)
1885 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1886 if (updateClosest(SlotU, LRU))
1887 SlotMIDep = SubRegMIDep;
1893 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1894 LaneBitmask LiveRegLaneMask,
1895 const MachineInstr *
MI,
1896 InstrIdTy LastDelta,
1897 LaneBitmaskToUseMap &UseByMask) {
1899 for (
const auto &KV : CachedMap) {
1900 LaneBitmask SubregLaneMask = KV.first;
1901 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1904 const LiveRegToUseMapElem &SubregE = KV.second;
1905 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1908 const bool MIDep = SubregE.MIDependent;
1909 LiveRegUse
U = SubregE.Use;
1911 U.Dist -= LastDelta;
1913 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1914 if (updateClosest(SlotU, U))
1921 void updateFurthestSubReg(
1922 const MachineInstr &
MI,
const LiveRegUse &U,
1923 const LaneBitmaskToUseMap &UseByMask,
1924 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1925 LiveRegUse &FurthestSubreg) {
1927 if (UseByMask.empty()) {
1928 updateFurthest(FurthestSubreg, U);
1932 for (
const auto &KV : UseByMask) {
1933 const LiveRegUse &SubregU = KV.second.Use;
1934 const bool SubregMIDep = KV.second.MIDependent;
1938 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1940 updateFurthest(FurthestSubreg, SubregU);
1945 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1946 SmallSet<Register, 4> MIDefs;
1948 for (
const MachineOperand &MO :
MI.all_defs()) {
1961 LiveRegUse *FurthestSubreg =
nullptr,
1963 *RelevantUses =
nullptr) {
1968 LaneBitmaskToUseMap UseByMask;
1970 maybeClearCachedLiveRegUses(
MI);
1971 const InstrIdTy LastDelta =
1972 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1985 bool MIDependent =
false;
1986 auto [CacheMap, CacheElem] =
1987 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1988 if (CacheMap && CacheElem) {
1989 MIDependent = CacheElem->MIDependent;
1992 U.Dist -= LastDelta;
2000 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
2001 U = LiveRegUse{NextUse, Dist};
2006 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
2008 updateFurthest(Furthest, U);
2010 if (!FurthestSubreg)
2014 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
2017 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
2019 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
2021 updateCachedLiveRegUses(
MI);
2040 for (
const auto &KV : Paths) {
2041 const Path &
P = KV.first;
2042 const PathInfo &PI = KV.second;
2046 printMBBNameAttr(J,
"src", *
P.src(), MST);
2047 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
2049 if (PI.ShortestDistance.has_value()) {
2051 PI.ShortestDistance.value().toJsonValue());
2053 J.
attribute(
"shortest-distance",
nullptr);
2056 if (PI.ShortestUnweightedDistance.has_value()) {
2057 J.
attribute(
"shortest-unweighted-distance",
2058 PI.ShortestUnweightedDistance.value().toJsonValue());
2060 J.
attribute(
"shortest-unweighted-distance",
nullptr);
2063 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
2065 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2103 nullptr,
nullptr,
nullptr);