LLVM 24.0.0git
MachinePipeliner.h
Go to the documentation of this file.
1//===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===//
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// An implementation of the Swing Modulo Scheduling (SMS) software pipeliner.
10//
11// Software pipelining (SWP) is an instruction scheduling technique for loops
12// that overlap loop iterations and exploits ILP via a compiler transformation.
13//
14// Swing Modulo Scheduling is an implementation of software pipelining
15// that generates schedules that are near optimal in terms of initiation
16// interval, register requirements, and stage count. See the papers:
17//
18// "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa,
19// A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Proceedings of the 1996
20// Conference on Parallel Architectures and Compilation Techiniques.
21//
22// "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J.
23// Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE
24// Transactions on Computers, Vol. 50, No. 3, 2001.
25//
26// "An Implementation of Swing Modulo Scheduling With Extensions for
27// Superblocks", by T. Lattner, Master's Thesis, University of Illinois at
28// Urbana-Champaign, 2005.
29//
30//
31// The SMS algorithm consists of three main steps after computing the minimal
32// initiation interval (MII).
33// 1) Analyze the dependence graph and compute information about each
34// instruction in the graph.
35// 2) Order the nodes (instructions) by priority based upon the heuristics
36// described in the algorithm.
37// 3) Attempt to schedule the nodes in the specified order using the MII.
38//
39//===----------------------------------------------------------------------===//
40#ifndef LLVM_CODEGEN_MACHINEPIPELINER_H
41#define LLVM_CODEGEN_MACHINEPIPELINER_H
42
43#include "llvm/ADT/STLExtras.h"
44#include "llvm/ADT/SetVector.h"
54
55#include <deque>
56
57namespace llvm {
58
59class AAResults;
60class LiveIntervals;
61class NodeSet;
62class SMSchedule;
63
66
67/// Software pipelining policy for a loop, which a target can customize by
68/// implementing TargetSubtargetInfo::overridePipelinerPolicy.
70 /// Limit the register pressure of the scheduled loop, retrying at a higher
71 /// II when a schedule needs too many registers.
73};
74
76public:
77 static char ID;
78
80
81 bool runOnMachineFunction(MachineFunction &MF) override;
82
83 void getAnalysisUsage(AnalysisUsage &AU) const override;
84};
85
87 : public OptionalPassInfoMixin<MachinePipelinerPass> {
88public:
91};
92
93/// Represents a dependence between two instruction.
95 SUnit *Dst = nullptr;
96 SDep Pred;
97 unsigned Distance = 0;
98 bool IsValidationOnly = false;
99
100public:
101 /// Creates an edge corresponding to an edge represented by \p PredOrSucc and
102 /// \p Dep in the original DAG. This pair has no information about the
103 /// direction of the edge, so we need to pass an additional argument \p
104 /// IsSucc.
105 SwingSchedulerDDGEdge(SUnit *PredOrSucc, const SDep &Dep, bool IsSucc,
106 bool IsValidationOnly)
107 : Dst(PredOrSucc), Pred(Dep), Distance(0u),
108 IsValidationOnly(IsValidationOnly) {
109 SUnit *Src = Dep.getSUnit();
110
111 if (IsSucc) {
112 std::swap(Src, Dst);
113 Pred.setSUnit(Src);
114 }
115
116 // An anti-dependence to PHI means loop-carried dependence.
117 if (Pred.getKind() == SDep::Anti && Src->getInstr()->isPHI()) {
118 Distance = 1;
119 std::swap(Src, Dst);
120 auto Reg = Pred.getReg();
121 Pred = SDep(Src, SDep::Kind::Data, Reg);
122 }
123 }
124
125 /// Returns the SUnit from which the edge comes (source node).
126 SUnit *getSrc() const { return Pred.getSUnit(); }
127
128 /// Returns the SUnit to which the edge points (destination node).
129 SUnit *getDst() const { return Dst; }
130
131 /// Returns the latency value for the edge.
132 unsigned getLatency() const { return Pred.getLatency(); }
133
134 /// Sets the latency for the edge.
135 void setLatency(unsigned Latency) { Pred.setLatency(Latency); }
136
137 /// Returns the distance value for the edge.
138 unsigned getDistance() const { return Distance; }
139
140 /// Sets the distance value for the edge.
141 void setDistance(unsigned D) { Distance = D; }
142
143 /// Returns the register associated with the edge.
144 Register getReg() const { return Pred.getReg(); }
145
146 /// Returns true if the edge represents anti dependence.
147 bool isAntiDep() const { return Pred.getKind() == SDep::Kind::Anti; }
148
149 /// Returns true if the edge represents output dependence.
150 bool isOutputDep() const { return Pred.getKind() == SDep::Kind::Output; }
151
152 /// Returns true if the edge represents a dependence that is not data, anti or
153 /// output dependence.
154 bool isOrderDep() const { return Pred.getKind() == SDep::Kind::Order; }
155
156 /// Returns true if the edge represents unknown scheduling barrier.
157 bool isBarrier() const { return Pred.isBarrier(); }
158
159 /// Returns true if the edge represents an artificial dependence.
160 bool isArtificial() const { return Pred.isArtificial(); }
161
162 /// Tests if this is a Data dependence that is associated with a register.
163 bool isAssignedRegDep() const { return Pred.isAssignedRegDep(); }
164
165 /// Returns true for DDG nodes that we ignore when computing the cost
166 /// functions. We ignore the back-edge recurrence in order to avoid unbounded
167 /// recursion in the calculation of the ASAP, ALAP, etc functions.
168 LLVM_ABI bool ignoreDependence(bool IgnoreAnti) const;
169
170 /// Returns true if this edge is intended to be used only for validating the
171 /// schedule.
172 bool isValidationOnly() const { return IsValidationOnly; }
173};
174
175/// Represents loop-carried dependencies. Because SwingSchedulerDAG doesn't
176/// assume cycle dependencies as the name suggests, such dependencies must be
177/// handled separately. After DAG construction is finished, these dependencies
178/// are added to SwingSchedulerDDG.
179/// TODO: Also handle output-dependencies introduced by physical registers.
183
185
187 auto Ite = OrderDeps.find(Key);
188 if (Ite == OrderDeps.end())
189 return nullptr;
190 return &Ite->second;
191 }
192
193 /// Adds some edges to the original DAG that correspond to loop-carried
194 /// dependencies. Historically, loop-carried edges are represented by using
195 /// non-loop-carried edges in the original DAG. This function appends such
196 /// edges to preserve the previous behavior.
197 LLVM_ABI void modifySUnits(std::vector<SUnit> &SUnits,
198 const TargetInstrInfo *TII);
199
200 LLVM_ABI void dump(SUnit *SU, const TargetRegisterInfo *TRI,
201 const MachineRegisterInfo *MRI) const;
202};
203
204/// This class provides APIs to retrieve edges from/to an SUnit node, with a
205/// particular focus on loop-carried dependencies. Since SUnit is not designed
206/// to represent such edges, handling them directly using its APIs has required
207/// non-trivial logic in the past. This class serves as a wrapper around SUnit,
208/// offering a simpler interface for managing these dependencies.
211
212 struct SwingSchedulerDDGEdges {
213 EdgesType Preds;
214 EdgesType Succs;
215
216 /// This field is a subset of ValidationOnlyEdges. These edges are used only
217 /// by specific heuristics, mainly for cycle detection. Although they are
218 /// unnecessary in theory (i.e., ignoring them should still yield a valid
219 /// schedule), they are retained to preserve the existing behavior. Since we
220 /// only need which extra edges exist from a given SUnit, we only store the
221 /// destination SUnits.
222 SmallVector<SUnit *, 4> ExtraSuccs;
223 };
224
225 void initEdges(SUnit *SU);
226
227 SUnit *EntrySU;
228 SUnit *ExitSU;
229
230 std::vector<SwingSchedulerDDGEdges> EdgesVec;
231 SwingSchedulerDDGEdges EntrySUEdges;
232 SwingSchedulerDDGEdges ExitSUEdges;
233
234 /// Edges that are used only when validating the schedule. These edges are
235 /// not considered to drive the optimization heuristics.
236 SmallVector<SwingSchedulerDDGEdge, 8> ValidationOnlyEdges;
237
238 /// Adds a NON-validation-only edge to the DDG. Assumes to be called only by
239 /// the ctor.
240 void addEdge(const SUnit *SU, const SwingSchedulerDDGEdge &Edge);
241
242 SwingSchedulerDDGEdges &getEdges(const SUnit *SU);
243 const SwingSchedulerDDGEdges &getEdges(const SUnit *SU) const;
244
245public:
246 LLVM_ABI SwingSchedulerDDG(std::vector<SUnit> &SUnits, SUnit *EntrySU,
247 SUnit *ExitSU, const LoopCarriedEdges &LCE);
248
249 LLVM_ABI const EdgesType &getInEdges(const SUnit *SU) const;
250
251 LLVM_ABI const EdgesType &getOutEdges(const SUnit *SU) const;
252
254
255 LLVM_ABI bool isValidSchedule(const SMSchedule &Schedule) const;
256};
257
258/// This class builds the dependence graph for the instructions in a loop,
259/// and attempts to schedule the instructions using the SMS algorithm.
262
263 std::unique_ptr<SwingSchedulerDDG> DDG;
264
265 /// The minimum initiation interval between iterations for this schedule.
266 unsigned MII = 0;
267 /// The maximum initiation interval between iterations for this schedule.
268 unsigned MAX_II = 0;
269 /// Set to true if a valid pipelined schedule is found for the loop.
270 bool Scheduled = false;
271 MachineLoop &Loop;
272 LiveIntervals &LIS;
273 const RegisterClassInfo &RegClassInfo;
274 unsigned II_setByPragma = 0;
275 TargetInstrInfo::PipelinerLoopInfo *LoopPipelinerInfo = nullptr;
276
277 /// Policy for this loop, after target and command line overrides.
279
280 /// A topological ordering of the SUnits, which is needed for changing
281 /// dependences and iterating over the SUnits.
283
284 struct NodeInfo {
285 int ASAP = 0;
286 int ALAP = 0;
287 int ZeroLatencyDepth = 0;
288 int ZeroLatencyHeight = 0;
289
290 NodeInfo() = default;
291 };
292 /// Computed properties for each node in the graph.
293 std::vector<NodeInfo> ScheduleInfo;
294
295 enum OrderKind { BottomUp = 0, TopDown = 1 };
296 /// Computed node ordering for scheduling.
297 SetVector<SUnit *> NodeOrder;
298
299 using NodeSetType = SmallVector<NodeSet, 8>;
300 using ValueMapTy = DenseMap<unsigned, unsigned>;
301 using MBBVectorTy = SmallVectorImpl<MachineBasicBlock *>;
303
304 /// Instructions to change when emitting the final schedule.
306
307 /// We may create a new instruction, so remember it because it
308 /// must be deleted when the pass is finished.
310
311 /// Ordered list of DAG postprocessing steps.
312 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
313
314 /// Used to compute single-iteration dependencies (i.e., buildSchedGraph).
315 AliasAnalysis *AA;
316
317 /// Used to compute loop-carried dependencies (i.e.,
318 /// addLoopCarriedDependences).
319 BatchAAResults BAA;
320
321 /// Helper class to implement Johnson's circuit finding algorithm.
322 class Circuits {
323 std::vector<SUnit> &SUnits;
324 SetVector<SUnit *> Stack;
325 BitVector Blocked;
328 // Node to Index from ScheduleDAGTopologicalSort
329 std::vector<int> *Node2Idx;
330 unsigned NumPaths = 0u;
331 static unsigned MaxPaths;
332
333 public:
334 Circuits(std::vector<SUnit> &SUs, ScheduleDAGTopologicalSort &Topo)
335 : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) {
336 Node2Idx = new std::vector<int>(SUs.size());
337 unsigned Idx = 0;
338 for (const auto &NodeNum : Topo)
339 Node2Idx->at(NodeNum) = Idx++;
340 }
341 Circuits &operator=(const Circuits &other) = delete;
342 Circuits(const Circuits &other) = delete;
343 ~Circuits() { delete Node2Idx; }
344
345 /// Reset the data structures used in the circuit algorithm.
346 void reset() {
347 Stack.clear();
348 Blocked.reset();
349 B.assign(SUnits.size(), SmallPtrSet<SUnit *, 4>());
350 NumPaths = 0;
351 }
352
353 LLVM_ABI void createAdjacencyStructure(SwingSchedulerDDG *DDG);
354 LLVM_ABI bool circuit(int V, int S, NodeSetType &NodeSets,
355 const SwingSchedulerDAG *DAG,
356 bool HasBackedge = false);
357 LLVM_ABI void unblock(int U);
358 };
359
360 struct LLVM_ABI CopyToPhiMutation : public ScheduleDAGMutation {
361 void apply(ScheduleDAGInstrs *DAG) override;
362 };
363
364public:
367 LiveIntervals &lis, const RegisterClassInfo &rci,
369 AliasAnalysis *AA)
370 : ScheduleDAGInstrs(MF, MLI, false), ORE(ORE), Loop(L), LIS(lis),
371 RegClassInfo(rci), II_setByPragma(II), LoopPipelinerInfo(PLI),
372 Topo(SUnits, &ExitSU), AA(AA), BAA(*AA) {
373 initPolicy();
374 MF.getSubtarget().getSMSMutations(Mutations);
376 Mutations.push_back(std::make_unique<CopyToPhiMutation>());
377 BAA.enableCrossIterationMode();
378 }
379
380 void schedule() override;
381 void finishBlock() override;
382
383 /// Return true if the loop kernel has been scheduled.
384 bool hasNewSchedule() { return Scheduled; }
385
386 /// Return the earliest time an instruction may be scheduled.
387 int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; }
388
389 /// Return the latest time an instruction my be scheduled.
390 int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; }
391
392 /// The mobility function, which the number of slots in which
393 /// an instruction may be scheduled.
394 int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); }
395
396 /// The depth, in the dependence graph, for a node.
397 unsigned getDepth(SUnit *Node) { return Node->getDepth(); }
398
399 /// The maximum unweighted length of a path from an arbitrary node to the
400 /// given node in which each edge has latency 0
402 return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth;
403 }
404
405 /// The height, in the dependence graph, for a node.
406 unsigned getHeight(SUnit *Node) { return Node->getHeight(); }
407
408 /// The maximum unweighted length of a path from the given node to an
409 /// arbitrary node in which each edge has latency 0
411 return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight;
412 }
413
414 void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule);
415
416 void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs);
417
418 /// Return the new base register that was stored away for the changed
419 /// instruction.
422 InstrChanges.find(SU);
423 if (It != InstrChanges.end())
424 return It->second.first;
425 return Register();
426 }
427
428 void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
429 Mutations.push_back(std::move(Mutation));
430 }
431
432 static bool classof(const ScheduleDAGInstrs *DAG) { return true; }
433
434 const SwingSchedulerDDG *getDDG() const { return DDG.get(); }
435
436 bool mayOverlapInLaterIter(const MachineInstr *BaseMI,
437 const MachineInstr *OtherMI) const;
438
439private:
440 /// Set the policy for this loop, allowing the target to override it.
441 void initPolicy();
442 LoopCarriedEdges addLoopCarriedDependences();
443 void updatePhiDependences();
444 void changeDependences();
445 unsigned calculateResMII();
446 unsigned calculateRecMII(NodeSetType &RecNodeSets);
447 void findCircuits(NodeSetType &NodeSets);
448 void fuseRecs(NodeSetType &NodeSets);
449 void removeDuplicateNodes(NodeSetType &NodeSets);
450 void computeNodeFunctions(NodeSetType &NodeSets);
451 void registerPressureFilter(NodeSetType &NodeSets);
452 void colocateNodeSets(NodeSetType &NodeSets);
453 void checkNodeSets(NodeSetType &NodeSets);
454 void groupRemainingNodes(NodeSetType &NodeSets);
455 void addConnectedNodes(SUnit *SU, NodeSet &NewSet,
456 SetVector<SUnit *> &NodesAdded);
457 void computeNodeOrder(NodeSetType &NodeSets);
458 void checkValidNodeOrder(const NodeSetType &Circuits) const;
459 bool schedulePipeline(SMSchedule &Schedule);
460 bool computeDelta(const MachineInstr &MI, int &Delta) const;
461 MachineInstr *findDefInLoop(Register Reg);
462 bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos,
463 unsigned &OffsetPos, Register &NewBase,
464 int64_t &NewOffset);
465 void postProcessDAG();
466 /// Set the Minimum Initiation Interval for this schedule attempt.
467 void setMII(unsigned ResMII, unsigned RecMII);
468 /// Set the Maximum Initiation Interval for this schedule attempt.
469 void setMAX_II();
470};
471
472/// A NodeSet contains a set of SUnit DAG nodes with additional information
473/// that assigns a priority to the set.
474class NodeSet {
475 SetVector<SUnit *> Nodes;
476 bool HasRecurrence = false;
477 unsigned RecMII = 0;
478 int MaxMOV = 0;
479 unsigned MaxDepth = 0;
480 unsigned Colocate = 0;
481 SUnit *ExceedPressure = nullptr;
482 unsigned Latency = 0;
483
484public:
486
487 NodeSet() = default;
489 : Nodes(S, E), HasRecurrence(true) {
490 // Calculate the latency of this node set.
491 // Example to demonstrate the calculation:
492 // Given: N0 -> N1 -> N2 -> N0
493 // Edges:
494 // (N0 -> N1, 3)
495 // (N0 -> N1, 5)
496 // (N1 -> N2, 2)
497 // (N2 -> N0, 1)
498 // The total latency which is a lower bound of the recurrence MII is the
499 // longest path from N0 back to N0 given only the edges of this node set.
500 // In this example, the latency is: 5 + 2 + 1 = 8.
501 //
502 // Hold a map from each SUnit in the circle to the maximum distance from the
503 // source node by only considering the nodes.
504 const SwingSchedulerDDG *DDG = DAG->getDDG();
505 DenseMap<SUnit *, unsigned> SUnitToDistance;
506 for (auto *Node : Nodes)
507 SUnitToDistance[Node] = 0;
508
509 for (unsigned I = 1, E = Nodes.size(); I <= E; ++I) {
510 SUnit *U = Nodes[I - 1];
511 SUnit *V = Nodes[I % Nodes.size()];
512 for (const SwingSchedulerDDGEdge &Succ : DDG->getOutEdges(U)) {
513 SUnit *SuccSUnit = Succ.getDst();
514 if (V != SuccSUnit)
515 continue;
516 unsigned &DU = SUnitToDistance[U];
517 unsigned &DV = SUnitToDistance[V];
518 if (DU + Succ.getLatency() > DV)
519 DV = DU + Succ.getLatency();
520 }
521 }
522 // Handle a back-edge in loop carried dependencies
523 SUnit *FirstNode = Nodes[0];
524 SUnit *LastNode = Nodes[Nodes.size() - 1];
525
526 for (SUnit *SU : DDG->getExtraOutEdges(LastNode)) {
527 // If we have an order dep that is potentially loop carried then a
528 // back-edge exists between the last node and the first node in extra
529 // edges. Handle it manually by adding 1 to the distance of the last node.
530 if (SU != FirstNode)
531 continue;
532 unsigned &First = SUnitToDistance[FirstNode];
533 unsigned Last = SUnitToDistance[LastNode];
534 First = std::max(First, Last + 1);
535 }
536
537 // The latency is the distance from the source node to itself.
538 Latency = SUnitToDistance[Nodes.front()];
539 }
540
541 bool insert(SUnit *SU) { return Nodes.insert(SU); }
542
543 void insert(iterator S, iterator E) { Nodes.insert(S, E); }
544
545 template <typename UnaryPredicate> bool remove_if(UnaryPredicate P) {
546 return Nodes.remove_if(P);
547 }
548
549 unsigned count(SUnit *SU) const { return Nodes.count(SU); }
550
551 bool hasRecurrence() { return HasRecurrence; };
552
553 unsigned size() const { return Nodes.size(); }
554
555 bool empty() const { return Nodes.empty(); }
556
557 SUnit *getNode(unsigned i) const { return Nodes[i]; };
558
559 void setRecMII(unsigned mii) { RecMII = mii; };
560
561 void setColocate(unsigned c) { Colocate = c; };
562
563 void setExceedPressure(SUnit *SU) { ExceedPressure = SU; }
564
565 bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; }
566
567 int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; }
568
569 int getRecMII() { return RecMII; }
570
571 /// Summarize node functions for the entire node set.
573 for (SUnit *SU : *this) {
574 MaxMOV = std::max(MaxMOV, SSD->getMOV(SU));
575 MaxDepth = std::max(MaxDepth, SSD->getDepth(SU));
576 }
577 }
578
579 unsigned getLatency() { return Latency; }
580
581 unsigned getMaxDepth() { return MaxDepth; }
582
583 void clear() {
584 Nodes.clear();
585 RecMII = 0;
586 HasRecurrence = false;
587 MaxMOV = 0;
588 MaxDepth = 0;
589 Colocate = 0;
590 ExceedPressure = nullptr;
591 }
592
593 operator SetVector<SUnit *> &() { return Nodes; }
594
595 /// Sort the node sets by importance. First, rank them by recurrence MII,
596 /// then by mobility (least mobile done first), and finally by depth.
597 /// Each node set may contain a colocate value which is used as the first
598 /// tie breaker, if it's set.
599 bool operator>(const NodeSet &RHS) const {
600 if (RecMII == RHS.RecMII) {
601 if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate)
602 return Colocate < RHS.Colocate;
603 if (MaxMOV == RHS.MaxMOV)
604 return MaxDepth > RHS.MaxDepth;
605 return MaxMOV < RHS.MaxMOV;
606 }
607 return RecMII > RHS.RecMII;
608 }
609
610 bool operator==(const NodeSet &RHS) const {
611 return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV &&
612 MaxDepth == RHS.MaxDepth;
613 }
614
615 bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); }
616
617 iterator begin() { return Nodes.begin(); }
618 iterator end() { return Nodes.end(); }
619 LLVM_ABI void print(raw_ostream &os) const;
620
621#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
622 LLVM_DUMP_METHOD void dump() const;
623#endif
624};
625
626// 16 was selected based on the number of ProcResource kinds for all
627// existing Subtargets, so that SmallVector don't need to resize too often.
628static const int DefaultProcResSize = 16;
629
631private:
632 const MCSubtargetInfo *STI;
633 const MCSchedModel &SM;
634 const TargetSubtargetInfo *ST;
635 const TargetInstrInfo *TII;
637 const bool UseDFA;
638 /// DFA resources for each slot
640 /// Modulo Reservation Table. When a resource with ID R is consumed in cycle
641 /// C, it is counted in MRT[C mod II][R]. (Used when UseDFA == F)
643 /// The number of scheduled micro operations for each slot. Micro operations
644 /// are assumed to be scheduled one per cycle, starting with the cycle in
645 /// which the instruction is scheduled.
646 llvm::SmallVector<int> NumScheduledMops;
647 /// Each processor resource is associated with a so-called processor resource
648 /// mask. This vector allows to correlate processor resource IDs with
649 /// processor resource masks. There is exactly one element per each processor
650 /// resource declared by the scheduling model.
652 int InitiationInterval = 0;
653 /// The number of micro operations that can be scheduled at a cycle.
654 int IssueWidth;
655
656 int calculateResMIIDFA() const;
657 /// Check if MRT is overbooked
658 bool isOverbooked() const;
659 /// Reserve resources on MRT
660 void reserveResources(const MCSchedClassDesc *SCDesc, int Cycle);
661 /// Unreserve resources on MRT
662 void unreserveResources(const MCSchedClassDesc *SCDesc, int Cycle);
663
664 /// Return M satisfying Dividend = Divisor * X + M, 0 < M < Divisor.
665 /// The slot on MRT to reserve a resource for the cycle C is positiveModulo(C,
666 /// II).
667 int positiveModulo(int Dividend, int Divisor) const {
668 assert(Divisor > 0);
669 int R = Dividend % Divisor;
670 if (R < 0)
671 R += Divisor;
672 return R;
673 }
674
675#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
676 LLVM_DUMP_METHOD void dumpMRT() const;
677#endif
678
679public:
681 : STI(ST), SM(ST->getSchedModel()), ST(ST), TII(ST->getInstrInfo()),
682 DAG(DAG), UseDFA(ST->useDFAforSMS()),
683 ProcResourceMasks(SM.getNumProcResourceKinds(), 0),
684 IssueWidth(SM.IssueWidth) {
685 initProcResourceVectors(SM, ProcResourceMasks);
686 if (IssueWidth <= 0)
687 // If IssueWidth is not specified, set a sufficiently large value
688 IssueWidth = 100;
689 if (SwpForceIssueWidth > 0)
690 IssueWidth = SwpForceIssueWidth;
691 }
692
693 LLVM_ABI void initProcResourceVectors(const MCSchedModel &SM,
695
696 /// Check if the resources occupied by a machine instruction are available
697 /// in the current state.
698 LLVM_ABI bool canReserveResources(SUnit &SU, int Cycle);
699
700 /// Reserve the resources occupied by a machine instruction and change the
701 /// current state to reflect that change.
702 LLVM_ABI void reserveResources(SUnit &SU, int Cycle);
703
704 LLVM_ABI int calculateResMII() const;
705
706 /// Initialize resources with the initiation interval II.
707 LLVM_ABI void init(int II);
708};
709
710/// This class represents the scheduled code. The main data structure is a
711/// map from scheduled cycle to instructions. During scheduling, the
712/// data structure explicitly represents all stages/iterations. When
713/// the algorithm finshes, the schedule is collapsed into a single stage,
714/// which represents instructions from different loop iterations.
715///
716/// The SMS algorithm allows negative values for cycles, so the first cycle
717/// in the schedule is the smallest cycle value.
719private:
720 /// Map from execution cycle to instructions.
721 DenseMap<int, std::deque<SUnit *>> ScheduledInstrs;
722
723 /// Map from instruction to execution cycle.
724 std::map<SUnit *, int> InstrToCycle;
725
726 /// Keep track of the first cycle value in the schedule. It starts
727 /// as zero, but the algorithm allows negative values.
728 int FirstCycle = 0;
729
730 /// Keep track of the last cycle value in the schedule.
731 int LastCycle = 0;
732
733 /// The initiation interval (II) for the schedule.
734 int InitiationInterval = 0;
735
736 /// Target machine information.
737 const TargetSubtargetInfo &ST;
738
739 /// Virtual register information.
741
742 ResourceManager ProcItinResources;
743
744public:
746 : ST(mf->getSubtarget()), MRI(mf->getRegInfo()),
747 ProcItinResources(&ST, DAG) {}
748
749 void reset() {
750 ScheduledInstrs.clear();
751 InstrToCycle.clear();
752 FirstCycle = 0;
753 LastCycle = 0;
754 InitiationInterval = 0;
755 }
756
757 /// Set the initiation interval for this schedule.
759 InitiationInterval = ii;
760 ProcItinResources.init(ii);
761 }
762
763 /// Return the initiation interval for this schedule.
764 int getInitiationInterval() const { return InitiationInterval; }
765
766 /// Return the first cycle in the completed schedule. This
767 /// can be a negative value.
768 int getFirstCycle() const { return FirstCycle; }
769
770 /// Return the last cycle in the finalized schedule.
771 int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; }
772
773 LLVM_ABI void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart,
774 int II, SwingSchedulerDAG *DAG);
775 LLVM_ABI bool insert(SUnit *SU, int StartCycle, int EndCycle, int II);
776
777 /// Iterators for the cycle to instruction map.
781
782 /// Return true if the instruction is scheduled at the specified stage.
783 bool isScheduledAtStage(SUnit *SU, unsigned StageNum) {
784 return (stageScheduled(SU) == (int)StageNum);
785 }
786
787 /// Return the stage for a scheduled instruction. Return -1 if
788 /// the instruction has not been scheduled.
789 int stageScheduled(SUnit *SU) const {
790 std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
791 if (it == InstrToCycle.end())
792 return -1;
793 return (it->second - FirstCycle) / InitiationInterval;
794 }
795
796 /// Return the cycle for a scheduled instruction. This function normalizes
797 /// the first cycle to be 0.
798 unsigned cycleScheduled(SUnit *SU) const {
799 std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
800 assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled.");
801 return (it->second - FirstCycle) % InitiationInterval;
802 }
803
804 /// Return the maximum stage count needed for this schedule.
805 unsigned getMaxStageCount() {
806 return (LastCycle - FirstCycle) / InitiationInterval;
807 }
808
809 /// Return the instructions that are scheduled at the specified cycle.
810 std::deque<SUnit *> &getInstructions(int cycle) {
811 return ScheduledInstrs[cycle];
812 }
813
815 computeUnpipelineableNodes(SwingSchedulerDAG *SSD,
817
818 LLVM_ABI std::deque<SUnit *>
819 reorderInstructions(const SwingSchedulerDAG *SSD,
820 const std::deque<SUnit *> &Instrs) const;
821
822 LLVM_ABI bool
823 normalizeNonPipelinedInstructions(SwingSchedulerDAG *SSD,
825 LLVM_ABI bool isValidSchedule(SwingSchedulerDAG *SSD);
826 LLVM_ABI void finalizeSchedule(SwingSchedulerDAG *SSD);
827 LLVM_ABI void orderDependence(const SwingSchedulerDAG *SSD, SUnit *SU,
828 std::deque<SUnit *> &Insts) const;
829 LLVM_ABI bool isLoopCarried(const SwingSchedulerDAG *SSD,
830 MachineInstr &Phi) const;
831 LLVM_ABI bool isLoopCarriedDefOfUse(const SwingSchedulerDAG *SSD,
832 MachineInstr *Def,
833 MachineOperand &MO) const;
834
835 LLVM_ABI bool
836 onlyHasLoopCarriedOutputOrOrderPreds(SUnit *SU,
837 const SwingSchedulerDDG *DDG) const;
838 LLVM_ABI void print(raw_ostream &os) const;
839 LLVM_ABI void dump() const;
840};
841
842} // end namespace llvm
843
844#endif // LLVM_CODEGEN_MACHINEPIPELINER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
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_ABI
Definition Compiler.h:215
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:678
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
uint64_t IntrinsicInst * II
#define P(N)
PowerPC VSX FMA Mutation
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
Value * RHS
Represent the analysis usage information of a pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
BitVector & reset()
Reset all bits in the bitvector.
Definition BitVector.h:409
iterator end()
Definition DenseMap.h:169
Generic base class for all target subtargets.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
SUnit * getNode(unsigned i) const
SetVector< SUnit * >::const_iterator iterator
bool isExceedSU(SUnit *SU)
void insert(iterator S, iterator E)
void setRecMII(unsigned mii)
void computeNodeSetInfo(SwingSchedulerDAG *SSD)
Summarize node functions for the entire node set.
unsigned getMaxDepth()
unsigned count(SUnit *SU) const
NodeSet()=default
void setColocate(unsigned c)
unsigned getLatency()
NodeSet(iterator S, iterator E, const SwingSchedulerDAG *DAG)
bool operator>(const NodeSet &RHS) const
Sort the node sets by importance.
int compareRecMII(NodeSet &RHS)
unsigned size() const
bool operator!=(const NodeSet &RHS) const
bool insert(SUnit *SU)
bool operator==(const NodeSet &RHS) const
bool remove_if(UnaryPredicate P)
bool empty() const
void setExceedPressure(SUnit *SU)
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Wrapper class representing virtual and physical registers.
Definition Register.h:20
LLVM_ABI void initProcResourceVectors(const MCSchedModel &SM, SmallVectorImpl< uint64_t > &Masks)
ResourceManager(const TargetSubtargetInfo *ST, ScheduleDAGInstrs *DAG)
Scheduling dependency.
Definition ScheduleDAG.h:52
SUnit * getSUnit() const
@ Output
A register output-dependence (aka WAW).
Definition ScheduleDAG.h:58
@ Order
Any other ordering dependency.
Definition ScheduleDAG.h:59
@ Anti
A register anti-dependence (aka WAR).
Definition ScheduleDAG.h:57
This class represents the scheduled code.
void setInitiationInterval(int ii)
Set the initiation interval for this schedule.
unsigned getMaxStageCount()
Return the maximum stage count needed for this schedule.
int stageScheduled(SUnit *SU) const
Return the stage for a scheduled instruction.
bool isScheduledAtStage(SUnit *SU, unsigned StageNum)
Return true if the instruction is scheduled at the specified stage.
int getInitiationInterval() const
Return the initiation interval for this schedule.
std::deque< SUnit * > & getInstructions(int cycle)
Return the instructions that are scheduled at the specified cycle.
int getFirstCycle() const
Return the first cycle in the completed schedule.
DenseMap< int, std::deque< SUnit * > >::const_iterator const_sched_iterator
DenseMap< int, std::deque< SUnit * > >::iterator sched_iterator
Iterators for the cycle to instruction map.
unsigned cycleScheduled(SUnit *SU) const
Return the cycle for a scheduled instruction.
SMSchedule(MachineFunction *mf, SwingSchedulerDAG *DAG)
int getFinalCycle() const
Return the last cycle in the finalized schedule.
Scheduling unit. This is a node in the scheduling DAG.
A ScheduleDAG for scheduling lists of MachineInstr.
ScheduleDAGInstrs(MachineFunction &mf, const MachineLoopInfo *mli, bool RemoveKillFlags=false)
const MachineLoopInfo * MLI
Mutate the DAG as a postpass after normal DAG building.
This class can compute a topological ordering for SUnits and provides methods for dynamically updatin...
std::vector< SUnit > SUnits
The scheduling units.
MachineFunction & MF
Machine function.
ScheduleDAG & operator=(const ScheduleDAG &)=delete
SUnit ExitSU
Special node for the region exit.
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
const value_type & front() const
Return the first element of the SetVector.
Definition SetVector.h:138
typename vector_type::const_iterator const_iterator
Definition SetVector.h:73
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...
unsigned getDepth(SUnit *Node)
The depth, in the dependence graph, for a node.
int getASAP(SUnit *Node)
Return the earliest time an instruction may be scheduled.
const SwingSchedulerDDG * getDDG() const
bool hasNewSchedule()
Return true if the loop kernel has been scheduled.
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
int getZeroLatencyDepth(SUnit *Node)
The maximum unweighted length of a path from an arbitrary node to the given node in which each edge h...
SwingSchedulerDAG(MachineFunction &MF, const MachineLoopInfo *MLI, MachineOptimizationRemarkEmitter *ORE, MachineLoop &L, LiveIntervals &lis, const RegisterClassInfo &rci, unsigned II, TargetInstrInfo::PipelinerLoopInfo *PLI, AliasAnalysis *AA)
int getMOV(SUnit *Node)
The mobility function, which the number of slots in which an instruction may be scheduled.
int getZeroLatencyHeight(SUnit *Node)
The maximum unweighted length of a path from the given node to an arbitrary node in which each edge h...
Register getInstrBaseReg(SUnit *SU) const
Return the new base register that was stored away for the changed instruction.
static bool classof(const ScheduleDAGInstrs *DAG)
unsigned getHeight(SUnit *Node)
The height, in the dependence graph, for a node.
int getALAP(SUnit *Node)
Return the latest time an instruction my be scheduled.
Represents a dependence between two instruction.
SUnit * getDst() const
Returns the SUnit to which the edge points (destination node).
Register getReg() const
Returns the register associated with the edge.
void setDistance(unsigned D)
Sets the distance value for the edge.
bool isBarrier() const
Returns true if the edge represents unknown scheduling barrier.
void setLatency(unsigned Latency)
Sets the latency for the edge.
SwingSchedulerDDGEdge(SUnit *PredOrSucc, const SDep &Dep, bool IsSucc, bool IsValidationOnly)
Creates an edge corresponding to an edge represented by PredOrSucc and Dep in the original DAG.
bool isAntiDep() const
Returns true if the edge represents anti dependence.
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
bool isArtificial() const
Returns true if the edge represents an artificial dependence.
LLVM_ABI bool ignoreDependence(bool IgnoreAnti) const
Returns true for DDG nodes that we ignore when computing the cost functions.
bool isOrderDep() const
Returns true if the edge represents a dependence that is not data, anti or output dependence.
unsigned getLatency() const
Returns the latency value for the edge.
SUnit * getSrc() const
Returns the SUnit from which the edge comes (source node).
bool isValidationOnly() const
Returns true if this edge is intended to be used only for validating the schedule.
unsigned getDistance() const
Returns the distance value for the edge.
bool isOutputDep() const
Returns true if the edge represents output dependence.
This class provides APIs to retrieve edges from/to an SUnit node, with a particular focus on loop-car...
LLVM_ABI SwingSchedulerDDG(std::vector< SUnit > &SUnits, SUnit *EntrySU, SUnit *ExitSU, const LoopCarriedEdges &LCE)
LLVM_ABI ArrayRef< SUnit * > getExtraOutEdges(const SUnit *SU) const
LLVM_ABI const EdgesType & getInEdges(const SUnit *SU) const
LLVM_ABI bool isValidSchedule(const SMSchedule &Schedule) const
Check if Schedule doesn't violate the validation-only dependencies.
LLVM_ABI const EdgesType & getOutEdges(const SUnit *SU) const
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
static int64_t computeDelta(SectionEntry *A, SectionEntry *B)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI cl::opt< bool > SwpEnableCopyToPhi
LLVM_ABI cl::opt< int > SwpForceIssueWidth
A command line argument to force pipeliner to use specified issue width.
static const int DefaultProcResSize
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
Represents loop-carried dependencies.
SmallSetVector< SUnit *, 8 > OrderDep
const OrderDep * getOrderDepOrNull(SUnit *Key) const
LLVM_ABI void modifySUnits(std::vector< SUnit > &SUnits, const TargetInstrInfo *TII)
Adds some edges to the original DAG that correspond to loop-carried dependencies.
LLVM_ABI void dump(SUnit *SU, const TargetRegisterInfo *TRI, const MachineRegisterInfo *MRI) const
DenseMap< SUnit *, OrderDep > OrderDepsType
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:273
Software pipelining policy for a loop, which a target can customize by implementing TargetSubtargetIn...
bool ShouldLimitRegPressure
Limit the register pressure of the scheduled loop, retrying at a higher II when a schedule needs too ...
A CRTP mix-in for passes that can be skipped.