40
40
#ifndef LLVM_CODEGEN_MACHINEPIPELINER_H
41
41
#define LLVM_CODEGEN_MACHINEPIPELINER_H
42
42
43
+ #include " llvm/ADT/STLExtras.h"
43
44
#include " llvm/ADT/SetVector.h"
45
+ #include " llvm/Analysis/AliasAnalysis.h"
44
46
#include " llvm/CodeGen/DFAPacketizer.h"
45
47
#include " llvm/CodeGen/MachineDominators.h"
46
48
#include " llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
@@ -59,6 +61,8 @@ namespace llvm {
59
61
class AAResults ;
60
62
class NodeSet ;
61
63
class SMSchedule ;
64
+ class SwingSchedulerDDGEdge ;
65
+ class SwingSchedulerDDG ;
62
66
63
67
extern cl::opt<bool > SwpEnableCopyToPhi;
64
68
extern cl::opt<int > SwpForceIssueWidth;
@@ -114,10 +118,123 @@ class MachinePipeliner : public MachineFunctionPass {
114
118
bool useWindowScheduler (bool Changed);
115
119
};
116
120
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
+
117
231
// / This class builds the dependence graph for the instructions in a loop,
118
232
// / and attempts to schedule the instructions using the SMS algorithm.
119
233
class SwingSchedulerDAG : public ScheduleDAGInstrs {
120
234
MachinePipeliner &Pass;
235
+
236
+ std::unique_ptr<SwingSchedulerDDG> DDG;
237
+
121
238
// / The minimum initiation interval between iterations for this schedule.
122
239
unsigned MII = 0 ;
123
240
// / The maximum initiation interval between iterations for this schedule.
@@ -130,7 +247,7 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
130
247
unsigned II_setByPragma = 0 ;
131
248
TargetInstrInfo::PipelinerLoopInfo *LoopPipelinerInfo = nullptr ;
132
249
133
- // / A toplogical ordering of the SUnits, which is needed for changing
250
+ // / A topological ordering of the SUnits, which is needed for changing
134
251
// / dependences and iterating over the SUnits.
135
252
ScheduleDAGTopologicalSort Topo;
136
253
@@ -252,27 +369,7 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
252
369
return ScheduleInfo[Node->NodeNum ].ZeroLatencyHeight ;
253
370
}
254
371
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 ;
276
373
277
374
void applyInstrChange (MachineInstr *MI, SMSchedule &Schedule);
278
375
@@ -294,6 +391,8 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
294
391
295
392
static bool classof (const ScheduleDAGInstrs *DAG) { return true ; }
296
393
394
+ const SwingSchedulerDDG *getDDG () const { return DDG.get (); }
395
+
297
396
private:
298
397
void addLoopCarriedDependences (AAResults *AA);
299
398
void updatePhiDependences ();
@@ -357,15 +456,16 @@ class NodeSet {
357
456
//
358
457
// Hold a map from each SUnit in the circle to the maximum distance from the
359
458
// source node by only considering the nodes.
459
+ const SwingSchedulerDDG *DDG = DAG->getDDG ();
360
460
DenseMap<SUnit *, unsigned > SUnitToDistance;
361
461
for (auto *Node : Nodes)
362
462
SUnitToDistance[Node] = 0 ;
363
463
364
464
for (unsigned I = 1 , E = Nodes.size (); I <= E; ++I) {
365
465
SUnit *U = Nodes[I - 1 ];
366
466
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 ();
369
469
if (V != SuccSUnit)
370
470
continue ;
371
471
if (SUnitToDistance[U] + Succ.getLatency () > SUnitToDistance[V]) {
@@ -377,13 +477,13 @@ class NodeSet {
377
477
SUnit *FirstNode = Nodes[0 ];
378
478
SUnit *LastNode = Nodes[Nodes.size () - 1 ];
379
479
380
- for (auto &PI : LastNode-> Preds ) {
480
+ for (auto &PI : DDG-> getInEdges (LastNode) ) {
381
481
// If we have an order dep that is potentially loop carried then a
382
482
// back-edge exists between the last node and the first node that isn't
383
483
// modeled in the DAG. Handle it manually by adding 1 to the distance of
384
484
// 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 ))
387
487
continue ;
388
488
SUnitToDistance[FirstNode] =
389
489
std::max (SUnitToDistance[FirstNode], SUnitToDistance[LastNode] + 1 );
@@ -627,11 +727,13 @@ class SMSchedule {
627
727
628
728
// / Return the cycle of the earliest scheduled instruction in the dependence
629
729
// / chain.
630
- int earliestCycleInChain (const SDep &Dep);
730
+ int earliestCycleInChain (const SwingSchedulerDDGEdge &Dep,
731
+ const SwingSchedulerDDG *DDG);
631
732
632
733
// / Return the cycle of the latest scheduled instruction in the dependence
633
734
// / chain.
634
- int latestCycleInChain (const SDep &Dep);
735
+ int latestCycleInChain (const SwingSchedulerDDGEdge &Dep,
736
+ const SwingSchedulerDDG *DDG);
635
737
636
738
void computeStart (SUnit *SU, int *MaxEarlyStart, int *MinLateStart, int II,
637
739
SwingSchedulerDAG *DAG);
@@ -694,7 +796,7 @@ class SMSchedule {
694
796
MachineOperand &MO) const ;
695
797
696
798
bool onlyHasLoopCarriedOutputOrOrderPreds (SUnit *SU,
697
- SwingSchedulerDAG *DAG ) const ;
799
+ const SwingSchedulerDDG *DDG ) const ;
698
800
void print (raw_ostream &os) const ;
699
801
void dump () const ;
700
802
};
0 commit comments