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 unsigned getRelativeLoopDepth(
const MachineBasicBlock *From,
992 const MachineBasicBlock *To)
const {
993 return pathInfoFor(From, To).RelativeLoopDepth;
996 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
997 const MachineBasicBlock *To)
const {
998 std::optional<NextUseDistance> MaybeD =
999 pathInfoFor(From, To).ShortestDistance;
1000 if (MaybeD.has_value())
1001 return MaybeD.value();
1003 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1004 return initializePathInfoShortestDistance(From, To, Dist);
1007 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
1008 const MachineBasicBlock *To)
const {
1009 std::optional<NextUseDistance> MaybeD =
1010 pathInfoFor(From, To).ShortestUnweightedDistance;
1011 if (MaybeD.has_value())
1012 return MaybeD.value();
1014 return initializePathInfoShortestUnweightedDistance(
1015 From, To, getUnweightedInterBlockDistance(From, To));
1023 struct MBBDistPair {
1024 NextUseDistance Distance;
1025 const MachineBasicBlock *MBB;
1026 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1027 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
1028 : Distance(
D), MBB(
B) {}
1030 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
1031 MBBDistPair &operator+=(NextUseDistance
D) {
1036 void print(raw_ostream &OS)
const {
1057 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1058 const MachineLoop *CurLoop)
const {
1063 for (MachineBasicBlock *LMBB : Latches) {
1067 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1068 if (Dst <
LD.Distance) {
1078 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1079 const MachineLoop *CurLoop)
const {
1084 for (MachineBasicBlock *LMBB : Latches) {
1088 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1089 if (Dst <
LD.Distance) {
1098 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1099 const MachineLoop *CurLoop)
const {
1101 MLI->getExitEdges(*CurLoop, ExitEdges);
1104 for (
auto [Exit, Dest] : ExitEdges) {
1108 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1109 if (Dst <
LD.Distance) {
1120 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1121 MachineLoop *CurLoop)
const {
1122 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1126 return {getSize(CurMBB), CurMBB};
1128 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1129 MBBDistPair
LD{0,
nullptr};
1131 LD += getSize(LoopHeader);
1133 if (CurMBB != LoopHeader)
1134 LD += getShortestPath(LoopHeader, CurMBB);
1139 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1141 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1142 LD += getSize(CurMBB);
1144 if (
LD.MBB != LoopHeader)
1145 LD += getSize(
LD.MBB);
1152 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1153 MachineLoop *OuterLoop)
const {
1154 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1156 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1158 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1160 if (OuterLoop == CurLoop)
1164 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1166 MBBDistPair
LD{0,
nullptr};
1167 LD += getSize(ParentHdr);
1168 LD += getShortestPath(ParentHdr, CurHdr);
1169 LD += CurLD.Distance.applyLoopWeight();
1170 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1171 LD += getSize(
LD.MBB);
1173 CurLoop = ParentLoop;
1182 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1183 MachineLoop *CurLoop)
const {
1184 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1185 LD.Distance =
LD.Distance.applyLoopWeight();
1191 MBBDistPair calcWeightedDistanceThroughLoop(
1192 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1193 const MachineLoop *ParentLoop =
nullptr)
const {
1195 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1197 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1206 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1207 const MachineInstr *
UseMI,
1208 const MachineBasicBlock *UseMBB)
const {
1209 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1215 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1216 MachineLoop *CurLoop,
1217 MachineLoop *UseLoop)
const {
1220 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1221 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1222 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1226 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1227 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1228 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1229 MachineLoop *UseLoop)
const {
1230 return appendDistanceToUse(
1231 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1236 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1237 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1238 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1241 if (isStandAloneLoop(CurLoop))
1242 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1245 if (!OutermostLoop->
contains(UseLoop)) {
1251 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1257 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1258 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1260 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1261 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1266 if (CurLoop == OutermostLoop)
1269 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1274 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1275 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1276 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1277 MachineLoop *UseLoop)
const {
1278 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1279 CurMBB, CurLoop, UseMBB, UseLoop),
1284 bool machineOperandCoveredBy(
const MachineOperand &MO,
1285 LaneBitmask LaneMask)
const {
1286 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1287 return (Mask & LaneMask) ==
Mask;
1292 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1293 const MachineInstr *CurMI,
1294 const MachineInstr *
UseMI)
const {
1298 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1306 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1314 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1317 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1318 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1319 if (RegMO.
getReg() == LiveReg &&
1320 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1321 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1332 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1333 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1334 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1335 assert(UseLoop &&
"There is no backedge.");
1336 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1337 "Unexpected loop configuration");
1339 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1340 MBBDistPair InnerLoopLD =
1341 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1342 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1344 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1349 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1350 const MachineBasicBlock *CurMBB,
1351 MachineLoop *CurLoop,
1352 const MachineInstr *
UseMI)
const {
1354 InstrIdTy CurTailLen = getTailLen(CurMI);
1355 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1356 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1357 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1358 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1359 NextUseDistance Dst =
1360 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1362 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1372 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1373 const MachineInstr *ToMI)
const {
1374 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1375 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1377 if (FromMBB == ToMBB) {
1378 NextUseDistance RV = getDistance(FromMI, ToMI);
1379 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1383 InstrIdTy FromTailLen = getTailLen(FromMI);
1384 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1385 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1386 assert(Dst.isReachable() &&
1387 "calcShortestDistance called for instructions in non-reachable"
1389 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1390 assert(RV >= 0 &&
"unexpected negative distance");
1399 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1400 const MachineInstr *ToMI)
const {
1401 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1402 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1404 if (FromMBB == ToMBB)
1405 return getDistance(FromMI, ToMI);
1407 InstrIdTy FromTailLen = getTailLen(FromMI);
1408 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1409 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1410 assert(Dst.isReachable() &&
1411 "calcShortestUnweightedDistance called for instructions in"
1412 " non-reachable basic blocks!");
1413 return FromTailLen + Dst + ToHeadLen;
1428 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1429 const MachineInstr &CurMI,
1430 const MachineOperand *UseMO)
const {
1432 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1434 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1435 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1437 if (Cfg.PreciseUseModeling) {
1439 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1440 UseMI = &PhiUseEdge->back();
1441 UseMBB = PhiUseEdge;
1442 UseLoop = MLI->getLoopFor(PhiUseEdge);
1446 enum class LoopConfig {
1454 auto [LpCfg, PreHdr, CommonParent] = [&]()
1455 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1457 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1460 return {CurMBB == UseMBB ? LoopConfig::Same
1461 : LoopConfig::CurContainsUse,
1462 findChildPreheader(CurLoop, UseLoop),
nullptr};
1465 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1467 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1468 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1470 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1476 if (!Cfg.PromoteToPreheader) {
1478 case LoopConfig::NoCur:
1479 case LoopConfig::Same:
1480 case LoopConfig::CurContainsUse:
1483 case LoopConfig::UseContainsCur: {
1484 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1485 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1486 UseMI, UseMBB, UseLoop);
1490 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1492 case LoopConfig::Siblings:
1493 case LoopConfig::Unrelated:
1494 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1495 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1504 UseMI = &PreHdr->back();
1506 UseLoop = CommonParent;
1510 case LoopConfig::NoCur:
1512 (sizeOf(*
UseMI) ? 0 : 1)};
1514 case LoopConfig::Same:
1515 case LoopConfig::CurContainsUse:
1516 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1518 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1522 case LoopConfig::UseContainsCur:
1523 case LoopConfig::Siblings:
1525 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1527 case LoopConfig::Unrelated:
1528 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1529 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1540 bool isUseReachablePrecise(
const MachineInstr &
MI,
1541 const MachineBasicBlock *
MBB,
1542 const MachineOperand *UseMO,
1543 const MachineInstr *
UseMI,
1544 const MachineBasicBlock *UseMBB)
const {
1547 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1552 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1553 if (!isReachableOrSame(
MBB, PhiUseEdge))
1558 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1560 if (
MBB == UseMBB) {
1564 if (instrsAreInOrder(&
MI,
UseMI))
1569 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1570 return UseLoop && !UseLoop->
contains(DefMBB);
1574 return instrsAreInOrder(
DefMI, &
MI);
1576 MachineLoop *
Loop = MLI->getLoopFor(
MBB);
1580 MachineLoop *TopLoop =
Loop->getOutermostLoop();
1581 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1582 !isForwardReachable(UseMBB,
MBB);
1589 void printPaths(raw_ostream &OS)
const {
1590 OS <<
"\n---------------- Paths --------------- {\n";
1591 for (
const auto &[
P, PI] : Paths) {
1602 void printInterBlockDistances(raw_ostream &OS)
const {
1603 using MBBPair = std::pair<unsigned, unsigned>;
1604 using Elem = std::pair<NextUseDistance, MBBPair>;
1605 std::vector<Elem> SortedDistances;
1607 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1608 for (
const auto &[ToNum, Dist] : Dsts) {
1609 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1612 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1613 if (
A.first !=
B.first)
1614 return A.first <
B.first;
1616 if (
A.second.first !=
B.second.first)
1617 return A.second.first <
B.second.first;
1619 return A.second.second <
B.second.second;
1622 OS <<
"\n--------- InterBlockDistances -------- {\n";
1623 for (
const Elem &
E : SortedDistances) {
1625 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1633 printInterBlockDistances(
dbgs());
1644 struct LiveRegToUseMapElem {
1647 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1648 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1649 : Use(
U), MIDependent(MIDep) {}
1651 void print(raw_ostream &OS)
const {
1653 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1664 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1665 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1667 const MachineInstr *CachedDistancesMI =
nullptr;
1668 LiveRegToUseMap CachedDistances;
1669 LiveRegToUseMap PendingCachedDistances;
1670 unsigned DistanceCacheHits = 0;
1671 unsigned DistanceCacheMisses = 0;
1673 void resetDistanceCache() {
1674 CachedDistancesMI =
nullptr;
1675 CachedDistances.clear();
1676 DistanceCacheHits = 0;
1677 DistanceCacheMisses = 0;
1680 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1681 if (CachedDistancesMI &&
1682 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1683 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1684 CachedDistancesMI =
nullptr;
1685 CachedDistances.clear();
1689 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1690 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1691 if (!CacheElem.MIDependent)
1694 const LiveRegUse &
U = CacheElem.Use;
1697 if (
U.Dist < LastDelta)
1700 const MachineInstr *
UseMI =
U.Use->getParent();
1708 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1709 !instrsAreInOrder(
UseMI, &
MI);
1712 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1713 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1714 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1715 if (!DistanceCacheEnabled)
1716 return {
nullptr,
nullptr};
1718 ++DistanceCacheMisses;
1719 auto I = CachedDistances.find(
Reg);
1720 if (
I == CachedDistances.end())
1721 return {
nullptr,
nullptr};
1722 const LaneBitmaskToUseMap &RegSlot =
I->second;
1723 if (RegSlot.empty())
1724 return {
nullptr,
nullptr};
1726 auto J = RegSlot.find(LaneMask);
1727 if (J == RegSlot.end())
1728 return {
nullptr,
nullptr};
1730 const LiveRegToUseMapElem &MaskSlot = J->second;
1731 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1732 return {
nullptr,
nullptr};
1734 --DistanceCacheMisses;
1735 ++DistanceCacheHits;
1736 return {&RegSlot, &MaskSlot};
1739 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1740 LiveRegUse U,
bool MIDependent) {
1741 if (!DistanceCacheEnabled)
1744 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1745 LaneBitmaskToUseMap &RegSlot =
I->second;
1746 RegSlot.try_emplace(Mask, U, MIDependent);
1749 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1750 if (!DistanceCacheEnabled)
1753 CachedDistancesMI = &
MI;
1754 CachedDistances = std::move(PendingCachedDistances);
1755 PendingCachedDistances.clear();
1759 void printDistanceCache(raw_ostream &OS)
const {
1760 OS <<
"\n----------- Distance Cache ----------- {\n";
1761 OS <<
" CachedAt: ";
1762 if (CachedDistancesMI)
1763 OS << *CachedDistancesMI;
1767 constexpr size_t RegNameWidth = 20;
1768 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1770 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1772 for (
const auto &[Mask, Elem] : ByMask) {
1774 raw_string_ostream KOS(
RegName);
1775 if (Mask == AllLanes) {
1778 SmallVector<unsigned> Indexes;
1779 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1780 if (Indexes.
size() == 1)
1790 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1796 printDistanceCache(
dbgs());
1806 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1807 SubRegIndexesForRegClass;
1808 void collectSubRegUsesByMask(
1809 const SmallVectorImpl<const MachineOperand *> &
Uses,
1810 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1811 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1817 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1820 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1823 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1824 const MachineOperand *MO =
Uses[
I];
1825 auto [SubRegMIDep, Dist] = Distances[
I];
1826 const LiveRegUse LRU{MO, Dist};
1828 ArrayRef<unsigned> Indexes;
1833 Indexes = RCSubRegIndexes;
1836 for (
unsigned Idx : Indexes) {
1837 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1838 if (
Mask.all() || Mask == LiveRegLaneMask)
1841 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1842 if (updateClosest(SlotU, LRU))
1843 SlotMIDep = SubRegMIDep;
1849 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1850 LaneBitmask LiveRegLaneMask,
1851 const MachineInstr *
MI,
1852 InstrIdTy LastDelta,
1853 LaneBitmaskToUseMap &UseByMask) {
1855 for (
const auto &KV : CachedMap) {
1856 LaneBitmask SubregLaneMask = KV.first;
1857 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1860 const LiveRegToUseMapElem &SubregE = KV.second;
1861 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1864 const bool MIDep = SubregE.MIDependent;
1865 LiveRegUse
U = SubregE.Use;
1867 U.Dist -= LastDelta;
1869 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1870 if (updateClosest(SlotU, U))
1877 void updateFurthestSubReg(
1878 const MachineInstr &
MI,
const LiveRegUse &U,
1879 const LaneBitmaskToUseMap &UseByMask,
1880 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1881 LiveRegUse &FurthestSubreg) {
1883 if (UseByMask.empty()) {
1884 updateFurthest(FurthestSubreg, U);
1888 for (
const auto &KV : UseByMask) {
1889 const LiveRegUse &SubregU = KV.second.Use;
1890 const bool SubregMIDep = KV.second.MIDependent;
1894 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1896 updateFurthest(FurthestSubreg, SubregU);
1901 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1902 SmallSet<Register, 4> MIDefs;
1904 for (
const MachineOperand &MO :
MI.all_defs()) {
1917 LiveRegUse *FurthestSubreg =
nullptr,
1919 *RelevantUses =
nullptr) {
1924 LaneBitmaskToUseMap UseByMask;
1926 maybeClearCachedLiveRegUses(
MI);
1927 const InstrIdTy LastDelta =
1928 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1941 bool MIDependent =
false;
1942 auto [CacheMap, CacheElem] =
1943 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1944 if (CacheMap && CacheElem) {
1945 MIDependent = CacheElem->MIDependent;
1948 U.Dist -= LastDelta;
1956 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
1957 U = LiveRegUse{NextUse, Dist};
1962 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
1964 updateFurthest(Furthest, U);
1966 if (!FurthestSubreg)
1970 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
1973 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
1975 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1977 updateCachedLiveRegUses(
MI);
1996 for (
const auto &KV : Paths) {
1997 const Path &
P = KV.first;
1998 const PathInfo &PI = KV.second;
2002 printMBBNameAttr(J,
"src", *
P.src(), MST);
2003 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
2005 if (PI.ShortestDistance.has_value()) {
2007 PI.ShortestDistance.value().toJsonValue());
2009 J.
attribute(
"shortest-distance",
nullptr);
2012 if (PI.ShortestUnweightedDistance.has_value()) {
2013 J.
attribute(
"shortest-unweighted-distance",
2014 PI.ShortestUnweightedDistance.value().toJsonValue());
2016 J.
attribute(
"shortest-unweighted-distance",
nullptr);
2019 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
2021 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2059 nullptr,
nullptr,
nullptr);