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