282 InstrToIdMap InstrToId;
285 void initializeTables() {
287 calcInstrIds(&BB, InstrToId);
288 initializeCfgPaths();
289 initializeInterBlockDistances();
297 resetDistanceCache();
311 void calcInstrIds(
const MachineBasicBlock *BB,
312 InstrToIdMap &MutableInstrToId)
const {
315 MutableInstrToId[&
MI] =
Id;
322 InstrIdTy getInstrId(
const MachineInstr *
MI)
const {
323 auto It = InstrToId.find(
MI);
324 if (It != InstrToId.end())
329 auto &MutableInstrToId =
const_cast<InstrToIdMap &
>(InstrToId);
330 calcInstrIds(
MI->getParent(), MutableInstrToId);
331 return InstrToId.find(
MI)->second;
336 InstrIdTy getHeadLen(
const MachineInstr *
MI)
const {
337 const MachineBasicBlock *
MBB =
MI->getParent();
343 InstrIdTy getTailLen(
const MachineInstr *
MI)
const {
344 const MachineBasicBlock *
MBB =
MI->getParent();
350 InstrIdTy getDistance(
const MachineInstr *From,
351 const MachineInstr *To)
const {
353 return getInstrId(To) - getInstrId(From);
360 DenseMap<Register, SmallVector<const MachineOperand *>> RegUseMap;
364 auto I = RegUseMap.find(
Reg);
365 if (
I != RegUseMap.end())
370 for (
const MachineOperand &UseMO : MRI->use_nodbg_operands(
Reg)) {
371 if (!UseMO.isUndef())
372 Uses.push_back(&UseMO);
378 return !getRegisterUses(
Reg).empty();
387 std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
391 constexpr Path() : P(nullptr, nullptr) {}
392 constexpr Path(
const MachineBasicBlock *Src,
const MachineBasicBlock *Dst)
394 Path(
const StorageTy &Pair) : P(Pair) {}
396 constexpr operator const StorageTy &()
const {
return P; }
397 using DenseMapInfo = llvm::DenseMapInfo<StorageTy>;
399 const MachineBasicBlock *src()
const {
return P.first; }
400 const MachineBasicBlock *dst()
const {
return P.second; }
403 enum class EdgeKind { Back = -1, None = 0, Forward = 1 };
404 static constexpr StringRef toString(EdgeKind EK) {
405 if (EK == EdgeKind::Back)
407 if (EK == EdgeKind::Forward)
415 int ForwardReachable;
416 unsigned RelativeLoopDepth;
417 std::optional<NextUseDistance> ShortestDistance;
418 std::optional<NextUseDistance> ShortestUnweightedDistance;
422 : EK(EdgeKind::
None), Reachable(
false), ForwardReachable(-1),
423 RelativeLoopDepth(0), Size(0) {}
425 bool isBackedge()
const {
return EK == EdgeKind::Back; }
427 bool isForwardReachableSet()
const {
return 0 <= ForwardReachable; }
428 bool isForwardReachableUnset()
const {
return ForwardReachable < 0; }
429 bool isForwardReachable()
const {
return ForwardReachable == 1; }
430 bool isNotForwardReachable()
const {
return ForwardReachable == 0; }
432 void print(raw_ostream &OS)
const {
433 OS <<
"{ek=" <<
toString(EK) <<
" reach=" << Reachable
434 <<
" fwd-reach=" << ForwardReachable
435 <<
" loop-depth=" << RelativeLoopDepth <<
" size=" << Size;
436 if (ShortestDistance) {
437 OS <<
" shortest-dist=";
438 ShortestDistance->print(OS);
440 if (ShortestUnweightedDistance) {
441 OS <<
" shortest-unweighted-dist=";
442 ShortestUnweightedDistance->print(OS);
458 DenseMap<Path, PathInfo, Path::DenseMapInfo> Paths;
460 const PathInfo *maybePathInfoFor(
const MachineBasicBlock *From,
461 const MachineBasicBlock *To)
const {
462 auto I = Paths.find({From, To});
463 return I == Paths.end() ? nullptr : &
I->second;
466 PathInfo &getOrInitPathInfo(
const MachineBasicBlock *From,
467 const MachineBasicBlock *To)
const {
469 auto &MutablePaths = NonConstThis->Paths;
472 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
476 bool Reachable = calcIsReachable(
P.src(),
P.dst());
480 return NonConstThis->initializePathInfo(MutablePaths.at(
P),
P,
481 EdgeKind::None, Reachable);
484 const PathInfo &pathInfoFor(
const MachineBasicBlock *From,
485 const MachineBasicBlock *To)
const {
486 return getOrInitPathInfo(From, To);
493 PathInfo &initializePathInfo(PathInfo &Slot, Path
P, EdgeKind EK,
496 Slot.Reachable = Reachable;
497 Slot.ForwardReachable = EK == EdgeKind::None ? -1 : EK == EdgeKind::Forward;
498 Slot.RelativeLoopDepth =
499 Slot.Reachable ? calcRelativeLoopDepth(
P.src(),
P.dst()) : 0;
500 Slot.Size =
P.src() ==
P.dst() ? calcSize(
P.src()) : 0;
501 if (EK != EdgeKind::None)
502 Slot.ShortestUnweightedDistance = 0;
506 PathInfo &initializePathInfo(Path
P, EdgeKind EK,
bool Reachable)
const {
508 auto &MutablePaths = NonConstThis->Paths;
509 return NonConstThis->initializePathInfo(MutablePaths[
P],
P, EK, Reachable);
512 std::pair<PathInfo *, bool> maybeInitializePathInfo(Path
P, EdgeKind EK,
513 bool Reachable)
const {
515 auto &MutablePaths = NonConstThis->Paths;
516 auto [
I,
Inserted] = MutablePaths.try_emplace(
P);
518 NonConstThis->initializePathInfo(
I->second,
P, EK, Reachable);
522 bool initializePathInfoForwardReachable(
const MachineBasicBlock *From,
523 const MachineBasicBlock *To,
525 PathInfo &
Slot = getOrInitPathInfo(From, To);
532 initializePathInfoShortestDistance(
const MachineBasicBlock *From,
533 const MachineBasicBlock *To,
534 NextUseDistance
Value)
const {
535 PathInfo &
Slot = getOrInitPathInfo(From, To);
542 initializePathInfoShortestUnweightedDistance(
const MachineBasicBlock *From,
543 const MachineBasicBlock *To,
544 NextUseDistance
Value)
const {
545 PathInfo &
Slot = getOrInitPathInfo(From, To);
546 assert(!
Slot.ShortestUnweightedDistance.has_value());
557 for (
const Path &
P : ReachablePaths)
558 initializePathInfo(
P, EdgeKind::None,
true);
559 for (
const Path &
P : UnreachablePaths)
560 initializePathInfo(
P, EdgeKind::None,
false);
566 for (
bool R : {
true,
false}) {
567 const auto &ToInit =
R ? ReachablePaths : UnreachablePaths;
568 for (
const Path &
P : ToInit) {
569 PathInfo &
Slot = getOrInitPathInfo(
P.src(),
P.dst());
570 assert(
Slot.isForwardReachableUnset() ||
Slot.ForwardReachable == R);
571 Slot.ForwardReachable =
R;
579 void initializeCfgPaths() {
582 enum VisitState { Undiscovered, Visiting, Finished };
583 DenseMap<const MachineBasicBlock *, VisitState> State;
586 State[&MF->front()] = Undiscovered;
588 while (!Work.
empty()) {
589 const MachineBasicBlock *Src = Work.
back();
590 VisitState &SrcState = State[Src];
595 if (SrcState == Visiting || SrcState == Finished) {
602 for (
const MachineBasicBlock *Dst : Src->successors()) {
603 const VisitState DstState = State.
lookup(Dst);
606 if (DstState == Undiscovered) {
607 EK = EdgeKind::Forward;
609 }
else if (DstState == Visiting) {
612 EK = EdgeKind::Forward;
617 initializePathInfo(
P, EK,
true);
628 static bool isStandAloneLoop(
const MachineLoop *Loop) {
632 static MachineLoop *findChildLoop(MachineLoop *
const Parent,
633 MachineLoop *Descendant) {
634 for (MachineLoop *L = Descendant;
L != Parent;
L =
L->getParentLoop()) {
635 if (
L->getParentLoop() == Parent)
644 static std::pair<MachineLoop *, unsigned>
645 findCommonParent(MachineLoop *
A,
const MachineLoop *
B) {
647 for (;
A !=
nullptr;
A =
A->getParentLoop(), ++
Depth) {
654 static const MachineBasicBlock *
655 getOutermostPreheader(
const MachineLoop *Loop) {
659 static MachineBasicBlock *findChildPreheader(MachineLoop *
const Parent,
660 MachineLoop *Descendant) {
661 MachineLoop *ChildLoop = findChildLoop(Parent, Descendant);
665 static const MachineBasicBlock *
666 getIncomingBlockIfPhiUse(
const MachineInstr *
MI,
const MachineOperand *MO) {
675 InstrIdTy calcSize(
const MachineBasicBlock *BB)
const {
682 NextUseDistance calcWeightedSize(
const MachineBasicBlock *From,
683 const MachineBasicBlock *To)
const {
685 getRelativeLoopDepth(From, To));
689 unsigned calcRelativeLoopDepth(
const MachineBasicBlock *From,
690 const MachineBasicBlock *To)
const {
691 MachineLoop *LoopFrom = MLI->getLoopFor(From);
692 MachineLoop *LoopTo = MLI->getLoopFor(To);
707 return findCommonParent(LoopFrom, LoopTo).second;
714 bool calcIsReachable(
const MachineBasicBlock *From,
715 const MachineBasicBlock *To,
716 bool ForwardOnly =
false)
const {
717 if (From == To && !MLI->getLoopFor(From))
720 if (!ForwardOnly && interBlockDistanceExists(From, To))
723 enum { VisitOp, PopOp };
724 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
726 DenseSet<const MachineBasicBlock *> Visited{From};
732 auto Finally = [&](
bool Reachable) {
737 IntermediatePath.
clear();
738 for (
const MachineBasicBlock *
MBB : Visited) {
745 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
747 initializePaths(IntermediatePath, Unreachable);
752 while (!Work.
empty()) {
763 if (Current->succ_empty())
766 if (Current != From) {
771 for (
const MachineBasicBlock *Succ : Current->successors()) {
772 if (ForwardOnly && isBackedge(Current, Succ))
778 if (
auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
779 if (CachedReachable.value())
781 Visited.insert(Succ);
785 if (Visited.insert(Succ).second)
804 struct InterBlockDistance {
805 NextUseDistance Weighted;
806 NextUseDistance Unweighted;
807 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
808 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
809 : Weighted(
W), Unweighted(UW) {}
810 bool operator==(
const InterBlockDistance &
Other)
const {
811 return Weighted ==
Other.Weighted && Unweighted ==
Other.Unweighted;
813 bool operator!=(
const InterBlockDistance &
Other)
const {
814 return !(*
this ==
Other);
817 void print(raw_ostream &OS)
const {
821 Unweighted.print(OS);
830 using InterBlockDistanceMap =
831 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
832 InterBlockDistanceMap InterBlockDistances;
834 void initializeInterBlockDistances() {
835 InterBlockDistanceMap Distances;
844 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
845 InterBlockDistanceMap::mapped_type Curr;
846 Curr.reserve(Prev.size());
851 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
855 unsigned SuccNum = Succ->getNumber();
856 const unsigned UnweightedSize{getSize(Succ)};
858 for (
const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
861 if (DestBlockNum == MBBNum)
864 const MachineBasicBlock *DestMBB =
865 MF->getBlockNumbered(DestBlockNum);
867 const NextUseDistance UnweightedDist{UnweightedSize +
868 DestDist.Unweighted};
870 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
872 const NextUseDistance WeightedDist =
878 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
880 InterBlockDistance &
Slot =
I->second;
882 Slot.Unweighted =
min(
Slot.Unweighted, UnweightedDist);
887 Distances[MBBNum] = std::move(Curr);
891 InterBlockDistances = std::move(Distances);
895 const InterBlockDistance *
896 getInterBlockDistanceMapValue(
const MachineBasicBlock *From,
897 const MachineBasicBlock *To)
const {
898 auto I = InterBlockDistances.find(From->
getNumber());
899 if (
I == InterBlockDistances.end())
901 const InterBlockDistanceMap::mapped_type &FromSlot =
I->second;
903 return J == FromSlot.end() ? nullptr : &J->second;
906 bool interBlockDistanceExists(
const MachineBasicBlock *From,
907 const MachineBasicBlock *To)
const {
908 return getInterBlockDistanceMapValue(From, To);
911 NextUseDistance getInterBlockDistance(
const MachineBasicBlock *From,
912 const MachineBasicBlock *To,
913 bool Unweighted)
const {
915 assert(From != To &&
"The basic blocks should be different.");
919 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
922 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
926 return Unweighted ? BD->Unweighted : BD->Weighted;
930 getWeightedInterBlockDistance(
const MachineBasicBlock *From,
931 const MachineBasicBlock *To)
const {
932 return getInterBlockDistance(From, To,
false);
936 getUnweightedInterBlockDistance(
const MachineBasicBlock *From,
937 const MachineBasicBlock *To)
const {
938 return getInterBlockDistance(From, To,
true);
945 InstrIdTy getSize(
const MachineBasicBlock *BB)
const {
946 return pathInfoFor(BB, BB).Size;
949 bool isReachable(
const MachineBasicBlock *From,
950 const MachineBasicBlock *To)
const {
951 return pathInfoFor(From, To).Reachable;
954 bool isReachableOrSame(
const MachineBasicBlock *From,
955 const MachineBasicBlock *To)
const {
956 return From == To || pathInfoFor(From, To).Reachable;
959 bool isForwardReachable(
const MachineBasicBlock *From,
960 const MachineBasicBlock *To)
const {
961 const PathInfo &PI = pathInfoFor(From, To);
962 if (PI.isForwardReachableSet())
963 return PI.isForwardReachable();
965 return initializePathInfoForwardReachable(
967 PI.Reachable && calcIsReachable(From, To,
true));
972 std::optional<bool> isMaybeReachable(
const MachineBasicBlock *From,
973 const MachineBasicBlock *To,
974 bool ForwardOnly)
const {
975 const PathInfo *PI = maybePathInfoFor(From, To);
980 if (PI->isForwardReachable())
983 if (PI->isNotForwardReachable())
987 return PI->Reachable;
990 bool isBackedge(
const MachineBasicBlock *From,
991 const MachineBasicBlock *To)
const {
992 return pathInfoFor(From, To).isBackedge();
997 bool instrsAreInOrder(
const MachineInstr *
A,
const MachineInstr *
B)
const {
998 assert(
A->getParent() ==
B->getParent() &&
999 "instructions must be in the same basic block!");
1000 if (
A ==
B || getInstrId(
A) < getInstrId(
B))
1006 for (
auto &
PHI :
A->getParent()->phis()) {
1015 unsigned getRelativeLoopDepth(
const MachineBasicBlock *From,
1016 const MachineBasicBlock *To)
const {
1017 return pathInfoFor(From, To).RelativeLoopDepth;
1020 NextUseDistance getShortestPath(
const MachineBasicBlock *From,
1021 const MachineBasicBlock *To)
const {
1022 std::optional<NextUseDistance> MaybeD =
1023 pathInfoFor(From, To).ShortestDistance;
1024 if (MaybeD.has_value())
1025 return MaybeD.value();
1027 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1028 return initializePathInfoShortestDistance(From, To, Dist);
1031 NextUseDistance getShortestUnweightedPath(
const MachineBasicBlock *From,
1032 const MachineBasicBlock *To)
const {
1033 std::optional<NextUseDistance> MaybeD =
1034 pathInfoFor(From, To).ShortestUnweightedDistance;
1035 if (MaybeD.has_value())
1036 return MaybeD.value();
1038 return initializePathInfoShortestUnweightedDistance(
1039 From, To, getUnweightedInterBlockDistance(From, To));
1047 struct MBBDistPair {
1048 NextUseDistance Distance;
1049 const MachineBasicBlock *MBB;
1050 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1051 MBBDistPair(NextUseDistance
D,
const MachineBasicBlock *
B)
1052 : Distance(
D), MBB(
B) {}
1054 MBBDistPair operator+(NextUseDistance
D) {
return {Distance +
D, MBB}; }
1055 MBBDistPair &operator+=(NextUseDistance
D) {
1060 void print(raw_ostream &OS)
const {
1081 MBBDistPair calcShortestDistanceToLatch(
const MachineBasicBlock *CurMBB,
1082 const MachineLoop *CurLoop)
const {
1087 for (MachineBasicBlock *LMBB : Latches) {
1091 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1092 if (Dst <
LD.Distance) {
1102 calcShortestUnweightedDistanceToLatch(
const MachineBasicBlock *CurMBB,
1103 const MachineLoop *CurLoop)
const {
1108 for (MachineBasicBlock *LMBB : Latches) {
1112 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1113 if (Dst <
LD.Distance) {
1122 MBBDistPair calcShortestDistanceToExit(
const MachineBasicBlock *CurMBB,
1123 const MachineLoop *CurLoop)
const {
1128 for (
auto [Exit, Dest] : ExitEdges) {
1132 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1133 if (Dst <
LD.Distance) {
1144 calcShortestDistanceThroughInnermostLoop(
const MachineBasicBlock *CurMBB,
1145 MachineLoop *CurLoop)
const {
1146 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1150 return {getSize(CurMBB), CurMBB};
1152 MachineBasicBlock *LoopHeader = CurLoop->
getHeader();
1153 MBBDistPair
LD{0,
nullptr};
1155 LD += getSize(LoopHeader);
1157 if (CurMBB != LoopHeader)
1158 LD += getShortestPath(LoopHeader, CurMBB);
1163 LD = calcShortestDistanceToExit(CurMBB, CurLoop) +
LD.Distance;
1165 if (CurMBB != LoopHeader && CurMBB !=
LD.MBB)
1166 LD += getSize(CurMBB);
1168 if (
LD.MBB != LoopHeader)
1169 LD += getSize(
LD.MBB);
1176 MBBDistPair calcShortestDistanceThroughLoop(
const MachineBasicBlock *CurMBB,
1177 MachineLoop *OuterLoop)
const {
1178 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1180 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1182 MachineBasicBlock *CurHdr = CurLoop->
getHeader();
1184 if (OuterLoop == CurLoop)
1188 MachineBasicBlock *ParentHdr = ParentLoop->
getHeader();
1190 MBBDistPair
LD{0,
nullptr};
1191 LD += getSize(ParentHdr);
1192 LD += getShortestPath(ParentHdr, CurHdr);
1193 LD += CurLD.Distance.applyLoopWeight();
1194 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) +
LD.Distance;
1195 LD += getSize(
LD.MBB);
1197 CurLoop = ParentLoop;
1206 calcWeightedDistanceThroughLoopViaMBB(
const MachineBasicBlock *CurMBB,
1207 MachineLoop *CurLoop)
const {
1208 MBBDistPair
LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1209 LD.Distance =
LD.Distance.applyLoopWeight();
1215 MBBDistPair calcWeightedDistanceThroughLoop(
1216 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1217 const MachineLoop *ParentLoop =
nullptr)
const {
1219 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1221 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1230 NextUseDistance appendDistanceToUse(
const MBBDistPair &Exit,
1231 const MachineInstr *
UseMI,
1232 const MachineBasicBlock *UseMBB)
const {
1233 return Exit.Distance + getShortestPath(
Exit.MBB, UseMBB) +
1239 MBBDistPair calcDistanceThroughSubLoopUse(
const MachineBasicBlock *CurMBB,
1240 MachineLoop *CurLoop,
1241 MachineLoop *UseLoop)
const {
1244 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1245 assert(UseLoopSubLoop &&
"CurLoop should be nested in UseLoop");
1246 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1250 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1251 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1252 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1253 MachineLoop *UseLoop)
const {
1254 return appendDistanceToUse(
1255 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop),
UseMI, UseMBB);
1260 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1261 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1262 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1265 if (isStandAloneLoop(CurLoop))
1266 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1269 if (!OutermostLoop->
contains(UseLoop)) {
1275 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1281 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1282 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1284 assert(CurLoop != OutermostLoop &&
"The loop cannot be the outermost.");
1285 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1290 if (CurLoop == OutermostLoop)
1293 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1298 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1299 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1300 const MachineInstr *
UseMI,
const MachineBasicBlock *UseMBB,
1301 MachineLoop *UseLoop)
const {
1302 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1303 CurMBB, CurLoop, UseMBB, UseLoop),
1308 bool machineOperandCoveredBy(
const MachineOperand &MO,
1309 LaneBitmask LaneMask)
const {
1310 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(MO.
getSubReg());
1311 return (Mask & LaneMask) ==
Mask;
1316 bool isIncomingValFromBackedge(
Register LiveReg, LaneBitmask LiveLaneMask,
1317 const MachineInstr *CurMI,
1318 const MachineInstr *
UseMI)
const {
1322 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->
getParent());
1330 (CurLoop && !UseLoop->
contains(CurLoop)) ||
1338 for (
unsigned I = 1;
I <
NumOps;
I += 2) {
1341 assert(RegMO.
isReg() &&
"Expected register operand of PHI");
1342 assert(MBBMO.
isMBB() &&
"Expected MBB operand of PHI");
1343 if (RegMO.
getReg() == LiveReg &&
1344 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1345 MachineBasicBlock *IncomingBB = MBBMO.
getMBB();
1356 const MachineInstr *CurMI,
const MachineBasicBlock *CurMBB,
1357 MachineLoop *CurLoop,
const MachineInstr *
UseMI,
1358 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop)
const {
1359 assert(UseLoop &&
"There is no backedge.");
1360 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->
contains(CurLoop) &&
1361 "Unexpected loop configuration");
1363 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1364 MBBDistPair InnerLoopLD =
1365 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1366 MBBDistPair
LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1368 InnerLoopLD.Distance +
LD.Distance + getSize(
LD.MBB) + UseHeadLen};
1373 NextUseDistance calcBackedgeDistance(
const MachineInstr *CurMI,
1374 const MachineBasicBlock *CurMBB,
1375 MachineLoop *CurLoop,
1376 const MachineInstr *
UseMI)
const {
1378 InstrIdTy CurTailLen = getTailLen(CurMI);
1379 InstrIdTy UseHeadLen = getHeadLen(
UseMI);
1380 MBBDistPair
LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1381 const MachineBasicBlock *HdrMBB = CurLoop->
getHeader();
1382 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1383 NextUseDistance Dst =
1384 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1386 return CurTailLen +
LD.Distance + getSize(
LD.MBB) + Hdr + Dst + UseHeadLen;
1396 NextUseDistance calcShortestDistance(
const MachineInstr *FromMI,
1397 const MachineInstr *ToMI)
const {
1398 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1399 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1401 if (FromMBB == ToMBB) {
1402 NextUseDistance RV = getDistance(FromMI, ToMI);
1403 assert(RV >= 0 &&
"unexpected negative distance from getDistance");
1407 InstrIdTy FromTailLen = getTailLen(FromMI);
1408 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1409 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1410 assert(Dst.isReachable() &&
1411 "calcShortestDistance called for instructions in non-reachable"
1413 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1414 assert(RV >= 0 &&
"unexpected negative distance");
1423 calcShortestUnweightedDistance(
const MachineInstr *FromMI,
1424 const MachineInstr *ToMI)
const {
1425 const MachineBasicBlock *FromMBB = FromMI->
getParent();
1426 const MachineBasicBlock *ToMBB = ToMI->
getParent();
1428 if (FromMBB == ToMBB)
1429 return getDistance(FromMI, ToMI);
1431 InstrIdTy FromTailLen = getTailLen(FromMI);
1432 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1433 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1434 assert(Dst.isReachable() &&
1435 "calcShortestUnweightedDistance called for instructions in"
1436 " non-reachable basic blocks!");
1437 return FromTailLen + Dst + ToHeadLen;
1452 calcDistanceToUse(
Register LiveReg, LaneBitmask LiveLaneMask,
1453 const MachineInstr &CurMI,
1454 const MachineOperand *UseMO)
const {
1456 const MachineBasicBlock *CurMBB = CurMI.
getParent();
1458 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1459 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1461 if (Cfg.PreciseUseModeling) {
1463 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1464 UseMI = &PhiUseEdge->back();
1465 UseMBB = PhiUseEdge;
1466 UseLoop = MLI->getLoopFor(PhiUseEdge);
1470 enum class LoopConfig {
1478 auto [LpCfg, PreHdr, CommonParent] = [&]()
1479 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1481 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop),
nullptr};
1484 return {CurMBB == UseMBB ? LoopConfig::Same
1485 : LoopConfig::CurContainsUse,
1486 findChildPreheader(CurLoop, UseLoop),
nullptr};
1489 if (MachineLoop *
P = findCommonParent(UseLoop, CurLoop).first) {
1491 return {LoopConfig::Siblings, findChildPreheader(
P, UseLoop),
P};
1492 return {LoopConfig::UseContainsCur,
nullptr,
nullptr};
1494 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop),
nullptr};
1500 if (!Cfg.PromoteToPreheader) {
1502 case LoopConfig::NoCur:
1503 case LoopConfig::Same:
1504 case LoopConfig::CurContainsUse:
1507 case LoopConfig::UseContainsCur: {
1508 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI,
UseMI)) {
1509 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1510 UseMI, UseMBB, UseLoop);
1514 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1516 case LoopConfig::Siblings:
1517 case LoopConfig::Unrelated:
1518 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1519 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1528 UseMI = &PreHdr->back();
1530 UseLoop = CommonParent;
1534 case LoopConfig::NoCur:
1536 (sizeOf(*
UseMI) ? 0 : 1)};
1538 case LoopConfig::Same:
1539 case LoopConfig::CurContainsUse:
1540 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI,
UseMI))
1542 calcBackedgeDistance(&CurMI, CurMBB, CurLoop,
UseMI)};
1546 case LoopConfig::UseContainsCur:
1547 case LoopConfig::Siblings:
1549 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1551 case LoopConfig::Unrelated:
1552 return {
InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1553 CurMBB, CurLoop,
UseMI, UseMBB, UseLoop)};
1564 bool isUseReachablePrecise(
const MachineInstr &
MI,
1565 const MachineBasicBlock *
MBB,
1566 const MachineOperand *UseMO,
1567 const MachineInstr *
UseMI,
1568 const MachineBasicBlock *UseMBB)
const {
1571 if (
MBB != UseMBB && !isReachable(
MBB, UseMBB))
1576 if (
auto *PhiUseEdge = getIncomingBlockIfPhiUse(
UseMI, UseMO)) {
1577 if (!isReachableOrSame(
MBB, PhiUseEdge))
1582 const MachineInstr *
DefMI = MRI->getUniqueVRegDef(UseMO->
getReg());
1584 if (
MBB == UseMBB) {
1588 if (instrsAreInOrder(&
MI,
UseMI))
1593 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1594 return UseLoop && !UseLoop->
contains(DefMBB);
1598 return instrsAreInOrder(
DefMI, &
MI);
1600 MachineLoop *Loop = MLI->getLoopFor(
MBB);
1605 return !TopLoop->
contains(DefMBB) || !isReachable(
MBB, DefMBB) ||
1606 !isForwardReachable(UseMBB,
MBB);
1615 void populatePathTable() {
1616 for (
const MachineBasicBlock &MBB1 : *MF) {
1617 for (
const MachineBasicBlock &MBB2 : *MF) {
1620 getShortestPath(&MBB1, &MBB2);
1625 void printPaths(raw_ostream &OS)
const {
1626 OS <<
"\n---------------- Paths --------------- {\n";
1627 for (
const auto &[
P, PI] : Paths) {
1639 void dumpShortestPaths()
const {
1640 for (
const auto &
P : Paths) {
1641 const MachineBasicBlock *From =
P.first.src();
1642 const MachineBasicBlock *To =
P.first.dst();
1643 std::optional<NextUseDistance> Dist =
P.second.ShortestDistance;
1646 << Dist.value_or(-1).fmt() <<
"\n";
1650 void printInterBlockDistances(raw_ostream &OS)
const {
1651 using MBBPair = std::pair<unsigned, unsigned>;
1652 using Elem = std::pair<NextUseDistance, MBBPair>;
1653 std::vector<Elem> SortedDistances;
1655 for (
const auto &[FromNum, Dsts] : InterBlockDistances) {
1656 for (
const auto &[ToNum, Dist] : Dsts) {
1657 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1660 llvm::sort(SortedDistances, [](
const auto &
A,
const auto &
B) {
1661 if (
A.first !=
B.first)
1662 return A.first <
B.first;
1664 if (
A.second.first !=
B.second.first)
1665 return A.second.first <
B.second.first;
1667 return A.second.second <
B.second.second;
1670 OS <<
"\n--------- InterBlockDistances -------- {\n";
1671 for (
const Elem &
E : SortedDistances) {
1673 OS <<
" bb." <<
E.second.first <<
" -> bb." <<
E.second.second <<
": ";
1681 printInterBlockDistances(
dbgs());
1692 struct LiveRegToUseMapElem {
1695 LiveRegToUseMapElem() : Use(), MIDependent(
false) {}
1696 LiveRegToUseMapElem(LiveRegUse U,
bool MIDep)
1697 : Use(
U), MIDependent(MIDep) {}
1699 void print(raw_ostream &OS)
const {
1701 OS << (MIDependent ?
" [mi-dep]" :
" [mi-indep]");
1712 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1713 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1715 const MachineInstr *CachedDistancesMI =
nullptr;
1716 LiveRegToUseMap CachedDistances;
1717 LiveRegToUseMap PendingCachedDistances;
1718 unsigned DistanceCacheHits = 0;
1719 unsigned DistanceCacheMisses = 0;
1721 void resetDistanceCache() {
1722 CachedDistancesMI =
nullptr;
1723 CachedDistances.clear();
1724 DistanceCacheHits = 0;
1725 DistanceCacheMisses = 0;
1728 void maybeClearCachedLiveRegUses(
const MachineInstr &
MI) {
1729 if (CachedDistancesMI &&
1730 (CachedDistancesMI->getParent() !=
MI.getParent() ||
1731 !instrsAreInOrder(CachedDistancesMI, &
MI))) {
1732 CachedDistancesMI =
nullptr;
1733 CachedDistances.clear();
1737 bool okToUseCacheElem(
const LiveRegToUseMapElem &CacheElem,
1738 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1739 if (!CacheElem.MIDependent)
1742 const LiveRegUse &
U = CacheElem.Use;
1745 if (
U.Dist < LastDelta)
1748 const MachineInstr *
UseMI =
U.Use->getParent();
1756 return !instrsAreInOrder(CachedDistancesMI,
UseMI) ||
1757 !instrsAreInOrder(
UseMI, &
MI);
1760 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1761 findCachedLiveRegUse(
Register Reg, LaneBitmask LaneMask,
1762 const MachineInstr &
MI,
const InstrIdTy LastDelta) {
1763 if (!DistanceCacheEnabled)
1764 return {
nullptr,
nullptr};
1766 ++DistanceCacheMisses;
1767 auto I = CachedDistances.find(
Reg);
1768 if (
I == CachedDistances.end())
1769 return {
nullptr,
nullptr};
1770 const LaneBitmaskToUseMap &RegSlot =
I->second;
1771 if (RegSlot.empty())
1772 return {
nullptr,
nullptr};
1774 auto J = RegSlot.find(LaneMask);
1775 if (J == RegSlot.end())
1776 return {
nullptr,
nullptr};
1778 const LiveRegToUseMapElem &MaskSlot = J->second;
1779 if (!okToUseCacheElem(MaskSlot,
MI, LastDelta))
1780 return {
nullptr,
nullptr};
1782 --DistanceCacheMisses;
1783 ++DistanceCacheHits;
1784 return {&RegSlot, &MaskSlot};
1787 void cacheLiveRegUse(
const MachineInstr &
MI,
Register Reg, LaneBitmask Mask,
1788 LiveRegUse U,
bool MIDependent) {
1789 if (!DistanceCacheEnabled)
1792 auto I = PendingCachedDistances.try_emplace(
Reg).first;
1793 LaneBitmaskToUseMap &RegSlot =
I->second;
1794 RegSlot.try_emplace(Mask, U, MIDependent);
1797 void updateCachedLiveRegUses(
const MachineInstr &
MI) {
1798 if (!DistanceCacheEnabled)
1801 CachedDistancesMI = &
MI;
1802 CachedDistances = std::move(PendingCachedDistances);
1803 PendingCachedDistances.clear();
1807 void printDistanceCache(raw_ostream &OS)
const {
1808 OS <<
"\n----------- Distance Cache ----------- {\n";
1809 OS <<
" CachedAt: ";
1810 if (CachedDistancesMI)
1811 OS << *CachedDistancesMI;
1815 constexpr size_t RegNameWidth = 20;
1816 for (
const auto &[
Reg, ByMask] : CachedDistances) {
1817 const TargetRegisterClass *RC = MRI->getRegClass(
Reg);
1818 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(
Reg);
1820 for (
const auto &[Mask, Elem] : ByMask) {
1822 raw_string_ostream KOS(
RegName);
1823 if (Mask == AllLanes) {
1826 SmallVector<unsigned> Indexes;
1827 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1828 if (Indexes.
size() == 1)
1838 OS <<
" (hits=" << DistanceCacheHits <<
" misses=" << DistanceCacheMisses
1844 printDistanceCache(
dbgs());
1854 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1855 SubRegIndexesForRegClass;
1856 void collectSubRegUsesByMask(
1857 const SmallVectorImpl<const MachineOperand *> &
Uses,
1858 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1859 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1864 const TargetRegisterClass *RC = MRI->getRegClass(
Uses.front()->getReg());
1865 auto [SRI,
Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1868 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1871 for (
size_t I = 0;
I <
Uses.size(); ++
I) {
1872 const MachineOperand *MO =
Uses[
I];
1873 auto [SubRegMIDep, Dist] = Distances[
I];
1874 const LiveRegUse LRU{MO, Dist};
1876 ArrayRef<unsigned> Indexes;
1881 Indexes = RCSubRegIndexes;
1884 for (
unsigned Idx : Indexes) {
1885 LaneBitmask
Mask = TRI->getSubRegIndexLaneMask(Idx);
1886 if (
Mask.all() || Mask == LiveRegLaneMask)
1889 auto &[SlotU, SlotMIDep] = UseByMask[
Mask];
1890 if (updateClosest(SlotU, LRU))
1891 SlotMIDep = SubRegMIDep;
1897 void collectSubRegUsesByMaskFromCache(
const LaneBitmaskToUseMap &CachedMap,
1898 LaneBitmask LiveRegLaneMask,
1899 const MachineInstr *
MI,
1900 InstrIdTy LastDelta,
1901 LaneBitmaskToUseMap &UseByMask) {
1903 for (
const auto &KV : CachedMap) {
1904 LaneBitmask SubregLaneMask = KV.first;
1905 if (SubregLaneMask.
all() || SubregLaneMask == LiveRegLaneMask)
1908 const LiveRegToUseMapElem &SubregE = KV.second;
1909 if (!okToUseCacheElem(SubregE, *
MI, LastDelta))
1912 const bool MIDep = SubregE.MIDependent;
1913 LiveRegUse
U = SubregE.Use;
1915 U.Dist -= LastDelta;
1917 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1918 if (updateClosest(SlotU, U))
1925 void updateFurthestSubReg(
1926 const MachineInstr &
MI,
const LiveRegUse &U,
1927 const LaneBitmaskToUseMap &UseByMask,
1928 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1929 LiveRegUse &FurthestSubreg) {
1931 if (UseByMask.empty()) {
1932 updateFurthest(FurthestSubreg, U);
1936 for (
const auto &KV : UseByMask) {
1937 const LiveRegUse &SubregU = KV.second.Use;
1938 const bool SubregMIDep = KV.second.MIDependent;
1942 cacheLiveRegUse(
MI, SubregU.Use->getReg(), KV.first, SubregU,
1944 updateFurthest(FurthestSubreg, SubregU);
1949 SmallSet<Register, 4> collectDefinedRegisters(
const MachineInstr &
MI)
const {
1950 SmallSet<Register, 4> MIDefs;
1952 for (
const MachineOperand &MO :
MI.all_defs()) {
1965 LiveRegUse *FurthestSubreg =
nullptr,
1967 *RelevantUses =
nullptr) {
1972 LaneBitmaskToUseMap UseByMask;
1974 maybeClearCachedLiveRegUses(
MI);
1975 const InstrIdTy LastDelta =
1976 CachedDistancesMI ? getDistance(CachedDistancesMI, &
MI) : 0;
1989 bool MIDependent =
false;
1990 auto [CacheMap, CacheElem] =
1991 findCachedLiveRegUse(Reg, LaneMask,
MI, LastDelta);
1992 if (CacheMap && CacheElem) {
1993 MIDependent = CacheElem->MIDependent;
1996 U.Dist -= LastDelta;
2004 Reg, LaneMask,
MI,
Uses, &NextUse, &MIDependent, &Distances);
2005 U = LiveRegUse{NextUse, Dist};
2010 cacheLiveRegUse(
MI, Reg, LaneMask, U, MIDependent);
2012 updateFurthest(Furthest, U);
2014 if (!FurthestSubreg)
2018 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &
MI, LastDelta,
2021 collectSubRegUsesByMask(
Uses, Distances, LaneMask, UseByMask);
2023 updateFurthestSubReg(
MI, U, UseByMask, RelevantUses, *FurthestSubreg);
2025 updateCachedLiveRegUses(
MI);
2044 for (
const auto &KV : Paths) {
2045 const Path &
P = KV.first;
2046 const PathInfo &PI = KV.second;
2050 printMBBNameAttr(J,
"src", *
P.src(), MST);
2051 printMBBNameAttr(J,
"dst", *
P.dst(), MST);
2053 if (PI.ShortestDistance.has_value()) {
2055 PI.ShortestDistance.value().toJsonValue());
2057 J.
attribute(
"shortest-distance",
nullptr);
2060 if (PI.ShortestUnweightedDistance.has_value()) {
2061 J.
attribute(
"shortest-unweighted-distance",
2062 PI.ShortestUnweightedDistance.value().toJsonValue());
2064 J.
attribute(
"shortest-unweighted-distance",
nullptr);
2067 J.
attribute(
"edge-kind",
static_cast<int>(PI.EK));
2069 J.
attribute(
"forward-reachable", PI.ForwardReachable);
2107 nullptr,
nullptr,
nullptr);