Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===//
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
// This file provides an interface for customizing the standard MachineScheduler
10
// pass. Note that the entire pass may be replaced as follows:
11
//
12
// <Target>TargetMachine::createPassConfig(PassManagerBase &PM) {
13
//   PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID);
14
//   ...}
15
//
16
// The MachineScheduler pass is only responsible for choosing the regions to be
17
// scheduled. Targets can override the DAG builder and scheduler without
18
// replacing the pass as follows:
19
//
20
// ScheduleDAGInstrs *<Target>PassConfig::
21
// createMachineScheduler(MachineSchedContext *C) {
22
//   return new CustomMachineScheduler(C);
23
// }
24
//
25
// The default scheduler, ScheduleDAGMILive, builds the DAG and drives list
26
// scheduling while updating the instruction stream, register pressure, and live
27
// intervals. Most targets don't need to override the DAG builder and list
28
// scheduler, but subtargets that require custom scheduling heuristics may
29
// plugin an alternate MachineSchedStrategy. The strategy is responsible for
30
// selecting the highest priority node from the list:
31
//
32
// ScheduleDAGInstrs *<Target>PassConfig::
33
// createMachineScheduler(MachineSchedContext *C) {
34
//   return new ScheduleDAGMILive(C, CustomStrategy(C));
35
// }
36
//
37
// The DAG builder can also be customized in a sense by adding DAG mutations
38
// that will run after DAG building and before list scheduling. DAG mutations
39
// can adjust dependencies based on target-specific knowledge or add weak edges
40
// to aid heuristics:
41
//
42
// ScheduleDAGInstrs *<Target>PassConfig::
43
// createMachineScheduler(MachineSchedContext *C) {
44
//   ScheduleDAGMI *DAG = createGenericSchedLive(C);
45
//   DAG->addMutation(new CustomDAGMutation(...));
46
//   return DAG;
47
// }
48
//
49
// A target that supports alternative schedulers can use the
50
// MachineSchedRegistry to allow command line selection. This can be done by
51
// implementing the following boilerplate:
52
//
53
// static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) {
54
//  return new CustomMachineScheduler(C);
55
// }
56
// static MachineSchedRegistry
57
// SchedCustomRegistry("custom", "Run my target's custom scheduler",
58
//                     createCustomMachineSched);
59
//
60
//
61
// Finally, subtargets that don't need to implement custom heuristics but would
62
// like to configure the GenericScheduler's policy for a given scheduler region,
63
// including scheduling direction and register pressure tracking policy, can do
64
// this:
65
//
66
// void <SubTarget>Subtarget::
67
// overrideSchedPolicy(MachineSchedPolicy &Policy,
68
//                     unsigned NumRegionInstrs) const {
69
//   Policy.<Flag> = true;
70
// }
71
//
72
//===----------------------------------------------------------------------===//
73
 
74
#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
75
#define LLVM_CODEGEN_MACHINESCHEDULER_H
76
 
77
#include "llvm/ADT/APInt.h"
78
#include "llvm/ADT/ArrayRef.h"
79
#include "llvm/ADT/BitVector.h"
80
#include "llvm/ADT/STLExtras.h"
81
#include "llvm/ADT/SmallVector.h"
82
#include "llvm/ADT/StringRef.h"
83
#include "llvm/ADT/Twine.h"
84
#include "llvm/CodeGen/MachineBasicBlock.h"
85
#include "llvm/CodeGen/MachinePassRegistry.h"
86
#include "llvm/CodeGen/RegisterPressure.h"
87
#include "llvm/CodeGen/ScheduleDAG.h"
88
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
89
#include "llvm/CodeGen/ScheduleDAGMutation.h"
90
#include "llvm/CodeGen/TargetSchedule.h"
91
#include "llvm/Support/CommandLine.h"
92
#include "llvm/Support/ErrorHandling.h"
93
#include <algorithm>
94
#include <cassert>
95
#include <memory>
96
#include <string>
97
#include <vector>
98
 
99
namespace llvm {
100
 
101
extern cl::opt<bool> ForceTopDown;
102
extern cl::opt<bool> ForceBottomUp;
103
extern cl::opt<bool> VerifyScheduling;
104
#ifndef NDEBUG
105
extern cl::opt<bool> ViewMISchedDAGs;
106
extern cl::opt<bool> PrintDAGs;
107
#else
108
extern const bool ViewMISchedDAGs;
109
extern const bool PrintDAGs;
110
#endif
111
 
112
class AAResults;
113
class LiveIntervals;
114
class MachineDominatorTree;
115
class MachineFunction;
116
class MachineInstr;
117
class MachineLoopInfo;
118
class RegisterClassInfo;
119
class SchedDFSResult;
120
class ScheduleHazardRecognizer;
121
class TargetInstrInfo;
122
class TargetPassConfig;
123
class TargetRegisterInfo;
124
 
125
/// MachineSchedContext provides enough context from the MachineScheduler pass
126
/// for the target to instantiate a scheduler.
127
struct MachineSchedContext {
128
  MachineFunction *MF = nullptr;
129
  const MachineLoopInfo *MLI = nullptr;
130
  const MachineDominatorTree *MDT = nullptr;
131
  const TargetPassConfig *PassConfig = nullptr;
132
  AAResults *AA = nullptr;
133
  LiveIntervals *LIS = nullptr;
134
 
135
  RegisterClassInfo *RegClassInfo;
136
 
137
  MachineSchedContext();
138
  virtual ~MachineSchedContext();
139
};
140
 
141
/// MachineSchedRegistry provides a selection of available machine instruction
142
/// schedulers.
143
class MachineSchedRegistry
144
    : public MachinePassRegistryNode<
145
          ScheduleDAGInstrs *(*)(MachineSchedContext *)> {
146
public:
147
  using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *);
148
 
149
  // RegisterPassParser requires a (misnamed) FunctionPassCtor type.
150
  using FunctionPassCtor = ScheduleDAGCtor;
151
 
152
  static MachinePassRegistry<ScheduleDAGCtor> Registry;
153
 
154
  MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
155
      : MachinePassRegistryNode(N, D, C) {
156
    Registry.Add(this);
157
  }
158
 
159
  ~MachineSchedRegistry() { Registry.Remove(this); }
160
 
161
  // Accessors.
162
  //
163
  MachineSchedRegistry *getNext() const {
164
    return (MachineSchedRegistry *)MachinePassRegistryNode::getNext();
165
  }
166
 
167
  static MachineSchedRegistry *getList() {
168
    return (MachineSchedRegistry *)Registry.getList();
169
  }
170
 
171
  static void setListener(MachinePassRegistryListener<FunctionPassCtor> *L) {
172
    Registry.setListener(L);
173
  }
174
};
175
 
176
class ScheduleDAGMI;
177
 
178
/// Define a generic scheduling policy for targets that don't provide their own
179
/// MachineSchedStrategy. This can be overriden for each scheduling region
180
/// before building the DAG.
181
struct MachineSchedPolicy {
182
  // Allow the scheduler to disable register pressure tracking.
183
  bool ShouldTrackPressure = false;
184
  /// Track LaneMasks to allow reordering of independent subregister writes
185
  /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
186
  bool ShouldTrackLaneMasks = false;
187
 
188
  // Allow the scheduler to force top-down or bottom-up scheduling. If neither
189
  // is true, the scheduler runs in both directions and converges.
190
  bool OnlyTopDown = false;
191
  bool OnlyBottomUp = false;
192
 
193
  // Disable heuristic that tries to fetch nodes from long dependency chains
194
  // first.
195
  bool DisableLatencyHeuristic = false;
196
 
197
  // Compute DFSResult for use in scheduling heuristics.
198
  bool ComputeDFSResult = false;
199
 
200
  MachineSchedPolicy() = default;
201
};
202
 
203
/// MachineSchedStrategy - Interface to the scheduling algorithm used by
204
/// ScheduleDAGMI.
205
///
206
/// Initialization sequence:
207
///   initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots
208
class MachineSchedStrategy {
209
  virtual void anchor();
210
 
211
public:
212
  virtual ~MachineSchedStrategy() = default;
213
 
214
  /// Optionally override the per-region scheduling policy.
215
  virtual void initPolicy(MachineBasicBlock::iterator Begin,
216
                          MachineBasicBlock::iterator End,
217
                          unsigned NumRegionInstrs) {}
218
 
219
  virtual void dumpPolicy() const {}
220
 
221
  /// Check if pressure tracking is needed before building the DAG and
222
  /// initializing this strategy. Called after initPolicy.
223
  virtual bool shouldTrackPressure() const { return true; }
224
 
225
  /// Returns true if lanemasks should be tracked. LaneMask tracking is
226
  /// necessary to reorder independent subregister defs for the same vreg.
227
  /// This has to be enabled in combination with shouldTrackPressure().
228
  virtual bool shouldTrackLaneMasks() const { return false; }
229
 
230
  // If this method returns true, handling of the scheduling regions
231
  // themselves (in case of a scheduling boundary in MBB) will be done
232
  // beginning with the topmost region of MBB.
233
  virtual bool doMBBSchedRegionsTopDown() const { return false; }
234
 
235
  /// Initialize the strategy after building the DAG for a new region.
236
  virtual void initialize(ScheduleDAGMI *DAG) = 0;
237
 
238
  /// Tell the strategy that MBB is about to be processed.
239
  virtual void enterMBB(MachineBasicBlock *MBB) {};
240
 
241
  /// Tell the strategy that current MBB is done.
242
  virtual void leaveMBB() {};
243
 
244
  /// Notify this strategy that all roots have been released (including those
245
  /// that depend on EntrySU or ExitSU).
246
  virtual void registerRoots() {}
247
 
248
  /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
249
  /// schedule the node at the top of the unscheduled region. Otherwise it will
250
  /// be scheduled at the bottom.
251
  virtual SUnit *pickNode(bool &IsTopNode) = 0;
252
 
253
  /// Scheduler callback to notify that a new subtree is scheduled.
254
  virtual void scheduleTree(unsigned SubtreeID) {}
255
 
256
  /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
257
  /// instruction and updated scheduled/remaining flags in the DAG nodes.
258
  virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
259
 
260
  /// When all predecessor dependencies have been resolved, free this node for
261
  /// top-down scheduling.
262
  virtual void releaseTopNode(SUnit *SU) = 0;
263
 
264
  /// When all successor dependencies have been resolved, free this node for
265
  /// bottom-up scheduling.
266
  virtual void releaseBottomNode(SUnit *SU) = 0;
267
};
268
 
269
/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
270
/// schedules machine instructions according to the given MachineSchedStrategy
271
/// without much extra book-keeping. This is the common functionality between
272
/// PreRA and PostRA MachineScheduler.
273
class ScheduleDAGMI : public ScheduleDAGInstrs {
274
protected:
275
  AAResults *AA;
276
  LiveIntervals *LIS;
277
  std::unique_ptr<MachineSchedStrategy> SchedImpl;
278
 
279
  /// Ordered list of DAG postprocessing steps.
280
  std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
281
 
282
  /// The top of the unscheduled zone.
283
  MachineBasicBlock::iterator CurrentTop;
284
 
285
  /// The bottom of the unscheduled zone.
286
  MachineBasicBlock::iterator CurrentBottom;
287
 
288
  /// Record the next node in a scheduled cluster.
289
  const SUnit *NextClusterPred = nullptr;
290
  const SUnit *NextClusterSucc = nullptr;
291
 
292
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
293
  /// The number of instructions scheduled so far. Used to cut off the
294
  /// scheduler at the point determined by misched-cutoff.
295
  unsigned NumInstrsScheduled = 0;
296
#endif
297
 
298
public:
299
  ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
300
                bool RemoveKillFlags)
301
      : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA),
302
        LIS(C->LIS), SchedImpl(std::move(S)) {}
303
 
304
  // Provide a vtable anchor
305
  ~ScheduleDAGMI() override;
306
 
307
  /// If this method returns true, handling of the scheduling regions
308
  /// themselves (in case of a scheduling boundary in MBB) will be done
309
  /// beginning with the topmost region of MBB.
310
  bool doMBBSchedRegionsTopDown() const override {
311
    return SchedImpl->doMBBSchedRegionsTopDown();
312
  }
313
 
314
  // Returns LiveIntervals instance for use in DAG mutators and such.
315
  LiveIntervals *getLIS() const { return LIS; }
316
 
317
  /// Return true if this DAG supports VReg liveness and RegPressure.
318
  virtual bool hasVRegLiveness() const { return false; }
319
 
320
  /// Add a postprocessing step to the DAG builder.
321
  /// Mutations are applied in the order that they are added after normal DAG
322
  /// building and before MachineSchedStrategy initialization.
323
  ///
324
  /// ScheduleDAGMI takes ownership of the Mutation object.
325
  void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
326
    if (Mutation)
327
      Mutations.push_back(std::move(Mutation));
328
  }
329
 
330
  MachineBasicBlock::iterator top() const { return CurrentTop; }
331
  MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
332
 
333
  /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
334
  /// region. This covers all instructions in a block, while schedule() may only
335
  /// cover a subset.
336
  void enterRegion(MachineBasicBlock *bb,
337
                   MachineBasicBlock::iterator begin,
338
                   MachineBasicBlock::iterator end,
339
                   unsigned regioninstrs) override;
340
 
341
  /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
342
  /// reorderable instructions.
343
  void schedule() override;
344
 
345
  void startBlock(MachineBasicBlock *bb) override;
346
  void finishBlock() override;
347
 
348
  /// Change the position of an instruction within the basic block and update
349
  /// live ranges and region boundary iterators.
350
  void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
351
 
352
  const SUnit *getNextClusterPred() const { return NextClusterPred; }
353
 
354
  const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
355
 
356
  void viewGraph(const Twine &Name, const Twine &Title) override;
357
  void viewGraph() override;
358
 
359
protected:
360
  // Top-Level entry points for the schedule() driver...
361
 
362
  /// Apply each ScheduleDAGMutation step in order. This allows different
363
  /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
364
  void postprocessDAG();
365
 
366
  /// Release ExitSU predecessors and setup scheduler queues.
367
  void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
368
 
369
  /// Update scheduler DAG and queues after scheduling an instruction.
370
  void updateQueues(SUnit *SU, bool IsTopNode);
371
 
372
  /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
373
  void placeDebugValues();
374
 
375
  /// dump the scheduled Sequence.
376
  void dumpSchedule() const;
377
 
378
  // Lesser helpers...
379
  bool checkSchedLimit();
380
 
381
  void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
382
                             SmallVectorImpl<SUnit*> &BotRoots);
383
 
384
  void releaseSucc(SUnit *SU, SDep *SuccEdge);
385
  void releaseSuccessors(SUnit *SU);
386
  void releasePred(SUnit *SU, SDep *PredEdge);
387
  void releasePredecessors(SUnit *SU);
388
};
389
 
390
/// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules
391
/// machine instructions while updating LiveIntervals and tracking regpressure.
392
class ScheduleDAGMILive : public ScheduleDAGMI {
393
protected:
394
  RegisterClassInfo *RegClassInfo;
395
 
396
  /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
397
  /// will be empty.
398
  SchedDFSResult *DFSResult = nullptr;
399
  BitVector ScheduledTrees;
400
 
401
  MachineBasicBlock::iterator LiveRegionEnd;
402
 
403
  /// Maps vregs to the SUnits of their uses in the current scheduling region.
404
  VReg2SUnitMultiMap VRegUses;
405
 
406
  // Map each SU to its summary of pressure changes. This array is updated for
407
  // liveness during bottom-up scheduling. Top-down scheduling may proceed but
408
  // has no affect on the pressure diffs.
409
  PressureDiffs SUPressureDiffs;
410
 
411
  /// Register pressure in this region computed by initRegPressure.
412
  bool ShouldTrackPressure = false;
413
  bool ShouldTrackLaneMasks = false;
414
  IntervalPressure RegPressure;
415
  RegPressureTracker RPTracker;
416
 
417
  /// List of pressure sets that exceed the target's pressure limit before
418
  /// scheduling, listed in increasing set ID order. Each pressure set is paired
419
  /// with its max pressure in the currently scheduled regions.
420
  std::vector<PressureChange> RegionCriticalPSets;
421
 
422
  /// The top of the unscheduled zone.
423
  IntervalPressure TopPressure;
424
  RegPressureTracker TopRPTracker;
425
 
426
  /// The bottom of the unscheduled zone.
427
  IntervalPressure BotPressure;
428
  RegPressureTracker BotRPTracker;
429
 
430
public:
431
  ScheduleDAGMILive(MachineSchedContext *C,
432
                    std::unique_ptr<MachineSchedStrategy> S)
433
      : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
434
        RegClassInfo(C->RegClassInfo), RPTracker(RegPressure),
435
        TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
436
 
437
  ~ScheduleDAGMILive() override;
438
 
439
  /// Return true if this DAG supports VReg liveness and RegPressure.
440
  bool hasVRegLiveness() const override { return true; }
441
 
442
  /// Return true if register pressure tracking is enabled.
443
  bool isTrackingPressure() const { return ShouldTrackPressure; }
444
 
445
  /// Get current register pressure for the top scheduled instructions.
446
  const IntervalPressure &getTopPressure() const { return TopPressure; }
447
  const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
448
 
449
  /// Get current register pressure for the bottom scheduled instructions.
450
  const IntervalPressure &getBotPressure() const { return BotPressure; }
451
  const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
452
 
453
  /// Get register pressure for the entire scheduling region before scheduling.
454
  const IntervalPressure &getRegPressure() const { return RegPressure; }
455
 
456
  const std::vector<PressureChange> &getRegionCriticalPSets() const {
457
    return RegionCriticalPSets;
458
  }
459
 
460
  PressureDiff &getPressureDiff(const SUnit *SU) {
461
    return SUPressureDiffs[SU->NodeNum];
462
  }
463
  const PressureDiff &getPressureDiff(const SUnit *SU) const {
464
    return SUPressureDiffs[SU->NodeNum];
465
  }
466
 
467
  /// Compute a DFSResult after DAG building is complete, and before any
468
  /// queue comparisons.
469
  void computeDFSResult();
470
 
471
  /// Return a non-null DFS result if the scheduling strategy initialized it.
472
  const SchedDFSResult *getDFSResult() const { return DFSResult; }
473
 
474
  BitVector &getScheduledTrees() { return ScheduledTrees; }
475
 
476
  /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
477
  /// region. This covers all instructions in a block, while schedule() may only
478
  /// cover a subset.
479
  void enterRegion(MachineBasicBlock *bb,
480
                   MachineBasicBlock::iterator begin,
481
                   MachineBasicBlock::iterator end,
482
                   unsigned regioninstrs) override;
483
 
484
  /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
485
  /// reorderable instructions.
486
  void schedule() override;
487
 
488
  /// Compute the cyclic critical path through the DAG.
489
  unsigned computeCyclicCriticalPath();
490
 
491
  void dump() const override;
492
 
493
protected:
494
  // Top-Level entry points for the schedule() driver...
495
 
496
  /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking
497
  /// enabled. This sets up three trackers. RPTracker will cover the entire DAG
498
  /// region, TopTracker and BottomTracker will be initialized to the top and
499
  /// bottom of the DAG region without covereing any unscheduled instruction.
500
  void buildDAGWithRegPressure();
501
 
502
  /// Release ExitSU predecessors and setup scheduler queues. Re-position
503
  /// the Top RP tracker in case the region beginning has changed.
504
  void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
505
 
506
  /// Move an instruction and update register pressure.
507
  void scheduleMI(SUnit *SU, bool IsTopNode);
508
 
509
  // Lesser helpers...
510
 
511
  void initRegPressure();
512
 
513
  void updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses);
514
 
515
  void updateScheduledPressure(const SUnit *SU,
516
                               const std::vector<unsigned> &NewMaxPressure);
517
 
518
  void collectVRegUses(SUnit &SU);
519
};
520
 
521
//===----------------------------------------------------------------------===//
522
///
523
/// Helpers for implementing custom MachineSchedStrategy classes. These take
524
/// care of the book-keeping associated with list scheduling heuristics.
525
///
526
//===----------------------------------------------------------------------===//
527
 
528
/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
529
/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
530
/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
531
///
532
/// This is a convenience class that may be used by implementations of
533
/// MachineSchedStrategy.
534
class ReadyQueue {
535
  unsigned ID;
536
  std::string Name;
537
  std::vector<SUnit*> Queue;
538
 
539
public:
540
  ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
541
 
542
  unsigned getID() const { return ID; }
543
 
544
  StringRef getName() const { return Name; }
545
 
546
  // SU is in this queue if it's NodeQueueID is a superset of this ID.
547
  bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
548
 
549
  bool empty() const { return Queue.empty(); }
550
 
551
  void clear() { Queue.clear(); }
552
 
553
  unsigned size() const { return Queue.size(); }
554
 
555
  using iterator = std::vector<SUnit*>::iterator;
556
 
557
  iterator begin() { return Queue.begin(); }
558
 
559
  iterator end() { return Queue.end(); }
560
 
561
  ArrayRef<SUnit*> elements() { return Queue; }
562
 
563
  iterator find(SUnit *SU) { return llvm::find(Queue, SU); }
564
 
565
  void push(SUnit *SU) {
566
    Queue.push_back(SU);
567
    SU->NodeQueueId |= ID;
568
  }
569
 
570
  iterator remove(iterator I) {
571
    (*I)->NodeQueueId &= ~ID;
572
    *I = Queue.back();
573
    unsigned idx = I - Queue.begin();
574
    Queue.pop_back();
575
    return Queue.begin() + idx;
576
  }
577
 
578
  void dump() const;
579
};
580
 
581
/// Summarize the unscheduled region.
582
struct SchedRemainder {
583
  // Critical path through the DAG in expected latency.
584
  unsigned CriticalPath;
585
  unsigned CyclicCritPath;
586
 
587
  // Scaled count of micro-ops left to schedule.
588
  unsigned RemIssueCount;
589
 
590
  bool IsAcyclicLatencyLimited;
591
 
592
  // Unscheduled resources
593
  SmallVector<unsigned, 16> RemainingCounts;
594
 
595
  SchedRemainder() { reset(); }
596
 
597
  void reset() {
598
    CriticalPath = 0;
599
    CyclicCritPath = 0;
600
    RemIssueCount = 0;
601
    IsAcyclicLatencyLimited = false;
602
    RemainingCounts.clear();
603
  }
604
 
605
  void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
606
};
607
 
608
/// Each Scheduling boundary is associated with ready queues. It tracks the
609
/// current cycle in the direction of movement, and maintains the state
610
/// of "hazards" and other interlocks at the current cycle.
611
class SchedBoundary {
612
public:
613
  /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
614
  enum {
615
    TopQID = 1,
616
    BotQID = 2,
617
    LogMaxQID = 2
618
  };
619
 
620
  ScheduleDAGMI *DAG = nullptr;
621
  const TargetSchedModel *SchedModel = nullptr;
622
  SchedRemainder *Rem = nullptr;
623
 
624
  ReadyQueue Available;
625
  ReadyQueue Pending;
626
 
627
  ScheduleHazardRecognizer *HazardRec = nullptr;
628
 
629
private:
630
  /// True if the pending Q should be checked/updated before scheduling another
631
  /// instruction.
632
  bool CheckPending;
633
 
634
  /// Number of cycles it takes to issue the instructions scheduled in this
635
  /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls.
636
  /// See getStalls().
637
  unsigned CurrCycle;
638
 
639
  /// Micro-ops issued in the current cycle
640
  unsigned CurrMOps;
641
 
642
  /// MinReadyCycle - Cycle of the soonest available instruction.
643
  unsigned MinReadyCycle;
644
 
645
  // The expected latency of the critical path in this scheduled zone.
646
  unsigned ExpectedLatency;
647
 
648
  // The latency of dependence chains leading into this zone.
649
  // For each node scheduled bottom-up: DLat = max DLat, N.Depth.
650
  // For each cycle scheduled: DLat -= 1.
651
  unsigned DependentLatency;
652
 
653
  /// Count the scheduled (issued) micro-ops that can be retired by
654
  /// time=CurrCycle assuming the first scheduled instr is retired at time=0.
655
  unsigned RetiredMOps;
656
 
657
  // Count scheduled resources that have been executed. Resources are
658
  // considered executed if they become ready in the time that it takes to
659
  // saturate any resource including the one in question. Counts are scaled
660
  // for direct comparison with other resources. Counts can be compared with
661
  // MOps * getMicroOpFactor and Latency * getLatencyFactor.
662
  SmallVector<unsigned, 16> ExecutedResCounts;
663
 
664
  /// Cache the max count for a single resource.
665
  unsigned MaxExecutedResCount;
666
 
667
  // Cache the critical resources ID in this scheduled zone.
668
  unsigned ZoneCritResIdx;
669
 
670
  // Is the scheduled region resource limited vs. latency limited.
671
  bool IsResourceLimited;
672
 
673
  // Record the highest cycle at which each resource has been reserved by a
674
  // scheduled instruction.
675
  SmallVector<unsigned, 16> ReservedCycles;
676
 
677
  /// For each PIdx, stores first index into ReservedCycles that corresponds to
678
  /// it.
679
  ///
680
  /// For example, consider the following 3 resources (ResourceCount =
681
  /// 3):
682
  ///
683
  ///   +------------+--------+
684
  ///   |ResourceName|NumUnits|
685
  ///   +------------+--------+
686
  ///   |     X      |    2   |
687
  ///   +------------+--------+
688
  ///   |     Y      |    3   |
689
  ///   +------------+--------+
690
  ///   |     Z      |    1   |
691
  ///   +------------+--------+
692
  ///
693
  /// In this case, the total number of resource instances is 6. The
694
  /// vector \ref ReservedCycles will have a slot for each instance. The
695
  /// vector \ref ReservedCyclesIndex will track at what index the first
696
  /// instance of the resource is found in the vector of \ref
697
  /// ReservedCycles:
698
  ///
699
  ///                              Indexes of instances in ReservedCycles
700
  ///                              0   1   2   3   4  5
701
  /// ReservedCyclesIndex[0] = 0; [X0, X1,
702
  /// ReservedCyclesIndex[1] = 2;          Y0, Y1, Y2
703
  /// ReservedCyclesIndex[2] = 5;                     Z
704
  SmallVector<unsigned, 16> ReservedCyclesIndex;
705
 
706
  // For each PIdx, stores the resource group IDs of its subunits
707
  SmallVector<APInt, 16> ResourceGroupSubUnitMasks;
708
 
709
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
710
  // Remember the greatest possible stall as an upper bound on the number of
711
  // times we should retry the pending queue because of a hazard.
712
  unsigned MaxObservedStall;
713
#endif
714
 
715
public:
716
  /// Pending queues extend the ready queues with the same ID and the
717
  /// PendingFlag set.
718
  SchedBoundary(unsigned ID, const Twine &Name):
719
    Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") {
720
    reset();
721
  }
722
 
723
  ~SchedBoundary();
724
 
725
  void reset();
726
 
727
  void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel,
728
            SchedRemainder *rem);
729
 
730
  bool isTop() const {
731
    return Available.getID() == TopQID;
732
  }
733
 
734
  /// Number of cycles to issue the instructions scheduled in this zone.
735
  unsigned getCurrCycle() const { return CurrCycle; }
736
 
737
  /// Micro-ops issued in the current cycle
738
  unsigned getCurrMOps() const { return CurrMOps; }
739
 
740
  // The latency of dependence chains leading into this zone.
741
  unsigned getDependentLatency() const { return DependentLatency; }
742
 
743
  /// Get the number of latency cycles "covered" by the scheduled
744
  /// instructions. This is the larger of the critical path within the zone
745
  /// and the number of cycles required to issue the instructions.
746
  unsigned getScheduledLatency() const {
747
    return std::max(ExpectedLatency, CurrCycle);
748
  }
749
 
750
  unsigned getUnscheduledLatency(SUnit *SU) const {
751
    return isTop() ? SU->getHeight() : SU->getDepth();
752
  }
753
 
754
  unsigned getResourceCount(unsigned ResIdx) const {
755
    return ExecutedResCounts[ResIdx];
756
  }
757
 
758
  /// Get the scaled count of scheduled micro-ops and resources, including
759
  /// executed resources.
760
  unsigned getCriticalCount() const {
761
    if (!ZoneCritResIdx)
762
      return RetiredMOps * SchedModel->getMicroOpFactor();
763
    return getResourceCount(ZoneCritResIdx);
764
  }
765
 
766
  /// Get a scaled count for the minimum execution time of the scheduled
767
  /// micro-ops that are ready to execute by getExecutedCount. Notice the
768
  /// feedback loop.
769
  unsigned getExecutedCount() const {
770
    return std::max(CurrCycle * SchedModel->getLatencyFactor(),
771
                    MaxExecutedResCount);
772
  }
773
 
774
  unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
775
 
776
  // Is the scheduled region resource limited vs. latency limited.
777
  bool isResourceLimited() const { return IsResourceLimited; }
778
 
779
  /// Get the difference between the given SUnit's ready time and the current
780
  /// cycle.
781
  unsigned getLatencyStallCycles(SUnit *SU);
782
 
783
  unsigned getNextResourceCycleByInstance(unsigned InstanceIndex,
784
                                          unsigned Cycles);
785
 
786
  std::pair<unsigned, unsigned> getNextResourceCycle(const MCSchedClassDesc *SC,
787
                                                     unsigned PIdx,
788
                                                     unsigned Cycles);
789
 
790
  bool isUnbufferedGroup(unsigned PIdx) const {
791
    return SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin &&
792
           !SchedModel->getProcResource(PIdx)->BufferSize;
793
  }
794
 
795
  bool checkHazard(SUnit *SU);
796
 
797
  unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs);
798
 
799
  unsigned getOtherResourceCount(unsigned &OtherCritIdx);
800
 
801
  /// Release SU to make it ready. If it's not in hazard, remove it from
802
  /// pending queue (if already in) and push into available queue.
803
  /// Otherwise, push the SU into pending queue.
804
  ///
805
  /// @param SU The unit to be released.
806
  /// @param ReadyCycle Until which cycle the unit is ready.
807
  /// @param InPQueue Whether SU is already in pending queue.
808
  /// @param Idx Position offset in pending queue (if in it).
809
  void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
810
                   unsigned Idx = 0);
811
 
812
  void bumpCycle(unsigned NextCycle);
813
 
814
  void incExecutedResources(unsigned PIdx, unsigned Count);
815
 
816
  unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx,
817
                         unsigned Cycles, unsigned ReadyCycle);
818
 
819
  void bumpNode(SUnit *SU);
820
 
821
  void releasePending();
822
 
823
  void removeReady(SUnit *SU);
824
 
825
  /// Call this before applying any other heuristics to the Available queue.
826
  /// Updates the Available/Pending Q's if necessary and returns the single
827
  /// available instruction, or NULL if there are multiple candidates.
828
  SUnit *pickOnlyChoice();
829
 
830
  /// Dump the state of the information that tracks resource usage.
831
  void dumpReservedCycles() const;
832
  void dumpScheduledState() const;
833
};
834
 
835
/// Base class for GenericScheduler. This class maintains information about
836
/// scheduling candidates based on TargetSchedModel making it easy to implement
837
/// heuristics for either preRA or postRA scheduling.
838
class GenericSchedulerBase : public MachineSchedStrategy {
839
public:
840
  /// Represent the type of SchedCandidate found within a single queue.
841
  /// pickNodeBidirectional depends on these listed by decreasing priority.
842
  enum CandReason : uint8_t {
843
    NoCand, Only1, PhysReg, RegExcess, RegCritical, Stall, Cluster, Weak,
844
    RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
845
    TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
846
 
847
#ifndef NDEBUG
848
  static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
849
#endif
850
 
851
  /// Policy for scheduling the next instruction in the candidate's zone.
852
  struct CandPolicy {
853
    bool ReduceLatency = false;
854
    unsigned ReduceResIdx = 0;
855
    unsigned DemandResIdx = 0;
856
 
857
    CandPolicy() = default;
858
 
859
    bool operator==(const CandPolicy &RHS) const {
860
      return ReduceLatency == RHS.ReduceLatency &&
861
             ReduceResIdx == RHS.ReduceResIdx &&
862
             DemandResIdx == RHS.DemandResIdx;
863
    }
864
    bool operator!=(const CandPolicy &RHS) const {
865
      return !(*this == RHS);
866
    }
867
  };
868
 
869
  /// Status of an instruction's critical resource consumption.
870
  struct SchedResourceDelta {
871
    // Count critical resources in the scheduled region required by SU.
872
    unsigned CritResources = 0;
873
 
874
    // Count critical resources from another region consumed by SU.
875
    unsigned DemandedResources = 0;
876
 
877
    SchedResourceDelta() = default;
878
 
879
    bool operator==(const SchedResourceDelta &RHS) const {
880
      return CritResources == RHS.CritResources
881
        && DemandedResources == RHS.DemandedResources;
882
    }
883
    bool operator!=(const SchedResourceDelta &RHS) const {
884
      return !operator==(RHS);
885
    }
886
  };
887
 
888
  /// Store the state used by GenericScheduler heuristics, required for the
889
  /// lifetime of one invocation of pickNode().
890
  struct SchedCandidate {
891
    CandPolicy Policy;
892
 
893
    // The best SUnit candidate.
894
    SUnit *SU;
895
 
896
    // The reason for this candidate.
897
    CandReason Reason;
898
 
899
    // Whether this candidate should be scheduled at top/bottom.
900
    bool AtTop;
901
 
902
    // Register pressure values for the best candidate.
903
    RegPressureDelta RPDelta;
904
 
905
    // Critical resource consumption of the best candidate.
906
    SchedResourceDelta ResDelta;
907
 
908
    SchedCandidate() { reset(CandPolicy()); }
909
    SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
910
 
911
    void reset(const CandPolicy &NewPolicy) {
912
      Policy = NewPolicy;
913
      SU = nullptr;
914
      Reason = NoCand;
915
      AtTop = false;
916
      RPDelta = RegPressureDelta();
917
      ResDelta = SchedResourceDelta();
918
    }
919
 
920
    bool isValid() const { return SU; }
921
 
922
    // Copy the status of another candidate without changing policy.
923
    void setBest(SchedCandidate &Best) {
924
      assert(Best.Reason != NoCand && "uninitialized Sched candidate");
925
      SU = Best.SU;
926
      Reason = Best.Reason;
927
      AtTop = Best.AtTop;
928
      RPDelta = Best.RPDelta;
929
      ResDelta = Best.ResDelta;
930
    }
931
 
932
    void initResourceDelta(const ScheduleDAGMI *DAG,
933
                           const TargetSchedModel *SchedModel);
934
  };
935
 
936
protected:
937
  const MachineSchedContext *Context;
938
  const TargetSchedModel *SchedModel = nullptr;
939
  const TargetRegisterInfo *TRI = nullptr;
940
 
941
  SchedRemainder Rem;
942
 
943
  GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {}
944
 
945
  void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
946
                 SchedBoundary *OtherZone);
947
 
948
#ifndef NDEBUG
949
  void traceCandidate(const SchedCandidate &Cand);
950
#endif
951
 
952
private:
953
  bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone,
954
                           bool ComputeRemLatency, unsigned &RemLatency) const;
955
};
956
 
957
// Utility functions used by heuristics in tryCandidate().
958
bool tryLess(int TryVal, int CandVal,
959
             GenericSchedulerBase::SchedCandidate &TryCand,
960
             GenericSchedulerBase::SchedCandidate &Cand,
961
             GenericSchedulerBase::CandReason Reason);
962
bool tryGreater(int TryVal, int CandVal,
963
                GenericSchedulerBase::SchedCandidate &TryCand,
964
                GenericSchedulerBase::SchedCandidate &Cand,
965
                GenericSchedulerBase::CandReason Reason);
966
bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
967
                GenericSchedulerBase::SchedCandidate &Cand,
968
                SchedBoundary &Zone);
969
bool tryPressure(const PressureChange &TryP,
970
                 const PressureChange &CandP,
971
                 GenericSchedulerBase::SchedCandidate &TryCand,
972
                 GenericSchedulerBase::SchedCandidate &Cand,
973
                 GenericSchedulerBase::CandReason Reason,
974
                 const TargetRegisterInfo *TRI,
975
                 const MachineFunction &MF);
976
unsigned getWeakLeft(const SUnit *SU, bool isTop);
977
int biasPhysReg(const SUnit *SU, bool isTop);
978
 
979
/// GenericScheduler shrinks the unscheduled zone using heuristics to balance
980
/// the schedule.
981
class GenericScheduler : public GenericSchedulerBase {
982
public:
983
  GenericScheduler(const MachineSchedContext *C):
984
    GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
985
    Bot(SchedBoundary::BotQID, "BotQ") {}
986
 
987
  void initPolicy(MachineBasicBlock::iterator Begin,
988
                  MachineBasicBlock::iterator End,
989
                  unsigned NumRegionInstrs) override;
990
 
991
  void dumpPolicy() const override;
992
 
993
  bool shouldTrackPressure() const override {
994
    return RegionPolicy.ShouldTrackPressure;
995
  }
996
 
997
  bool shouldTrackLaneMasks() const override {
998
    return RegionPolicy.ShouldTrackLaneMasks;
999
  }
1000
 
1001
  void initialize(ScheduleDAGMI *dag) override;
1002
 
1003
  SUnit *pickNode(bool &IsTopNode) override;
1004
 
1005
  void schedNode(SUnit *SU, bool IsTopNode) override;
1006
 
1007
  void releaseTopNode(SUnit *SU) override {
1008
    if (SU->isScheduled)
1009
      return;
1010
 
1011
    Top.releaseNode(SU, SU->TopReadyCycle, false);
1012
    TopCand.SU = nullptr;
1013
  }
1014
 
1015
  void releaseBottomNode(SUnit *SU) override {
1016
    if (SU->isScheduled)
1017
      return;
1018
 
1019
    Bot.releaseNode(SU, SU->BotReadyCycle, false);
1020
    BotCand.SU = nullptr;
1021
  }
1022
 
1023
  void registerRoots() override;
1024
 
1025
protected:
1026
  ScheduleDAGMILive *DAG = nullptr;
1027
 
1028
  MachineSchedPolicy RegionPolicy;
1029
 
1030
  // State of the top and bottom scheduled instruction boundaries.
1031
  SchedBoundary Top;
1032
  SchedBoundary Bot;
1033
 
1034
  /// Candidate last picked from Top boundary.
1035
  SchedCandidate TopCand;
1036
  /// Candidate last picked from Bot boundary.
1037
  SchedCandidate BotCand;
1038
 
1039
  void checkAcyclicLatency();
1040
 
1041
  void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
1042
                     const RegPressureTracker &RPTracker,
1043
                     RegPressureTracker &TempTracker);
1044
 
1045
  virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
1046
                            SchedBoundary *Zone) const;
1047
 
1048
  SUnit *pickNodeBidirectional(bool &IsTopNode);
1049
 
1050
  void pickNodeFromQueue(SchedBoundary &Zone,
1051
                         const CandPolicy &ZonePolicy,
1052
                         const RegPressureTracker &RPTracker,
1053
                         SchedCandidate &Candidate);
1054
 
1055
  void reschedulePhysReg(SUnit *SU, bool isTop);
1056
};
1057
 
1058
/// PostGenericScheduler - Interface to the scheduling algorithm used by
1059
/// ScheduleDAGMI.
1060
///
1061
/// Callbacks from ScheduleDAGMI:
1062
///   initPolicy -> initialize(DAG) -> registerRoots -> pickNode ...
1063
class PostGenericScheduler : public GenericSchedulerBase {
1064
protected:
1065
  ScheduleDAGMI *DAG = nullptr;
1066
  SchedBoundary Top;
1067
  SmallVector<SUnit*, 8> BotRoots;
1068
 
1069
public:
1070
  PostGenericScheduler(const MachineSchedContext *C):
1071
    GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {}
1072
 
1073
  ~PostGenericScheduler() override = default;
1074
 
1075
  void initPolicy(MachineBasicBlock::iterator Begin,
1076
                  MachineBasicBlock::iterator End,
1077
                  unsigned NumRegionInstrs) override {
1078
    /* no configurable policy */
1079
  }
1080
 
1081
  /// PostRA scheduling does not track pressure.
1082
  bool shouldTrackPressure() const override { return false; }
1083
 
1084
  void initialize(ScheduleDAGMI *Dag) override;
1085
 
1086
  void registerRoots() override;
1087
 
1088
  SUnit *pickNode(bool &IsTopNode) override;
1089
 
1090
  void scheduleTree(unsigned SubtreeID) override {
1091
    llvm_unreachable("PostRA scheduler does not support subtree analysis.");
1092
  }
1093
 
1094
  void schedNode(SUnit *SU, bool IsTopNode) override;
1095
 
1096
  void releaseTopNode(SUnit *SU) override {
1097
    if (SU->isScheduled)
1098
      return;
1099
    Top.releaseNode(SU, SU->TopReadyCycle, false);
1100
  }
1101
 
1102
  // Only called for roots.
1103
  void releaseBottomNode(SUnit *SU) override {
1104
    BotRoots.push_back(SU);
1105
  }
1106
 
1107
protected:
1108
  virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
1109
 
1110
  void pickNodeFromQueue(SchedCandidate &Cand);
1111
};
1112
 
1113
/// Create the standard converging machine scheduler. This will be used as the
1114
/// default scheduler if the target does not set a default.
1115
/// Adds default DAG mutations.
1116
ScheduleDAGMILive *createGenericSchedLive(MachineSchedContext *C);
1117
 
1118
/// Create a generic scheduler with no vreg liveness or DAG mutation passes.
1119
ScheduleDAGMI *createGenericSchedPostRA(MachineSchedContext *C);
1120
 
1121
std::unique_ptr<ScheduleDAGMutation>
1122
createLoadClusterDAGMutation(const TargetInstrInfo *TII,
1123
                             const TargetRegisterInfo *TRI);
1124
 
1125
std::unique_ptr<ScheduleDAGMutation>
1126
createStoreClusterDAGMutation(const TargetInstrInfo *TII,
1127
                              const TargetRegisterInfo *TRI);
1128
 
1129
std::unique_ptr<ScheduleDAGMutation>
1130
createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
1131
                               const TargetRegisterInfo *TRI);
1132
 
1133
} // end namespace llvm
1134
 
1135
#endif // LLVM_CODEGEN_MACHINESCHEDULER_H