LLVM 24.0.0git
AMDGPUNextUseAnalysis.cpp
Go to the documentation of this file.
1//===---------------------- AMDGPUNextUseAnalysis.cpp ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the AMDGPUNextUseAnalysis pass, a machine-level analysis
10// that computes the distance from each instruction to the "nearest" next use of
11// every live virtual register. These distances guide register spilling
12// decisions by identifying which live values are furthest from their next use
13// and are therefore the best candidates to spill.
14//
15// The analysis is based on the Braun & Hack CC'09 paper "Register Spilling and
16// Live-Range Splitting for SSA-Form Programs."
17//
18// Key concepts:
19//
20// NextUseDistance A loop-depth-weighted instruction count representing
21// how far away a register's next use is. Distances
22// through deeper loops are scaled by fromLoopDepth() so
23// that uses inside hot loops appear closer.
24//
25// Inter-block Pre-computed shortest weighted distances between all
26// distances pairs of basic blocks, used to efficiently answer
27// cross-block next-use queries. Each intermediate block
28// is weighted by fromLoopDepth() applied once per loop
29// boundary crossing relative to the destination.
30//
31// Configuration flags (see Config struct in the header):
32//
33// CountPhis Count PHI instructions toward distance and block size.
34// ForwardOnly Restrict inter-block distances to forward-reachable
35// paths.
36// PreciseUseModeling Model PHI uses at their incoming edge block and filter
37// uses with intermediate redefinitions.
38// PromoteToPreheader Route loop-entry and inner-loop uses to the preheader.
39//
40// This file contains:
41//
42// - Command-line options for configuration and debug output
43// - LiveRegUse / JSON helpers
44// - AMDGPUNextUseAnalysisImpl (the main analysis implementation)
45// - Instruction ID assignment and block size computation
46// - CFG path pre-computation (reachability, loop depth, back-edges)
47// - Inter-block distance computation
48// - Per-register next-use distance queries and caching
49// - AMDGPUNextUseAnalysis (public facade, pimpl)
50// - Legacy and new pass manager wrappers
51//
52//===----------------------------------------------------------------------===//
53
55#include "AMDGPU.h"
56#include "GCNRegPressure.h"
57#include "GCNSubtarget.h"
58
67#include "llvm/Support/JSON.h"
68#include "llvm/Support/Timer.h"
71
72#include <string>
73
74using namespace llvm;
75
76#define DEBUG_TYPE "amdgpu-next-use-analysis"
77
78//==============================================================================
79// Options etc
80//==============================================================================
81namespace {
82
84 DistanceCacheEnabled("amdgpu-next-use-analysis-distance-cache",
85 cl::init(true), cl::Hidden,
86 cl::desc("Enable live-reg-use distance cache"));
87
89 DumpNextUseDistanceAsJson("amdgpu-next-use-analysis-dump-distance-as-json",
91
92cl::opt<bool> DumpNextUseDistanceDefToUse(
93 "amdgpu-next-use-analysis-dump-distance-def-to-use", cl::init(false),
95
97 DumpNextUseDistanceVerbose("amdgpu-next-use-analysis-dump-distance-verbose",
98 cl::init(false), cl::Hidden);
99
100// 'graphics' and 'compute' modes arose due to initial competing implementations
101// of next-use analysis that emphasized different types of workloads. This
102// implementation is a compromise that combines aspects of both. Over time, the
103// hope is we will be able to remove some of these differences and settle on a
104// more unified implementation.
106 ConfigPresetOpt("amdgpu-next-use-analysis-config", cl::Hidden,
107 cl::init("graphics"),
108 cl::desc("Config preset: 'graphics' or 'compute'"));
109
110cl::opt<bool> ConfigCountPhisOpt(
111 "amdgpu-next-use-analysis-count-phis", cl::Hidden,
112 cl::desc("Count PHI instructions toward distance and block size"));
113cl::opt<bool> ConfigForwardOnlyOpt(
114 "amdgpu-next-use-analysis-forward-only", cl::Hidden,
115 cl::desc("Restrict inter-block distances to forward-reachable paths"));
116cl::opt<bool> ConfigPreciseUseModelingOpt(
117 "amdgpu-next-use-analysis-precise-use-modeling", cl::Hidden,
118 cl::desc("Model PHI uses via incoming edge block with loop-aware "
119 "reachability filtering"));
120cl::opt<bool> ConfigPromoteToPreheaderOpt(
121 "amdgpu-next-use-analysis-use-preheader-model", cl::Hidden,
122 cl::desc("Promote loop-entry and inner-loop uses to the loop preheader"));
123} // namespace
124
125//==============================================================================
126// LiveRegUse - Represents a live register use with its distance. Used for
127// tracking and sorting register uses by distance.
128//==============================================================================
129namespace {
130using UseDistancePair = AMDGPUNextUseAnalysis::UseDistancePair;
131struct LiveRegUse : public UseDistancePair {
132 // 'nullptr' indicates an unset/invalid state.
133 LiveRegUse() : UseDistancePair(nullptr, 0) {}
134 LiveRegUse(const MachineOperand *Use, NextUseDistance Dist)
135 : UseDistancePair(Use, Dist) {}
136 LiveRegUse(const UseDistancePair &P) : UseDistancePair(P) {}
137
138 bool isUnset() const { return Use == nullptr; }
139
140 Register getReg() const { return Use->getReg(); }
141 unsigned getSubReg() const { return Use->getSubReg(); }
142 bool isCloserThan(const LiveRegUse &X) const {
143 if (Dist < X.Dist)
144 return true;
145
146 if (Dist > X.Dist)
147 return false;
148
149 if (Use == X.Use)
150 return false;
151
152 // Ugh. When !CountPhis, PHIs and the first non-PHI instruction have id
153 // 0. In this case, consider PHIs as less than the first non-PHI
154 // instruction.
155 const MachineInstr *ThisMI = Use->getParent();
156 const MachineInstr *XMI = X.Use->getParent();
157 const MachineBasicBlock *ThisMBB = ThisMI->getParent();
158 if (ThisMBB == XMI->getParent()) {
159 if (ThisMI->isPHI() && !XMI->isPHI() &&
160 XMI == &(*ThisMBB->getFirstNonPHI()))
161 return true;
162 }
163
164 // Ensure deterministic results
165 return X.getReg() < getReg();
166 }
167
168 void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr,
169 const MachineRegisterInfo *MRI = nullptr) const {
170 if (isUnset()) {
171 OS << "<unset>";
172 return;
173 }
174 Dist.print(OS);
175 OS << " [" << printReg(getReg(), TRI, getSubReg(), MRI) << "]";
176 }
177
178 LLVM_DUMP_METHOD void dump() const {
179 print(dbgs());
180 dbgs() << '\n';
181 }
182};
183
184inline bool updateClosest(LiveRegUse &Closest, const LiveRegUse &X) {
185 if (!Closest.Use || X.isCloserThan(Closest)) {
186 Closest = X;
187 return true;
188 }
189 return false;
190}
191
192inline bool updateFurthest(LiveRegUse &Furthest, const LiveRegUse &X) {
193 if (!Furthest.Use || Furthest.isCloserThan(X)) {
194 Furthest = X;
195 return true;
196 }
197 return false;
198}
199} // namespace
200
201//==============================================================================
202// JSON helpers
203//==============================================================================
204namespace {
205template <typename Lambda>
206void printStringAttr(json::OStream &J, const char *Name, Lambda L) {
207 J.attributeBegin(Name);
208 raw_ostream &OS = J.rawValueBegin();
209 OS << '"';
210 L(OS);
211 OS << '"';
212 J.rawValueEnd();
213 J.attributeEnd();
214}
215void printStringAttr(json::OStream &J, const char *Name, Printable P) {
216 printStringAttr(J, Name, [&](raw_ostream &OS) { OS << P; });
217}
218
219void printStringAttr(json::OStream &J, const char *Name, const MachineInstr &MI,
220 ModuleSlotTracker &MST) {
221 printStringAttr(J, Name, [&](raw_ostream &OS) {
222 MI.print(OS, MST,
223 /* IsStandalone */ false,
224 /* SkipOpers */ false,
225 /* SkipDebugLoc */ false,
226 /* AddNewLine ---> */ false,
227 /* TargetInstrInfo */ nullptr);
228 });
229}
230
231void printMBBNameAttr(json::OStream &J, const char *Name,
233 printStringAttr(J, Name, [&](raw_ostream &OS) {
234 MBB.printName(OS, MachineBasicBlock::PrintNameIr, &MST);
235 });
236}
237
238template <typename NameLambda, typename ValueT>
239void printAttr(json::OStream &J, NameLambda NL, ValueT V) {
240 std::string Name;
241 raw_string_ostream NameOS(Name);
242 NL(NameOS);
243 J.attribute(NameOS.str(), V);
244}
245
246template <typename ValueT>
247void printAttr(json::OStream &J, const Printable &P, ValueT V) {
248 printAttr(J, [&](raw_ostream &OS) { OS << P; }, V);
249}
250
251} // namespace
252
253//==============================================================================
254// AMDGPUNextUseAnalysisImpl
255//==============================================================================
257public:
262 static constexpr bool InstrRelative = true;
263 static constexpr bool InstrInvariant = false;
264
265private:
266 const MachineFunction *MF = nullptr;
267 const SIRegisterInfo *TRI = nullptr;
268 const SIInstrInfo *TII = nullptr;
269 const MachineLoopInfo *MLI = nullptr;
270 const MachineRegisterInfo *MRI = nullptr;
271
272 using InstrIdTy = unsigned;
274 InstrToIdMap InstrToId;
276
277 void initializeTables() {
278 for (const MachineBasicBlock &BB : *MF)
279 calcInstrIds(&BB, InstrToId);
280 initializeCfgPaths();
281 initializeInterBlockDistances();
282 }
283
284 void clearTables() {
285 InstrToId.clear();
286 RegUseMap.clear();
287 Paths.clear();
288
289 resetDistanceCache();
290 }
291
292 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
293 // Instruction Ids
294 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
295private:
296 unsigned sizeOf(const MachineInstr &MI) const {
297 // When !Cfg.CountPhis, PHIs do not contribute to distances/sizes since they
298 // generally don't result in the generation of a machine instruction.
299 // FIXME: Consider using MI.isPseudo() or maybe MI.isMetaInstruction().
300 return Cfg.CountPhis ? 1 : !MI.isPHI();
301 }
302
303 void calcInstrIds(const MachineBasicBlock *BB,
304 InstrToIdMap &MutableInstrToId) const {
305 InstrIdTy Id = 0;
306 for (auto &MI : BB->instrs()) {
307 MutableInstrToId[&MI] = Id;
308 Id += sizeOf(MI);
309 }
310 }
311
312 /// Returns MI's instruction Id. It renumbers (part of) the BB if MI is not
313 /// found in the map.
314 InstrIdTy getInstrId(const MachineInstr *MI) const {
315 auto It = InstrToId.find(MI);
316 if (It != InstrToId.end())
317 return It->second;
318
319 // Renumber the MBB.
320 // TODO: Renumber from MI onwards.
321 auto &MutableInstrToId = const_cast<InstrToIdMap &>(InstrToId);
322 calcInstrIds(MI->getParent(), MutableInstrToId);
323 return InstrToId.find(MI)->second;
324 }
325
326 // Length of the segment from MI (inclusive) to the first instruction of the
327 // basic block.
328 InstrIdTy getHeadLen(const MachineInstr *MI) const {
329 const MachineBasicBlock *MBB = MI->getParent();
330 return getInstrId(MI) + getInstrId(&MBB->instr_front()) + 1;
331 }
332
333 // Length of the segment from MI (exclusive) to the last instruction of the
334 // basic block.
335 InstrIdTy getTailLen(const MachineInstr *MI) const {
336 const MachineBasicBlock *MBB = MI->getParent();
337 return getInstrId(&MBB->instr_back()) - getInstrId(MI);
338 }
339
340 // Length of the segment from 'From' to 'To' (exclusive). Both instructions
341 // must be in the same basic block.
342 InstrIdTy getDistance(const MachineInstr *From,
343 const MachineInstr *To) const {
344 assert(From->getParent() == To->getParent());
345 return getInstrId(To) - getInstrId(From);
346 }
347
348 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
349 // RegUses - cache of uses by register
350 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
351private:
352 DenseMap<Register, SmallVector<const MachineOperand *>> RegUseMap;
353
355 getRegisterUses(Register Reg) const {
356 auto I = RegUseMap.find(Reg);
357 if (I != RegUseMap.end())
358 return I->second;
359
360 auto *NonConstThis = const_cast<AMDGPUNextUseAnalysisImpl *>(this);
361 SmallVector<const MachineOperand *> &Uses = NonConstThis->RegUseMap[Reg];
362 for (const MachineOperand &UseMO : MRI->use_nodbg_operands(Reg)) {
363 if (!UseMO.isUndef())
364 Uses.push_back(&UseMO);
365 }
366 return Uses;
367 }
368
369 bool hasAtLeastOneUse(Register Reg) const {
370 return !getRegisterUses(Reg).empty();
371 }
372
373 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374 // Paths
375 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376private:
377 class Path {
378 using StorageTy =
379 std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
380 StorageTy P;
381
382 public:
383 constexpr Path() : P(nullptr, nullptr) {}
384 constexpr Path(const MachineBasicBlock *Src, const MachineBasicBlock *Dst)
385 : P(Src, Dst) {}
386 Path(const StorageTy &Pair) : P(Pair) {}
387
388 constexpr operator const StorageTy &() const { return P; }
389 using DenseMapInfo = llvm::DenseMapInfo<StorageTy>;
390
391 const MachineBasicBlock *src() const { return P.first; }
392 const MachineBasicBlock *dst() const { return P.second; }
393 };
394
395 enum class EdgeKind { Back = -1, None = 0, Forward = 1 };
396 static constexpr StringRef toString(EdgeKind EK) {
397 if (EK == EdgeKind::Back)
398 return "back";
399 if (EK == EdgeKind::Forward)
400 return "fwd";
401 return "none";
402 }
403
404 struct PathInfo {
405 EdgeKind EK;
406 bool Reachable;
407 int ForwardReachable;
408 unsigned RelativeLoopDepth;
409 std::optional<NextUseDistance> ShortestDistance;
410 std::optional<NextUseDistance> ShortestUnweightedDistance;
411 InstrIdTy Size;
412
413 PathInfo()
414 : EK(EdgeKind::None), Reachable(false), ForwardReachable(-1),
415 RelativeLoopDepth(0), Size(0) {}
416
417 bool isBackedge() const { return EK == EdgeKind::Back; }
418
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; }
423
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);
431 }
432 if (ShortestUnweightedDistance) {
433 OS << " shortest-unweighted-dist=";
434 ShortestUnweightedDistance->print(OS);
435 }
436 OS << "}";
437 }
438
439 LLVM_DUMP_METHOD void dump() const {
440 print(dbgs());
441 dbgs() << '\n';
442 }
443 };
444
445 //----------------------------------------------------------------------------
446 // Path Storage - 'Paths' is lazily populated and some members are lazily
447 // computed. All mutations should go through one of the 'initializePathInfo*'
448 // flavors below.
449 //----------------------------------------------------------------------------
450 DenseMap<Path, PathInfo, Path::DenseMapInfo> Paths;
451
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;
456 }
457
458 PathInfo &getOrInitPathInfo(const MachineBasicBlock *From,
459 const MachineBasicBlock *To) const {
460 auto *NonConstThis = const_cast<AMDGPUNextUseAnalysisImpl *>(this);
461 auto &MutablePaths = NonConstThis->Paths;
462
463 Path P(From, To);
464 auto [I, Inserted] = MutablePaths.try_emplace(P);
465 if (!Inserted)
466 return I->second;
467
468 bool Reachable = calcIsReachable(P.src(), P.dst());
469
470 // Iterator may have been invalidated by calcIsReachable, so get a fresh
471 // reference to the slot.
472 return NonConstThis->initializePathInfo(MutablePaths.at(P), P,
473 EdgeKind::None, Reachable);
474 }
475
476 const PathInfo &pathInfoFor(const MachineBasicBlock *From,
477 const MachineBasicBlock *To) const {
478 return getOrInitPathInfo(From, To);
479 }
480
481 //----------------------------------------------------------------------------
482 // initializePathInfo* - various flavors of PathInfo initialization. They
483 // (should) always funnel to the first flavor below.
484 //----------------------------------------------------------------------------
485 PathInfo &initializePathInfo(PathInfo &Slot, Path P, EdgeKind EK,
486 bool Reachable) {
487 Slot.EK = 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;
495 return Slot;
496 }
497
498 PathInfo &initializePathInfo(Path P, EdgeKind EK, bool Reachable) const {
499 auto *NonConstThis = const_cast<AMDGPUNextUseAnalysisImpl *>(this);
500 auto &MutablePaths = NonConstThis->Paths;
501 return NonConstThis->initializePathInfo(MutablePaths[P], P, EK, Reachable);
502 }
503
504 bool initializePathInfoForwardReachable(const MachineBasicBlock *From,
505 const MachineBasicBlock *To,
506 bool Value) const {
507 PathInfo &Slot = getOrInitPathInfo(From, To);
508 assert(Slot.isForwardReachableUnset());
509 Slot.ForwardReachable = Value;
510 return Value;
511 }
512
513 NextUseDistance
514 initializePathInfoShortestDistance(const MachineBasicBlock *From,
515 const MachineBasicBlock *To,
516 NextUseDistance Value) const {
517 PathInfo &Slot = getOrInitPathInfo(From, To);
518 assert(!Slot.ShortestDistance.has_value());
519 Slot.ShortestDistance = Value;
520 return Value;
521 }
522
523 NextUseDistance
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());
529 Slot.ShortestUnweightedDistance = Value;
530 return Value;
531 }
532
533 //----------------------------------------------------------------------------
534 // initialize*Paths
535 //----------------------------------------------------------------------------
536private:
537 void initializePaths(const SmallVector<Path> &ReachablePaths,
538 const SmallVector<Path> &UnreachablePaths) const {
539 for (const Path &P : ReachablePaths)
540 initializePathInfo(P, EdgeKind::None, true);
541 for (const Path &P : UnreachablePaths)
542 initializePathInfo(P, EdgeKind::None, false);
543 }
544
545 void
546 initializeForwardOnlyPaths(const SmallVector<Path> &ReachablePaths,
547 const SmallVector<Path> &UnreachablePaths) const {
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;
554 }
555 }
556 }
557
558 // Follow the control flow graph starting at the entry block until all blocks
559 // have been visited. Along the way, initialize the PathInfo for each edge
560 // traversed.
561 void initializeCfgPaths() {
562 Paths.clear();
563
564 enum VisitState { Undiscovered, Visiting, Finished };
565 DenseMap<const MachineBasicBlock *, VisitState> State;
566
568 State[&MF->front()] = Undiscovered;
569
570 while (!Work.empty()) {
571 const MachineBasicBlock *Src = Work.back();
572 VisitState &SrcState = State[Src];
573
574 // A block may already be 'Finished' if it is reachable from multiple
575 // predecessors causing it to be pushed more than once while still
576 // 'Undiscovered'.
577 if (SrcState == Visiting || SrcState == Finished) {
578 Work.pop_back();
579 SrcState = Finished;
580 continue;
581 }
582
583 SrcState = Visiting;
584 for (const MachineBasicBlock *Dst : Src->successors()) {
585 const VisitState DstState = State.lookup(Dst);
586
587 EdgeKind EK;
588 if (DstState == Undiscovered) {
589 EK = EdgeKind::Forward;
590 Work.push_back(Dst);
591 } else if (DstState == Visiting) {
592 EK = EdgeKind::Back;
593 } else {
594 EK = EdgeKind::Forward;
595 }
596
597 Path P(Src, Dst);
598 assert(!Paths.contains(P));
599 initializePathInfo(P, EK, /*Reachable*/ true);
600 }
601 }
602
603 LLVM_DEBUG(dumpPaths());
604 }
605
606 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
607 // Loop helpers
608 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
609private:
610 static bool isStandAloneLoop(const MachineLoop *Loop) {
611 return Loop->getSubLoops().empty() && Loop->isOutermost();
612 }
613
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)
618 return L;
619 }
620 return nullptr;
621 }
622
623 // If loops 'A' and 'B' share a common parent loop, return that loop and the
624 // depth of 'A' relative to it. Otherwise return nullptr and the loop depth of
625 // 'A'.
626 static std::pair<MachineLoop *, unsigned>
627 findCommonParent(MachineLoop *A, const MachineLoop *B) {
628 unsigned Depth = 0;
629 for (; A != nullptr; A = A->getParentLoop(), ++Depth) {
630 if (A->contains(B))
631 break;
632 }
633 return {A, Depth};
634 }
635
636 static const MachineBasicBlock *
637 getOutermostPreheader(const MachineLoop *Loop) {
638 return Loop ? Loop->getOutermostLoop()->getLoopPreheader() : nullptr;
639 }
640
641 static MachineBasicBlock *findChildPreheader(MachineLoop *const Parent,
642 MachineLoop *Descendant) {
643 MachineLoop *ChildLoop = findChildLoop(Parent, Descendant);
644 return ChildLoop ? ChildLoop->getLoopPreheader() : nullptr;
645 }
646
647 static const MachineBasicBlock *
648 getIncomingBlockIfPhiUse(const MachineInstr *MI, const MachineOperand *MO) {
649 return MI->isPHI() ? MI->getOperand(MO->getOperandNo() + 1).getMBB()
650 : nullptr;
651 }
652
653 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
654 // Calculate features
655 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
656private:
657 InstrIdTy calcSize(const MachineBasicBlock *BB) const {
658 InstrIdTy Size = BB->size();
659 if (!Cfg.CountPhis)
660 Size -= std::distance(BB->begin(), BB->getFirstNonPHI());
661 return Size;
662 }
663
664 // Return the loop depth of 'From' relative to 'To'.
665 unsigned calcRelativeLoopDepth(const MachineBasicBlock *From,
666 const MachineBasicBlock *To) const {
667 MachineLoop *LoopFrom = MLI->getLoopFor(From);
668 MachineLoop *LoopTo = MLI->getLoopFor(To);
669
670 if (!LoopFrom)
671 return 0;
672
673 if (!LoopTo)
674 return LoopFrom->getLoopDepth();
675
676 if (LoopFrom->contains(LoopTo)) // covers LoopFrom == LoopTo
677 return 0;
678
679 if (LoopTo->contains(LoopFrom))
680 return LoopFrom->getLoopDepth() - LoopTo->getLoopDepth();
681
682 // Loops are siblings of some sort.
683 return findCommonParent(LoopFrom, LoopTo).second;
684 }
685
686 // Attempt to find a path from 'From' to 'To' using a depth first search. If
687 // 'ForwardOnly' is true, do not follow backedges. As a performance
688 // improvement, this may initialize reachable intermediate paths or paths we
689 // determine are unreachable.
690 bool calcIsReachable(const MachineBasicBlock *From,
691 const MachineBasicBlock *To,
692 bool ForwardOnly = false) const {
693 if (From == To && !MLI->getLoopFor(From))
694 return false;
695
696 if (!ForwardOnly && interBlockDistanceExists(From, To))
697 return true;
698
699 enum { VisitOp, PopOp };
700 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
701 SmallVector<MBBOpPair> Work{{From, VisitOp}};
702 DenseSet<const MachineBasicBlock *> Visited{From};
703
704 SmallVector<Path> IntermediatePath;
705 SmallVector<Path> Unreachable;
706
707 // Should be run at every function exit point.
708 auto Finally = [&](bool Reachable) {
709 // This is an optimization. For intermediate paths we found while
710 // calculating reachability for 'From' --> 'To', remember their
711 // reachability.
712 if (!Reachable) {
713 IntermediatePath.clear();
714 for (const MachineBasicBlock *MBB : Visited) {
715 if (MBB != From)
716 Unreachable.emplace_back(MBB, To);
717 }
718 }
719
720 if (ForwardOnly)
721 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
722 else
723 initializePaths(IntermediatePath, Unreachable);
724
725 return Reachable;
726 };
727
728 while (!Work.empty()) {
729 auto [Current, Op] = Work.pop_back_val();
730
731 // Backtracking
732 if (Op == PopOp) {
733 IntermediatePath.pop_back();
734 if (ForwardOnly)
735 Unreachable.emplace_back(Current, To);
736 continue;
737 }
738
739 if (Current->succ_empty())
740 continue;
741
742 if (Current != From) {
743 IntermediatePath.emplace_back(Current, To);
744 Work.emplace_back(Current, PopOp);
745 }
746
747 for (const MachineBasicBlock *Succ : Current->successors()) {
748 if (ForwardOnly && isBackedge(Current, Succ))
749 continue;
750
751 if (Succ == To)
752 return Finally(true);
753
754 if (auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
755 if (CachedReachable.value())
756 return Finally(true);
757 Visited.insert(Succ);
758 continue;
759 }
760
761 if (Visited.insert(Succ).second)
762 Work.emplace_back(Succ, VisitOp);
763 }
764 }
765
766 return Finally(false);
767 }
768
769 //----------------------------------------------------------------------------
770 // Inter-block distance - the weighted and unweighted cost (i.e. "distance")
771 // to travel from one MachineBasicBlock to another.
772 //
773 // Values are pre-computed and stored in 'InterBlockDistances' using a
774 // backwards data-flow algorithm similar to the one described in 4.1 of a
775 // "Register Spilling and Live-Range Splitting for SSA-Form Programs" by
776 // Matthias Braun and Sebastian Hack, CC'09. This replaced a prior
777 // implementation based on Dijkstra's shortest path algorithm.
778 //----------------------------------------------------------------------------
779private:
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;
788 }
789 bool operator!=(const InterBlockDistance &Other) const {
790 return !(*this == Other);
791 }
792
793 void print(raw_ostream &OS) const {
794 OS << "{W=";
795 Weighted.print(OS);
796 OS << " U=";
797 Unweighted.print(OS);
798 OS << "}";
799 }
800
801 LLVM_DUMP_METHOD void dump() const {
802 print(dbgs());
803 dbgs() << '\n';
804 }
805 };
806 using InterBlockDistanceMap =
807 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
808 InterBlockDistanceMap InterBlockDistances;
809
810 void initializeInterBlockDistances() {
811 InterBlockDistanceMap Distances;
812
813 bool Changed;
814 do {
815 Changed = false;
816 for (const MachineBasicBlock *MBB : post_order(MF)) {
817 unsigned MBBNum = MBB->getNumber();
818
819 // Save previous state for convergence check
820 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
821 InterBlockDistanceMap::mapped_type Curr;
822 Curr.reserve(Prev.size());
823
824 // Direct successors are distance 0 by definition: no instructions are
825 // executed between exiting MBB and entering Succ.
826 for (const MachineBasicBlock *Succ : MBB->successors())
827 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
828
829 // Propagate further destinations through each successor.
830 for (const MachineBasicBlock *Succ : MBB->successors()) {
831 unsigned SuccNum = Succ->getNumber();
832 const unsigned UnweightedSize{getSize(Succ)};
833
834 for (const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
835 // MBB -> MBB is considered unreachable (getInterBlockDistance
836 // asserts From != To).
837 if (DestBlockNum == MBBNum)
838 continue;
839
840 const MachineBasicBlock *DestMBB =
841 MF->getBlockNumbered(DestBlockNum);
842
843 const NextUseDistance UnweightedDist{UnweightedSize +
844 DestDist.Unweighted};
845
846 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
847
848 const NextUseDistance WeightedDist =
849 DestDist.Weighted +
850 NextUseDistance::fromSize(UnweightedSize, SuccToDestLoopDepth);
851
852 // Insert or update distances (take minimum)
853 auto [I, First] =
854 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
855 if (!First) {
856 InterBlockDistance &Slot = I->second;
857 Slot.Weighted = min(Slot.Weighted, WeightedDist);
858 Slot.Unweighted = min(Slot.Unweighted, UnweightedDist);
859 }
860 }
861 }
862 Changed |= (Prev != Curr);
863 Distances[MBBNum] = std::move(Curr);
864 }
865 } while (Changed);
866
867 InterBlockDistances = std::move(Distances);
868 LLVM_DEBUG(dumpInterBlockDistances());
869 }
870
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())
876 return nullptr;
877 const InterBlockDistanceMap::mapped_type &FromSlot = I->second;
878 auto J = FromSlot.find(To->getNumber());
879 return J == FromSlot.end() ? nullptr : &J->second;
880 }
881
882 bool interBlockDistanceExists(const MachineBasicBlock *From,
883 const MachineBasicBlock *To) const {
884 return getInterBlockDistanceMapValue(From, To);
885 }
886
887 NextUseDistance getInterBlockDistance(const MachineBasicBlock *From,
888 const MachineBasicBlock *To,
889 bool Unweighted) const {
890
891 assert(From != To && "The basic blocks should be different.");
892 if (!From || !To)
894
895 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
897
898 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
899 if (!BD)
901
902 return Unweighted ? BD->Unweighted : BD->Weighted;
903 }
904
905 NextUseDistance
906 getWeightedInterBlockDistance(const MachineBasicBlock *From,
907 const MachineBasicBlock *To) const {
908 return getInterBlockDistance(From, To, false);
909 }
910
911 NextUseDistance
912 getUnweightedInterBlockDistance(const MachineBasicBlock *From,
913 const MachineBasicBlock *To) const {
914 return getInterBlockDistance(From, To, true);
915 }
916
917 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
918 // Feature getters. Use cached results if available. If not calculate.
919 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
920private:
921 InstrIdTy getSize(const MachineBasicBlock *BB) const {
922 return pathInfoFor(BB, BB).Size;
923 }
924
925 bool isReachable(const MachineBasicBlock *From,
926 const MachineBasicBlock *To) const {
927 return pathInfoFor(From, To).Reachable;
928 }
929
930 bool isReachableOrSame(const MachineBasicBlock *From,
931 const MachineBasicBlock *To) const {
932 return From == To || pathInfoFor(From, To).Reachable;
933 }
934
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();
940
941 return initializePathInfoForwardReachable(
942 From, To,
943 PI.Reachable && calcIsReachable(From, To, /*ForwardOnly*/ true));
944 }
945
946 // Return true/false if we know that 'To' is reachable or not from
947 // 'From'. Otherwise return 'std::nullopt'.
948 std::optional<bool> isMaybeReachable(const MachineBasicBlock *From,
949 const MachineBasicBlock *To,
950 bool ForwardOnly) const {
951 const PathInfo *PI = maybePathInfoFor(From, To);
952 if (!PI)
953 return std::nullopt;
954
955 if (ForwardOnly) {
956 if (PI->isForwardReachable())
957 return true;
958
959 if (PI->isNotForwardReachable())
960 return false;
961 return std::nullopt;
962 }
963 return PI->Reachable;
964 }
965
966 bool isBackedge(const MachineBasicBlock *From,
967 const MachineBasicBlock *To) const {
968 return pathInfoFor(From, To).isBackedge();
969 }
970
971 // Can be used as a substitute for DT->dominates(A, B) if A and B are in the
972 // same basic block.
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))
977 return true;
978 if (!A->isPHI())
979 return false;
980 if (!B->isPHI())
981 return true;
982 for (auto &PHI : A->getParent()->phis()) {
983 if (&PHI == A)
984 return true;
985 if (&PHI == B)
986 return false;
987 }
988 return false;
989 }
990
991 unsigned getRelativeLoopDepth(const MachineBasicBlock *From,
992 const MachineBasicBlock *To) const {
993 return pathInfoFor(From, To).RelativeLoopDepth;
994 }
995
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();
1002
1003 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1004 return initializePathInfoShortestDistance(From, To, Dist);
1005 }
1006
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();
1013
1014 return initializePathInfoShortestUnweightedDistance(
1015 From, To, getUnweightedInterBlockDistance(From, To));
1016 }
1017
1018 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1019 /// MBBDistPair - Represents the distance to a machine basic block.
1020 /// Used for returning both the distance and the target block together.
1021 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1022private:
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) {}
1029
1030 MBBDistPair operator+(NextUseDistance D) { return {Distance + D, MBB}; }
1031 MBBDistPair &operator+=(NextUseDistance D) {
1032 Distance += D;
1033 return *this;
1034 }
1035
1036 void print(raw_ostream &OS) const {
1037 OS << "{";
1038 Distance.print(OS);
1039 if (MBB)
1040 OS << " " << printMBBReference(*MBB);
1041 else
1042 OS << " <null>";
1043 OS << "}";
1044 }
1045
1046 LLVM_DUMP_METHOD void dump() const {
1047 print(dbgs());
1048 dbgs() << '\n';
1049 }
1050 };
1051
1052 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1053 // CFG Helpers
1054 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1055private:
1056 // Return the shortest distance to a latch
1057 MBBDistPair calcShortestDistanceToLatch(const MachineBasicBlock *CurMBB,
1058 const MachineLoop *CurLoop) const {
1060 CurLoop->getLoopLatches(Latches);
1061 MBBDistPair LD;
1062
1063 for (MachineBasicBlock *LMBB : Latches) {
1064 if (LMBB == CurMBB)
1065 return {0, CurMBB};
1066
1067 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1068 if (Dst < LD.Distance) {
1069 LD.Distance = Dst;
1070 LD.MBB = LMBB;
1071 }
1072 }
1073 return LD;
1074 }
1075
1076 // Return the shortest unweighted distance to a latch
1077 MBBDistPair
1078 calcShortestUnweightedDistanceToLatch(const MachineBasicBlock *CurMBB,
1079 const MachineLoop *CurLoop) const {
1081 CurLoop->getLoopLatches(Latches);
1082 MBBDistPair LD;
1083
1084 for (MachineBasicBlock *LMBB : Latches) {
1085 if (LMBB == CurMBB)
1086 return {0, CurMBB};
1087
1088 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1089 if (Dst < LD.Distance) {
1090 LD.Distance = Dst;
1091 LD.MBB = LMBB;
1092 }
1093 }
1094 return LD;
1095 }
1096
1097 // Return the shortest distance to an exit
1098 MBBDistPair calcShortestDistanceToExit(const MachineBasicBlock *CurMBB,
1099 const MachineLoop *CurLoop) const {
1101 MLI->getExitEdges(*CurLoop, ExitEdges);
1102 MBBDistPair LD;
1103
1104 for (auto [Exit, Dest] : ExitEdges) {
1105 if (Exit == CurMBB)
1106 return {0, CurMBB};
1107
1108 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1109 if (Dst < LD.Distance) {
1110 LD.Distance = Dst;
1111 LD.MBB = Exit;
1112 }
1113 }
1114 return LD;
1115 }
1116
1117 // Return the shortest distance through a loop (header to latch) that goes
1118 // through CurMBB.
1119 MBBDistPair
1120 calcShortestDistanceThroughInnermostLoop(const MachineBasicBlock *CurMBB,
1121 MachineLoop *CurLoop) const {
1122 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1123
1124 // This is a hot spot. Check it before doing anything else.
1125 if (CurLoop->getNumBlocks() == 1)
1126 return {getSize(CurMBB), CurMBB};
1127
1128 MachineBasicBlock *LoopHeader = CurLoop->getHeader();
1129 MBBDistPair LD{0, nullptr};
1130
1131 LD += getSize(LoopHeader);
1132
1133 if (CurMBB != LoopHeader)
1134 LD += getShortestPath(LoopHeader, CurMBB);
1135
1136 if (CurLoop->isLoopExiting(CurMBB))
1137 LD.MBB = CurMBB;
1138 else
1139 LD = calcShortestDistanceToExit(CurMBB, CurLoop) + LD.Distance;
1140
1141 if (CurMBB != LoopHeader && CurMBB != LD.MBB)
1142 LD += getSize(CurMBB);
1143
1144 if (LD.MBB != LoopHeader)
1145 LD += getSize(LD.MBB);
1146
1147 return LD;
1148 }
1149
1150 // Return the shortest distance through a loop (header to latch) that goes
1151 // through CurMBB.
1152 MBBDistPair calcShortestDistanceThroughLoop(const MachineBasicBlock *CurMBB,
1153 MachineLoop *OuterLoop) const {
1154 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1155 MBBDistPair CurLD =
1156 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1157
1158 MachineBasicBlock *CurHdr = CurLoop->getHeader();
1159 for (;;) {
1160 if (OuterLoop == CurLoop)
1161 return CurLD;
1162
1163 MachineLoop *ParentLoop = CurLoop->getParentLoop();
1164 MachineBasicBlock *ParentHdr = ParentLoop->getHeader();
1165
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);
1172 CurLD = LD;
1173 CurLoop = ParentLoop;
1174 CurHdr = ParentHdr;
1175 }
1176 llvm_unreachable("CurMBB not contained in OuterLoop");
1177 }
1178
1179 // Similar to calcShortestDistanceThroughLoop with LoopWeight applied to the
1180 // returned distance.
1181 MBBDistPair
1182 calcWeightedDistanceThroughLoopViaMBB(const MachineBasicBlock *CurMBB,
1183 MachineLoop *CurLoop) const {
1184 MBBDistPair LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1185 LD.Distance = LD.Distance.applyLoopWeight();
1186 return LD;
1187 }
1188
1189 // Return the weighted, shortest distance through a loop (header to latch).
1190 // If ParentLoop is provided, use it to adjust the loop depth.
1191 MBBDistPair calcWeightedDistanceThroughLoop(
1192 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1193 const MachineLoop *ParentLoop = nullptr) const {
1194 if (CurLoop->getNumBlocks() != 1)
1195 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1196
1197 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1198 if (ParentLoop)
1199 LoopDepth -= ParentLoop->getLoopDepth();
1200
1201 return {NextUseDistance::fromSize(getSize(CurMBB), LoopDepth),
1202 CurLoop->getLoopLatch()};
1203 }
1204
1205 // Calculate total distance from exit point to use instruction
1206 NextUseDistance appendDistanceToUse(const MBBDistPair &Exit,
1207 const MachineInstr *UseMI,
1208 const MachineBasicBlock *UseMBB) const {
1209 return Exit.Distance + getShortestPath(Exit.MBB, UseMBB) +
1210 getHeadLen(UseMI);
1211 }
1212
1213 // Return the weighted, shortest distance through the CurLoop which is a
1214 // sub-loop of UseLoop.
1215 MBBDistPair calcDistanceThroughSubLoopUse(const MachineBasicBlock *CurMBB,
1216 MachineLoop *CurLoop,
1217 MachineLoop *UseLoop) const {
1218 // All the sub-loops of the UseLoop will be executed before the use.
1219 // Hence, we should take this into consideration in distance calculation.
1220 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1221 assert(UseLoopSubLoop && "CurLoop should be nested in UseLoop");
1222 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1223 }
1224
1225 // Similar to calcDistanceThroughSubLoopUse, adding the distance to 'UseMI'.
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);
1232 }
1233
1234 // Return the weighted distance through a loop to an outside use loop.
1235 // Differentiates between uses inside or outside of the current loop nest.
1236 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1237 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1238 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop) const {
1239 assert(!CurLoop->contains(UseLoop));
1240
1241 if (isStandAloneLoop(CurLoop))
1242 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1243
1244 MachineLoop *OutermostLoop = CurLoop->getOutermostLoop();
1245 if (!OutermostLoop->contains(UseLoop)) {
1246 // We should take into consideration the whole loop nest in the
1247 // calculation of the distance because we will reach the use after
1248 // executing the whole loop nest.
1249
1250 // ... But make sure that we pick a route that goes through CurMBB
1251 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1252 }
1253
1254 // At this point we know that CurLoop and UseLoop are independent and they
1255 // are in the same loop nest.
1256
1257 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1258 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1259
1260 assert(CurLoop != OutermostLoop && "The loop cannot be the outermost.");
1261 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1262 for (;;) {
1263 if (CurLoop->getLoopDepth() == UseLoopDepth)
1264 break;
1265 CurLoop = CurLoop->getParentLoop();
1266 if (CurLoop == OutermostLoop)
1267 break;
1268 }
1269 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1270 }
1271
1272 // Similar to calcDistanceThroughLoopToOutsideLoopUse but adds the distance to
1273 // an instruction in the loop.
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),
1280 UseMI, UseMBB);
1281 }
1282
1283 // Return true if 'MO' is covered by 'LaneMask'
1284 bool machineOperandCoveredBy(const MachineOperand &MO,
1285 LaneBitmask LaneMask) const {
1286 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(MO.getSubReg());
1287 return (Mask & LaneMask) == Mask;
1288 }
1289
1290 // Returns true iff uses of LiveReg/LiveLaneMask in PHI UseMI are coming from
1291 // a backedge when starting at CurMI.
1292 bool isIncomingValFromBackedge(Register LiveReg, LaneBitmask LiveLaneMask,
1293 const MachineInstr *CurMI,
1294 const MachineInstr *UseMI) const {
1295 if (!UseMI->isPHI())
1296 return false;
1297
1298 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->getParent());
1299 MachineLoop *UseLoop = MLI->getLoopFor(UseMI->getParent());
1300
1301 // Not a backedge if ...
1302 // A: not in a loop at all
1303 // B: or CurMI is in a loop outside of UseLoop
1304 // C: or UseMI is not in the UseLoop header
1305 if (/*A:*/ !UseLoop ||
1306 /*B:*/ (CurLoop && !UseLoop->contains(CurLoop)) ||
1307 /*C:*/ UseMI->getParent() != UseLoop->getHeader())
1308 return false;
1309
1311 UseLoop->getLoopLatches(Latches);
1312
1313 const unsigned NumOps = UseMI->getNumOperands();
1314 for (unsigned I = 1; I < NumOps; I += 2) {
1315 const MachineOperand &RegMO = UseMI->getOperand(I - 1);
1316 const MachineOperand &MBBMO = UseMI->getOperand(I);
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();
1322 if (llvm::is_contained(Latches, IncomingBB))
1323 return true;
1324 }
1325 }
1326 return false;
1327 }
1328
1329 // Return the distance from 'CurMI' through a parent loop backedge PHI Use
1330 // ('UseMI').
1331 CacheableNextUseDistance calcDistanceViaEnclosingBackedge(
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");
1338
1339 InstrIdTy UseHeadLen = getHeadLen(UseMI);
1340 MBBDistPair InnerLoopLD =
1341 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1342 MBBDistPair LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1343 return {InstrInvariant,
1344 InnerLoopLD.Distance + LD.Distance + getSize(LD.MBB) + UseHeadLen};
1345 }
1346
1347 // Optimized version of calcBackedgeDistance when we already know that CurMI
1348 // and UseMI are in the same basic block
1349 NextUseDistance calcBackedgeDistance(const MachineInstr *CurMI,
1350 const MachineBasicBlock *CurMBB,
1351 MachineLoop *CurLoop,
1352 const MachineInstr *UseMI) const {
1353 // use is in the next loop iteration
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);
1361
1362 return CurTailLen + LD.Distance + getSize(LD.MBB) + Hdr + Dst + UseHeadLen;
1363 }
1364
1365 //----------------------------------------------------------------------------
1366 // Calculate inter-instruction distances
1367 //----------------------------------------------------------------------------
1368private:
1369 // Calculate the shortest weighted path from MachineInstruction 'FromMI' to
1370 // 'ToMI'. It is weighted distance in that paths that exit loops are made to
1371 // look much further away.
1372 NextUseDistance calcShortestDistance(const MachineInstr *FromMI,
1373 const MachineInstr *ToMI) const {
1374 const MachineBasicBlock *FromMBB = FromMI->getParent();
1375 const MachineBasicBlock *ToMBB = ToMI->getParent();
1376
1377 if (FromMBB == ToMBB) {
1378 NextUseDistance RV = getDistance(FromMI, ToMI);
1379 assert(RV >= 0 && "unexpected negative distance from getDistance");
1380 return RV;
1381 }
1382
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"
1388 " basic blocks!");
1389 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1390 assert(RV >= 0 && "unexpected negative distance");
1391 return RV;
1392 }
1393
1394 // Calculate the shortest unweighted path from MachineInstruction 'FromMI' to
1395 // 'ToMI'. In contrast with 'calcShortestDistance', distances are based solely
1396 // on basic block instruction counts and traversing a loop exit does not
1397 // affect the value.
1398 NextUseDistance
1399 calcShortestUnweightedDistance(const MachineInstr *FromMI,
1400 const MachineInstr *ToMI) const {
1401 const MachineBasicBlock *FromMBB = FromMI->getParent();
1402 const MachineBasicBlock *ToMBB = ToMI->getParent();
1403
1404 if (FromMBB == ToMBB)
1405 return getDistance(FromMI, ToMI);
1406
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;
1414 }
1415
1416 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1417 // calcDistanceToUse* - various flavors of calculating the distance from an
1418 // instruction 'CurMI' to the use of a live [sub]register.
1419 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1420private:
1421 // Return the distance from 'CurMI' to a live [sub]register use ('UseMI').
1422 //
1423 // Cfg flags controlling behavior:
1424 // PreciseUseModeling — rewrite PHI uses to their incoming edge block;
1425 // also selects unweighted cross-block distance
1426 // PromoteToPreheader — route loop-entry / inner-loop uses to the preheader
1428 calcDistanceToUse(Register LiveReg, LaneBitmask LiveLaneMask,
1429 const MachineInstr &CurMI,
1430 const MachineOperand *UseMO) const {
1431 const MachineInstr *UseMI = UseMO->getParent();
1432 const MachineBasicBlock *CurMBB = CurMI.getParent();
1433 const MachineBasicBlock *UseMBB = UseMI->getParent();
1434 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1435 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1436
1437 if (Cfg.PreciseUseModeling) {
1438 // Map PHI use to the end of its incoming edge block.
1439 if (auto *PhiUseEdge = getIncomingBlockIfPhiUse(UseMI, UseMO)) {
1440 UseMI = &PhiUseEdge->back();
1441 UseMBB = PhiUseEdge;
1442 UseLoop = MLI->getLoopFor(PhiUseEdge);
1443 }
1444 }
1445
1446 enum class LoopConfig {
1447 NoCur,
1448 Same,
1449 CurContainsUse,
1450 UseContainsCur,
1451 Siblings,
1452 Unrelated
1453 };
1454 auto [LpCfg, PreHdr, CommonParent] = [&]()
1455 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1456 if (!CurLoop) {
1457 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop), nullptr};
1458 }
1459 if (CurLoop->contains(UseLoop)) {
1460 return {CurMBB == UseMBB ? LoopConfig::Same
1461 : LoopConfig::CurContainsUse,
1462 findChildPreheader(CurLoop, UseLoop), nullptr};
1463 }
1464
1465 if (MachineLoop *P = findCommonParent(UseLoop, CurLoop).first) {
1466 if (P != UseLoop)
1467 return {LoopConfig::Siblings, findChildPreheader(P, UseLoop), P};
1468 return {LoopConfig::UseContainsCur, nullptr, nullptr};
1469 }
1470 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop), nullptr};
1471 }();
1472
1473 //--------------------------------------------------------------------------
1474 // Don't PromoteToPreheader
1475 //--------------------------------------------------------------------------
1476 if (!Cfg.PromoteToPreheader) {
1477 switch (LpCfg) {
1478 case LoopConfig::NoCur:
1479 case LoopConfig::Same:
1480 case LoopConfig::CurContainsUse:
1481 return {InstrRelative, calcShortestDistance(&CurMI, UseMI)};
1482
1483 case LoopConfig::UseContainsCur: {
1484 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI, UseMI)) {
1485 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1486 UseMI, UseMBB, UseLoop);
1487 }
1488
1489 return {InstrInvariant, calcDistanceThroughSubLoopToUseMI(
1490 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1491 }
1492 case LoopConfig::Siblings:
1493 case LoopConfig::Unrelated:
1494 return {InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1495 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1496 }
1497 llvm_unreachable("unexpected loop configuration!");
1498 }
1499
1500 //--------------------------------------------------------------------------
1501 // PromoteToPreheader
1502 //--------------------------------------------------------------------------
1503 if (PreHdr) {
1504 UseMI = &PreHdr->back();
1505 UseMBB = PreHdr;
1506 UseLoop = CommonParent;
1507 }
1508
1509 switch (LpCfg) {
1510 case LoopConfig::NoCur:
1511 return {InstrRelative, calcShortestUnweightedDistance(&CurMI, UseMI) -
1512 (sizeOf(*UseMI) ? 0 : 1)};
1513
1514 case LoopConfig::Same:
1515 case LoopConfig::CurContainsUse:
1516 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI, UseMI))
1517 return {InstrRelative,
1518 calcBackedgeDistance(&CurMI, CurMBB, CurLoop, UseMI)};
1519
1520 return {InstrRelative, calcShortestUnweightedDistance(&CurMI, UseMI)};
1521
1522 case LoopConfig::UseContainsCur:
1523 case LoopConfig::Siblings:
1524 return {InstrInvariant, calcDistanceThroughSubLoopToUseMI(
1525 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1526
1527 case LoopConfig::Unrelated:
1528 return {InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1529 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1530 }
1531 llvm_unreachable("unexpected loop configuration!");
1532 }
1533
1534 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1535 // getUses helpers (compute mode)
1536 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1537private:
1538 // Returns true if Use is reachable from MI. Handles backedges and intervening
1539 // defs.
1540 bool isUseReachablePrecise(const MachineInstr &MI,
1541 const MachineBasicBlock *MBB,
1542 const MachineOperand *UseMO,
1543 const MachineInstr *UseMI,
1544 const MachineBasicBlock *UseMBB) const {
1545
1546 // Filter out uses that are clearly unreachable
1547 if (MBB != UseMBB && !isReachable(MBB, UseMBB))
1548 return false;
1549
1550 // PHI uses are considered part of the incoming BB. Check for reachability
1551 // at the edge.
1552 if (auto *PhiUseEdge = getIncomingBlockIfPhiUse(UseMI, UseMO)) {
1553 if (!isReachableOrSame(MBB, PhiUseEdge))
1554 return false;
1555 }
1556
1557 // Filter out uses with an intermediate def.
1558 const MachineInstr *DefMI = MRI->getUniqueVRegDef(UseMO->getReg());
1559 const MachineBasicBlock *DefMBB = DefMI->getParent();
1560 if (MBB == UseMBB) {
1561 if (UseMI->isPHI() && MBB == DefMBB)
1562 return true;
1563
1564 if (instrsAreInOrder(&MI, UseMI))
1565 return true;
1566
1567 // A Def in the loop means that the value at MI will not survive through
1568 // to this use.
1569 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1570 return UseLoop && !UseLoop->contains(DefMBB);
1571 }
1572
1573 if (MBB == DefMBB)
1574 return instrsAreInOrder(DefMI, &MI);
1575
1576 MachineLoop *Loop = MLI->getLoopFor(MBB);
1577 if (!Loop)
1578 return true;
1579
1580 MachineLoop *TopLoop = Loop->getOutermostLoop();
1581 return !TopLoop->contains(DefMBB) || !isReachable(MBB, DefMBB) ||
1582 !isForwardReachable(UseMBB, MBB);
1583 }
1584
1585 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1586 // Debug/Developer Helpers
1587 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1588private:
1589 void printPaths(raw_ostream &OS) const {
1590 OS << "\n---------------- Paths --------------- {\n";
1591 for (const auto &[P, PI] : Paths) {
1592 OS << " " << printMBBReference(*P.src()) << " -> "
1593 << printMBBReference(*P.dst()) << ": ";
1594 PI.print(OS);
1595 OS << '\n';
1596 }
1597 OS << "}\n";
1598 }
1599
1600 LLVM_DUMP_METHOD void dumpPaths() const { printPaths(dbgs()); }
1601
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;
1606
1607 for (const auto &[FromNum, Dsts] : InterBlockDistances) {
1608 for (const auto &[ToNum, Dist] : Dsts) {
1609 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1610 }
1611 }
1612 llvm::sort(SortedDistances, [](const auto &A, const auto &B) {
1613 if (A.first != B.first)
1614 return A.first < B.first;
1615
1616 if (A.second.first != B.second.first)
1617 return A.second.first < B.second.first;
1618
1619 return A.second.second < B.second.second;
1620 });
1621
1622 OS << "\n--------- InterBlockDistances -------- {\n";
1623 for (const Elem &E : SortedDistances) {
1624
1625 OS << " bb." << E.second.first << " -> bb." << E.second.second << ": ";
1626 E.first.print(OS);
1627 OS << '\n';
1628 }
1629 OS << "}\n";
1630 }
1631
1632 LLVM_DUMP_METHOD void dumpInterBlockDistances() const {
1633 printInterBlockDistances(dbgs());
1634 }
1635
1636 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1637 // LiveRegUse Caching - A cache of the distances for the last
1638 // MachineInstruction. When getting the distances for a MachineInstruction, if
1639 // it is the same basic block as the cached instruction, we can generally use
1640 // an offset from the cached values to compute the distances. There are some
1641 // exceptions - see 'cacheLiveRegUse'.
1642 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1643private:
1644 struct LiveRegToUseMapElem {
1645 LiveRegUse Use;
1646 bool MIDependent;
1647 LiveRegToUseMapElem() : Use(), MIDependent(false) {}
1648 LiveRegToUseMapElem(LiveRegUse U, bool MIDep)
1649 : Use(U), MIDependent(MIDep) {}
1650
1651 void print(raw_ostream &OS) const {
1652 Use.print(OS);
1653 OS << (MIDependent ? " [mi-dep]" : " [mi-indep]");
1654 }
1655
1656 LLVM_DUMP_METHOD void dump() const {
1657 print(dbgs());
1658 dbgs() << '\n';
1659 }
1660 };
1661
1662 // Using std::map because LaneBitmask does not work out-of-the-box as a
1663 // DenseMap key and I did not see a performance benefit over std::map.
1664 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1665 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1666
1667 const MachineInstr *CachedDistancesMI = nullptr;
1668 LiveRegToUseMap CachedDistances;
1669 LiveRegToUseMap PendingCachedDistances;
1670 unsigned DistanceCacheHits = 0;
1671 unsigned DistanceCacheMisses = 0;
1672
1673 void resetDistanceCache() {
1674 CachedDistancesMI = nullptr;
1675 CachedDistances.clear();
1676 DistanceCacheHits = 0;
1677 DistanceCacheMisses = 0;
1678 }
1679
1680 void maybeClearCachedLiveRegUses(const MachineInstr &MI) {
1681 if (CachedDistancesMI &&
1682 (CachedDistancesMI->getParent() != MI.getParent() ||
1683 !instrsAreInOrder(CachedDistancesMI, &MI))) {
1684 CachedDistancesMI = nullptr;
1685 CachedDistances.clear();
1686 }
1687 }
1688
1689 bool okToUseCacheElem(const LiveRegToUseMapElem &CacheElem,
1690 const MachineInstr &MI, const InstrIdTy LastDelta) {
1691 if (!CacheElem.MIDependent)
1692 return true;
1693
1694 const LiveRegUse &U = CacheElem.Use;
1695
1696 // Never okay to produce a negative distance
1697 if (U.Dist < LastDelta)
1698 return false;
1699
1700 const MachineInstr *UseMI = U.Use->getParent();
1701
1702 // Always okay if use is in another basic block or UseMI is MI
1703 if (UseMI->getParent() != MI.getParent() || UseMI == &MI)
1704 return true;
1705
1706 // If CachedDistancesMI <= Use < MI we could have a problem since we don't
1707 // know if Use is still reachable.
1708 return !instrsAreInOrder(CachedDistancesMI, UseMI) ||
1709 !instrsAreInOrder(UseMI, &MI);
1710 }
1711
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};
1717
1718 ++DistanceCacheMisses; // Assume miss
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};
1725
1726 auto J = RegSlot.find(LaneMask);
1727 if (J == RegSlot.end())
1728 return {nullptr, nullptr};
1729
1730 const LiveRegToUseMapElem &MaskSlot = J->second;
1731 if (!okToUseCacheElem(MaskSlot, MI, LastDelta))
1732 return {nullptr, nullptr};
1733
1734 --DistanceCacheMisses;
1735 ++DistanceCacheHits;
1736 return {&RegSlot, &MaskSlot};
1737 }
1738
1739 void cacheLiveRegUse(const MachineInstr &MI, Register Reg, LaneBitmask Mask,
1740 LiveRegUse U, bool MIDependent) {
1741 if (!DistanceCacheEnabled)
1742 return;
1743
1744 auto I = PendingCachedDistances.try_emplace(Reg).first;
1745 LaneBitmaskToUseMap &RegSlot = I->second;
1746 RegSlot.try_emplace(Mask, U, MIDependent);
1747 }
1748
1749 void updateCachedLiveRegUses(const MachineInstr &MI) {
1750 if (!DistanceCacheEnabled)
1751 return;
1752
1753 CachedDistancesMI = &MI;
1754 CachedDistances = std::move(PendingCachedDistances);
1755 PendingCachedDistances.clear();
1756 LLVM_DEBUG(dumpDistanceCache());
1757 }
1758
1759 void printDistanceCache(raw_ostream &OS) const {
1760 OS << "\n----------- Distance Cache ----------- {\n";
1761 OS << " CachedAt: ";
1762 if (CachedDistancesMI)
1763 OS << *CachedDistancesMI;
1764 else
1765 OS << "<none>\n";
1766
1767 constexpr size_t RegNameWidth = 20;
1768 for (const auto &[Reg, ByMask] : CachedDistances) {
1769 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
1770 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(Reg);
1771
1772 for (const auto &[Mask, Elem] : ByMask) {
1773 std::string RegName;
1774 raw_string_ostream KOS(RegName);
1775 if (Mask == AllLanes) {
1776 KOS << printReg(Reg);
1777 } else {
1778 SmallVector<unsigned> Indexes;
1779 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1780 if (Indexes.size() == 1)
1781 KOS << printReg(Reg, TRI, Indexes.front(), MRI);
1782 else
1783 KOS << printReg(Reg) << " mask=" << Mask.getAsInteger();
1784 }
1785 OS << " " << left_justify(RegName, RegNameWidth) << " : ";
1786 Elem.print(OS);
1787 OS << '\n';
1788 }
1789 }
1790 OS << " (hits=" << DistanceCacheHits << " misses=" << DistanceCacheMisses
1791 << ")\n";
1792 OS << "}\n";
1793 }
1794
1795 LLVM_DUMP_METHOD void dumpDistanceCache() const {
1796 printDistanceCache(dbgs());
1797 }
1798
1799 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1800 // Processing Live Reg Uses
1801 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1802private:
1803 // Decompose each use in 'Uses' by sub-reg and store the nearest one in
1804 // 'UseByMask'. Ignores subregs matching 'LiveRegLaneMask' - these are handled
1805 // as registers, not sub-regs.
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) {
1812
1813 assert(Uses.size());
1814 assert(Uses.size() == Distances.size());
1815
1816 const TargetRegisterClass *RC = MRI->getRegClass(Uses.front()->getReg());
1817 auto [SRI, Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1818 if (Inserted)
1819 TRI->getCoveringSubRegIndexes(RC, LaneBitmask::getAll(), SRI->second);
1820 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1821
1822 unsigned OneIndex; // Backing store for 'Indexes' below when 1 index
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};
1827
1828 ArrayRef<unsigned> Indexes;
1829 if (MO->getSubReg()) {
1830 OneIndex = MO->getSubReg();
1831 Indexes = ArrayRef(OneIndex);
1832 } else {
1833 Indexes = RCSubRegIndexes;
1834 }
1835
1836 for (unsigned Idx : Indexes) {
1837 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(Idx);
1838 if (Mask.all() || Mask == LiveRegLaneMask)
1839 continue;
1840
1841 auto &[SlotU, SlotMIDep] = UseByMask[Mask];
1842 if (updateClosest(SlotU, LRU))
1843 SlotMIDep = SubRegMIDep;
1844 }
1845 }
1846 }
1847
1848 // Similar to 'collectSubRegUsesByMask' above, but uses cached distances.
1849 void collectSubRegUsesByMaskFromCache(const LaneBitmaskToUseMap &CachedMap,
1850 LaneBitmask LiveRegLaneMask,
1851 const MachineInstr *MI,
1852 InstrIdTy LastDelta,
1853 LaneBitmaskToUseMap &UseByMask) {
1854
1855 for (const auto &KV : CachedMap) {
1856 LaneBitmask SubregLaneMask = KV.first;
1857 if (SubregLaneMask.all() || SubregLaneMask == LiveRegLaneMask)
1858 continue;
1859
1860 const LiveRegToUseMapElem &SubregE = KV.second;
1861 if (!okToUseCacheElem(SubregE, *MI, LastDelta))
1862 continue;
1863
1864 const bool MIDep = SubregE.MIDependent;
1865 LiveRegUse U = SubregE.Use;
1866 if (MIDep)
1867 U.Dist -= LastDelta;
1868
1869 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1870 if (updateClosest(SlotU, U))
1871 SlotMIDep = MIDep;
1872 }
1873 }
1874
1875 // Loops through 'UseByMask' finding the furthest sub-register and updating
1876 // 'FurthestSubreg' accordingly.
1877 void updateFurthestSubReg(
1878 const MachineInstr &MI, const LiveRegUse &U,
1879 const LaneBitmaskToUseMap &UseByMask,
1880 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1881 LiveRegUse &FurthestSubreg) {
1882
1883 if (UseByMask.empty()) {
1884 updateFurthest(FurthestSubreg, U);
1885 return;
1886 }
1887
1888 for (const auto &KV : UseByMask) {
1889 const LiveRegUse &SubregU = KV.second.Use;
1890 const bool SubregMIDep = KV.second.MIDependent;
1891
1892 if (RelevantUses)
1893 RelevantUses->try_emplace(SubregU.Use, SubregU);
1894 cacheLiveRegUse(MI, SubregU.Use->getReg(), KV.first, SubregU,
1895 SubregMIDep);
1896 updateFurthest(FurthestSubreg, SubregU);
1897 }
1898 }
1899
1900 // Used to populate 'MIDefs' to be passed to 'getNextUseDistances'.
1901 SmallSet<Register, 4> collectDefinedRegisters(const MachineInstr &MI) const {
1902 SmallSet<Register, 4> MIDefs;
1903
1904 for (const MachineOperand &MO : MI.all_defs()) {
1905 if (MO.isReg() && MO.getReg().isValid() && hasAtLeastOneUse(MO.getReg()))
1906 MIDefs.insert(MO.getReg());
1907 }
1908 return MIDefs;
1909 }
1910
1911 // Computes distances from 'MI' to each registers in 'LiveRegs'. Returns the
1912 // furthest register and (optionally) sub-register in 'Furthest' and
1913 // 'FurthestSubreg' respectively.
1914public:
1916 const MachineInstr &MI, LiveRegUse &Furthest,
1917 LiveRegUse *FurthestSubreg = nullptr,
1919 *RelevantUses = nullptr) {
1920 const SmallSet<Register, 4> MIDefs(collectDefinedRegisters(MI));
1921
1924 LaneBitmaskToUseMap UseByMask;
1925
1926 maybeClearCachedLiveRegUses(MI);
1927 const InstrIdTy LastDelta =
1928 CachedDistancesMI ? getDistance(CachedDistancesMI, &MI) : 0;
1929
1930 for (auto &KV : LiveRegs) {
1931 const Register Reg = KV.first;
1932 const LaneBitmask LaneMask = KV.second;
1933
1934 if (MIDefs.contains(Reg))
1935 continue;
1936
1937 Uses.clear();
1938 UseByMask.clear();
1939
1940 LiveRegUse U;
1941 bool MIDependent = false;
1942 auto [CacheMap, CacheElem] =
1943 findCachedLiveRegUse(Reg, LaneMask, MI, LastDelta);
1944 if (CacheMap && CacheElem) {
1945 MIDependent = CacheElem->MIDependent;
1946 U = CacheElem->Use;
1947 if (MIDependent)
1948 U.Dist -= LastDelta;
1949 } else {
1950 getReachableUses(Reg, LaneMask, MI, Uses);
1951 if (Uses.empty())
1952 continue;
1953
1954 const MachineOperand *NextUse = nullptr;
1956 Reg, LaneMask, MI, Uses, &NextUse, &MIDependent, &Distances);
1957 U = LiveRegUse{NextUse, Dist};
1958 }
1959
1960 if (RelevantUses)
1961 RelevantUses->try_emplace(U.Use, U);
1962 cacheLiveRegUse(MI, Reg, LaneMask, U, MIDependent);
1963
1964 updateFurthest(Furthest, U);
1965
1966 if (!FurthestSubreg)
1967 continue;
1968
1969 if (CacheMap) {
1970 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &MI, LastDelta,
1971 UseByMask);
1972 } else {
1973 collectSubRegUsesByMask(Uses, Distances, LaneMask, UseByMask);
1974 }
1975 updateFurthestSubReg(MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1976 }
1977 updateCachedLiveRegUses(MI);
1978 }
1979
1980 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1981 // Helper methods for printAsJson
1982 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1983private:
1984 static format_object<unsigned> Fmt(unsigned Id) { return format("%u", Id); }
1985
1986public:
1988 J.attribute("id", getInstrId(&MI));
1989 J.attribute("head-len", getHeadLen(&MI));
1990 J.attribute("tail-len", getTailLen(&MI));
1991 }
1992
1994 J.attributeBegin("paths");
1995 J.arrayBegin();
1996 for (const auto &KV : Paths) {
1997 const Path &P = KV.first;
1998 const PathInfo &PI = KV.second;
1999
2000 J.objectBegin();
2001
2002 printMBBNameAttr(J, "src", *P.src(), MST);
2003 printMBBNameAttr(J, "dst", *P.dst(), MST);
2004
2005 if (PI.ShortestDistance.has_value()) {
2006 J.attribute("shortest-distance",
2007 PI.ShortestDistance.value().toJsonValue());
2008 } else {
2009 J.attribute("shortest-distance", nullptr);
2010 }
2011
2012 if (PI.ShortestUnweightedDistance.has_value()) {
2013 J.attribute("shortest-unweighted-distance",
2014 PI.ShortestUnweightedDistance.value().toJsonValue());
2015 } else {
2016 J.attribute("shortest-unweighted-distance", nullptr);
2017 }
2018
2019 J.attribute("edge-kind", static_cast<int>(PI.EK));
2020 J.attribute("reachable", PI.Reachable);
2021 J.attribute("forward-reachable", PI.ForwardReachable);
2022
2023 J.objectEnd();
2024 }
2025 J.arrayEnd();
2026 J.attributeEnd();
2027 }
2028
2029public:
2031 ~AMDGPUNextUseAnalysisImpl() { clearTables(); }
2032
2035 Cfg = NewCfg;
2036 clearTables();
2037 initializeTables();
2038 }
2039
2040 unsigned getDistanceCacheHits() const { return DistanceCacheHits; }
2041 unsigned getDistanceCacheMisses() const { return DistanceCacheMisses; }
2042
2043 void getReachableUses(Register LiveReg, LaneBitmask LaneMask,
2044 const MachineInstr &MI,
2046
2047 /// \Returns the shortest next-use distance for \p LiveReg.
2049 getShortestDistance(Register LiveReg, LaneBitmask LaneMask,
2050 const MachineInstr &FromMI,
2052 const MachineOperand **ShortestUseOut, bool *MIDependent,
2053 SmallVector<CacheableNextUseDistance> *Distances) const;
2054
2058 return getShortestDistance(LiveReg, LaneBitmask::getAll(), FromMI, Uses,
2059 nullptr, nullptr, nullptr);
2060 }
2061};
2062
2064 const MachineFunction *MF, const MachineLoopInfo *ML) {
2065
2066 this->MF = MF;
2067 this->MLI = ML;
2068
2069 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2070 TII = ST.getInstrInfo();
2071 TRI = &TII->getRegisterInfo();
2072 MRI = &MF->getRegInfo();
2073
2074 // FIXME: Hopefully we will soon converge on a single way of calculating
2075 // next-use distance and remove these presets.
2076 if (ConfigPresetOpt == "compute")
2078 else
2080
2081 if (ConfigCountPhisOpt.getNumOccurrences())
2082 Cfg.CountPhis = ConfigCountPhisOpt;
2083 if (ConfigForwardOnlyOpt.getNumOccurrences())
2084 Cfg.ForwardOnly = ConfigForwardOnlyOpt;
2085 if (ConfigPreciseUseModelingOpt.getNumOccurrences())
2086 Cfg.PreciseUseModeling = ConfigPreciseUseModelingOpt;
2087 if (ConfigPromoteToPreheaderOpt.getNumOccurrences())
2088 Cfg.PromoteToPreheader = ConfigPromoteToPreheaderOpt;
2089
2090 initializeTables();
2091}
2092
2094 Register LiveReg, LaneBitmask LaneMask, const MachineInstr &CurMI,
2096 const MachineOperand **ShortestUseOut, bool *CurMIDependentOut,
2097 SmallVector<CacheableNextUseDistance> *Distances) const {
2098
2099 assert(!LiveReg.isPhysical() && !TRI->isAGPR(*MRI, LiveReg) &&
2100 "Next-use distance is calculated for SGPRs and VGPRs");
2101 const MachineOperand *NextUse = nullptr;
2102 auto NextUseDist = NextUseDistance::unreachable();
2103 bool CurMIDependent = false;
2104
2105 if (Distances) {
2106 Distances->clear();
2107 Distances->reserve(Uses.size());
2108 }
2109 for (auto *UseMO : Uses) {
2110 auto [Dep, D] = calcDistanceToUse(LiveReg, LaneMask, CurMI, UseMO);
2111
2112 if (D < NextUseDist) {
2113 NextUseDist = D;
2114 NextUse = UseMO;
2115 CurMIDependent = Dep;
2116 }
2117
2118 if (Distances)
2119 Distances->push_back({Dep, D});
2120 }
2121 if (ShortestUseOut)
2122 *ShortestUseOut = NextUse;
2123 if (CurMIDependentOut)
2124 *CurMIDependentOut = CurMIDependent;
2125
2126 assert(NextUseDist.isReachable() &&
2127 "getShortestDistance called with no reachable uses");
2128 return NextUseDist;
2129}
2130
2132 Register Reg, LaneBitmask LaneMask, const MachineInstr &MI,
2134 const bool CheckMask = LaneMask != LaneBitmask::getAll() &&
2135 LaneMask != MRI->getMaxLaneMaskForVReg(Reg);
2136 const MachineBasicBlock *MBB = MI.getParent();
2137
2138 for (const MachineOperand *UseMO : getRegisterUses(Reg)) {
2139 const MachineInstr *UseMI = UseMO->getParent();
2140 const MachineBasicBlock *UseMBB = UseMI->getParent();
2141
2142 if (CheckMask && !machineOperandCoveredBy(*UseMO, LaneMask))
2143 continue;
2144
2145 bool Reachable;
2146 if (Cfg.PreciseUseModeling)
2147 Reachable = isUseReachablePrecise(MI, MBB, UseMO, UseMI, UseMBB);
2148 else if (MBB == UseMBB)
2149 Reachable = instrsAreInOrder(&MI, UseMI);
2150 else
2151 Reachable = isForwardReachable(MBB, UseMBB);
2152
2153 if (Reachable)
2154 Uses.push_back(UseMO);
2155 }
2156}
2157
2158//==============================================================================
2159// AMDGPUNextUseAnalysis
2160//==============================================================================
2161AMDGPUNextUseAnalysis::AMDGPUNextUseAnalysis(const MachineFunction *MF,
2162 const MachineLoopInfo *MLI) {
2163 Impl = std::make_unique<AMDGPUNextUseAnalysisImpl>(MF, MLI);
2164}
2165AMDGPUNextUseAnalysis::AMDGPUNextUseAnalysis(AMDGPUNextUseAnalysis &&Other)
2166 : Impl(std::move(Other.Impl)) {}
2168
2170AMDGPUNextUseAnalysis::operator=(AMDGPUNextUseAnalysis &&Other) {
2171 if (this != &Other)
2172 Impl = std::move(Other.Impl);
2173 return *this;
2174}
2175
2177 return Impl->getConfig();
2178}
2179
2180void AMDGPUNextUseAnalysis::setConfig(Config Cfg) { Impl->setConfig(Cfg); }
2181
2182/// \Returns the next-use distance for \p LiveReg.
2184 Register LiveReg, const MachineInstr &FromMI,
2186 const MachineOperand **ShortestUseOut,
2187 SmallVector<NextUseDistance> *DistancesOut) const {
2188
2190 auto Dist = Impl->getShortestDistance(LiveReg, LaneBitmask::getAll(), FromMI,
2191 Uses, ShortestUseOut, nullptr,
2192 DistancesOut ? &Distances : nullptr);
2193 if (DistancesOut) {
2194 for (auto [MIDep, D] : Distances)
2195 DistancesOut->push_back(D);
2196 }
2197 return Dist;
2198}
2199
2202 UseDistancePair &FurthestOut, UseDistancePair *FurthestSubregOut,
2204
2205 LiveRegUse Furthest;
2206 LiveRegUse FurthestSubreg;
2207 Impl->getNextUseDistances(LiveRegs, MI, Furthest,
2208 FurthestSubregOut ? &FurthestSubreg : nullptr,
2209 RelevantUses);
2210 FurthestOut = Furthest;
2211 if (FurthestSubregOut)
2212 *FurthestSubregOut = FurthestSubreg;
2213}
2215 Register LiveReg, LaneBitmask LaneMask, const MachineInstr &MI,
2217 return Impl->getReachableUses(LiveReg, LaneMask, MI, Uses);
2218}
2219
2220//==============================================================================
2221// AMDGPUNextUseAnalysisLegacyPass
2222//==============================================================================
2223
2224//------------------------------------------------------------------------------
2225// Legacy Analysis Pass
2226//------------------------------------------------------------------------------
2230 return "Next Use Analysis";
2231}
2232
2234 MachineFunction &MF) {
2235 const MachineLoopInfo *MLI =
2237 NUA.reset(new AMDGPUNextUseAnalysis(&MF, MLI));
2238 return false;
2239}
2240
2247
2250
2252 "Next Use Analysis", false, true)
2255 "Next Use Analysis", false, true)
2256
2257//------------------------------------------------------------------------------
2258// New Pass Manager Analysis Pass
2259//------------------------------------------------------------------------------
2261
2265 const MachineLoopInfo &MLI = MFAM.getResult<MachineLoopAnalysis>(MF);
2266 return AMDGPUNextUseAnalysis(&MF, &MLI);
2267}
2268
2269//==============================================================================
2270// AMDGPUNextUseAnalysisPrinterLegacyPass
2271//==============================================================================
2272namespace {
2273void printInstrMember(json::OStream &J, ModuleSlotTracker &MST,
2274 const MachineInstr &MI,
2275 const AMDGPUNextUseAnalysisImpl &NUA) {
2276 printStringAttr(J, "instr", MI, MST);
2277 if (DumpNextUseDistanceVerbose)
2279}
2280
2281void printDistances(
2282 json::OStream &J, const MachineRegisterInfo &MRI, const SIRegisterInfo &TRI,
2283 ModuleSlotTracker &MST,
2285 if (!DumpNextUseDistanceVerbose)
2286 return;
2287
2288 // Sorting isn't necessary for the purposes of JSON, but it reduces
2289 // FileCheck differences.
2291 for (const MachineOperand *K : Uses.keys())
2292 Keys.push_back(K);
2293 llvm::sort(Keys, [](const auto &A, const auto &B) {
2294 return A->getReg() < B->getReg() ||
2295 (A->getReg() == B->getReg() && A->getSubReg() < B->getSubReg());
2296 });
2297
2298 J.attributeBegin("distances");
2299 J.objectBegin();
2300
2301 for (const MachineOperand *K : Keys) {
2302 const LiveRegUse U = Uses.at(K);
2303 printAttr(J, printReg(U.getReg(), &TRI, U.getSubReg(), &MRI),
2304 U.Dist.toJsonValue());
2305 }
2306
2307 J.objectEnd();
2308 J.attributeEnd();
2309}
2310
2311void printFurthestUse(json::OStream &J, const MachineRegisterInfo &MRI,
2313 const LiveRegUse F, bool Subreg = false) {
2314 J.attributeBegin(Subreg ? "furthest-subreg" : "furthest");
2315 J.objectBegin();
2316
2317 if (F.Use) {
2318 printStringAttr(
2319 J, "register",
2320 printReg(F.getReg(), &TRI, Subreg ? F.getSubReg() : 0, &MRI));
2321
2322 if (DumpNextUseDistanceVerbose) {
2323 printStringAttr(J, "use", [&](raw_ostream &OS) { OS << (*F.Use); });
2324 printStringAttr(J, "use-mi", *F.Use->getParent(), MST);
2325 }
2326 J.attribute("distance", F.Dist.toJsonValue());
2327 }
2328
2329 J.objectEnd();
2330 J.attributeEnd();
2331}
2332
2333void printDistanceFromDefToUse(json::OStream &J, const MachineFunction &MF,
2334 const AMDGPUNextUseAnalysis &NUA,
2335 const SIRegisterInfo &TRI,
2336 const MachineRegisterInfo &MRI) {
2337 auto getRegNextUseDistance = [&](Register DefReg) {
2338 const MachineInstr &DefMI = *MRI.def_instr_begin(DefReg);
2339
2342 if (Uses.empty())
2344 return NUA.getShortestDistance(DefReg, DefMI, Uses);
2345 };
2346
2347 J.attributeBegin("distance-from-def-to-closest-use");
2348 J.objectBegin();
2349
2350 for (const MachineBasicBlock &MBB : MF) {
2351 for (const MachineInstr &MI : MBB) {
2352 for (const MachineOperand &MO : MI.all_defs()) {
2353 Register Reg = MO.getReg();
2354 if (Reg.isPhysical())
2355 continue;
2356 NextUseDistance D = getRegNextUseDistance(Reg);
2357 printAttr(J, printReg(Reg, &TRI, 0, &MRI), D.toJsonValue());
2358 }
2359 }
2360 }
2361
2362 J.objectEnd();
2363 J.attributeEnd();
2364}
2365
2366void printNextUseDistancesAsJson(json::OStream &J, const MachineFunction &MF,
2367 const AMDGPUNextUseAnalysis &NUA,
2368 const AMDGPUNextUseAnalysisImpl &NUAImpl,
2369 const LiveIntervals &LIS) {
2370 using UseDistancePair = AMDGPUNextUseAnalysis::UseDistancePair;
2371 const Function &F = MF.getFunction();
2372 const Module *M = F.getParent();
2373
2375 const SIInstrInfo *TII = ST.getInstrInfo();
2377 const MachineRegisterInfo &MRI = MF.getRegInfo();
2378
2379 // We don't actually care about register pressure here - just using
2380 // GCNDownwardRPTracker as a convenient way of getting the set of live
2381 // registers at a given instruction.
2382 GCNDownwardRPTracker RPTracker(LIS);
2383 ModuleSlotTracker MST(M);
2385
2387
2388 J.attributeBegin("furthest-distances");
2389 J.objectBegin();
2390
2391 for (const MachineBasicBlock &MBB : MF) {
2392 std::string BBName;
2393 raw_string_ostream BBOS(BBName);
2395
2396 J.attributeBegin(BBOS.str());
2397 J.arrayBegin();
2398
2399 const MachineInstr *PrevMI = nullptr;
2400 for (const MachineInstr &MI : MBB) {
2401 // Update register pressure tracker
2402 if (!PrevMI || PrevMI->getOpcode() == AMDGPU::PHI)
2403 RPTracker.reset(MI, MBB.end());
2404 RPTracker.advance();
2405
2406 UseDistancePair Furthest;
2407 UseDistancePair FurthestSubreg;
2408 RelevantUses.clear();
2409 NUA.getNextUseDistances(RPTracker.getLiveRegs(), MI, Furthest,
2410 &FurthestSubreg, &RelevantUses);
2411
2412 J.objectBegin();
2413 printInstrMember(J, MST, MI, NUAImpl);
2414 printDistances(J, MRI, TRI, MST, RelevantUses);
2415 printFurthestUse(J, MRI, TRI, MST, Furthest);
2416 printFurthestUse(J, MRI, TRI, MST, FurthestSubreg, /*Subreg*/ true);
2417 J.objectEnd();
2418
2419 PrevMI = &MI;
2420 }
2421
2422 J.arrayEnd();
2423 J.attributeEnd();
2424 }
2425
2426 J.objectEnd();
2427 J.attributeEnd();
2428
2429 if (DumpNextUseDistanceVerbose || DumpNextUseDistanceDefToUse)
2430 printDistanceFromDefToUse(J, MF, NUA, TRI, MRI);
2431
2432 if (DumpNextUseDistanceVerbose)
2433 NUAImpl.printPaths(J, MST);
2434
2435 if (DistanceCacheEnabled) {
2436 J.attributeBegin("metrics");
2437 J.objectBegin();
2438 {
2439 J.attributeBegin("distance-cache");
2440 J.objectBegin();
2441 {
2442 J.attribute("hits", NUAImpl.getDistanceCacheHits());
2443 J.attribute("misses", NUAImpl.getDistanceCacheMisses());
2444 }
2445 J.objectEnd();
2446 J.attributeEnd(); // distance-cache
2447 }
2448 J.objectEnd();
2449 J.attributeEnd(); // metrics
2450 }
2451}
2452
2453void printAsJson(raw_ostream &FallbackOS, TimerGroup &JsonTimerGroup,
2454 Timer &JsonTimer, const MachineFunction &MF,
2455 const AMDGPUNextUseAnalysis &NUA,
2456 const AMDGPUNextUseAnalysisImpl &NUAImpl,
2457 const LiveIntervals &LIS) {
2458 std::string FN = DumpNextUseDistanceAsJson;
2459
2460 auto dump = [&](raw_ostream &OS) {
2461 json::OStream J(OS, 2);
2462 J.objectBegin();
2463
2464 J.attributeBegin("next-use-analysis");
2465 J.objectBegin();
2466 printNextUseDistancesAsJson(J, MF, NUA, NUAImpl, LIS);
2467 J.objectEnd();
2468 J.attributeEnd();
2469
2470 JsonTimer.stopTimer();
2471 JsonTimerGroup.printJSONValues(OS, ",\n");
2472
2473 J.objectEnd();
2474 };
2475
2476 if (!DumpNextUseDistanceAsJson.getNumOccurrences()) {
2477 dump(FallbackOS);
2478 } else if (FN.empty() || FN == "-") {
2479 dump(outs());
2480 } else {
2481 std::error_code EC;
2482 ToolOutputFile OutF(FN, EC, sys::fs::OF_None);
2483 dump(OutF.os());
2484 OutF.keep();
2485 }
2486}
2487} // namespace
2488
2489//------------------------------------------------------------------------------
2490// Legacy Printer Pass
2491//------------------------------------------------------------------------------
2494
2496 return "AMDGPU Next Use Analysis Printer";
2497}
2498
2500 MachineFunction &MF) {
2501 TimerGroup JsonTimerGroup("amdgpu-next-use-analysis-json",
2502 "AMDGPU Next Use Analysis JSON Printer", false);
2503 Timer JsonTimer("json", "Total time spent generating json", JsonTimerGroup);
2504 JsonTimer.startTimer();
2505
2507 const AMDGPUNextUseAnalysis &NUA =
2508 getAnalysis<AMDGPUNextUseAnalysisLegacyPass>().getNextUseAnalysis();
2509
2510 printAsJson(errs(), JsonTimerGroup, JsonTimer, MF, NUA, *NUA.Impl, LIS);
2511
2512 return false;
2513}
2514
2523
2527
2529 "amdgpu-next-use-printer",
2530 "AMDGPU Next Use Analysis Printer", false, false)
2531
2534
2536 "amdgpu-next-use-printer",
2537 "AMDGPU Next Use Analysis Printer", false, false)
2538
2539//------------------------------------------------------------------------------
2540// New Pass Manager Printer Pass
2541//------------------------------------------------------------------------------
2545
2546 TimerGroup JsonTimerGroup("amdgpu-next-use-analysis-json",
2547 "AMDGPU Next Use Analysis JSON Printer", false);
2548 Timer JsonTimer("json", "Total time spent generating json", JsonTimerGroup);
2549 JsonTimer.startTimer();
2550
2551 const LiveIntervals &LIS = MFAM.getResult<LiveIntervalsAnalysis>(MF);
2552 const AMDGPUNextUseAnalysis &NUA =
2553 MFAM.getResult<AMDGPUNextUseAnalysisPass>(MF);
2554
2555 printAsJson(OS, JsonTimerGroup, JsonTimer, MF, NUA, *NUA.Impl, LIS);
2556
2557 return PreservedAnalyses::all();
2558}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
MachineBasicBlock & MBB
Function Alias Analysis false
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:686
This file defines the GCNRegPressure class, which tracks registry pressure by bookkeeping number of S...
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file supports working with JSON data.
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define P(N)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Remove Loads Into Fake Uses
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
void setConfig(AMDGPUNextUseAnalysis::Config NewCfg)
AMDGPUNextUseAnalysis::Config getConfig() const
void getNextUseDistances(const GCNRPTracker::LiveRegSet &LiveRegs, const MachineInstr &MI, LiveRegUse &Furthest, LiveRegUse *FurthestSubreg=nullptr, DenseMap< const MachineOperand *, UseDistancePair > *RelevantUses=nullptr)
void getReachableUses(Register LiveReg, LaneBitmask LaneMask, const MachineInstr &MI, SmallVector< const MachineOperand * > &Uses) const
void printVerboseInstrFields(json::OStream &J, const MachineInstr &MI) const
AMDGPUNextUseAnalysisImpl(const MachineFunction *, const MachineLoopInfo *)
void printPaths(json::OStream &J, ModuleSlotTracker &MST) const
NextUseDistance getShortestDistance(Register LiveReg, const MachineInstr &FromMI, const SmallVector< const MachineOperand * > &Uses) const
NextUseDistance getShortestDistance(Register LiveReg, LaneBitmask LaneMask, const MachineInstr &FromMI, const SmallVector< const MachineOperand * > &Uses, const MachineOperand **ShortestUseOut, bool *MIDependent, SmallVector< CacheableNextUseDistance > *Distances) const
\Returns the shortest next-use distance for LiveReg.
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void getReachableUses(Register LiveReg, LaneBitmask LaneMask, const MachineInstr &MI, SmallVector< const MachineOperand * > &Uses) const
void getNextUseDistances(const DenseMap< unsigned, LaneBitmask > &LiveRegs, const MachineInstr &MI, UseDistancePair &Furthest, UseDistancePair *FurthestSubreg=nullptr, DenseMap< const MachineOperand *, UseDistancePair > *RelevantUses=nullptr) const
NextUseDistance getShortestDistance(Register LiveReg, const MachineInstr &CurMI, const SmallVector< const MachineOperand * > &Uses, const MachineOperand **ShortestUseOut=nullptr, SmallVector< NextUseDistance > *Distances=nullptr) const
\Returns the shortest next-use distance from CurMI for LiveReg.
AMDGPUNextUseAnalysis & operator=(AMDGPUNextUseAnalysis &&Other)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:794
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
DenseMap< unsigned, LaneBitmask > LiveRegSet
const HexagonRegisterInfo & getRegisterInfo() const
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
unsigned getNumBlocks() const
Get the number of blocks in this loop in constant time.
BlockT * getHeader() const
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
void getLoopLatches(SmallVectorImpl< BlockT * > &LoopLatches) const
Return all loop latch blocks of this loop.
unsigned getLoopDepth() const
Return the nesting level of this loop.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
bool isLoopExiting(const BlockT *BB) const
True if terminator in the block can branch to another block that is outside of the current loop.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
@ PrintNameIr
Add IR name where available.
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
LLVM_ABI void printName(raw_ostream &os, unsigned printNameFlags=PrintNameIr, ModuleSlotTracker *moduleSlotTracker=nullptr) const
Print the basic block's name as:
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
def_instr_iterator def_instr_begin(Register RegNo) const
Manage lifetime of a slot tracker for printing IR.
void incorporateFunction(const Function &F)
Incorporate the given function.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
static constexpr NextUseDistance fromSize(unsigned Size, unsigned Depth)
static constexpr NextUseDistance unreachable()
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Simple wrapper around std::function<void(raw_ostream&)>.
Definition Printable.h:38
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition SmallSet.h:229
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The TimerGroup class is used to group together related timers into a single report that is printed wh...
Definition Timer.h:191
LLVM_ABI const char * printJSONValues(raw_ostream &OS, const char *delim)
Definition Timer.cpp:464
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
Definition Timer.h:87
LLVM_ABI void stopTimer()
Stop the timer.
Definition Timer.cpp:159
LLVM_ABI void startTimer()
Start the timer running.
Definition Timer.cpp:150
This class contains a raw_fd_ostream and adds a few extra features commonly needed for compiler-like ...
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
Definition JSON.h:983
LLVM_ABI void attributeBegin(llvm::StringRef Key)
Definition JSON.cpp:883
void attribute(llvm::StringRef Key, const Value &Contents)
Emit an attribute whose value is self-contained (number, vector<int> etc).
Definition JSON.h:1038
LLVM_ABI void arrayBegin()
Definition JSON.cpp:845
LLVM_ABI void objectBegin()
Definition JSON.cpp:864
LLVM_ABI raw_ostream & rawValueBegin()
Definition JSON.cpp:911
LLVM_ABI void arrayEnd()
Definition JSON.cpp:853
LLVM_ABI void attributeEnd()
Definition JSON.cpp:903
LLVM_ABI void rawValueEnd()
Definition JSON.cpp:918
LLVM_ABI void objectEnd()
Definition JSON.cpp:872
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
char & AMDGPUNextUseAnalysisLegacyID
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Other
Any other memory.
Definition ModRef.h:68
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition Format.h:123
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
char & AMDGPUNextUseAnalysisPrinterLegacyID
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
static Config Graphics()
Named presets.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
static constexpr LaneBitmask getAll()
Definition LaneBitmask.h:82
constexpr bool all() const
Definition LaneBitmask.h:54