219 const AMDGPUOptions &CLOpts;
228 InstrToIdMap InstrToId;
231 void initializeTables() {
233 calcInstrIds(&BB, InstrToId);
234 initializeCfgPaths();
235 initializeInterBlockDistances();
243 resetDistanceCache();
257 void calcInstrIds(
const MachineBasicBlock *BB,
258 InstrToIdMap &MutableInstrToId)
const {
261 MutableInstrToId[&
MI] =
Id;
268 InstrIdTy getInstrId(
const MachineInstr *
MI)
const {
269 auto It = InstrToId.find(
MI);
270 if (It != InstrToId.end())
275 auto &MutableInstrToId =
const_cast<InstrToIdMap &
>(InstrToId);
276 calcInstrIds(
MI->getParent(), MutableInstrToId);
277 return InstrToId.find(
MI)->second;
282 InstrIdTy getHeadLen(
const MachineInstr *
MI)
const {
289 InstrIdTy getTailLen(
const MachineInstr *
MI)
const {
296 InstrIdTy getDistance(
const MachineInstr *From,
297 const MachineInstr *To)
const {
299 return getInstrId(To) - getInstrId(From);
306 DenseMap<Register, SmallVector<const MachineOperand *>> RegUseMap;
310 auto I = RegUseMap.find(
Reg);
311 if (
I != RegUseMap.end())
316 for (
const MachineOperand &UseMO : MRI->use_nodbg_operands(
Reg)) {
317 if (!UseMO.isUndef())
318 Uses.push_back(&UseMO);
324 return !getRegisterUses(
Reg).empty();
333 std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
337 constexpr Path() : P(nullptr, nullptr) {}
338 constexpr Path(
const MachineBasicBlock *Src,
const MachineBasicBlock *Dst)
340 Path(
const StorageTy &Pair) : P(Pair) {}
342 constexpr operator const StorageTy &()
const {
return P; }
343 using DenseMapInfo = llvm::DenseMapInfo<StorageTy>;
345 const MachineBasicBlock *src()
const {
return P.first; }
346 const MachineBasicBlock *dst()
const {
return P.second; }
349 enum class EdgeKind { Back = -1, None = 0, Forward = 1 };
350 static constexpr StringRef toString(EdgeKind EK) {
351 if (EK == EdgeKind::Back)
353 if (EK == EdgeKind::Forward)
361 int ForwardReachable;
362 unsigned RelativeLoopDepth;
363 std::optional<NextUseDistance> ShortestDistance;
364 std::optional<NextUseDistance> ShortestUnweightedDistance;
368 : EK(EdgeKind::
None), Reachable(
false), ForwardReachable(-1),
369 RelativeLoopDepth(0), Size(0) {}
371 bool isBackedge()
const {
return EK == EdgeKind::Back; }
373 bool isForwardReachableSet()
const {
return 0 <= ForwardReachable; }
374 bool isForwardReachableUnset()
const {
return ForwardReachable < 0; }
375 bool isForwardReachable()
const {
return ForwardReachable == 1; }
376 bool isNotForwardReachable()
const {
return ForwardReachable == 0; }
378 void print(raw_ostream &OS)
const {
379 OS <<
"{ek=" <<
toString(EK) <<
" reach=" << Reachable
380 <<
" fwd-reach=" << ForwardReachable
381 <<
" loop-depth=" << RelativeLoopDepth <<
" size=" << Size;
382 if (ShortestDistance) {
383 OS <<
" shortest-dist=";
384 ShortestDistance->print(OS);
386 if (ShortestUnweightedDistance) {
387 OS <<
" shortest-unweighted-dist=";
388 ShortestUnweightedDistance->print(OS);
404 DenseMap<Path, PathInfo, Path::DenseMapInfo> Paths;
406 const PathInfo *maybePathInfoFor(
const MachineBasicBlock *From,
407 const MachineBasicBlock *To)
const {
408 auto I = Paths.find({From, To});
409 return I == Paths.end() ? nullptr : &
I->second;
412 PathInfo &getOrInitPathInfo(
const MachineBasicBlock *From,
413 const MachineBasicBlock *To)
const {
415 auto &MutablePaths = NonConstThis->Paths;
418 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
422 bool Reachable = calcIsReachable(
P.src(),
P.dst());
426 return NonConstThis->initializePathInfo(MutablePaths.at(
P),
P,
427 EdgeKind::None, Reachable);
430 const PathInfo &pathInfoFor(
const MachineBasicBlock *From,
431 const MachineBasicBlock *To)
const {
432 return getOrInitPathInfo(From, To);
439 PathInfo &initializePathInfo(PathInfo &Slot, Path
P, EdgeKind EK,
442 Slot.Reachable = Reachable;
443 Slot.ForwardReachable = EK == EdgeKind::None ? -1 : EK == EdgeKind::Forward;
444 Slot.RelativeLoopDepth =
445 Slot.Reachable ? calcRelativeLoopDepth(
P.src(),
P.dst()) : 0;
446 Slot.Size =
P.src() ==
P.dst() ? calcSize(
P.src()) : 0;
447 if (EK != EdgeKind::None)
448 Slot.ShortestUnweightedDistance = 0;
452 PathInfo &initializePathInfo(Path
P, EdgeKind EK,
bool Reachable)
const {
454 auto &MutablePaths = NonConstThis->Paths;
455 return NonConstThis->initializePathInfo(MutablePaths[
P],
P, EK, Reachable);
458 bool initializePathInfoForwardReachable(
const MachineBasicBlock *From,
459 const MachineBasicBlock *To,
461 PathInfo &
Slot = getOrInitPathInfo(From, To);
468 initializePathInfoShortestDistance(
const MachineBasicBlock *From,
469 const MachineBasicBlock *To,
470 NextUseDistance
Value)
const {
471 PathInfo &
Slot = getOrInitPathInfo(From, To);
478 initializePathInfoShortestUnweightedDistance(
const MachineBasicBlock *From,
479 const MachineBasicBlock *To,
480 NextUseDistance
Value)
const {
481 PathInfo &
Slot = getOrInitPathInfo(From, To);
482 assert(!
Slot.ShortestUnweightedDistance.has_value());
493 for (
const Path &
P : ReachablePaths)
494 initializePathInfo(
P, EdgeKind::None,
true);
495 for (
const Path &
P : UnreachablePaths)
496 initializePathInfo(
P, EdgeKind::None,
false);
502 for (
bool R : {
true,
false}) {
503 const auto &ToInit =
R ? ReachablePaths : UnreachablePaths;
504 for (
const Path &
P : ToInit) {
505 PathInfo &
Slot = getOrInitPathInfo(
P.src(),
P.dst());
506 assert(
Slot.isForwardReachableUnset() ||
Slot.ForwardReachable == R);
507 Slot.ForwardReachable =
R;
515 void initializeCfgPaths() {
518 enum VisitState { Undiscovered, Visiting, Finished };
519 DenseMap<const MachineBasicBlock *, VisitState> State;
522 State[&MF->front()] = Undiscovered;
524 while (!Work.
empty()) {
525 const MachineBasicBlock *Src = Work.
back();
526 VisitState &SrcState = State[Src];
531 if (SrcState == Visiting || SrcState == Finished) {
538 for (
const MachineBasicBlock *Dst : Src->successors()) {
539 const VisitState DstState = State.
lookup(Dst);
542 if (DstState == Undiscovered) {
543 EK = EdgeKind::Forward;
545 }
else if (DstState == Visiting) {
548 EK = EdgeKind::Forward;
553 initializePathInfo(
P, EK,
true);
564 static bool isStandAloneLoop(
const MachineLoop *
Loop) {
565 return Loop->getSubLoops().empty() &&
Loop->isOutermost();
568 static MachineLoop *findChildLoop(MachineLoop *
const Parent,
569 MachineLoop *Descendant) {
570 for (MachineLoop *L = Descendant;
L != Parent;
L =
L->getParentLoop()) {
571 if (
L->getParentLoop() == Parent)
580 static std::pair<MachineLoop *, unsigned>
581 findCommonParent(MachineLoop *
A,
const MachineLoop *
B) {
583 for (;
A !=
nullptr;
A =
A->getParentLoop(), ++
Depth) {
590 static const MachineBasicBlock *
591 getOutermostPreheader(
const MachineLoop *
Loop) {
592 return Loop ?
Loop->getOutermostLoop()->getLoopPreheader() :
nullptr;
595 static MachineBasicBlock *findChildPreheader(MachineLoop *
const Parent,
596 MachineLoop *Descendant) {
597 MachineLoop *ChildLoop = findChildLoop(Parent, Descendant);
601 static const MachineBasicBlock *
602 getIncomingBlockIfPhiUse(
const MachineInstr *
MI,
const MachineOperand *MO) {
611 InstrIdTy calcSize(
const MachineBasicBlock *BB)
const {
614 Size -=
static_cast<InstrIdTy
>(
620 unsigned calcRelativeLoopDepth(
const MachineBasicBlock *From,
621 const MachineBasicBlock *To)
const {
622 MachineLoop *LoopFrom = MLI->getLoopFor(From);
623 MachineLoop *LoopTo = MLI->getLoopFor(To);
638 return findCommonParent(LoopFrom, LoopTo).second;
645 bool calcIsReachable(
const MachineBasicBlock *From,
646 const MachineBasicBlock *To,
647 bool ForwardOnly =
false)
const {
648 if (From == To && !MLI->getLoopFor(From))
651 if (!ForwardOnly && interBlockDistanceExists(From, To))
654 enum { VisitOp, PopOp };
655 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
657 DenseSet<const MachineBasicBlock *> Visited{From};
663 auto Finally = [&](
bool Reachable) {
668 IntermediatePath.
clear();
669 for (
const MachineBasicBlock *
MBB : Visited) {
676 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
678 initializePaths(IntermediatePath, Unreachable);
683 while (!Work.
empty()) {
694 if (Current->succ_empty())
697 if (Current != From) {
702 for (
const MachineBasicBlock *Succ : Current->successors()) {
703 if (ForwardOnly && isBackedge(Current, Succ))
709 if (
auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
710 if (CachedReachable.value())
712 Visited.insert(Succ);
716 if (Visited.insert(Succ).second)
735 struct InterBlockDistance {
736 NextUseDistance Weighted;
737 NextUseDistance Unweighted;
738 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
739 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
740 : Weighted(
W), Unweighted(UW) {}
741 bool operator==(
const InterBlockDistance &
Other)
const {
742 return Weighted ==
Other.Weighted && Unweighted ==
Other.Unweighted;
744 bool operator!=(
const InterBlockDistance &
Other)
const {
745 return !(*
this ==
Other);
748 void print(raw_ostream &OS)
const {
752 Unweighted.print(OS);
761 using InterBlockDistanceMap =
762 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
763 InterBlockDistanceMap InterBlockDistances;
765 void initializeInterBlockDistances() {
766 InterBlockDistanceMap Distances;
775 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
776 InterBlockDistanceMap::mapped_type Curr;
777 Curr.reserve(Prev.size());
782 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
786 unsigned SuccNum = Succ->getNumber();
787 const unsigned UnweightedSize{getSize(Succ)};
789 for (
const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
792 if (DestBlockNum == MBBNum)
795 const MachineBasicBlock *DestMBB =
796 MF->getBlockNumbered(DestBlockNum);
798 const NextUseDistance UnweightedDist{UnweightedSize +
799 DestDist.Unweighted};
801 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
803 const NextUseDistance WeightedDist =
809 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
811 InterBlockDistance &
Slot =
I->second;
813 Slot.Unweighted =
min(
Slot.Unweighted, UnweightedDist);
818 Distances[MBBNum] = std::move(Curr);
822 InterBlockDistances = std::move(Distances);
826 const InterBlockDistance *
827 getInterBlockDistanceMapValue(
const MachineBasicBlock *From,
828 const MachineBasicBlock *To)
const {
829 auto I = InterBlockDistances.find(From->
getNumber());
830 if (
I == InterBlockDistances.end())
832 const InterBlockDistanceMap::mapped_type &FromSlot =
I->second;
834 return J == FromSlot.end() ? nullptr : &J->second;
837 bool interBlockDistanceExists(
const MachineBasicBlock *From,
838 const MachineBasicBlock *To)
const {
839 return getInterBlockDistanceMapValue(From, To);
842 NextUseDistance getInterBlockDistance(
const MachineBasicBlock *From,
843 const MachineBasicBlock *To,
844 bool Unweighted)
const {
846 assert(From != To &&
"The basic blocks should be different.");
850 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
853 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
857 return Unweighted ? BD->Unweighted : BD->Weighted;
861 getWeightedInterBlockDistance(
const MachineBasicBlock *From,
862 const MachineBasicBlock *To)
const {
863 return getInterBlockDistance(From, To,
false);
867 getUnweightedInterBlockDistance(
const MachineBasicBlock *From,
868 const MachineBasicBlock *To)
const {
869 return getInterBlockDistance(From, To,
true);
876 InstrIdTy getSize(
const MachineBasicBlock *BB)
const {
877 return pathInfoFor(BB, BB).Size;
880 bool isReachable(
const MachineBasicBlock *From,
881 const MachineBasicBlock *To)
const {
882 return pathInfoFor(From, To).Reachable;
885 bool isReachableOrSame(
const MachineBasicBlock *From,
886 const MachineBasicBlock *To)
const {
887 return From == To || pathInfoFor(From, To).Reachable;
890 bool isForwardReachable(
const MachineBasicBlock *From,
891 const MachineBasicBlock *To)
const {
892 const PathInfo &PI = pathInfoFor(From, To);
893 if (PI.isForwardReachableSet())
894 return PI.isForwardReachable();
896 return initializePathInfoForwardReachable(
898 PI.Reachable && calcIsReachable(From, To,
true));
903 std::optional<bool> isMaybeReachable(
const MachineBasicBlock *From,
904 const MachineBasicBlock *To,
905 bool ForwardOnly)
const {
906 const PathInfo *PI = maybePathInfoFor(From, To);
911 if (PI->isForwardReachable())
914 if (PI->isNotForwardReachable())
918 return PI->Reachable;
921 bool isBackedge(
const MachineBasicBlock *From,
922 const MachineBasicBlock *To)
const {
923 return pathInfoFor(From, To).isBackedge();
928 bool instrsAreInOrder(
const MachineInstr *
A,
const MachineInstr *
B)
const {
929 assert(
A->getParent() ==
B->getParent() &&
930 "instructions must be in the same basic block!");
931 if (
A ==
B || getInstrId(
A) < getInstrId(
B))
937 for (
auto &
PHI :
A->getParent()->phis()) {
946 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
947 const MachineBasicBlock *To)
const {
948 std::optional<NextUseDistance> MaybeD =
949 pathInfoFor(From, To).ShortestDistance;
950 if (MaybeD.has_value())
951 return MaybeD.value();
953 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
954 return initializePathInfoShortestDistance(From, To, Dist);
957 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
958 const MachineBasicBlock *To)
const {
959 std::optional<NextUseDistance> MaybeD =
960 pathInfoFor(From, To).ShortestUnweightedDistance;
961 if (MaybeD.has_value())
962 return MaybeD.value();
964 return initializePathInfoShortestUnweightedDistance(
965 From, To, getUnweightedInterBlockDistance(From, To));
974 NextUseDistance Distance;
975 const MachineBasicBlock *MBB;
976 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
977 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
978 : Distance(
D), MBB(
B) {}
980 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
981 MBBDistPair &operator+=(NextUseDistance
D) {
986 void print(raw_ostream &OS)
const {
1007 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1008 const MachineLoop *CurLoop)
const {
1013 for (MachineBasicBlock *LMBB : Latches) {
1017 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1018 if (Dst <
LD.Distance) {
1028 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1029 const MachineLoop *CurLoop)
const {
1034 for (MachineBasicBlock *LMBB : Latches) {
1038 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1039 if (Dst <
LD.Distance) {
1048 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1049 const MachineLoop *CurLoop)
const {
1051 MLI->getExitEdges(*CurLoop, ExitEdges);
1054 for (
auto [Exit, Dest] : ExitEdges) {
1058 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1059 if (Dst <
LD.Distance) {
1070 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1071 MachineLoop *CurLoop)
const {
1072 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1076 return {getSize(CurMBB), CurMBB};
1078 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1079 MBBDistPair
LD{0,
nullptr};
1081 LD += getSize(LoopHeader);
1083 if (CurMBB != LoopHeader)
1084 LD += getShortestPath(LoopHeader, CurMBB);
1089 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1091 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1092 LD += getSize(CurMBB);
1094 if (
LD.MBB != LoopHeader)
1095 LD += getSize(
LD.MBB);
1102 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1103 MachineLoop *OuterLoop)
const {
1104 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1106 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1108 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1110 if (OuterLoop == CurLoop)
1114 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1116 MBBDistPair
LD{0,
nullptr};
1117 LD += getSize(ParentHdr);
1118 LD += getShortestPath(ParentHdr, CurHdr);
1119 LD += CurLD.Distance.applyLoopWeight();
1120 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1121 LD += getSize(
LD.MBB);
1123 CurLoop = ParentLoop;
1132 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1133 MachineLoop *CurLoop)
const {
1134 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1135 LD.Distance =
LD.Distance.applyLoopWeight();
1141 MBBDistPair calcWeightedDistanceThroughLoop(
1142 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1143 const MachineLoop *ParentLoop =
nullptr)
const {
1145 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1147 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1156 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1157 const MachineInstr *
UseMI,
1158 const MachineBasicBlock *UseMBB)
const {
1159 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1165 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1166 MachineLoop *CurLoop,
1167 MachineLoop *UseLoop)
const {
1170 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1171 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1172 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1176 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1177 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1178 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1179 MachineLoop *UseLoop)
const {
1180 return appendDistanceToUse(
1181 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1186 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1187 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1188 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1191 if (isStandAloneLoop(CurLoop))
1192 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1195 if (!OutermostLoop->
contains(UseLoop)) {
1201 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1207 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1208 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1210 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1211 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1216 if (CurLoop == OutermostLoop)
1219 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1224 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1225 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1226 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1227 MachineLoop *UseLoop)
const {
1228 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1229 CurMBB, CurLoop, UseMBB, UseLoop),
1234 bool machineOperandCoveredBy(
const MachineOperand &MO,
1235 LaneBitmask LaneMask)
const {
1236 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1237 return (Mask & LaneMask) ==
Mask;
1242 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1243 const MachineInstr *CurMI,
1244 const MachineInstr *
UseMI)
const {
1248 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1256 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1264 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1267 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1268 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1269 if (RegMO.
getReg() == LiveReg &&
1270 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1271 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1282 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1283 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1284 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1285 assert(UseLoop &&
"There is no backedge.");
1286 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1287 "Unexpected loop configuration");
1289 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1290 MBBDistPair InnerLoopLD =
1291 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1292 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1294 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1299 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1300 const MachineBasicBlock *CurMBB,
1301 MachineLoop *CurLoop,
1302 const MachineInstr *
UseMI)
const {
1304 InstrIdTy CurTailLen = getTailLen(CurMI);
1305 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1306 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1307 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1308 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1309 NextUseDistance Dst =
1310 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1312 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1322 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1323 const MachineInstr *ToMI)
const {
1324 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1325 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1327 if (FromMBB == ToMBB) {
1328 NextUseDistance RV = getDistance(FromMI, ToMI);
1329 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1333 InstrIdTy FromTailLen = getTailLen(FromMI);
1334 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1335 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1336 assert(Dst.isReachable() &&
1337 "calcShortestDistance called for instructions in non-reachable"
1339 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1340 assert(RV >= 0 &&
"unexpected negative distance");
1349 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1350 const MachineInstr *ToMI)
const {
1351 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1352 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1354 if (FromMBB == ToMBB)
1355 return getDistance(FromMI, ToMI);
1357 InstrIdTy FromTailLen = getTailLen(FromMI);
1358 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1359 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1360 assert(Dst.isReachable() &&
1361 "calcShortestUnweightedDistance called for instructions in"
1362 " non-reachable basic blocks!");
1363 return FromTailLen + Dst + ToHeadLen;
1378 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1379 const MachineInstr &CurMI,
1380 const MachineOperand *UseMO)
const {
1382 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1384 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1385 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1387 if (Cfg.PreciseUseModeling) {
1389 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1390 UseMI = &PhiUseEdge->back();
1391 UseMBB = PhiUseEdge;
1392 UseLoop = MLI->getLoopFor(PhiUseEdge);
1396 enum class LoopConfig {
1404 auto [LpCfg, PreHdr, CommonParent] = [&]()
1405 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1407 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1410 return {CurMBB == UseMBB ? LoopConfig::Same
1411 : LoopConfig::CurContainsUse,
1412 findChildPreheader(CurLoop, UseLoop),
nullptr};
1415 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1417 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1418 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1420 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1426 if (!Cfg.PromoteToPreheader) {
1428 case LoopConfig::NoCur:
1429 case LoopConfig::Same:
1430 case LoopConfig::CurContainsUse:
1433 case LoopConfig::UseContainsCur: {
1434 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1435 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1436 UseMI, UseMBB, UseLoop);
1440 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1442 case LoopConfig::Siblings:
1443 case LoopConfig::Unrelated:
1444 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1445 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1454 UseMI = &PreHdr->back();
1456 UseLoop = CommonParent;
1460 case LoopConfig::NoCur:
1462 (sizeOf(*
UseMI) ? 0 : 1)};
1464 case LoopConfig::Same:
1465 case LoopConfig::CurContainsUse:
1466 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1468 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1472 case LoopConfig::UseContainsCur:
1473 case LoopConfig::Siblings:
1475 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1477 case LoopConfig::Unrelated:
1478 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1479 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1490 bool isUseReachablePrecise(
const MachineInstr &
MI,
1491 const MachineBasicBlock *
MBB,
1492 const MachineOperand *UseMO,
1493 const MachineInstr *
UseMI,
1494 const MachineBasicBlock *UseMBB)
const {
1497 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1502 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1503 if (!isReachableOrSame(
MBB, PhiUseEdge))
1508 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1510 if (
MBB == UseMBB) {
1514 if (instrsAreInOrder(&
MI,
UseMI))
1519 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1520 return UseLoop && !UseLoop->
contains(DefMBB);
1524 return instrsAreInOrder(
DefMI, &
MI);
1526 MachineLoop *
Loop = MLI->getLoopFor(
MBB);
1530 MachineLoop *TopLoop =
Loop->getOutermostLoop();
1531 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1532 !isForwardReachable(UseMBB,
MBB);
1539 void printPaths(raw_ostream &OS)
const {
1540 OS <<
"\n---------------- Paths --------------- {\n";
1541 for (
const auto &[
P, PI] : Paths) {
1552 void printInterBlockDistances(raw_ostream &OS)
const {
1553 using MBBPair = std::pair<unsigned, unsigned>;
1554 using Elem = std::pair<NextUseDistance, MBBPair>;
1555 std::vector<Elem> SortedDistances;
1557 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1558 for (
const auto &[ToNum, Dist] : Dsts) {
1559 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1562 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1563 if (
A.first !=
B.first)
1564 return A.first <
B.first;
1566 if (
A.second.first !=
B.second.first)
1567 return A.second.first <
B.second.first;
1569 return A.second.second <
B.second.second;
1572 OS <<
"\n--------- InterBlockDistances -------- {\n";
1573 for (
const Elem &
E : SortedDistances) {
1575 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1583 printInterBlockDistances(
dbgs());
1594 struct LiveRegToUseMapElem {
1597 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1598 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1599 : Use(
U), MIDependent(MIDep) {}
1601 void print(raw_ostream &OS)
const {
1603 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1614 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1615 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1617 const MachineInstr *CachedDistancesMI =
nullptr;
1618 LiveRegToUseMap CachedDistances;
1619 LiveRegToUseMap PendingCachedDistances;
1620 unsigned DistanceCacheHits = 0;
1621 unsigned DistanceCacheMisses = 0;
1623 void resetDistanceCache() {
1624 CachedDistancesMI =
nullptr;
1625 CachedDistances.clear();
1626 DistanceCacheHits = 0;
1627 DistanceCacheMisses = 0;
1630 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1631 if (CachedDistancesMI &&
1632 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1633 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1634 CachedDistancesMI =
nullptr;
1635 CachedDistances.clear();
1639 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1640 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1641 if (!CacheElem.MIDependent)
1644 const LiveRegUse &
U = CacheElem.Use;
1647 if (
U.Dist < LastDelta)
1650 const MachineInstr *
UseMI =
U.Use->getParent();
1658 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1659 !instrsAreInOrder(
UseMI, &
MI);
1662 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1663 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1664 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1665 if (!CLOpts.next_use_analysis_distance_cache)
1666 return {
nullptr,
nullptr};
1668 ++DistanceCacheMisses;
1669 auto I = CachedDistances.find(
Reg);
1670 if (
I == CachedDistances.end())
1671 return {
nullptr,
nullptr};
1672 const LaneBitmaskToUseMap &RegSlot =
I->second;
1673 if (RegSlot.empty())
1674 return {
nullptr,
nullptr};
1676 auto J = RegSlot.find(LaneMask);
1677 if (J == RegSlot.end())
1678 return {
nullptr,
nullptr};
1680 const LiveRegToUseMapElem &MaskSlot = J->second;
1681 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1682 return {
nullptr,
nullptr};
1684 --DistanceCacheMisses;
1685 ++DistanceCacheHits;
1686 return {&RegSlot, &MaskSlot};
1689 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1690 LiveRegUse U,
bool MIDependent) {
1691 if (!CLOpts.next_use_analysis_distance_cache)
1694 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1695 LaneBitmaskToUseMap &RegSlot =
I->second;
1696 RegSlot.try_emplace(Mask, U, MIDependent);
1699 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1700 if (!CLOpts.next_use_analysis_distance_cache)
1703 CachedDistancesMI = &
MI;
1704 CachedDistances = std::move(PendingCachedDistances);
1705 PendingCachedDistances.clear();
1709 void printDistanceCache(raw_ostream &OS)
const {
1710 OS <<
"\n----------- Distance Cache ----------- {\n";
1711 OS <<
" CachedAt: ";
1712 if (CachedDistancesMI)
1713 OS << *CachedDistancesMI;
1717 constexpr size_t RegNameWidth = 20;
1718 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1720 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1722 for (
const auto &[Mask, Elem] : ByMask) {
1724 raw_string_ostream KOS(
RegName);
1725 if (Mask == AllLanes) {
1728 SmallVector<unsigned> Indexes;
1729 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1730 if (Indexes.
size() == 1)
1740 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1746 printDistanceCache(
dbgs());
1756 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1757 SubRegIndexesForRegClass;
1758 void collectSubRegUsesByMask(
1759 const SmallVectorImpl<const MachineOperand *> &
Uses,
1760 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1761 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1767 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1770 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1773 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1774 const MachineOperand *MO =
Uses[
I];
1775 auto [SubRegMIDep, Dist] = Distances[
I];
1776 const LiveRegUse LRU{MO, Dist};
1778 ArrayRef<unsigned> Indexes;
1783 Indexes = RCSubRegIndexes;
1786 for (
unsigned Idx : Indexes) {
1787 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1788 if (
Mask.all() || Mask == LiveRegLaneMask)
1791 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1792 if (updateClosest(SlotU, LRU))
1793 SlotMIDep = SubRegMIDep;
1799 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1800 LaneBitmask LiveRegLaneMask,
1801 const MachineInstr *
MI,
1802 InstrIdTy LastDelta,
1803 LaneBitmaskToUseMap &UseByMask) {
1805 for (
const auto &KV : CachedMap) {
1806 LaneBitmask SubregLaneMask = KV.first;
1807 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1810 const LiveRegToUseMapElem &SubregE = KV.second;
1811 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1814 const bool MIDep = SubregE.MIDependent;
1815 LiveRegUse
U = SubregE.Use;
1817 U.Dist -= LastDelta;
1819 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1820 if (updateClosest(SlotU, U))
1827 void updateFurthestSubReg(
1828 const MachineInstr &
MI,
const LiveRegUse &U,
1829 const LaneBitmaskToUseMap &UseByMask,
1830 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1831 LiveRegUse &FurthestSubreg) {
1833 if (UseByMask.empty()) {
1834 updateFurthest(FurthestSubreg, U);
1838 for (
const auto &KV : UseByMask) {
1839 const LiveRegUse &SubregU = KV.second.Use;
1840 const bool SubregMIDep = KV.second.MIDependent;
1844 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1846 updateFurthest(FurthestSubreg, SubregU);
1851 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1852 SmallSet<Register, 4> MIDefs;
1854 for (
const MachineOperand &MO :
MI.all_defs()) {
1867 LiveRegUse *FurthestSubreg =
nullptr,
1869 *RelevantUses =
nullptr) {
1874 LaneBitmaskToUseMap UseByMask;
1876 maybeClearCachedLiveRegUses(
MI);
1877 const InstrIdTy LastDelta =
1878 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1891 bool MIDependent =
false;
1892 auto [CacheMap, CacheElem] =
1893 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1894 if (CacheMap && CacheElem) {
1895 MIDependent = CacheElem->MIDependent;
1898 U.Dist -= LastDelta;
1906 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
1907 U = LiveRegUse{NextUse, Dist};
1912 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
1914 updateFurthest(Furthest, U);
1916 if (!FurthestSubreg)
1920 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
1923 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
1925 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1927 updateCachedLiveRegUses(
MI);
1946 for (
const auto &KV : Paths) {
1947 const Path &
P = KV.first;
1948 const PathInfo &PI = KV.second;
1952 printMBBNameAttr(J,
"src", *
P.src(), MST);
1953 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
1955 if (PI.ShortestDistance.has_value()) {
1957 PI.ShortestDistance.value().toJsonValue());
1959 J.
attribute(
"shortest-distance",
nullptr);
1962 if (PI.ShortestUnweightedDistance.has_value()) {
1963 J.
attribute(
"shortest-unweighted-distance",
1964 PI.ShortestUnweightedDistance.value().toJsonValue());
1966 J.
attribute(
"shortest-unweighted-distance",
nullptr);
1969 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
1971 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2009 nullptr,
nullptr,
nullptr);