4040#ifndef LLVM_CODEGEN_MACHINEPIPELINER_H
4141#define LLVM_CODEGEN_MACHINEPIPELINER_H
4242
43+ #include " llvm/ADT/STLExtras.h"
4344#include " llvm/ADT/SetVector.h"
45+ #include " llvm/Analysis/AliasAnalysis.h"
4446#include " llvm/CodeGen/DFAPacketizer.h"
4547#include " llvm/CodeGen/MachineDominators.h"
4648#include " llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
@@ -59,6 +61,8 @@ namespace llvm {
5961class AAResults ;
6062class NodeSet ;
6163class SMSchedule ;
64+ class SwingSchedulerDDGEdge ;
65+ class SwingSchedulerDDG ;
6266
6367extern cl::opt<bool > SwpEnableCopyToPhi;
6468extern cl::opt<int > SwpForceIssueWidth;
@@ -114,10 +118,123 @@ class MachinePipeliner : public MachineFunctionPass {
114118 bool useWindowScheduler (bool Changed);
115119};
116120
121+ // / Represents a dependnece between two instruction.
122+ class SwingSchedulerDDGEdge {
123+ SUnit *Dst = nullptr ;
124+ SDep Pred;
125+ unsigned Distance = 0 ;
126+
127+ public:
128+ // / Creates an edge corresponding to an edge represented by \p PredOrSucc and
129+ // / \p Dep in the original DAG. This pair has no information about the
130+ // / direction of the edge, so we need to pass an additional argument \p
131+ // / IsSucc.
132+ SwingSchedulerDDGEdge (SUnit *PredOrSucc, const SDep &Dep, bool IsSucc)
133+ : Dst(PredOrSucc), Pred(Dep), Distance(0u ) {
134+ SUnit *Src = Dep.getSUnit ();
135+
136+ if (IsSucc) {
137+ std::swap (Src, Dst);
138+ Pred.setSUnit (Src);
139+ }
140+
141+ // An anti-dependence to PHI means loop-carried dependence.
142+ if (Pred.getKind () == SDep::Anti && Src->getInstr ()->isPHI ()) {
143+ Distance = 1 ;
144+ std::swap (Src, Dst);
145+ auto Reg = Pred.getReg ();
146+ Pred = SDep (Src, SDep::Kind::Data, Reg);
147+ }
148+ }
149+
150+ // / Returns the SUnit from which the edge comes (source node).
151+ SUnit *getSrc () const { return Pred.getSUnit (); }
152+
153+ // / Returns the SUnit to which the edge points (destination node).
154+ SUnit *getDst () const { return Dst; }
155+
156+ // / Returns the latency value for the edge.
157+ unsigned getLatency () const { return Pred.getLatency (); }
158+
159+ // / Sets the latency for the edge.
160+ void setLatency (unsigned Latency) { Pred.setLatency (Latency); }
161+
162+ // / Returns the distance value for the edge.
163+ unsigned getDistance () const { return Distance; }
164+
165+ // / Sets the distance value for the edge.
166+ void setDistance (unsigned D) { Distance = D; }
167+
168+ // / Returns the register associated with the edge.
169+ Register getReg () const { return Pred.getReg (); }
170+
171+ // / Returns true if the edge represents anti dependence.
172+ bool isAntiDep () const { return Pred.getKind () == SDep::Kind::Anti; }
173+
174+ // / Returns true if the edge represents output dependence.
175+ bool isOutputDep () const { return Pred.getKind () == SDep::Kind::Output; }
176+
177+ // / Returns true if the edge represents a dependence that is not data, anti or
178+ // / output dependence.
179+ bool isOrderDep () const { return Pred.getKind () == SDep::Kind::Order; }
180+
181+ // / Returns true if the edge represents unknown scheduling barrier.
182+ bool isBarrier () const { return Pred.isBarrier (); }
183+
184+ // / Returns true if the edge represents an artificial dependence.
185+ bool isArtificial () const { return Pred.isArtificial (); }
186+
187+ // / Tests if this is a Data dependence that is associated with a register.
188+ bool isAssignedRegDep () const { return Pred.isAssignedRegDep (); }
189+
190+ // / Returns true for DDG nodes that we ignore when computing the cost
191+ // / functions. We ignore the back-edge recurrence in order to avoid unbounded
192+ // / recursion in the calculation of the ASAP, ALAP, etc functions.
193+ bool ignoreDependence (bool IgnoreAnti) const ;
194+ };
195+
196+ // / Represents dependencies between instructions. This class is a wrapper of
197+ // / `SUnits` and its dependencies to manipulate back-edges in a natural way.
198+ // / Currently it only supports back-edges via PHI, which are expressed as
199+ // / anti-dependencies in the original DAG.
200+ // / FIXME: Support any other loop-carried dependencies
201+ class SwingSchedulerDDG {
202+ using EdgesType = SmallVector<SwingSchedulerDDGEdge, 4 >;
203+
204+ struct SwingSchedulerDDGEdges {
205+ EdgesType Preds;
206+ EdgesType Succs;
207+ };
208+
209+ void initEdges (SUnit *SU);
210+
211+ SUnit *EntrySU;
212+ SUnit *ExitSU;
213+
214+ std::vector<SwingSchedulerDDGEdges> EdgesVec;
215+ SwingSchedulerDDGEdges EntrySUEdges;
216+ SwingSchedulerDDGEdges ExitSUEdges;
217+
218+ void addEdge (SUnit *SU, const SwingSchedulerDDGEdge &Edge);
219+
220+ SwingSchedulerDDGEdges &getEdges (const SUnit *SU);
221+ const SwingSchedulerDDGEdges &getEdges (const SUnit *SU) const ;
222+
223+ public:
224+ SwingSchedulerDDG (std::vector<SUnit> &SUnits, SUnit *EntrySU, SUnit *ExitSU);
225+
226+ const EdgesType &getInEdges (const SUnit *SU) const ;
227+
228+ const EdgesType &getOutEdges (const SUnit *SU) const ;
229+ };
230+
117231// / This class builds the dependence graph for the instructions in a loop,
118232// / and attempts to schedule the instructions using the SMS algorithm.
119233class SwingSchedulerDAG : public ScheduleDAGInstrs {
120234 MachinePipeliner &Pass;
235+
236+ std::unique_ptr<SwingSchedulerDDG> DDG;
237+
121238 // / The minimum initiation interval between iterations for this schedule.
122239 unsigned MII = 0 ;
123240 // / The maximum initiation interval between iterations for this schedule.
@@ -130,7 +247,7 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
130247 unsigned II_setByPragma = 0 ;
131248 TargetInstrInfo::PipelinerLoopInfo *LoopPipelinerInfo = nullptr ;
132249
133- // / A toplogical ordering of the SUnits, which is needed for changing
250+ // / A topological ordering of the SUnits, which is needed for changing
134251 // / dependences and iterating over the SUnits.
135252 ScheduleDAGTopologicalSort Topo;
136253
@@ -252,27 +369,7 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
252369 return ScheduleInfo[Node->NodeNum ].ZeroLatencyHeight ;
253370 }
254371
255- // / Return true if the dependence is a back-edge in the data dependence graph.
256- // / Since the DAG doesn't contain cycles, we represent a cycle in the graph
257- // / using an anti dependence from a Phi to an instruction.
258- bool isBackedge (SUnit *Source, const SDep &Dep) {
259- if (Dep.getKind () != SDep::Anti)
260- return false ;
261- return Source->getInstr ()->isPHI () || Dep.getSUnit ()->getInstr ()->isPHI ();
262- }
263-
264- bool isLoopCarriedDep (SUnit *Source, const SDep &Dep,
265- bool isSucc = true ) const ;
266-
267- // / The distance function, which indicates that operation V of iteration I
268- // / depends on operations U of iteration I-distance.
269- unsigned getDistance (SUnit *U, SUnit *V, const SDep &Dep) {
270- // Instructions that feed a Phi have a distance of 1. Computing larger
271- // values for arrays requires data dependence information.
272- if (V->getInstr ()->isPHI () && Dep.getKind () == SDep::Anti)
273- return 1 ;
274- return 0 ;
275- }
372+ bool isLoopCarriedDep (const SwingSchedulerDDGEdge &Edge) const ;
276373
277374 void applyInstrChange (MachineInstr *MI, SMSchedule &Schedule);
278375
@@ -294,6 +391,8 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
294391
295392 static bool classof (const ScheduleDAGInstrs *DAG) { return true ; }
296393
394+ const SwingSchedulerDDG *getDDG () const { return DDG.get (); }
395+
297396private:
298397 void addLoopCarriedDependences (AAResults *AA);
299398 void updatePhiDependences ();
@@ -357,15 +456,16 @@ class NodeSet {
357456 //
358457 // Hold a map from each SUnit in the circle to the maximum distance from the
359458 // source node by only considering the nodes.
459+ const SwingSchedulerDDG *DDG = DAG->getDDG ();
360460 DenseMap<SUnit *, unsigned > SUnitToDistance;
361461 for (auto *Node : Nodes)
362462 SUnitToDistance[Node] = 0 ;
363463
364464 for (unsigned I = 1 , E = Nodes.size (); I <= E; ++I) {
365465 SUnit *U = Nodes[I - 1 ];
366466 SUnit *V = Nodes[I % Nodes.size ()];
367- for (const SDep &Succ : U-> Succs ) {
368- SUnit *SuccSUnit = Succ.getSUnit ();
467+ for (const SwingSchedulerDDGEdge &Succ : DDG-> getOutEdges (U) ) {
468+ SUnit *SuccSUnit = Succ.getDst ();
369469 if (V != SuccSUnit)
370470 continue ;
371471 if (SUnitToDistance[U] + Succ.getLatency () > SUnitToDistance[V]) {
@@ -377,13 +477,13 @@ class NodeSet {
377477 SUnit *FirstNode = Nodes[0 ];
378478 SUnit *LastNode = Nodes[Nodes.size () - 1 ];
379479
380- for (auto &PI : LastNode-> Preds ) {
480+ for (auto &PI : DDG-> getInEdges (LastNode) ) {
381481 // If we have an order dep that is potentially loop carried then a
382482 // back-edge exists between the last node and the first node that isn't
383483 // modeled in the DAG. Handle it manually by adding 1 to the distance of
384484 // the last node.
385- if (PI.getSUnit () != FirstNode || PI.getKind () != SDep::Order ||
386- !DAG->isLoopCarriedDep (LastNode, PI, false ))
485+ if (PI.getSrc () != FirstNode || ! PI.isOrderDep () ||
486+ !DAG->isLoopCarriedDep (PI ))
387487 continue ;
388488 SUnitToDistance[FirstNode] =
389489 std::max (SUnitToDistance[FirstNode], SUnitToDistance[LastNode] + 1 );
@@ -627,11 +727,13 @@ class SMSchedule {
627727
628728 // / Return the cycle of the earliest scheduled instruction in the dependence
629729 // / chain.
630- int earliestCycleInChain (const SDep &Dep);
730+ int earliestCycleInChain (const SwingSchedulerDDGEdge &Dep,
731+ const SwingSchedulerDDG *DDG);
631732
632733 // / Return the cycle of the latest scheduled instruction in the dependence
633734 // / chain.
634- int latestCycleInChain (const SDep &Dep);
735+ int latestCycleInChain (const SwingSchedulerDDGEdge &Dep,
736+ const SwingSchedulerDDG *DDG);
635737
636738 void computeStart (SUnit *SU, int *MaxEarlyStart, int *MinLateStart, int II,
637739 SwingSchedulerDAG *DAG);
@@ -694,7 +796,7 @@ class SMSchedule {
694796 MachineOperand &MO) const ;
695797
696798 bool onlyHasLoopCarriedOutputOrOrderPreds (SUnit *SU,
697- SwingSchedulerDAG *DAG ) const ;
799+ const SwingSchedulerDDG *DDG ) const ;
698800 void print (raw_ostream &os) const ;
699801 void dump () const ;
700802};
0 commit comments