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 -= static_cast<InstrIdTy>(
661 std::distance(BB->begin(), BB->getFirstNonPHI()));
662 return Size;
663 }
664
665 // Return the loop depth of 'From' relative to 'To'.
666 unsigned calcRelativeLoopDepth(const MachineBasicBlock *From,
667 const MachineBasicBlock *To) const {
668 MachineLoop *LoopFrom = MLI->getLoopFor(From);
669 MachineLoop *LoopTo = MLI->getLoopFor(To);
670
671 if (!LoopFrom)
672 return 0;
673
674 if (!LoopTo)
675 return LoopFrom->getLoopDepth();
676
677 if (LoopFrom->contains(LoopTo)) // covers LoopFrom == LoopTo
678 return 0;
679
680 if (LoopTo->contains(LoopFrom))
681 return LoopFrom->getLoopDepth() - LoopTo->getLoopDepth();
682
683 // Loops are siblings of some sort.
684 return findCommonParent(LoopFrom, LoopTo).second;
685 }
686
687 // Attempt to find a path from 'From' to 'To' using a depth first search. If
688 // 'ForwardOnly' is true, do not follow backedges. As a performance
689 // improvement, this may initialize reachable intermediate paths or paths we
690 // determine are unreachable.
691 bool calcIsReachable(const MachineBasicBlock *From,
692 const MachineBasicBlock *To,
693 bool ForwardOnly = false) const {
694 if (From == To && !MLI->getLoopFor(From))
695 return false;
696
697 if (!ForwardOnly && interBlockDistanceExists(From, To))
698 return true;
699
700 enum { VisitOp, PopOp };
701 using MBBOpPair = std::pair<const MachineBasicBlock *, int>;
702 SmallVector<MBBOpPair> Work{{From, VisitOp}};
703 DenseSet<const MachineBasicBlock *> Visited{From};
704
705 SmallVector<Path> IntermediatePath;
706 SmallVector<Path> Unreachable;
707
708 // Should be run at every function exit point.
709 auto Finally = [&](bool Reachable) {
710 // This is an optimization. For intermediate paths we found while
711 // calculating reachability for 'From' --> 'To', remember their
712 // reachability.
713 if (!Reachable) {
714 IntermediatePath.clear();
715 for (const MachineBasicBlock *MBB : Visited) {
716 if (MBB != From)
717 Unreachable.emplace_back(MBB, To);
718 }
719 }
720
721 if (ForwardOnly)
722 initializeForwardOnlyPaths(IntermediatePath, Unreachable);
723 else
724 initializePaths(IntermediatePath, Unreachable);
725
726 return Reachable;
727 };
728
729 while (!Work.empty()) {
730 auto [Current, Op] = Work.pop_back_val();
731
732 // Backtracking
733 if (Op == PopOp) {
734 IntermediatePath.pop_back();
735 if (ForwardOnly)
736 Unreachable.emplace_back(Current, To);
737 continue;
738 }
739
740 if (Current->succ_empty())
741 continue;
742
743 if (Current != From) {
744 IntermediatePath.emplace_back(Current, To);
745 Work.emplace_back(Current, PopOp);
746 }
747
748 for (const MachineBasicBlock *Succ : Current->successors()) {
749 if (ForwardOnly && isBackedge(Current, Succ))
750 continue;
751
752 if (Succ == To)
753 return Finally(true);
754
755 if (auto CachedReachable = isMaybeReachable(Succ, To, ForwardOnly)) {
756 if (CachedReachable.value())
757 return Finally(true);
758 Visited.insert(Succ);
759 continue;
760 }
761
762 if (Visited.insert(Succ).second)
763 Work.emplace_back(Succ, VisitOp);
764 }
765 }
766
767 return Finally(false);
768 }
769
770 //----------------------------------------------------------------------------
771 // Inter-block distance - the weighted and unweighted cost (i.e. "distance")
772 // to travel from one MachineBasicBlock to another.
773 //
774 // Values are pre-computed and stored in 'InterBlockDistances' using a
775 // backwards data-flow algorithm similar to the one described in 4.1 of a
776 // "Register Spilling and Live-Range Splitting for SSA-Form Programs" by
777 // Matthias Braun and Sebastian Hack, CC'09. This replaced a prior
778 // implementation based on Dijkstra's shortest path algorithm.
779 //----------------------------------------------------------------------------
780private:
781 struct InterBlockDistance {
782 NextUseDistance Weighted;
783 NextUseDistance Unweighted;
784 InterBlockDistance() : Weighted(-1), Unweighted(-1) {}
785 InterBlockDistance(NextUseDistance W, NextUseDistance UW)
786 : Weighted(W), Unweighted(UW) {}
787 bool operator==(const InterBlockDistance &Other) const {
788 return Weighted == Other.Weighted && Unweighted == Other.Unweighted;
789 }
790 bool operator!=(const InterBlockDistance &Other) const {
791 return !(*this == Other);
792 }
793
794 void print(raw_ostream &OS) const {
795 OS << "{W=";
796 Weighted.print(OS);
797 OS << " U=";
798 Unweighted.print(OS);
799 OS << "}";
800 }
801
802 LLVM_DUMP_METHOD void dump() const {
803 print(dbgs());
804 dbgs() << '\n';
805 }
806 };
807 using InterBlockDistanceMap =
808 DenseMap<unsigned, DenseMap<unsigned, InterBlockDistance>>;
809 InterBlockDistanceMap InterBlockDistances;
810
811 void initializeInterBlockDistances() {
812 InterBlockDistanceMap Distances;
813
814 bool Changed;
815 do {
816 Changed = false;
817 for (const MachineBasicBlock *MBB : post_order(MF)) {
818 unsigned MBBNum = MBB->getNumber();
819
820 // Save previous state for convergence check
821 InterBlockDistanceMap::mapped_type Prev = std::move(Distances[MBBNum]);
822 InterBlockDistanceMap::mapped_type Curr;
823 Curr.reserve(Prev.size());
824
825 // Direct successors are distance 0 by definition: no instructions are
826 // executed between exiting MBB and entering Succ.
827 for (const MachineBasicBlock *Succ : MBB->successors())
828 Curr[Succ->getNumber()] = InterBlockDistance(0, 0);
829
830 // Propagate further destinations through each successor.
831 for (const MachineBasicBlock *Succ : MBB->successors()) {
832 unsigned SuccNum = Succ->getNumber();
833 const unsigned UnweightedSize{getSize(Succ)};
834
835 for (const auto &[DestBlockNum, DestDist] : Distances[SuccNum]) {
836 // MBB -> MBB is considered unreachable (getInterBlockDistance
837 // asserts From != To).
838 if (DestBlockNum == MBBNum)
839 continue;
840
841 const MachineBasicBlock *DestMBB =
842 MF->getBlockNumbered(DestBlockNum);
843
844 const NextUseDistance UnweightedDist{UnweightedSize +
845 DestDist.Unweighted};
846
847 unsigned SuccToDestLoopDepth = calcRelativeLoopDepth(Succ, DestMBB);
848
849 const NextUseDistance WeightedDist =
850 DestDist.Weighted +
851 NextUseDistance::fromSize(UnweightedSize, SuccToDestLoopDepth);
852
853 // Insert or update distances (take minimum)
854 auto [I, First] =
855 Curr.try_emplace(DestBlockNum, WeightedDist, UnweightedDist);
856 if (!First) {
857 InterBlockDistance &Slot = I->second;
858 Slot.Weighted = min(Slot.Weighted, WeightedDist);
859 Slot.Unweighted = min(Slot.Unweighted, UnweightedDist);
860 }
861 }
862 }
863 Changed |= (Prev != Curr);
864 Distances[MBBNum] = std::move(Curr);
865 }
866 } while (Changed);
867
868 InterBlockDistances = std::move(Distances);
869 LLVM_DEBUG(dumpInterBlockDistances());
870 }
871
872 const InterBlockDistance *
873 getInterBlockDistanceMapValue(const MachineBasicBlock *From,
874 const MachineBasicBlock *To) const {
875 auto I = InterBlockDistances.find(From->getNumber());
876 if (I == InterBlockDistances.end())
877 return nullptr;
878 const InterBlockDistanceMap::mapped_type &FromSlot = I->second;
879 auto J = FromSlot.find(To->getNumber());
880 return J == FromSlot.end() ? nullptr : &J->second;
881 }
882
883 bool interBlockDistanceExists(const MachineBasicBlock *From,
884 const MachineBasicBlock *To) const {
885 return getInterBlockDistanceMapValue(From, To);
886 }
887
888 NextUseDistance getInterBlockDistance(const MachineBasicBlock *From,
889 const MachineBasicBlock *To,
890 bool Unweighted) const {
891
892 assert(From != To && "The basic blocks should be different.");
893 if (!From || !To)
895
896 if (Cfg.ForwardOnly && !isForwardReachable(From, To))
898
899 const InterBlockDistance *BD = getInterBlockDistanceMapValue(From, To);
900 if (!BD)
902
903 return Unweighted ? BD->Unweighted : BD->Weighted;
904 }
905
906 NextUseDistance
907 getWeightedInterBlockDistance(const MachineBasicBlock *From,
908 const MachineBasicBlock *To) const {
909 return getInterBlockDistance(From, To, false);
910 }
911
912 NextUseDistance
913 getUnweightedInterBlockDistance(const MachineBasicBlock *From,
914 const MachineBasicBlock *To) const {
915 return getInterBlockDistance(From, To, true);
916 }
917
918 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
919 // Feature getters. Use cached results if available. If not calculate.
920 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
921private:
922 InstrIdTy getSize(const MachineBasicBlock *BB) const {
923 return pathInfoFor(BB, BB).Size;
924 }
925
926 bool isReachable(const MachineBasicBlock *From,
927 const MachineBasicBlock *To) const {
928 return pathInfoFor(From, To).Reachable;
929 }
930
931 bool isReachableOrSame(const MachineBasicBlock *From,
932 const MachineBasicBlock *To) const {
933 return From == To || pathInfoFor(From, To).Reachable;
934 }
935
936 bool isForwardReachable(const MachineBasicBlock *From,
937 const MachineBasicBlock *To) const {
938 const PathInfo &PI = pathInfoFor(From, To);
939 if (PI.isForwardReachableSet())
940 return PI.isForwardReachable();
941
942 return initializePathInfoForwardReachable(
943 From, To,
944 PI.Reachable && calcIsReachable(From, To, /*ForwardOnly*/ true));
945 }
946
947 // Return true/false if we know that 'To' is reachable or not from
948 // 'From'. Otherwise return 'std::nullopt'.
949 std::optional<bool> isMaybeReachable(const MachineBasicBlock *From,
950 const MachineBasicBlock *To,
951 bool ForwardOnly) const {
952 const PathInfo *PI = maybePathInfoFor(From, To);
953 if (!PI)
954 return std::nullopt;
955
956 if (ForwardOnly) {
957 if (PI->isForwardReachable())
958 return true;
959
960 if (PI->isNotForwardReachable())
961 return false;
962 return std::nullopt;
963 }
964 return PI->Reachable;
965 }
966
967 bool isBackedge(const MachineBasicBlock *From,
968 const MachineBasicBlock *To) const {
969 return pathInfoFor(From, To).isBackedge();
970 }
971
972 // Can be used as a substitute for DT->dominates(A, B) if A and B are in the
973 // same basic block.
974 bool instrsAreInOrder(const MachineInstr *A, const MachineInstr *B) const {
975 assert(A->getParent() == B->getParent() &&
976 "instructions must be in the same basic block!");
977 if (A == B || getInstrId(A) < getInstrId(B))
978 return true;
979 if (!A->isPHI())
980 return false;
981 if (!B->isPHI())
982 return true;
983 for (auto &PHI : A->getParent()->phis()) {
984 if (&PHI == A)
985 return true;
986 if (&PHI == B)
987 return false;
988 }
989 return false;
990 }
991
992 NextUseDistance getShortestPath(const MachineBasicBlock *From,
993 const MachineBasicBlock *To) const {
994 std::optional<NextUseDistance> MaybeD =
995 pathInfoFor(From, To).ShortestDistance;
996 if (MaybeD.has_value())
997 return MaybeD.value();
998
999 NextUseDistance Dist = getWeightedInterBlockDistance(From, To);
1000 return initializePathInfoShortestDistance(From, To, Dist);
1001 }
1002
1003 NextUseDistance getShortestUnweightedPath(const MachineBasicBlock *From,
1004 const MachineBasicBlock *To) const {
1005 std::optional<NextUseDistance> MaybeD =
1006 pathInfoFor(From, To).ShortestUnweightedDistance;
1007 if (MaybeD.has_value())
1008 return MaybeD.value();
1009
1010 return initializePathInfoShortestUnweightedDistance(
1011 From, To, getUnweightedInterBlockDistance(From, To));
1012 }
1013
1014 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1015 /// MBBDistPair - Represents the distance to a machine basic block.
1016 /// Used for returning both the distance and the target block together.
1017 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1018private:
1019 struct MBBDistPair {
1020 NextUseDistance Distance;
1021 const MachineBasicBlock *MBB;
1022 MBBDistPair() : Distance(NextUseDistance::unreachable()), MBB(nullptr) {}
1023 MBBDistPair(NextUseDistance D, const MachineBasicBlock *B)
1024 : Distance(D), MBB(B) {}
1025
1026 MBBDistPair operator+(NextUseDistance D) { return {Distance + D, MBB}; }
1027 MBBDistPair &operator+=(NextUseDistance D) {
1028 Distance += D;
1029 return *this;
1030 }
1031
1032 void print(raw_ostream &OS) const {
1033 OS << "{";
1034 Distance.print(OS);
1035 if (MBB)
1036 OS << " " << printMBBReference(*MBB);
1037 else
1038 OS << " <null>";
1039 OS << "}";
1040 }
1041
1042 LLVM_DUMP_METHOD void dump() const {
1043 print(dbgs());
1044 dbgs() << '\n';
1045 }
1046 };
1047
1048 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1049 // CFG Helpers
1050 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1051private:
1052 // Return the shortest distance to a latch
1053 MBBDistPair calcShortestDistanceToLatch(const MachineBasicBlock *CurMBB,
1054 const MachineLoop *CurLoop) const {
1056 CurLoop->getLoopLatches(Latches);
1057 MBBDistPair LD;
1058
1059 for (MachineBasicBlock *LMBB : Latches) {
1060 if (LMBB == CurMBB)
1061 return {0, CurMBB};
1062
1063 NextUseDistance Dst = getShortestPath(CurMBB, LMBB);
1064 if (Dst < LD.Distance) {
1065 LD.Distance = Dst;
1066 LD.MBB = LMBB;
1067 }
1068 }
1069 return LD;
1070 }
1071
1072 // Return the shortest unweighted distance to a latch
1073 MBBDistPair
1074 calcShortestUnweightedDistanceToLatch(const MachineBasicBlock *CurMBB,
1075 const MachineLoop *CurLoop) const {
1077 CurLoop->getLoopLatches(Latches);
1078 MBBDistPair LD;
1079
1080 for (MachineBasicBlock *LMBB : Latches) {
1081 if (LMBB == CurMBB)
1082 return {0, CurMBB};
1083
1084 NextUseDistance Dst = getShortestUnweightedPath(CurMBB, LMBB);
1085 if (Dst < LD.Distance) {
1086 LD.Distance = Dst;
1087 LD.MBB = LMBB;
1088 }
1089 }
1090 return LD;
1091 }
1092
1093 // Return the shortest distance to an exit
1094 MBBDistPair calcShortestDistanceToExit(const MachineBasicBlock *CurMBB,
1095 const MachineLoop *CurLoop) const {
1097 MLI->getExitEdges(*CurLoop, ExitEdges);
1098 MBBDistPair LD;
1099
1100 for (auto [Exit, Dest] : ExitEdges) {
1101 if (Exit == CurMBB)
1102 return {0, CurMBB};
1103
1104 NextUseDistance Dst = getShortestPath(CurMBB, Exit);
1105 if (Dst < LD.Distance) {
1106 LD.Distance = Dst;
1107 LD.MBB = Exit;
1108 }
1109 }
1110 return LD;
1111 }
1112
1113 // Return the shortest distance through a loop (header to latch) that goes
1114 // through CurMBB.
1115 MBBDistPair
1116 calcShortestDistanceThroughInnermostLoop(const MachineBasicBlock *CurMBB,
1117 MachineLoop *CurLoop) const {
1118 assert(MLI->getLoopFor(CurMBB) == CurLoop);
1119
1120 // This is a hot spot. Check it before doing anything else.
1121 if (CurLoop->getNumBlocks() == 1)
1122 return {getSize(CurMBB), CurMBB};
1123
1124 MachineBasicBlock *LoopHeader = CurLoop->getHeader();
1125 MBBDistPair LD{0, nullptr};
1126
1127 LD += getSize(LoopHeader);
1128
1129 if (CurMBB != LoopHeader)
1130 LD += getShortestPath(LoopHeader, CurMBB);
1131
1132 if (CurLoop->isLoopExiting(CurMBB))
1133 LD.MBB = CurMBB;
1134 else
1135 LD = calcShortestDistanceToExit(CurMBB, CurLoop) + LD.Distance;
1136
1137 if (CurMBB != LoopHeader && CurMBB != LD.MBB)
1138 LD += getSize(CurMBB);
1139
1140 if (LD.MBB != LoopHeader)
1141 LD += getSize(LD.MBB);
1142
1143 return LD;
1144 }
1145
1146 // Return the shortest distance through a loop (header to latch) that goes
1147 // through CurMBB.
1148 MBBDistPair calcShortestDistanceThroughLoop(const MachineBasicBlock *CurMBB,
1149 MachineLoop *OuterLoop) const {
1150 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1151 MBBDistPair CurLD =
1152 calcShortestDistanceThroughInnermostLoop(CurMBB, CurLoop);
1153
1154 MachineBasicBlock *CurHdr = CurLoop->getHeader();
1155 for (;;) {
1156 if (OuterLoop == CurLoop)
1157 return CurLD;
1158
1159 MachineLoop *ParentLoop = CurLoop->getParentLoop();
1160 MachineBasicBlock *ParentHdr = ParentLoop->getHeader();
1161
1162 MBBDistPair LD{0, nullptr};
1163 LD += getSize(ParentHdr);
1164 LD += getShortestPath(ParentHdr, CurHdr);
1165 LD += CurLD.Distance.applyLoopWeight();
1166 LD = calcShortestDistanceToExit(CurLD.MBB, ParentLoop) + LD.Distance;
1167 LD += getSize(LD.MBB);
1168 CurLD = LD;
1169 CurLoop = ParentLoop;
1170 CurHdr = ParentHdr;
1171 }
1172 llvm_unreachable("CurMBB not contained in OuterLoop");
1173 }
1174
1175 // Similar to calcShortestDistanceThroughLoop with LoopWeight applied to the
1176 // returned distance.
1177 MBBDistPair
1178 calcWeightedDistanceThroughLoopViaMBB(const MachineBasicBlock *CurMBB,
1179 MachineLoop *CurLoop) const {
1180 MBBDistPair LD = calcShortestDistanceThroughLoop(CurMBB, CurLoop);
1181 LD.Distance = LD.Distance.applyLoopWeight();
1182 return LD;
1183 }
1184
1185 // Return the weighted, shortest distance through a loop (header to latch).
1186 // If ParentLoop is provided, use it to adjust the loop depth.
1187 MBBDistPair calcWeightedDistanceThroughLoop(
1188 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1189 const MachineLoop *ParentLoop = nullptr) const {
1190 if (CurLoop->getNumBlocks() != 1)
1191 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1192
1193 unsigned LoopDepth = MLI->getLoopDepth(CurMBB);
1194 if (ParentLoop)
1195 LoopDepth -= ParentLoop->getLoopDepth();
1196
1197 return {NextUseDistance::fromSize(getSize(CurMBB), LoopDepth),
1198 CurLoop->getLoopLatch()};
1199 }
1200
1201 // Calculate total distance from exit point to use instruction
1202 NextUseDistance appendDistanceToUse(const MBBDistPair &Exit,
1203 const MachineInstr *UseMI,
1204 const MachineBasicBlock *UseMBB) const {
1205 return Exit.Distance + getShortestPath(Exit.MBB, UseMBB) +
1206 getHeadLen(UseMI);
1207 }
1208
1209 // Return the weighted, shortest distance through the CurLoop which is a
1210 // sub-loop of UseLoop.
1211 MBBDistPair calcDistanceThroughSubLoopUse(const MachineBasicBlock *CurMBB,
1212 MachineLoop *CurLoop,
1213 MachineLoop *UseLoop) const {
1214 // All the sub-loops of the UseLoop will be executed before the use.
1215 // Hence, we should take this into consideration in distance calculation.
1216 MachineLoop *UseLoopSubLoop = findChildLoop(UseLoop, CurLoop);
1217 assert(UseLoopSubLoop && "CurLoop should be nested in UseLoop");
1218 return calcWeightedDistanceThroughLoop(CurMBB, UseLoopSubLoop, UseLoop);
1219 }
1220
1221 // Similar to calcDistanceThroughSubLoopUse, adding the distance to 'UseMI'.
1222 NextUseDistance calcDistanceThroughSubLoopToUseMI(
1223 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1224 const MachineInstr *UseMI, const MachineBasicBlock *UseMBB,
1225 MachineLoop *UseLoop) const {
1226 return appendDistanceToUse(
1227 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop), UseMI, UseMBB);
1228 }
1229
1230 // Return the weighted distance through a loop to an outside use loop.
1231 // Differentiates between uses inside or outside of the current loop nest.
1232 MBBDistPair calcDistanceThroughLoopToOutsideLoopUse(
1233 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1234 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop) const {
1235 assert(!CurLoop->contains(UseLoop));
1236
1237 if (isStandAloneLoop(CurLoop))
1238 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, CurLoop);
1239
1240 MachineLoop *OutermostLoop = CurLoop->getOutermostLoop();
1241 if (!OutermostLoop->contains(UseLoop)) {
1242 // We should take into consideration the whole loop nest in the
1243 // calculation of the distance because we will reach the use after
1244 // executing the whole loop nest.
1245
1246 // ... But make sure that we pick a route that goes through CurMBB
1247 return calcWeightedDistanceThroughLoopViaMBB(CurMBB, OutermostLoop);
1248 }
1249
1250 // At this point we know that CurLoop and UseLoop are independent and they
1251 // are in the same loop nest.
1252
1253 if (MLI->getLoopDepth(CurMBB) <= MLI->getLoopDepth(UseMBB))
1254 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1255
1256 assert(CurLoop != OutermostLoop && "The loop cannot be the outermost.");
1257 const unsigned UseLoopDepth = MLI->getLoopDepth(UseMBB);
1258 for (;;) {
1259 if (CurLoop->getLoopDepth() == UseLoopDepth)
1260 break;
1261 CurLoop = CurLoop->getParentLoop();
1262 if (CurLoop == OutermostLoop)
1263 break;
1264 }
1265 return calcWeightedDistanceThroughLoop(CurMBB, CurLoop);
1266 }
1267
1268 // Similar to calcDistanceThroughLoopToOutsideLoopUse but adds the distance to
1269 // an instruction in the loop.
1270 NextUseDistance calcDistanceThroughLoopToOutsideLoopUseMI(
1271 const MachineBasicBlock *CurMBB, MachineLoop *CurLoop,
1272 const MachineInstr *UseMI, const MachineBasicBlock *UseMBB,
1273 MachineLoop *UseLoop) const {
1274 return appendDistanceToUse(calcDistanceThroughLoopToOutsideLoopUse(
1275 CurMBB, CurLoop, UseMBB, UseLoop),
1276 UseMI, UseMBB);
1277 }
1278
1279 // Return true if 'MO' is covered by 'LaneMask'
1280 bool machineOperandCoveredBy(const MachineOperand &MO,
1281 LaneBitmask LaneMask) const {
1282 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(MO.getSubReg());
1283 return (Mask & LaneMask) == Mask;
1284 }
1285
1286 // Returns true iff uses of LiveReg/LiveLaneMask in PHI UseMI are coming from
1287 // a backedge when starting at CurMI.
1288 bool isIncomingValFromBackedge(Register LiveReg, LaneBitmask LiveLaneMask,
1289 const MachineInstr *CurMI,
1290 const MachineInstr *UseMI) const {
1291 if (!UseMI->isPHI())
1292 return false;
1293
1294 MachineLoop *CurLoop = MLI->getLoopFor(CurMI->getParent());
1295 MachineLoop *UseLoop = MLI->getLoopFor(UseMI->getParent());
1296
1297 // Not a backedge if ...
1298 // A: not in a loop at all
1299 // B: or CurMI is in a loop outside of UseLoop
1300 // C: or UseMI is not in the UseLoop header
1301 if (/*A:*/ !UseLoop ||
1302 /*B:*/ (CurLoop && !UseLoop->contains(CurLoop)) ||
1303 /*C:*/ UseMI->getParent() != UseLoop->getHeader())
1304 return false;
1305
1307 UseLoop->getLoopLatches(Latches);
1308
1309 const unsigned NumOps = UseMI->getNumOperands();
1310 for (unsigned I = 1; I < NumOps; I += 2) {
1311 const MachineOperand &RegMO = UseMI->getOperand(I - 1);
1312 const MachineOperand &MBBMO = UseMI->getOperand(I);
1313 assert(RegMO.isReg() && "Expected register operand of PHI");
1314 assert(MBBMO.isMBB() && "Expected MBB operand of PHI");
1315 if (RegMO.getReg() == LiveReg &&
1316 machineOperandCoveredBy(RegMO, LiveLaneMask)) {
1317 MachineBasicBlock *IncomingBB = MBBMO.getMBB();
1318 if (llvm::is_contained(Latches, IncomingBB))
1319 return true;
1320 }
1321 }
1322 return false;
1323 }
1324
1325 // Return the distance from 'CurMI' through a parent loop backedge PHI Use
1326 // ('UseMI').
1327 CacheableNextUseDistance calcDistanceViaEnclosingBackedge(
1328 const MachineInstr *CurMI, const MachineBasicBlock *CurMBB,
1329 MachineLoop *CurLoop, const MachineInstr *UseMI,
1330 const MachineBasicBlock *UseMBB, MachineLoop *UseLoop) const {
1331 assert(UseLoop && "There is no backedge.");
1332 assert(CurLoop && (UseLoop != CurLoop) && UseLoop->contains(CurLoop) &&
1333 "Unexpected loop configuration");
1334
1335 InstrIdTy UseHeadLen = getHeadLen(UseMI);
1336 MBBDistPair InnerLoopLD =
1337 calcDistanceThroughSubLoopUse(CurMBB, CurLoop, UseLoop);
1338 MBBDistPair LD = calcShortestDistanceToLatch(InnerLoopLD.MBB, UseLoop);
1339 return {InstrInvariant,
1340 InnerLoopLD.Distance + LD.Distance + getSize(LD.MBB) + UseHeadLen};
1341 }
1342
1343 // Optimized version of calcBackedgeDistance when we already know that CurMI
1344 // and UseMI are in the same basic block
1345 NextUseDistance calcBackedgeDistance(const MachineInstr *CurMI,
1346 const MachineBasicBlock *CurMBB,
1347 MachineLoop *CurLoop,
1348 const MachineInstr *UseMI) const {
1349 // use is in the next loop iteration
1350 InstrIdTy CurTailLen = getTailLen(CurMI);
1351 InstrIdTy UseHeadLen = getHeadLen(UseMI);
1352 MBBDistPair LD = calcShortestUnweightedDistanceToLatch(CurMBB, CurLoop);
1353 const MachineBasicBlock *HdrMBB = CurLoop->getHeader();
1354 NextUseDistance Hdr = CurMBB == HdrMBB ? 0 : getSize(HdrMBB);
1355 NextUseDistance Dst =
1356 CurMBB == HdrMBB ? 0 : getShortestUnweightedPath(HdrMBB, CurMBB);
1357
1358 return CurTailLen + LD.Distance + getSize(LD.MBB) + Hdr + Dst + UseHeadLen;
1359 }
1360
1361 //----------------------------------------------------------------------------
1362 // Calculate inter-instruction distances
1363 //----------------------------------------------------------------------------
1364private:
1365 // Calculate the shortest weighted path from MachineInstruction 'FromMI' to
1366 // 'ToMI'. It is weighted distance in that paths that exit loops are made to
1367 // look much further away.
1368 NextUseDistance calcShortestDistance(const MachineInstr *FromMI,
1369 const MachineInstr *ToMI) const {
1370 const MachineBasicBlock *FromMBB = FromMI->getParent();
1371 const MachineBasicBlock *ToMBB = ToMI->getParent();
1372
1373 if (FromMBB == ToMBB) {
1374 NextUseDistance RV = getDistance(FromMI, ToMI);
1375 assert(RV >= 0 && "unexpected negative distance from getDistance");
1376 return RV;
1377 }
1378
1379 InstrIdTy FromTailLen = getTailLen(FromMI);
1380 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1381 NextUseDistance Dst = getShortestPath(FromMBB, ToMBB);
1382 assert(Dst.isReachable() &&
1383 "calcShortestDistance called for instructions in non-reachable"
1384 " basic blocks!");
1385 NextUseDistance RV = FromTailLen + Dst + ToHeadLen;
1386 assert(RV >= 0 && "unexpected negative distance");
1387 return RV;
1388 }
1389
1390 // Calculate the shortest unweighted path from MachineInstruction 'FromMI' to
1391 // 'ToMI'. In contrast with 'calcShortestDistance', distances are based solely
1392 // on basic block instruction counts and traversing a loop exit does not
1393 // affect the value.
1394 NextUseDistance
1395 calcShortestUnweightedDistance(const MachineInstr *FromMI,
1396 const MachineInstr *ToMI) const {
1397 const MachineBasicBlock *FromMBB = FromMI->getParent();
1398 const MachineBasicBlock *ToMBB = ToMI->getParent();
1399
1400 if (FromMBB == ToMBB)
1401 return getDistance(FromMI, ToMI);
1402
1403 InstrIdTy FromTailLen = getTailLen(FromMI);
1404 InstrIdTy ToHeadLen = getHeadLen(ToMI);
1405 NextUseDistance Dst = getShortestUnweightedPath(FromMBB, ToMBB);
1406 assert(Dst.isReachable() &&
1407 "calcShortestUnweightedDistance called for instructions in"
1408 " non-reachable basic blocks!");
1409 return FromTailLen + Dst + ToHeadLen;
1410 }
1411
1412 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1413 // calcDistanceToUse* - various flavors of calculating the distance from an
1414 // instruction 'CurMI' to the use of a live [sub]register.
1415 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1416private:
1417 // Return the distance from 'CurMI' to a live [sub]register use ('UseMI').
1418 //
1419 // Cfg flags controlling behavior:
1420 // PreciseUseModeling — rewrite PHI uses to their incoming edge block;
1421 // also selects unweighted cross-block distance
1422 // PromoteToPreheader — route loop-entry / inner-loop uses to the preheader
1424 calcDistanceToUse(Register LiveReg, LaneBitmask LiveLaneMask,
1425 const MachineInstr &CurMI,
1426 const MachineOperand *UseMO) const {
1427 const MachineInstr *UseMI = UseMO->getParent();
1428 const MachineBasicBlock *CurMBB = CurMI.getParent();
1429 const MachineBasicBlock *UseMBB = UseMI->getParent();
1430 MachineLoop *CurLoop = MLI->getLoopFor(CurMBB);
1431 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1432
1433 if (Cfg.PreciseUseModeling) {
1434 // Map PHI use to the end of its incoming edge block.
1435 if (auto *PhiUseEdge = getIncomingBlockIfPhiUse(UseMI, UseMO)) {
1436 UseMI = &PhiUseEdge->back();
1437 UseMBB = PhiUseEdge;
1438 UseLoop = MLI->getLoopFor(PhiUseEdge);
1439 }
1440 }
1441
1442 enum class LoopConfig {
1443 NoCur,
1444 Same,
1445 CurContainsUse,
1446 UseContainsCur,
1447 Siblings,
1448 Unrelated
1449 };
1450 auto [LpCfg, PreHdr, CommonParent] = [&]()
1451 -> std::tuple<LoopConfig, const MachineBasicBlock *, MachineLoop *> {
1452 if (!CurLoop) {
1453 return {LoopConfig::NoCur, getOutermostPreheader(UseLoop), nullptr};
1454 }
1455 if (CurLoop->contains(UseLoop)) {
1456 return {CurMBB == UseMBB ? LoopConfig::Same
1457 : LoopConfig::CurContainsUse,
1458 findChildPreheader(CurLoop, UseLoop), nullptr};
1459 }
1460
1461 if (MachineLoop *P = findCommonParent(UseLoop, CurLoop).first) {
1462 if (P != UseLoop)
1463 return {LoopConfig::Siblings, findChildPreheader(P, UseLoop), P};
1464 return {LoopConfig::UseContainsCur, nullptr, nullptr};
1465 }
1466 return {LoopConfig::Unrelated, getOutermostPreheader(UseLoop), nullptr};
1467 }();
1468
1469 //--------------------------------------------------------------------------
1470 // Don't PromoteToPreheader
1471 //--------------------------------------------------------------------------
1472 if (!Cfg.PromoteToPreheader) {
1473 switch (LpCfg) {
1474 case LoopConfig::NoCur:
1475 case LoopConfig::Same:
1476 case LoopConfig::CurContainsUse:
1477 return {InstrRelative, calcShortestDistance(&CurMI, UseMI)};
1478
1479 case LoopConfig::UseContainsCur: {
1480 if (isIncomingValFromBackedge(LiveReg, LiveLaneMask, &CurMI, UseMI)) {
1481 return calcDistanceViaEnclosingBackedge(&CurMI, CurMBB, CurLoop,
1482 UseMI, UseMBB, UseLoop);
1483 }
1484
1485 return {InstrInvariant, calcDistanceThroughSubLoopToUseMI(
1486 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1487 }
1488 case LoopConfig::Siblings:
1489 case LoopConfig::Unrelated:
1490 return {InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1491 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1492 }
1493 llvm_unreachable("unexpected loop configuration!");
1494 }
1495
1496 //--------------------------------------------------------------------------
1497 // PromoteToPreheader
1498 //--------------------------------------------------------------------------
1499 if (PreHdr) {
1500 UseMI = &PreHdr->back();
1501 UseMBB = PreHdr;
1502 UseLoop = CommonParent;
1503 }
1504
1505 switch (LpCfg) {
1506 case LoopConfig::NoCur:
1507 return {InstrRelative, calcShortestUnweightedDistance(&CurMI, UseMI) -
1508 (sizeOf(*UseMI) ? 0 : 1)};
1509
1510 case LoopConfig::Same:
1511 case LoopConfig::CurContainsUse:
1512 if (CurMBB == UseMBB && !instrsAreInOrder(&CurMI, UseMI))
1513 return {InstrRelative,
1514 calcBackedgeDistance(&CurMI, CurMBB, CurLoop, UseMI)};
1515
1516 return {InstrRelative, calcShortestUnweightedDistance(&CurMI, UseMI)};
1517
1518 case LoopConfig::UseContainsCur:
1519 case LoopConfig::Siblings:
1520 return {InstrInvariant, calcDistanceThroughSubLoopToUseMI(
1521 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1522
1523 case LoopConfig::Unrelated:
1524 return {InstrInvariant, calcDistanceThroughLoopToOutsideLoopUseMI(
1525 CurMBB, CurLoop, UseMI, UseMBB, UseLoop)};
1526 }
1527 llvm_unreachable("unexpected loop configuration!");
1528 }
1529
1530 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1531 // getUses helpers (compute mode)
1532 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1533private:
1534 // Returns true if Use is reachable from MI. Handles backedges and intervening
1535 // defs.
1536 bool isUseReachablePrecise(const MachineInstr &MI,
1537 const MachineBasicBlock *MBB,
1538 const MachineOperand *UseMO,
1539 const MachineInstr *UseMI,
1540 const MachineBasicBlock *UseMBB) const {
1541
1542 // Filter out uses that are clearly unreachable
1543 if (MBB != UseMBB && !isReachable(MBB, UseMBB))
1544 return false;
1545
1546 // PHI uses are considered part of the incoming BB. Check for reachability
1547 // at the edge.
1548 if (auto *PhiUseEdge = getIncomingBlockIfPhiUse(UseMI, UseMO)) {
1549 if (!isReachableOrSame(MBB, PhiUseEdge))
1550 return false;
1551 }
1552
1553 // Filter out uses with an intermediate def.
1554 const MachineInstr *DefMI = MRI->getUniqueVRegDef(UseMO->getReg());
1555 const MachineBasicBlock *DefMBB = DefMI->getParent();
1556 if (MBB == UseMBB) {
1557 if (UseMI->isPHI() && MBB == DefMBB)
1558 return true;
1559
1560 if (instrsAreInOrder(&MI, UseMI))
1561 return true;
1562
1563 // A Def in the loop means that the value at MI will not survive through
1564 // to this use.
1565 MachineLoop *UseLoop = MLI->getLoopFor(UseMBB);
1566 return UseLoop && !UseLoop->contains(DefMBB);
1567 }
1568
1569 if (MBB == DefMBB)
1570 return instrsAreInOrder(DefMI, &MI);
1571
1572 MachineLoop *Loop = MLI->getLoopFor(MBB);
1573 if (!Loop)
1574 return true;
1575
1576 MachineLoop *TopLoop = Loop->getOutermostLoop();
1577 return !TopLoop->contains(DefMBB) || !isReachable(MBB, DefMBB) ||
1578 !isForwardReachable(UseMBB, MBB);
1579 }
1580
1581 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1582 // Debug/Developer Helpers
1583 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1584private:
1585 void printPaths(raw_ostream &OS) const {
1586 OS << "\n---------------- Paths --------------- {\n";
1587 for (const auto &[P, PI] : Paths) {
1588 OS << " " << printMBBReference(*P.src()) << " -> "
1589 << printMBBReference(*P.dst()) << ": ";
1590 PI.print(OS);
1591 OS << '\n';
1592 }
1593 OS << "}\n";
1594 }
1595
1596 LLVM_DUMP_METHOD void dumpPaths() const { printPaths(dbgs()); }
1597
1598 void printInterBlockDistances(raw_ostream &OS) const {
1599 using MBBPair = std::pair<unsigned, unsigned>;
1600 using Elem = std::pair<NextUseDistance, MBBPair>;
1601 std::vector<Elem> SortedDistances;
1602
1603 for (const auto &[FromNum, Dsts] : InterBlockDistances) {
1604 for (const auto &[ToNum, Dist] : Dsts) {
1605 SortedDistances.emplace_back(Dist.Weighted, MBBPair(FromNum, ToNum));
1606 }
1607 }
1608 llvm::sort(SortedDistances, [](const auto &A, const auto &B) {
1609 if (A.first != B.first)
1610 return A.first < B.first;
1611
1612 if (A.second.first != B.second.first)
1613 return A.second.first < B.second.first;
1614
1615 return A.second.second < B.second.second;
1616 });
1617
1618 OS << "\n--------- InterBlockDistances -------- {\n";
1619 for (const Elem &E : SortedDistances) {
1620
1621 OS << " bb." << E.second.first << " -> bb." << E.second.second << ": ";
1622 E.first.print(OS);
1623 OS << '\n';
1624 }
1625 OS << "}\n";
1626 }
1627
1628 LLVM_DUMP_METHOD void dumpInterBlockDistances() const {
1629 printInterBlockDistances(dbgs());
1630 }
1631
1632 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1633 // LiveRegUse Caching - A cache of the distances for the last
1634 // MachineInstruction. When getting the distances for a MachineInstruction, if
1635 // it is the same basic block as the cached instruction, we can generally use
1636 // an offset from the cached values to compute the distances. There are some
1637 // exceptions - see 'cacheLiveRegUse'.
1638 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1639private:
1640 struct LiveRegToUseMapElem {
1641 LiveRegUse Use;
1642 bool MIDependent;
1643 LiveRegToUseMapElem() : Use(), MIDependent(false) {}
1644 LiveRegToUseMapElem(LiveRegUse U, bool MIDep)
1645 : Use(U), MIDependent(MIDep) {}
1646
1647 void print(raw_ostream &OS) const {
1648 Use.print(OS);
1649 OS << (MIDependent ? " [mi-dep]" : " [mi-indep]");
1650 }
1651
1652 LLVM_DUMP_METHOD void dump() const {
1653 print(dbgs());
1654 dbgs() << '\n';
1655 }
1656 };
1657
1658 // Using std::map because LaneBitmask does not work out-of-the-box as a
1659 // DenseMap key and I did not see a performance benefit over std::map.
1660 using LaneBitmaskToUseMap = std::map<LaneBitmask, LiveRegToUseMapElem>;
1661 using LiveRegToUseMap = DenseMap<Register, LaneBitmaskToUseMap>;
1662
1663 const MachineInstr *CachedDistancesMI = nullptr;
1664 LiveRegToUseMap CachedDistances;
1665 LiveRegToUseMap PendingCachedDistances;
1666 unsigned DistanceCacheHits = 0;
1667 unsigned DistanceCacheMisses = 0;
1668
1669 void resetDistanceCache() {
1670 CachedDistancesMI = nullptr;
1671 CachedDistances.clear();
1672 DistanceCacheHits = 0;
1673 DistanceCacheMisses = 0;
1674 }
1675
1676 void maybeClearCachedLiveRegUses(const MachineInstr &MI) {
1677 if (CachedDistancesMI &&
1678 (CachedDistancesMI->getParent() != MI.getParent() ||
1679 !instrsAreInOrder(CachedDistancesMI, &MI))) {
1680 CachedDistancesMI = nullptr;
1681 CachedDistances.clear();
1682 }
1683 }
1684
1685 bool okToUseCacheElem(const LiveRegToUseMapElem &CacheElem,
1686 const MachineInstr &MI, const InstrIdTy LastDelta) {
1687 if (!CacheElem.MIDependent)
1688 return true;
1689
1690 const LiveRegUse &U = CacheElem.Use;
1691
1692 // Never okay to produce a negative distance
1693 if (U.Dist < LastDelta)
1694 return false;
1695
1696 const MachineInstr *UseMI = U.Use->getParent();
1697
1698 // Always okay if use is in another basic block or UseMI is MI
1699 if (UseMI->getParent() != MI.getParent() || UseMI == &MI)
1700 return true;
1701
1702 // If CachedDistancesMI <= Use < MI we could have a problem since we don't
1703 // know if Use is still reachable.
1704 return !instrsAreInOrder(CachedDistancesMI, UseMI) ||
1705 !instrsAreInOrder(UseMI, &MI);
1706 }
1707
1708 std::pair<const LaneBitmaskToUseMap *, const LiveRegToUseMapElem *>
1709 findCachedLiveRegUse(Register Reg, LaneBitmask LaneMask,
1710 const MachineInstr &MI, const InstrIdTy LastDelta) {
1711 if (!DistanceCacheEnabled)
1712 return {nullptr, nullptr};
1713
1714 ++DistanceCacheMisses; // Assume miss
1715 auto I = CachedDistances.find(Reg);
1716 if (I == CachedDistances.end())
1717 return {nullptr, nullptr};
1718 const LaneBitmaskToUseMap &RegSlot = I->second;
1719 if (RegSlot.empty())
1720 return {nullptr, nullptr};
1721
1722 auto J = RegSlot.find(LaneMask);
1723 if (J == RegSlot.end())
1724 return {nullptr, nullptr};
1725
1726 const LiveRegToUseMapElem &MaskSlot = J->second;
1727 if (!okToUseCacheElem(MaskSlot, MI, LastDelta))
1728 return {nullptr, nullptr};
1729
1730 --DistanceCacheMisses;
1731 ++DistanceCacheHits;
1732 return {&RegSlot, &MaskSlot};
1733 }
1734
1735 void cacheLiveRegUse(const MachineInstr &MI, Register Reg, LaneBitmask Mask,
1736 LiveRegUse U, bool MIDependent) {
1737 if (!DistanceCacheEnabled)
1738 return;
1739
1740 auto I = PendingCachedDistances.try_emplace(Reg).first;
1741 LaneBitmaskToUseMap &RegSlot = I->second;
1742 RegSlot.try_emplace(Mask, U, MIDependent);
1743 }
1744
1745 void updateCachedLiveRegUses(const MachineInstr &MI) {
1746 if (!DistanceCacheEnabled)
1747 return;
1748
1749 CachedDistancesMI = &MI;
1750 CachedDistances = std::move(PendingCachedDistances);
1751 PendingCachedDistances.clear();
1752 LLVM_DEBUG(dumpDistanceCache());
1753 }
1754
1755 void printDistanceCache(raw_ostream &OS) const {
1756 OS << "\n----------- Distance Cache ----------- {\n";
1757 OS << " CachedAt: ";
1758 if (CachedDistancesMI)
1759 OS << *CachedDistancesMI;
1760 else
1761 OS << "<none>\n";
1762
1763 constexpr size_t RegNameWidth = 20;
1764 for (const auto &[Reg, ByMask] : CachedDistances) {
1765 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
1766 LaneBitmask AllLanes = MRI->getMaxLaneMaskForVReg(Reg);
1767
1768 for (const auto &[Mask, Elem] : ByMask) {
1769 std::string RegName;
1770 raw_string_ostream KOS(RegName);
1771 if (Mask == AllLanes) {
1772 KOS << printReg(Reg);
1773 } else {
1774 SmallVector<unsigned> Indexes;
1775 TRI->getCoveringSubRegIndexes(RC, Mask, Indexes);
1776 if (Indexes.size() == 1)
1777 KOS << printReg(Reg, TRI, Indexes.front(), MRI);
1778 else
1779 KOS << printReg(Reg) << " mask=" << Mask.getAsInteger();
1780 }
1781 OS << " " << left_justify(RegName, RegNameWidth) << " : ";
1782 Elem.print(OS);
1783 OS << '\n';
1784 }
1785 }
1786 OS << " (hits=" << DistanceCacheHits << " misses=" << DistanceCacheMisses
1787 << ")\n";
1788 OS << "}\n";
1789 }
1790
1791 LLVM_DUMP_METHOD void dumpDistanceCache() const {
1792 printDistanceCache(dbgs());
1793 }
1794
1795 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1796 // Processing Live Reg Uses
1797 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1798private:
1799 // Decompose each use in 'Uses' by sub-reg and store the nearest one in
1800 // 'UseByMask'. Ignores subregs matching 'LiveRegLaneMask' - these are handled
1801 // as registers, not sub-regs.
1802 DenseMap<const TargetRegisterClass *, SmallVector<unsigned>>
1803 SubRegIndexesForRegClass;
1804 void collectSubRegUsesByMask(
1805 const SmallVectorImpl<const MachineOperand *> &Uses,
1806 const SmallVectorImpl<CacheableNextUseDistance> &Distances,
1807 LaneBitmask LiveRegLaneMask, LaneBitmaskToUseMap &UseByMask) {
1808
1809 assert(Uses.size());
1810 assert(Uses.size() == Distances.size());
1811
1812 const TargetRegisterClass *RC = MRI->getRegClass(Uses.front()->getReg());
1813 auto [SRI, Inserted] = SubRegIndexesForRegClass.try_emplace(RC);
1814 if (Inserted)
1815 TRI->getCoveringSubRegIndexes(RC, LaneBitmask::getAll(), SRI->second);
1816 const SmallVector<unsigned> &RCSubRegIndexes = SRI->second;
1817
1818 unsigned OneIndex; // Backing store for 'Indexes' below when 1 index
1819 for (size_t I = 0; I < Uses.size(); ++I) {
1820 const MachineOperand *MO = Uses[I];
1821 auto [SubRegMIDep, Dist] = Distances[I];
1822 const LiveRegUse LRU{MO, Dist};
1823
1824 ArrayRef<unsigned> Indexes;
1825 if (MO->getSubReg()) {
1826 OneIndex = MO->getSubReg();
1827 Indexes = ArrayRef(OneIndex);
1828 } else {
1829 Indexes = RCSubRegIndexes;
1830 }
1831
1832 for (unsigned Idx : Indexes) {
1833 LaneBitmask Mask = TRI->getSubRegIndexLaneMask(Idx);
1834 if (Mask.all() || Mask == LiveRegLaneMask)
1835 continue;
1836
1837 auto &[SlotU, SlotMIDep] = UseByMask[Mask];
1838 if (updateClosest(SlotU, LRU))
1839 SlotMIDep = SubRegMIDep;
1840 }
1841 }
1842 }
1843
1844 // Similar to 'collectSubRegUsesByMask' above, but uses cached distances.
1845 void collectSubRegUsesByMaskFromCache(const LaneBitmaskToUseMap &CachedMap,
1846 LaneBitmask LiveRegLaneMask,
1847 const MachineInstr *MI,
1848 InstrIdTy LastDelta,
1849 LaneBitmaskToUseMap &UseByMask) {
1850
1851 for (const auto &KV : CachedMap) {
1852 LaneBitmask SubregLaneMask = KV.first;
1853 if (SubregLaneMask.all() || SubregLaneMask == LiveRegLaneMask)
1854 continue;
1855
1856 const LiveRegToUseMapElem &SubregE = KV.second;
1857 if (!okToUseCacheElem(SubregE, *MI, LastDelta))
1858 continue;
1859
1860 const bool MIDep = SubregE.MIDependent;
1861 LiveRegUse U = SubregE.Use;
1862 if (MIDep)
1863 U.Dist -= LastDelta;
1864
1865 auto &[SlotU, SlotMIDep] = UseByMask[SubregLaneMask];
1866 if (updateClosest(SlotU, U))
1867 SlotMIDep = MIDep;
1868 }
1869 }
1870
1871 // Loops through 'UseByMask' finding the furthest sub-register and updating
1872 // 'FurthestSubreg' accordingly.
1873 void updateFurthestSubReg(
1874 const MachineInstr &MI, const LiveRegUse &U,
1875 const LaneBitmaskToUseMap &UseByMask,
1876 DenseMap<const MachineOperand *, UseDistancePair> *RelevantUses,
1877 LiveRegUse &FurthestSubreg) {
1878
1879 if (UseByMask.empty()) {
1880 updateFurthest(FurthestSubreg, U);
1881 return;
1882 }
1883
1884 for (const auto &KV : UseByMask) {
1885 const LiveRegUse &SubregU = KV.second.Use;
1886 const bool SubregMIDep = KV.second.MIDependent;
1887
1888 if (RelevantUses)
1889 RelevantUses->try_emplace(SubregU.Use, SubregU);
1890 cacheLiveRegUse(MI, SubregU.Use->getReg(), KV.first, SubregU,
1891 SubregMIDep);
1892 updateFurthest(FurthestSubreg, SubregU);
1893 }
1894 }
1895
1896 // Used to populate 'MIDefs' to be passed to 'getNextUseDistances'.
1897 SmallSet<Register, 4> collectDefinedRegisters(const MachineInstr &MI) const {
1898 SmallSet<Register, 4> MIDefs;
1899
1900 for (const MachineOperand &MO : MI.all_defs()) {
1901 if (MO.isReg() && MO.getReg().isValid() && hasAtLeastOneUse(MO.getReg()))
1902 MIDefs.insert(MO.getReg());
1903 }
1904 return MIDefs;
1905 }
1906
1907 // Computes distances from 'MI' to each registers in 'LiveRegs'. Returns the
1908 // furthest register and (optionally) sub-register in 'Furthest' and
1909 // 'FurthestSubreg' respectively.
1910public:
1912 const MachineInstr &MI, LiveRegUse &Furthest,
1913 LiveRegUse *FurthestSubreg = nullptr,
1915 *RelevantUses = nullptr) {
1916 const SmallSet<Register, 4> MIDefs(collectDefinedRegisters(MI));
1917
1920 LaneBitmaskToUseMap UseByMask;
1921
1922 maybeClearCachedLiveRegUses(MI);
1923 const InstrIdTy LastDelta =
1924 CachedDistancesMI ? getDistance(CachedDistancesMI, &MI) : 0;
1925
1926 for (auto &KV : LiveRegs) {
1927 const Register Reg = KV.first;
1928 const LaneBitmask LaneMask = KV.second;
1929
1930 if (MIDefs.contains(Reg))
1931 continue;
1932
1933 Uses.clear();
1934 UseByMask.clear();
1935
1936 LiveRegUse U;
1937 bool MIDependent = false;
1938 auto [CacheMap, CacheElem] =
1939 findCachedLiveRegUse(Reg, LaneMask, MI, LastDelta);
1940 if (CacheMap && CacheElem) {
1941 MIDependent = CacheElem->MIDependent;
1942 U = CacheElem->Use;
1943 if (MIDependent)
1944 U.Dist -= LastDelta;
1945 } else {
1946 getReachableUses(Reg, LaneMask, MI, Uses);
1947 if (Uses.empty())
1948 continue;
1949
1950 const MachineOperand *NextUse = nullptr;
1952 Reg, LaneMask, MI, Uses, &NextUse, &MIDependent, &Distances);
1953 U = LiveRegUse{NextUse, Dist};
1954 }
1955
1956 if (RelevantUses)
1957 RelevantUses->try_emplace(U.Use, U);
1958 cacheLiveRegUse(MI, Reg, LaneMask, U, MIDependent);
1959
1960 updateFurthest(Furthest, U);
1961
1962 if (!FurthestSubreg)
1963 continue;
1964
1965 if (CacheMap) {
1966 collectSubRegUsesByMaskFromCache(*CacheMap, LaneMask, &MI, LastDelta,
1967 UseByMask);
1968 } else {
1969 collectSubRegUsesByMask(Uses, Distances, LaneMask, UseByMask);
1970 }
1971 updateFurthestSubReg(MI, U, UseByMask, RelevantUses, *FurthestSubreg);
1972 }
1973 updateCachedLiveRegUses(MI);
1974 }
1975
1976 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1977 // Helper methods for printAsJson
1978 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1979private:
1980 static format_object<unsigned> Fmt(unsigned Id) { return format("%u", Id); }
1981
1982public:
1984 J.attribute("id", getInstrId(&MI));
1985 J.attribute("head-len", getHeadLen(&MI));
1986 J.attribute("tail-len", getTailLen(&MI));
1987 }
1988
1990 J.attributeBegin("paths");
1991 J.arrayBegin();
1992 for (const auto &KV : Paths) {
1993 const Path &P = KV.first;
1994 const PathInfo &PI = KV.second;
1995
1996 J.objectBegin();
1997
1998 printMBBNameAttr(J, "src", *P.src(), MST);
1999 printMBBNameAttr(J, "dst", *P.dst(), MST);
2000
2001 if (PI.ShortestDistance.has_value()) {
2002 J.attribute("shortest-distance",
2003 PI.ShortestDistance.value().toJsonValue());
2004 } else {
2005 J.attribute("shortest-distance", nullptr);
2006 }
2007
2008 if (PI.ShortestUnweightedDistance.has_value()) {
2009 J.attribute("shortest-unweighted-distance",
2010 PI.ShortestUnweightedDistance.value().toJsonValue());
2011 } else {
2012 J.attribute("shortest-unweighted-distance", nullptr);
2013 }
2014
2015 J.attribute("edge-kind", static_cast<int>(PI.EK));
2016 J.attribute("reachable", PI.Reachable);
2017 J.attribute("forward-reachable", PI.ForwardReachable);
2018
2019 J.objectEnd();
2020 }
2021 J.arrayEnd();
2022 J.attributeEnd();
2023 }
2024
2025public:
2027 ~AMDGPUNextUseAnalysisImpl() { clearTables(); }
2028
2031 Cfg = NewCfg;
2032 clearTables();
2033 initializeTables();
2034 }
2035
2036 unsigned getDistanceCacheHits() const { return DistanceCacheHits; }
2037 unsigned getDistanceCacheMisses() const { return DistanceCacheMisses; }
2038
2039 void getReachableUses(Register LiveReg, LaneBitmask LaneMask,
2040 const MachineInstr &MI,
2042
2043 /// \Returns the shortest next-use distance for \p LiveReg.
2045 getShortestDistance(Register LiveReg, LaneBitmask LaneMask,
2046 const MachineInstr &FromMI,
2048 const MachineOperand **ShortestUseOut, bool *MIDependent,
2049 SmallVector<CacheableNextUseDistance> *Distances) const;
2050
2054 return getShortestDistance(LiveReg, LaneBitmask::getAll(), FromMI, Uses,
2055 nullptr, nullptr, nullptr);
2056 }
2057};
2058
2060 const MachineFunction *MF, const MachineLoopInfo *ML) {
2061
2062 this->MF = MF;
2063 this->MLI = ML;
2064
2065 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2066 TII = ST.getInstrInfo();
2067 TRI = &TII->getRegisterInfo();
2068 MRI = &MF->getRegInfo();
2069
2070 // FIXME: Hopefully we will soon converge on a single way of calculating
2071 // next-use distance and remove these presets.
2072 if (ConfigPresetOpt == "compute")
2074 else
2076
2077 if (ConfigCountPhisOpt.getNumOccurrences())
2078 Cfg.CountPhis = ConfigCountPhisOpt;
2079 if (ConfigForwardOnlyOpt.getNumOccurrences())
2080 Cfg.ForwardOnly = ConfigForwardOnlyOpt;
2081 if (ConfigPreciseUseModelingOpt.getNumOccurrences())
2082 Cfg.PreciseUseModeling = ConfigPreciseUseModelingOpt;
2083 if (ConfigPromoteToPreheaderOpt.getNumOccurrences())
2084 Cfg.PromoteToPreheader = ConfigPromoteToPreheaderOpt;
2085
2086 initializeTables();
2087}
2088
2090 Register LiveReg, LaneBitmask LaneMask, const MachineInstr &CurMI,
2092 const MachineOperand **ShortestUseOut, bool *CurMIDependentOut,
2093 SmallVector<CacheableNextUseDistance> *Distances) const {
2094
2095 assert(!LiveReg.isPhysical() && !TRI->isAGPR(*MRI, LiveReg) &&
2096 "Next-use distance is calculated for SGPRs and VGPRs");
2097 const MachineOperand *NextUse = nullptr;
2098 auto NextUseDist = NextUseDistance::unreachable();
2099 bool CurMIDependent = false;
2100
2101 if (Distances) {
2102 Distances->clear();
2103 Distances->reserve(Uses.size());
2104 }
2105 for (auto *UseMO : Uses) {
2106 auto [Dep, D] = calcDistanceToUse(LiveReg, LaneMask, CurMI, UseMO);
2107
2108 if (D < NextUseDist) {
2109 NextUseDist = D;
2110 NextUse = UseMO;
2111 CurMIDependent = Dep;
2112 }
2113
2114 if (Distances)
2115 Distances->push_back({Dep, D});
2116 }
2117 if (ShortestUseOut)
2118 *ShortestUseOut = NextUse;
2119 if (CurMIDependentOut)
2120 *CurMIDependentOut = CurMIDependent;
2121
2122 assert(NextUseDist.isReachable() &&
2123 "getShortestDistance called with no reachable uses");
2124 return NextUseDist;
2125}
2126
2128 Register Reg, LaneBitmask LaneMask, const MachineInstr &MI,
2130 const bool CheckMask = LaneMask != LaneBitmask::getAll() &&
2131 LaneMask != MRI->getMaxLaneMaskForVReg(Reg);
2132 const MachineBasicBlock *MBB = MI.getParent();
2133
2134 for (const MachineOperand *UseMO : getRegisterUses(Reg)) {
2135 const MachineInstr *UseMI = UseMO->getParent();
2136 const MachineBasicBlock *UseMBB = UseMI->getParent();
2137
2138 if (CheckMask && !machineOperandCoveredBy(*UseMO, LaneMask))
2139 continue;
2140
2141 bool Reachable;
2142 if (Cfg.PreciseUseModeling)
2143 Reachable = isUseReachablePrecise(MI, MBB, UseMO, UseMI, UseMBB);
2144 else if (MBB == UseMBB)
2145 Reachable = instrsAreInOrder(&MI, UseMI);
2146 else
2147 Reachable = isForwardReachable(MBB, UseMBB);
2148
2149 if (Reachable)
2150 Uses.push_back(UseMO);
2151 }
2152}
2153
2154//==============================================================================
2155// AMDGPUNextUseAnalysis
2156//==============================================================================
2157AMDGPUNextUseAnalysis::AMDGPUNextUseAnalysis(const MachineFunction *MF,
2158 const MachineLoopInfo *MLI) {
2159 Impl = std::make_unique<AMDGPUNextUseAnalysisImpl>(MF, MLI);
2160}
2161AMDGPUNextUseAnalysis::AMDGPUNextUseAnalysis(AMDGPUNextUseAnalysis &&Other)
2162 : Impl(std::move(Other.Impl)) {}
2164
2166AMDGPUNextUseAnalysis::operator=(AMDGPUNextUseAnalysis &&Other) {
2167 if (this != &Other)
2168 Impl = std::move(Other.Impl);
2169 return *this;
2170}
2171
2173 return Impl->getConfig();
2174}
2175
2176void AMDGPUNextUseAnalysis::setConfig(Config Cfg) { Impl->setConfig(Cfg); }
2177
2178/// \Returns the next-use distance for \p LiveReg.
2180 Register LiveReg, const MachineInstr &FromMI,
2182 const MachineOperand **ShortestUseOut,
2183 SmallVector<NextUseDistance> *DistancesOut) const {
2184
2186 auto Dist = Impl->getShortestDistance(LiveReg, LaneBitmask::getAll(), FromMI,
2187 Uses, ShortestUseOut, nullptr,
2188 DistancesOut ? &Distances : nullptr);
2189 if (DistancesOut) {
2190 for (auto [MIDep, D] : Distances)
2191 DistancesOut->push_back(D);
2192 }
2193 return Dist;
2194}
2195
2198 UseDistancePair &FurthestOut, UseDistancePair *FurthestSubregOut,
2200
2201 LiveRegUse Furthest;
2202 LiveRegUse FurthestSubreg;
2203 Impl->getNextUseDistances(LiveRegs, MI, Furthest,
2204 FurthestSubregOut ? &FurthestSubreg : nullptr,
2205 RelevantUses);
2206 FurthestOut = Furthest;
2207 if (FurthestSubregOut)
2208 *FurthestSubregOut = FurthestSubreg;
2209}
2211 Register LiveReg, LaneBitmask LaneMask, const MachineInstr &MI,
2213 return Impl->getReachableUses(LiveReg, LaneMask, MI, Uses);
2214}
2215
2216//==============================================================================
2217// AMDGPUNextUseAnalysisLegacyPass
2218//==============================================================================
2219
2220//------------------------------------------------------------------------------
2221// Legacy Analysis Pass
2222//------------------------------------------------------------------------------
2226 return "Next Use Analysis";
2227}
2228
2230 MachineFunction &MF) {
2231 const MachineLoopInfo *MLI =
2233 NUA.reset(new AMDGPUNextUseAnalysis(&MF, MLI));
2234 return false;
2235}
2236
2243
2246
2248 "Next Use Analysis", false, true)
2251 "Next Use Analysis", false, true)
2252
2253//------------------------------------------------------------------------------
2254// New Pass Manager Analysis Pass
2255//------------------------------------------------------------------------------
2257
2261 const MachineLoopInfo &MLI = MFAM.getResult<MachineLoopAnalysis>(MF);
2262 return AMDGPUNextUseAnalysis(&MF, &MLI);
2263}
2264
2265//==============================================================================
2266// AMDGPUNextUseAnalysisPrinterLegacyPass
2267//==============================================================================
2268namespace {
2269void printInstrMember(json::OStream &J, ModuleSlotTracker &MST,
2270 const MachineInstr &MI,
2271 const AMDGPUNextUseAnalysisImpl &NUA) {
2272 printStringAttr(J, "instr", MI, MST);
2273 if (DumpNextUseDistanceVerbose)
2275}
2276
2277void printDistances(
2279 ModuleSlotTracker &MST,
2281 if (!DumpNextUseDistanceVerbose)
2282 return;
2283
2284 // Sorting isn't necessary for the purposes of JSON, but it reduces
2285 // FileCheck differences.
2287 for (const MachineOperand *K : Uses.keys())
2288 Keys.push_back(K);
2289 llvm::sort(Keys, [](const auto &A, const auto &B) {
2290 return A->getReg() < B->getReg() ||
2291 (A->getReg() == B->getReg() && A->getSubReg() < B->getSubReg());
2292 });
2293
2294 J.attributeBegin("distances");
2295 J.objectBegin();
2296
2297 for (const MachineOperand *K : Keys) {
2298 const LiveRegUse U = Uses.at(K);
2299 printAttr(J, printReg(U.getReg(), &TRI, U.getSubReg(), &MRI),
2300 U.Dist.toJsonValue());
2301 }
2302
2303 J.objectEnd();
2304 J.attributeEnd();
2305}
2306
2307void printFurthestUse(json::OStream &J, const MachineRegisterInfo &MRI,
2309 const LiveRegUse F, bool Subreg = false) {
2310 J.attributeBegin(Subreg ? "furthest-subreg" : "furthest");
2311 J.objectBegin();
2312
2313 if (F.Use) {
2314 printStringAttr(
2315 J, "register",
2316 printReg(F.getReg(), &TRI, Subreg ? F.getSubReg() : 0, &MRI));
2317
2318 if (DumpNextUseDistanceVerbose) {
2319 printStringAttr(J, "use", [&](raw_ostream &OS) { OS << (*F.Use); });
2320 printStringAttr(J, "use-mi", *F.Use->getParent(), MST);
2321 }
2322 J.attribute("distance", F.Dist.toJsonValue());
2323 }
2324
2325 J.objectEnd();
2326 J.attributeEnd();
2327}
2328
2329void printDistanceFromDefToUse(json::OStream &J, const MachineFunction &MF,
2330 const AMDGPUNextUseAnalysis &NUA,
2331 const SIRegisterInfo &TRI,
2332 const MachineRegisterInfo &MRI) {
2333 auto getRegNextUseDistance = [&](Register DefReg) {
2334 const MachineInstr &DefMI = *MRI.def_instr_begin(DefReg);
2335
2338 if (Uses.empty())
2340 return NUA.getShortestDistance(DefReg, DefMI, Uses);
2341 };
2342
2343 J.attributeBegin("distance-from-def-to-closest-use");
2344 J.objectBegin();
2345
2346 for (const MachineBasicBlock &MBB : MF) {
2347 for (const MachineInstr &MI : MBB) {
2348 for (const MachineOperand &MO : MI.all_defs()) {
2349 Register Reg = MO.getReg();
2350 if (Reg.isPhysical())
2351 continue;
2352 NextUseDistance D = getRegNextUseDistance(Reg);
2353 printAttr(J, printReg(Reg, &TRI, 0, &MRI), D.toJsonValue());
2354 }
2355 }
2356 }
2357
2358 J.objectEnd();
2359 J.attributeEnd();
2360}
2361
2362void printNextUseDistancesAsJson(json::OStream &J, const MachineFunction &MF,
2363 const AMDGPUNextUseAnalysis &NUA,
2364 const AMDGPUNextUseAnalysisImpl &NUAImpl,
2365 LiveIntervals &LIS) {
2366 using UseDistancePair = AMDGPUNextUseAnalysis::UseDistancePair;
2367 const Function &F = MF.getFunction();
2368 const Module *M = F.getParent();
2369
2371 const SIInstrInfo *TII = ST.getInstrInfo();
2373 const MachineRegisterInfo &MRI = MF.getRegInfo();
2374
2375 // We don't actually care about register pressure here - just using
2376 // GCNDownwardRPTracker as a convenient way of getting the set of live
2377 // registers at a given instruction.
2378 GCNDownwardRPTracker RPTracker(LIS);
2379 ModuleSlotTracker MST(M);
2381
2383
2384 J.attributeBegin("furthest-distances");
2385 J.objectBegin();
2386
2387 for (const MachineBasicBlock &MBB : MF) {
2388 std::string BBName;
2389 raw_string_ostream BBOS(BBName);
2391
2392 J.attributeBegin(BBOS.str());
2393 J.arrayBegin();
2394
2395 const MachineInstr *PrevMI = nullptr;
2396 for (const MachineInstr &MI : MBB) {
2397 // Update register pressure tracker
2398 if (!PrevMI || PrevMI->getOpcode() == AMDGPU::PHI)
2399 RPTracker.reset(MI, MBB.end());
2400 RPTracker.advance();
2401
2402 // Report distance for every register live at MI including the ones
2403 // that the tracker retired. Add their live-in lanes back.
2404 GCNRPTracker::LiveRegSet LiveAtMI = RPTracker.getLiveRegs();
2405 if (!MI.isDebugInstr() && !MI.isPHI()) {
2407 for (const MachineOperand &MO : MI.all_uses()) {
2408 Register Reg = MO.getReg();
2409 if (!Reg.isVirtual() || !MO.readsReg())
2410 continue;
2411 LaneBitmask Mask = getLiveLaneMask(Reg, BaseIdx, LIS, MRI);
2412 assert(Mask.any() && "read register not live at its use");
2413 LiveAtMI[Reg] |= Mask;
2414 }
2415 }
2416
2417 UseDistancePair Furthest;
2418 UseDistancePair FurthestSubreg;
2419 RelevantUses.clear();
2420 NUA.getNextUseDistances(LiveAtMI, MI, Furthest, &FurthestSubreg,
2421 &RelevantUses);
2422
2423 J.objectBegin();
2424 printInstrMember(J, MST, MI, NUAImpl);
2425 printDistances(J, MRI, TRI, MST, RelevantUses);
2426 printFurthestUse(J, MRI, TRI, MST, Furthest);
2427 printFurthestUse(J, MRI, TRI, MST, FurthestSubreg, /*Subreg*/ true);
2428 J.objectEnd();
2429
2430 PrevMI = &MI;
2431 }
2432
2433 J.arrayEnd();
2434 J.attributeEnd();
2435 }
2436
2437 J.objectEnd();
2438 J.attributeEnd();
2439
2440 if (DumpNextUseDistanceVerbose || DumpNextUseDistanceDefToUse)
2441 printDistanceFromDefToUse(J, MF, NUA, TRI, MRI);
2442
2443 if (DumpNextUseDistanceVerbose)
2444 NUAImpl.printPaths(J, MST);
2445
2446 if (DistanceCacheEnabled) {
2447 J.attributeBegin("metrics");
2448 J.objectBegin();
2449 {
2450 J.attributeBegin("distance-cache");
2451 J.objectBegin();
2452 {
2453 J.attribute("hits", NUAImpl.getDistanceCacheHits());
2454 J.attribute("misses", NUAImpl.getDistanceCacheMisses());
2455 }
2456 J.objectEnd();
2457 J.attributeEnd(); // distance-cache
2458 }
2459 J.objectEnd();
2460 J.attributeEnd(); // metrics
2461 }
2462}
2463
2464void printAsJson(raw_ostream &FallbackOS, TimerGroup &JsonTimerGroup,
2465 Timer &JsonTimer, const MachineFunction &MF,
2466 const AMDGPUNextUseAnalysis &NUA,
2467 const AMDGPUNextUseAnalysisImpl &NUAImpl, LiveIntervals &LIS) {
2468 std::string FN = DumpNextUseDistanceAsJson;
2469
2470 auto dump = [&](raw_ostream &OS) {
2471 json::OStream J(OS, 2);
2472 J.objectBegin();
2473
2474 J.attributeBegin("next-use-analysis");
2475 J.objectBegin();
2476 printNextUseDistancesAsJson(J, MF, NUA, NUAImpl, LIS);
2477 J.objectEnd();
2478 J.attributeEnd();
2479
2480 JsonTimer.stopTimer();
2481 JsonTimerGroup.printJSONValues(OS, ",\n");
2482
2483 J.objectEnd();
2484 };
2485
2486 if (!DumpNextUseDistanceAsJson.getNumOccurrences()) {
2487 dump(FallbackOS);
2488 } else if (FN.empty() || FN == "-") {
2489 dump(outs());
2490 } else {
2491 std::error_code EC;
2492 ToolOutputFile OutF(FN, EC, sys::fs::OF_None);
2493 dump(OutF.os());
2494 OutF.keep();
2495 }
2496}
2497} // namespace
2498
2499//------------------------------------------------------------------------------
2500// Legacy Printer Pass
2501//------------------------------------------------------------------------------
2504
2506 return "AMDGPU Next Use Analysis Printer";
2507}
2508
2510 MachineFunction &MF) {
2511 TimerGroup JsonTimerGroup("amdgpu-next-use-analysis-json",
2512 "AMDGPU Next Use Analysis JSON Printer", false);
2513 Timer JsonTimer("json", "Total time spent generating json", JsonTimerGroup);
2514 JsonTimer.startTimer();
2515
2517 const AMDGPUNextUseAnalysis &NUA =
2518 getAnalysis<AMDGPUNextUseAnalysisLegacyPass>().getNextUseAnalysis();
2519
2520 printAsJson(errs(), JsonTimerGroup, JsonTimer, MF, NUA, *NUA.Impl, LIS);
2521
2522 return false;
2523}
2524
2533
2537
2539 "amdgpu-next-use-printer",
2540 "AMDGPU Next Use Analysis Printer", false, false)
2541
2544
2546 "amdgpu-next-use-printer",
2547 "AMDGPU Next Use Analysis Printer", false, false)
2548
2549//------------------------------------------------------------------------------
2550// New Pass Manager Printer Pass
2551//------------------------------------------------------------------------------
2555
2556 TimerGroup JsonTimerGroup("amdgpu-next-use-analysis-json",
2557 "AMDGPU Next Use Analysis JSON Printer", false);
2558 Timer JsonTimer("json", "Total time spent generating json", JsonTimerGroup);
2559 JsonTimer.startTimer();
2560
2561 LiveIntervals &LIS = MFAM.getResult<LiveIntervalsAnalysis>(MF);
2562 const AMDGPUNextUseAnalysis &NUA =
2563 MFAM.getResult<AMDGPUNextUseAnalysisPass>(MF);
2564
2565 printAsJson(OS, JsonTimerGroup, JsonTimer, MF, NUA, *NUA.Impl, LIS);
2566
2567 return PreservedAnalyses::all();
2568}
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:665
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:690
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
MachineRegisterInfo & MRI
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:793
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Downward RP tracker that relies on program order to advance down the instruction stream.
DenseMap< unsigned, LaneBitmask > LiveRegSet
const HexagonRegisterInfo & getRegisterInfo() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
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 readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
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 isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:70
SlotIndex getBaseIndex() const
Returns the base index for associated with this index.
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.
#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)
LaneBitmask getLiveLaneMask(unsigned Reg, SlotIndex SI, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, LaneBitmask LaneMaskFilter=LaneBitmask::getAll())
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