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