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"
55
56#include <deque>
57
58namespace llvm {
59
60class AAResults;
61class LiveIntervals;
62class NodeSet;
63class SMSchedule;
64
65/// Return true if BaseMI and OtherMI may access overlapping memory in a later
66/// iteration of the loop LoopBB. Returns true conservatively whenever overlap
67/// cannot be ruled out.
69 const MachineInstr *OtherMI,
70 const MachineBasicBlock *LoopBB,
72 const TargetInstrInfo &TII);
73
74/// Software pipelining policy for a loop, which a target can customize by
75/// implementing TargetSubtargetInfo::overridePipelinerPolicy.
77 /// Limit the register pressure of the scheduled loop, retrying at a higher
78 /// II when a schedule needs too many registers.
80};
81
83public:
84 static char ID;
85
87
88 bool runOnMachineFunction(MachineFunction &MF) override;
89
90 void getAnalysisUsage(AnalysisUsage &AU) const override;
91};
92
94 : public OptionalPassInfoMixin<MachinePipelinerPass> {
95public:
98};
99
100/// Represents a dependence between two instruction.
102 SUnit *Dst = nullptr;
103 SDep Pred;
104 unsigned Distance = 0;
105 bool IsValidationOnly = false;
106
107public:
108 /// Creates an edge corresponding to an edge represented by \p PredOrSucc and
109 /// \p Dep in the original DAG. This pair has no information about the
110 /// direction of the edge, so we need to pass an additional argument \p
111 /// IsSucc.
112 SwingSchedulerDDGEdge(SUnit *PredOrSucc, const SDep &Dep, bool IsSucc,
113 bool IsValidationOnly)
114 : Dst(PredOrSucc), Pred(Dep), Distance(0u),
115 IsValidationOnly(IsValidationOnly) {
116 SUnit *Src = Dep.getSUnit();
117
118 if (IsSucc) {
119 std::swap(Src, Dst);
120 Pred.setSUnit(Src);
121 }
122
123 // An anti-dependence to PHI means loop-carried dependence.
124 if (Pred.getKind() == SDep::Anti && Src->getInstr()->isPHI()) {
125 Distance = 1;
126 std::swap(Src, Dst);
127 auto Reg = Pred.getReg();
128 Pred = SDep(Src, SDep::Kind::Data, Reg);
129 }
130 }
131
132 /// Returns the SUnit from which the edge comes (source node).
133 SUnit *getSrc() const { return Pred.getSUnit(); }
134
135 /// Returns the SUnit to which the edge points (destination node).
136 SUnit *getDst() const { return Dst; }
137
138 /// Returns the latency value for the edge.
139 unsigned getLatency() const { return Pred.getLatency(); }
140
141 /// Sets the latency for the edge.
142 void setLatency(unsigned Latency) { Pred.setLatency(Latency); }
143
144 /// Returns the distance value for the edge.
145 unsigned getDistance() const { return Distance; }
146
147 /// Sets the distance value for the edge.
148 void setDistance(unsigned D) { Distance = D; }
149
150 /// Returns the register associated with the edge.
151 Register getReg() const { return Pred.getReg(); }
152
153 /// Returns true if the edge represents anti dependence.
154 bool isAntiDep() const { return Pred.getKind() == SDep::Kind::Anti; }
155
156 /// Returns true if the edge represents output dependence.
157 bool isOutputDep() const { return Pred.getKind() == SDep::Kind::Output; }
158
159 /// Returns true if the edge represents a dependence that is not data, anti or
160 /// output dependence.
161 bool isOrderDep() const { return Pred.getKind() == SDep::Kind::Order; }
162
163 /// Returns true if the edge represents unknown scheduling barrier.
164 bool isBarrier() const { return Pred.isBarrier(); }
165
166 /// Returns true if the edge represents an artificial dependence.
167 bool isArtificial() const { return Pred.isArtificial(); }
168
169 /// Tests if this is a Data dependence that is associated with a register.
170 bool isAssignedRegDep() const { return Pred.isAssignedRegDep(); }
171
172 /// Returns true for DDG nodes that we ignore when computing the cost
173 /// functions. We ignore the back-edge recurrence in order to avoid unbounded
174 /// recursion in the calculation of the ASAP, ALAP, etc functions.
175 LLVM_ABI bool ignoreDependence(bool IgnoreAnti) const;
176
177 /// Returns true if this edge is intended to be used only for validating the
178 /// schedule.
179 bool isValidationOnly() const { return IsValidationOnly; }
180};
181
182/// Represents loop-carried dependencies. Because SwingSchedulerDAG doesn't
183/// assume cycle dependencies as the name suggests, such dependencies must be
184/// handled separately. After DAG construction is finished, these dependencies
185/// are added to SwingSchedulerDDG.
186/// TODO: Also handle output-dependencies introduced by physical registers.
190
192
194 auto Ite = OrderDeps.find(Key);
195 if (Ite == OrderDeps.end())
196 return nullptr;
197 return &Ite->second;
198 }
199
200 /// Adds some edges to the original DAG that correspond to loop-carried
201 /// dependencies. Historically, loop-carried edges are represented by using
202 /// non-loop-carried edges in the original DAG. This function appends such
203 /// edges to preserve the previous behavior.
204 LLVM_ABI void modifySUnits(std::vector<SUnit> &SUnits,
205 const TargetInstrInfo *TII);
206
207#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
208 LLVM_ABI void dump(SUnit *SU, const TargetRegisterInfo *TRI,
209 const MachineRegisterInfo *MRI) const;
210#endif
211};
212
213/// This class provides APIs to retrieve edges from/to an SUnit node, with a
214/// particular focus on loop-carried dependencies. Since SUnit is not designed
215/// to represent such edges, handling them directly using its APIs has required
216/// non-trivial logic in the past. This class serves as a wrapper around SUnit,
217/// offering a simpler interface for managing these dependencies.
220
221 struct SwingSchedulerDDGEdges {
222 EdgesType Preds;
223 EdgesType Succs;
224
225 /// This field is a subset of ValidationOnlyEdges. These edges are used only
226 /// by specific heuristics, mainly for cycle detection. Although they are
227 /// unnecessary in theory (i.e., ignoring them should still yield a valid
228 /// schedule), they are retained to preserve the existing behavior. Since we
229 /// only need which extra edges exist from a given SUnit, we only store the
230 /// destination SUnits.
231 SmallVector<SUnit *, 4> ExtraSuccs;
232 };
233
234 void initEdges(SUnit *SU);
235
236 SUnit *EntrySU;
237 SUnit *ExitSU;
238
239 std::vector<SwingSchedulerDDGEdges> EdgesVec;
240 SwingSchedulerDDGEdges EntrySUEdges;
241 SwingSchedulerDDGEdges ExitSUEdges;
242
243 /// Edges that are used only when validating the schedule. These edges are
244 /// not considered to drive the optimization heuristics.
245 SmallVector<SwingSchedulerDDGEdge, 8> ValidationOnlyEdges;
246
247 /// Adds a NON-validation-only edge to the DDG. Assumes to be called only by
248 /// the ctor.
249 void addEdge(const SUnit *SU, const SwingSchedulerDDGEdge &Edge);
250
251 SwingSchedulerDDGEdges &getEdges(const SUnit *SU);
252 const SwingSchedulerDDGEdges &getEdges(const SUnit *SU) const;
253
254public:
255 LLVM_ABI SwingSchedulerDDG(std::vector<SUnit> &SUnits, SUnit *EntrySU,
256 SUnit *ExitSU, const LoopCarriedEdges &LCE);
257
258 LLVM_ABI const EdgesType &getInEdges(const SUnit *SU) const;
259
260 LLVM_ABI const EdgesType &getOutEdges(const SUnit *SU) const;
261
263
264 LLVM_ABI bool isValidSchedule(const SMSchedule &Schedule) const;
265};
266
267/// This class builds the dependence graph for the instructions in a loop,
268/// and attempts to schedule the instructions using the SMS algorithm.
271
272 std::unique_ptr<SwingSchedulerDDG> DDG;
273
274 /// The minimum initiation interval between iterations for this schedule.
275 unsigned MII = 0;
276 /// The maximum initiation interval between iterations for this schedule.
277 unsigned MAX_II = 0;
278 /// Set to true if a valid pipelined schedule is found for the loop.
279 bool Scheduled = false;
280 MachineLoop &Loop;
281 LiveIntervals &LIS;
282 const RegisterClassInfo &RegClassInfo;
283 unsigned II_setByPragma = 0;
284 TargetInstrInfo::PipelinerLoopInfo *LoopPipelinerInfo = nullptr;
285
286 /// Policy for this loop, after target and command line overrides.
288
289 /// A topological ordering of the SUnits, which is needed for changing
290 /// dependences and iterating over the SUnits.
292
293 struct NodeInfo {
294 int ASAP = 0;
295 int ALAP = 0;
296 int ZeroLatencyDepth = 0;
297 int ZeroLatencyHeight = 0;
298
299 NodeInfo() = default;
300 };
301 /// Computed properties for each node in the graph.
302 std::vector<NodeInfo> ScheduleInfo;
303
304 enum OrderKind { BottomUp = 0, TopDown = 1 };
305 /// Computed node ordering for scheduling.
306 SetVector<SUnit *> NodeOrder;
307
308 using NodeSetType = SmallVector<NodeSet, 8>;
309 using ValueMapTy = DenseMap<unsigned, unsigned>;
310 using MBBVectorTy = SmallVectorImpl<MachineBasicBlock *>;
312
313 /// Instructions to change when emitting the final schedule.
315
316 /// We may create a new instruction, so remember it because it
317 /// must be deleted when the pass is finished.
319
320 /// Ordered list of DAG postprocessing steps.
321 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
322
323 /// Used to compute single-iteration dependencies (i.e., buildSchedGraph).
324 AliasAnalysis *AA;
325
326 /// Used to compute loop-carried dependencies (i.e.,
327 /// addLoopCarriedDependences).
328 BatchAAResults BAA;
329
330 MachineDominatorTree *MDT = nullptr;
331
332 /// Helper class to implement Johnson's circuit finding algorithm.
333 class Circuits {
334 std::vector<SUnit> &SUnits;
335 SetVector<SUnit *> Stack;
336 BitVector Blocked;
339 // Node to Index from ScheduleDAGTopologicalSort
340 std::vector<int> *Node2Idx;
341 unsigned NumPaths = 0u;
342 static unsigned MaxPaths;
343
344 public:
345 Circuits(std::vector<SUnit> &SUs, ScheduleDAGTopologicalSort &Topo)
346 : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) {
347 Node2Idx = new std::vector<int>(SUs.size());
348 unsigned Idx = 0;
349 for (const auto &NodeNum : Topo)
350 Node2Idx->at(NodeNum) = Idx++;
351 }
352 Circuits &operator=(const Circuits &other) = delete;
353 Circuits(const Circuits &other) = delete;
354 ~Circuits() { delete Node2Idx; }
355
356 /// Reset the data structures used in the circuit algorithm.
357 void reset() {
358 Stack.clear();
359 Blocked.reset();
360 B.assign(SUnits.size(), SmallPtrSet<SUnit *, 4>());
361 NumPaths = 0;
362 }
363
364 LLVM_ABI void createAdjacencyStructure(SwingSchedulerDDG *DDG);
365 LLVM_ABI bool circuit(int V, int S, NodeSetType &NodeSets,
366 const SwingSchedulerDAG *DAG,
367 bool HasBackedge = false);
368 LLVM_ABI void unblock(int U);
369 };
370
371 struct LLVM_ABI CopyToPhiMutation : public ScheduleDAGMutation {
372 void apply(ScheduleDAGInstrs *DAG) override;
373 };
374
375public:
378 LiveIntervals &lis, const RegisterClassInfo &rci,
380 AliasAnalysis *AA, MachineDominatorTree *MDT = nullptr);
381
382 void schedule() override;
383 void finishBlock() override;
384
385 /// Return true if the loop kernel has been scheduled.
386 bool hasNewSchedule() { return Scheduled; }
387
388 /// Return the earliest time an instruction may be scheduled.
389 int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; }
390
391 /// Return the latest time an instruction my be scheduled.
392 int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; }
393
394 /// The mobility function, which the number of slots in which
395 /// an instruction may be scheduled.
396 int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); }
397
398 /// The depth, in the dependence graph, for a node.
399 unsigned getDepth(SUnit *Node) { return Node->getDepth(); }
400
401 /// The maximum unweighted length of a path from an arbitrary node to the
402 /// given node in which each edge has latency 0
404 return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth;
405 }
406
407 /// The height, in the dependence graph, for a node.
408 unsigned getHeight(SUnit *Node) { return Node->getHeight(); }
409
410 /// The maximum unweighted length of a path from the given node to an
411 /// arbitrary node in which each edge has latency 0
413 return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight;
414 }
415
416 void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule);
417
418 void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs);
419
420 /// Return the new base register that was stored away for the changed
421 /// instruction.
424 InstrChanges.find(SU);
425 if (It != InstrChanges.end())
426 return It->second.first;
427 return Register();
428 }
429
430 void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
431 Mutations.push_back(std::move(Mutation));
432 }
433
434 static bool classof(const ScheduleDAGInstrs *DAG) { return true; }
435
436 const SwingSchedulerDDG *getDDG() const { return DDG.get(); }
437
438private:
439 /// Set the policy for this loop, allowing the target to override it.
440 void initPolicy();
441 LoopCarriedEdges addLoopCarriedDependences();
442 void updatePhiDependences();
443 void changeDependences();
444 unsigned calculateResMII();
445 unsigned calculateRecMII(NodeSetType &RecNodeSets);
446 void findCircuits(NodeSetType &NodeSets);
447 void fuseRecs(NodeSetType &NodeSets);
448 void removeDuplicateNodes(NodeSetType &NodeSets);
449 void computeNodeFunctions(NodeSetType &NodeSets);
450 void registerPressureFilter(NodeSetType &NodeSets);
451 void colocateNodeSets(NodeSetType &NodeSets);
452 void checkNodeSets(NodeSetType &NodeSets);
453 void groupRemainingNodes(NodeSetType &NodeSets);
454 void addConnectedNodes(SUnit *SU, NodeSet &NewSet,
455 SetVector<SUnit *> &NodesAdded);
456 void computeNodeOrder(NodeSetType &NodeSets);
457 void checkValidNodeOrder(const NodeSetType &Circuits) const;
458 bool schedulePipeline(SMSchedule &Schedule);
459 MachineInstr *findDefInLoop(Register Reg);
460 bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos,
461 unsigned &OffsetPos, Register &NewBase,
462 int64_t &NewOffset);
463 void postProcessDAG();
464 /// Set the Minimum Initiation Interval for this schedule attempt.
465 void setMII(unsigned ResMII, unsigned RecMII);
466 /// Set the Maximum Initiation Interval for this schedule attempt.
467 void setMAX_II();
468};
469
470/// A NodeSet contains a set of SUnit DAG nodes with additional information
471/// that assigns a priority to the set.
472class NodeSet {
473 SetVector<SUnit *> Nodes;
474 bool HasRecurrence = false;
475 unsigned RecMII = 0;
476 int MaxMOV = 0;
477 unsigned MaxDepth = 0;
478 unsigned Colocate = 0;
479 SUnit *ExceedPressure = nullptr;
480 unsigned Latency = 0;
481
482public:
484
485 NodeSet() = default;
487 : Nodes(S, E), HasRecurrence(true) {
488 // Calculate the latency of this node set.
489 // Example to demonstrate the calculation:
490 // Given: N0 -> N1 -> N2 -> N0
491 // Edges:
492 // (N0 -> N1, 3)
493 // (N0 -> N1, 5)
494 // (N1 -> N2, 2)
495 // (N2 -> N0, 1)
496 // The total latency which is a lower bound of the recurrence MII is the
497 // longest path from N0 back to N0 given only the edges of this node set.
498 // In this example, the latency is: 5 + 2 + 1 = 8.
499 //
500 // Hold a map from each SUnit in the circle to the maximum distance from the
501 // source node by only considering the nodes.
502 const SwingSchedulerDDG *DDG = DAG->getDDG();
503 DenseMap<SUnit *, unsigned> SUnitToDistance;
504 for (auto *Node : Nodes)
505 SUnitToDistance[Node] = 0;
506
507 for (unsigned I = 1, E = Nodes.size(); I <= E; ++I) {
508 SUnit *U = Nodes[I - 1];
509 SUnit *V = Nodes[I % Nodes.size()];
510 for (const SwingSchedulerDDGEdge &Succ : DDG->getOutEdges(U)) {
511 SUnit *SuccSUnit = Succ.getDst();
512 if (V != SuccSUnit)
513 continue;
514 unsigned &DU = SUnitToDistance[U];
515 unsigned &DV = SUnitToDistance[V];
516 if (DU + Succ.getLatency() > DV)
517 DV = DU + Succ.getLatency();
518 }
519 }
520 // Handle a back-edge in loop carried dependencies
521 SUnit *FirstNode = Nodes[0];
522 SUnit *LastNode = Nodes[Nodes.size() - 1];
523
524 for (SUnit *SU : DDG->getExtraOutEdges(LastNode)) {
525 // If we have an order dep that is potentially loop carried then a
526 // back-edge exists between the last node and the first node in extra
527 // edges. Handle it manually by adding 1 to the distance of the last node.
528 if (SU != FirstNode)
529 continue;
530 unsigned &First = SUnitToDistance[FirstNode];
531 unsigned Last = SUnitToDistance[LastNode];
532 First = std::max(First, Last + 1);
533 }
534
535 // The latency is the distance from the source node to itself.
536 Latency = SUnitToDistance[Nodes.front()];
537 }
538
539 bool insert(SUnit *SU) { return Nodes.insert(SU); }
540
541 void insert(iterator S, iterator E) { Nodes.insert(S, E); }
542
543 template <typename UnaryPredicate> bool remove_if(UnaryPredicate P) {
544 return Nodes.remove_if(P);
545 }
546
547 unsigned count(SUnit *SU) const { return Nodes.count(SU); }
548
549 bool hasRecurrence() { return HasRecurrence; };
550
551 unsigned size() const { return Nodes.size(); }
552
553 bool empty() const { return Nodes.empty(); }
554
555 SUnit *getNode(unsigned i) const { return Nodes[i]; };
556
557 void setRecMII(unsigned mii) { RecMII = mii; };
558
559 void setColocate(unsigned c) { Colocate = c; };
560
561 void setExceedPressure(SUnit *SU) { ExceedPressure = SU; }
562
563 bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; }
564
565 int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; }
566
567 int getRecMII() { return RecMII; }
568
569 /// Summarize node functions for the entire node set.
571 for (SUnit *SU : *this) {
572 MaxMOV = std::max(MaxMOV, SSD->getMOV(SU));
573 MaxDepth = std::max(MaxDepth, SSD->getDepth(SU));
574 }
575 }
576
577 unsigned getLatency() { return Latency; }
578
579 unsigned getMaxDepth() { return MaxDepth; }
580
581 void clear() {
582 Nodes.clear();
583 RecMII = 0;
584 HasRecurrence = false;
585 MaxMOV = 0;
586 MaxDepth = 0;
587 Colocate = 0;
588 ExceedPressure = nullptr;
589 }
590
591 operator SetVector<SUnit *> &() { return Nodes; }
592
593 /// Sort the node sets by importance. First, rank them by recurrence MII,
594 /// then by mobility (least mobile done first), and finally by depth.
595 /// Each node set may contain a colocate value which is used as the first
596 /// tie breaker, if it's set.
597 bool operator>(const NodeSet &RHS) const {
598 if (RecMII == RHS.RecMII) {
599 if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate)
600 return Colocate < RHS.Colocate;
601 if (MaxMOV == RHS.MaxMOV)
602 return MaxDepth > RHS.MaxDepth;
603 return MaxMOV < RHS.MaxMOV;
604 }
605 return RecMII > RHS.RecMII;
606 }
607
608 bool operator==(const NodeSet &RHS) const {
609 return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV &&
610 MaxDepth == RHS.MaxDepth;
611 }
612
613 bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); }
614
615 iterator begin() { return Nodes.begin(); }
616 iterator end() { return Nodes.end(); }
617
618#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
619 LLVM_ABI void print(raw_ostream &os) const;
620 LLVM_DUMP_METHOD void dump() const;
621#endif
622};
623
624// 16 was selected based on the number of ProcResource kinds for all
625// existing Subtargets, so that SmallVector don't need to resize too often.
626static const int DefaultProcResSize = 16;
627
629private:
630 const MCSubtargetInfo *STI;
631 const MCSchedModel &SM;
632 const TargetSubtargetInfo *ST;
633 const TargetInstrInfo *TII;
635 const bool UseDFA;
636 /// DFA resources for each slot
638 /// Modulo Reservation Table. When a resource with ID R is consumed in cycle
639 /// C, it is counted in MRT[C mod II][R]. (Used when UseDFA == F)
641 /// The number of scheduled micro operations for each slot. Micro operations
642 /// are assumed to be scheduled one per cycle, starting with the cycle in
643 /// which the instruction is scheduled.
644 llvm::SmallVector<int> NumScheduledMops;
645 /// Each processor resource is associated with a so-called processor resource
646 /// mask. This vector allows to correlate processor resource IDs with
647 /// processor resource masks. There is exactly one element per each processor
648 /// resource declared by the scheduling model.
650 int InitiationInterval = 0;
651 /// The number of micro operations that can be scheduled at a cycle.
652 int IssueWidth;
653
654 int calculateResMIIDFA() const;
655 /// Check if MRT is overbooked
656 bool isOverbooked() const;
657 /// Reserve resources on MRT
658 void reserveResources(const MCSchedClassDesc *SCDesc, int Cycle);
659 /// Unreserve resources on MRT
660 void unreserveResources(const MCSchedClassDesc *SCDesc, int Cycle);
661
662 /// Return M satisfying Dividend = Divisor * X + M, 0 < M < Divisor.
663 /// The slot on MRT to reserve a resource for the cycle C is positiveModulo(C,
664 /// II).
665 int positiveModulo(int Dividend, int Divisor) const {
666 assert(Divisor > 0);
667 int R = Dividend % Divisor;
668 if (R < 0)
669 R += Divisor;
670 return R;
671 }
672
673#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
674 LLVM_DUMP_METHOD void dumpMRT() const;
675#endif
676
677public:
679 ScheduleDAGInstrs *DAG);
680
683
684 /// Check if the resources occupied by a machine instruction are available
685 /// in the current state.
686 LLVM_ABI bool canReserveResources(SUnit &SU, int Cycle);
687
688 /// Reserve the resources occupied by a machine instruction and change the
689 /// current state to reflect that change.
690 LLVM_ABI void reserveResources(SUnit &SU, int Cycle);
691
692 LLVM_ABI int calculateResMII() const;
693
694 /// Initialize resources with the initiation interval II.
695 LLVM_ABI void init(int II);
696};
697
698/// This class represents the scheduled code. The main data structure is a
699/// map from scheduled cycle to instructions. During scheduling, the
700/// data structure explicitly represents all stages/iterations. When
701/// the algorithm finshes, the schedule is collapsed into a single stage,
702/// which represents instructions from different loop iterations.
703///
704/// The SMS algorithm allows negative values for cycles, so the first cycle
705/// in the schedule is the smallest cycle value.
707private:
708 /// Map from execution cycle to instructions.
709 DenseMap<int, std::deque<SUnit *>> ScheduledInstrs;
710
711 /// Map from instruction to execution cycle.
712 std::map<SUnit *, int> InstrToCycle;
713
714 /// Keep track of the first cycle value in the schedule. It starts
715 /// as zero, but the algorithm allows negative values.
716 int FirstCycle = 0;
717
718 /// Keep track of the last cycle value in the schedule.
719 int LastCycle = 0;
720
721 /// The initiation interval (II) for the schedule.
722 int InitiationInterval = 0;
723
724 /// Target machine information.
725 const TargetSubtargetInfo &ST;
726
727 /// Virtual register information.
729
730 ResourceManager ProcItinResources;
731
732public:
734 : ST(mf->getSubtarget()), MRI(mf->getRegInfo()),
735 ProcItinResources(&ST, DAG) {}
736
737 void reset() {
738 ScheduledInstrs.clear();
739 InstrToCycle.clear();
740 FirstCycle = 0;
741 LastCycle = 0;
742 InitiationInterval = 0;
743 }
744
745 /// Set the initiation interval for this schedule.
747 InitiationInterval = ii;
748 ProcItinResources.init(ii);
749 }
750
751 /// Return the initiation interval for this schedule.
752 int getInitiationInterval() const { return InitiationInterval; }
753
754 /// Return the first cycle in the completed schedule. This
755 /// can be a negative value.
756 int getFirstCycle() const { return FirstCycle; }
757
758 /// Return the last cycle in the finalized schedule.
759 int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; }
760
761 LLVM_ABI void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart,
762 int II, SwingSchedulerDAG *DAG);
763 LLVM_ABI bool insert(SUnit *SU, int StartCycle, int EndCycle, int II);
764
765 /// Iterators for the cycle to instruction map.
769
770 /// Return true if the instruction is scheduled at the specified stage.
771 bool isScheduledAtStage(SUnit *SU, unsigned StageNum) {
772 return (stageScheduled(SU) == (int)StageNum);
773 }
774
775 /// Return the stage for a scheduled instruction. Return -1 if
776 /// the instruction has not been scheduled.
777 int stageScheduled(SUnit *SU) const {
778 std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
779 if (it == InstrToCycle.end())
780 return -1;
781 return (it->second - FirstCycle) / InitiationInterval;
782 }
783
784 /// Return the cycle for a scheduled instruction. This function normalizes
785 /// the first cycle to be 0.
786 unsigned cycleScheduled(SUnit *SU) const {
787 std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
788 assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled.");
789 return (it->second - FirstCycle) % InitiationInterval;
790 }
791
792 /// Return the maximum stage count needed for this schedule.
793 unsigned getMaxStageCount() {
794 return (LastCycle - FirstCycle) / InitiationInterval;
795 }
796
797 /// Return the instructions that are scheduled at the specified cycle.
798 std::deque<SUnit *> &getInstructions(int cycle) {
799 return ScheduledInstrs[cycle];
800 }
801
803 computeUnpipelineableNodes(SwingSchedulerDAG *SSD,
805
806 LLVM_ABI std::deque<SUnit *>
807 reorderInstructions(const SwingSchedulerDAG *SSD,
808 const std::deque<SUnit *> &Instrs) const;
809
810 LLVM_ABI bool
811 normalizeNonPipelinedInstructions(SwingSchedulerDAG *SSD,
813 LLVM_ABI bool isValidSchedule(SwingSchedulerDAG *SSD);
814 LLVM_ABI void finalizeSchedule(SwingSchedulerDAG *SSD);
815 LLVM_ABI void orderDependence(const SwingSchedulerDAG *SSD, SUnit *SU,
816 std::deque<SUnit *> &Insts) const;
817 LLVM_ABI bool isLoopCarried(const SwingSchedulerDAG *SSD,
818 MachineInstr &Phi) const;
819 LLVM_ABI bool isLoopCarriedDefOfUse(const SwingSchedulerDAG *SSD,
820 MachineInstr *Def,
821 MachineOperand &MO) const;
822
823 LLVM_ABI bool
824 onlyHasLoopCarriedOutputOrOrderPreds(SUnit *SU,
825 const SwingSchedulerDDG *DDG) const;
826 LLVM_ABI void print(raw_ostream &os) const;
827 LLVM_ABI void dump() const;
828};
829
830} // end namespace llvm
831
832#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:211
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:690
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
MachineRegisterInfo & MRI
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:686
Generic base class for all target subtargets.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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 int calculateResMII() const
LLVM_ABI void initProcResourceVectors(const MCSchedModel &SM, SmallVectorImpl< uint64_t > &Masks)
LLVM_ABI ResourceManager(const TargetSubtargetInfo *ST, ScheduleDAGInstrs *DAG)
LLVM_ABI void init(int II)
Initialize resources with the initiation interval II.
LLVM_ABI bool canReserveResources(SUnit &SU, int Cycle)
Check if the resources occupied by a machine instruction are available in the current state.
Scheduling dependency.
Definition ScheduleDAG.h:54
SUnit * getSUnit() const
@ Output
A register output-dependence (aka WAW).
Definition ScheduleDAG.h:60
@ Order
Any other ordering dependency.
Definition ScheduleDAG.h:61
@ Anti
A register anti-dependence (aka WAR).
Definition ScheduleDAG.h:59
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
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.
SwingSchedulerDAG(MachineFunction &MF, const MachineLoopInfo *MLI, MachineOptimizationRemarkEmitter *ORE, MachineLoop &L, LiveIntervals &lis, const RegisterClassInfo &rci, unsigned II, TargetInstrInfo::PipelinerLoopInfo *PLI, AliasAnalysis *AA, MachineDominatorTree *MDT=nullptr)
int getASAP(SUnit *Node)
Return the earliest time an instruction may be scheduled.
const SwingSchedulerDDG * getDDG() const
void finishBlock() override
Clean up after the software pipeliner runs.
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...
void schedule() override
We override the schedule function in ScheduleDAGInstrs to implement the scheduling part of the Swing ...
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)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool mayOverlapInLaterIter(const MachineInstr *BaseMI, const MachineInstr *OtherMI, const MachineBasicBlock *LoopBB, const MachineRegisterInfo &MRI, const TargetInstrInfo &TII)
Return true if BaseMI and OtherMI may access overlapping memory in a later iteration of the loop Loop...
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
LLVM_ABI void dump(SUnit *SU, const TargetRegisterInfo *TRI, const MachineRegisterInfo *MRI) const
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.
DenseMap< SUnit *, OrderDep > OrderDepsType
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:130
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:274
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.