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 a MachineSchedRegistry for registering alternative machine
     11 // schedulers. A Target may provide an alternative scheduler implementation by
     12 // implementing the following boilerplate:
     13 //
     14 // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) {
     15 //  return new CustomMachineScheduler(C);
     16 // }
     17 // static MachineSchedRegistry
     18 // SchedCustomRegistry("custom", "Run my target's custom scheduler",
     19 //                     createCustomMachineSched);
     20 //
     21 // Inside <Target>PassConfig:
     22 //   enablePass(&MachineSchedulerID);
     23 //   MachineSchedRegistry::setDefault(createCustomMachineSched);
     24 //
     25 //===----------------------------------------------------------------------===//
     26 
     27 #ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
     28 #define LLVM_CODEGEN_MACHINESCHEDULER_H
     29 
     30 #include "llvm/CodeGen/MachinePassRegistry.h"
     31 #include "llvm/CodeGen/RegisterPressure.h"
     32 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
     33 
     34 namespace llvm {
     35 
     36 extern cl::opt<bool> ForceTopDown;
     37 extern cl::opt<bool> ForceBottomUp;
     38 
     39 class AliasAnalysis;
     40 class LiveIntervals;
     41 class MachineDominatorTree;
     42 class MachineLoopInfo;
     43 class RegisterClassInfo;
     44 class ScheduleDAGInstrs;
     45 class SchedDFSResult;
     46 
     47 /// MachineSchedContext provides enough context from the MachineScheduler pass
     48 /// for the target to instantiate a scheduler.
     49 struct MachineSchedContext {
     50   MachineFunction *MF;
     51   const MachineLoopInfo *MLI;
     52   const MachineDominatorTree *MDT;
     53   const TargetPassConfig *PassConfig;
     54   AliasAnalysis *AA;
     55   LiveIntervals *LIS;
     56 
     57   RegisterClassInfo *RegClassInfo;
     58 
     59   MachineSchedContext();
     60   virtual ~MachineSchedContext();
     61 };
     62 
     63 /// MachineSchedRegistry provides a selection of available machine instruction
     64 /// schedulers.
     65 class MachineSchedRegistry : public MachinePassRegistryNode {
     66 public:
     67   typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *);
     68 
     69   // RegisterPassParser requires a (misnamed) FunctionPassCtor type.
     70   typedef ScheduleDAGCtor FunctionPassCtor;
     71 
     72   static MachinePassRegistry Registry;
     73 
     74   MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
     75     : MachinePassRegistryNode(N, D, (MachinePassCtor)C) {
     76     Registry.Add(this);
     77   }
     78   ~MachineSchedRegistry() { Registry.Remove(this); }
     79 
     80   // Accessors.
     81   //
     82   MachineSchedRegistry *getNext() const {
     83     return (MachineSchedRegistry *)MachinePassRegistryNode::getNext();
     84   }
     85   static MachineSchedRegistry *getList() {
     86     return (MachineSchedRegistry *)Registry.getList();
     87   }
     88   static ScheduleDAGCtor getDefault() {
     89     return (ScheduleDAGCtor)Registry.getDefault();
     90   }
     91   static void setDefault(ScheduleDAGCtor C) {
     92     Registry.setDefault((MachinePassCtor)C);
     93   }
     94   static void setDefault(StringRef Name) {
     95     Registry.setDefault(Name);
     96   }
     97   static void setListener(MachinePassRegistryListener *L) {
     98     Registry.setListener(L);
     99   }
    100 };
    101 
    102 class ScheduleDAGMI;
    103 
    104 /// MachineSchedStrategy - Interface to the scheduling algorithm used by
    105 /// ScheduleDAGMI.
    106 class MachineSchedStrategy {
    107 public:
    108   virtual ~MachineSchedStrategy() {}
    109 
    110   /// Initialize the strategy after building the DAG for a new region.
    111   virtual void initialize(ScheduleDAGMI *DAG) = 0;
    112 
    113   /// Notify this strategy that all roots have been released (including those
    114   /// that depend on EntrySU or ExitSU).
    115   virtual void registerRoots() {}
    116 
    117   /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
    118   /// schedule the node at the top of the unscheduled region. Otherwise it will
    119   /// be scheduled at the bottom.
    120   virtual SUnit *pickNode(bool &IsTopNode) = 0;
    121 
    122   /// \brief Scheduler callback to notify that a new subtree is scheduled.
    123   virtual void scheduleTree(unsigned SubtreeID) {}
    124 
    125   /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
    126   /// instruction and updated scheduled/remaining flags in the DAG nodes.
    127   virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
    128 
    129   /// When all predecessor dependencies have been resolved, free this node for
    130   /// top-down scheduling.
    131   virtual void releaseTopNode(SUnit *SU) = 0;
    132   /// When all successor dependencies have been resolved, free this node for
    133   /// bottom-up scheduling.
    134   virtual void releaseBottomNode(SUnit *SU) = 0;
    135 };
    136 
    137 /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
    138 /// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
    139 /// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
    140 ///
    141 /// This is a convenience class that may be used by implementations of
    142 /// MachineSchedStrategy.
    143 class ReadyQueue {
    144   unsigned ID;
    145   std::string Name;
    146   std::vector<SUnit*> Queue;
    147 
    148 public:
    149   ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
    150 
    151   unsigned getID() const { return ID; }
    152 
    153   StringRef getName() const { return Name; }
    154 
    155   // SU is in this queue if it's NodeQueueID is a superset of this ID.
    156   bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
    157 
    158   bool empty() const { return Queue.empty(); }
    159 
    160   void clear() { Queue.clear(); }
    161 
    162   unsigned size() const { return Queue.size(); }
    163 
    164   typedef std::vector<SUnit*>::iterator iterator;
    165 
    166   iterator begin() { return Queue.begin(); }
    167 
    168   iterator end() { return Queue.end(); }
    169 
    170   ArrayRef<SUnit*> elements() { return Queue; }
    171 
    172   iterator find(SUnit *SU) {
    173     return std::find(Queue.begin(), Queue.end(), SU);
    174   }
    175 
    176   void push(SUnit *SU) {
    177     Queue.push_back(SU);
    178     SU->NodeQueueId |= ID;
    179   }
    180 
    181   iterator remove(iterator I) {
    182     (*I)->NodeQueueId &= ~ID;
    183     *I = Queue.back();
    184     unsigned idx = I - Queue.begin();
    185     Queue.pop_back();
    186     return Queue.begin() + idx;
    187   }
    188 
    189 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    190   void dump();
    191 #endif
    192 };
    193 
    194 /// Mutate the DAG as a postpass after normal DAG building.
    195 class ScheduleDAGMutation {
    196 public:
    197   virtual ~ScheduleDAGMutation() {}
    198 
    199   virtual void apply(ScheduleDAGMI *DAG) = 0;
    200 };
    201 
    202 /// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that schedules
    203 /// machine instructions while updating LiveIntervals and tracking regpressure.
    204 class ScheduleDAGMI : public ScheduleDAGInstrs {
    205 protected:
    206   AliasAnalysis *AA;
    207   RegisterClassInfo *RegClassInfo;
    208   MachineSchedStrategy *SchedImpl;
    209 
    210   /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
    211   /// will be empty.
    212   SchedDFSResult *DFSResult;
    213   BitVector ScheduledTrees;
    214 
    215   /// Topo - A topological ordering for SUnits which permits fast IsReachable
    216   /// and similar queries.
    217   ScheduleDAGTopologicalSort Topo;
    218 
    219   /// Ordered list of DAG postprocessing steps.
    220   std::vector<ScheduleDAGMutation*> Mutations;
    221 
    222   MachineBasicBlock::iterator LiveRegionEnd;
    223 
    224   /// Register pressure in this region computed by buildSchedGraph.
    225   IntervalPressure RegPressure;
    226   RegPressureTracker RPTracker;
    227 
    228   /// List of pressure sets that exceed the target's pressure limit before
    229   /// scheduling, listed in increasing set ID order. Each pressure set is paired
    230   /// with its max pressure in the currently scheduled regions.
    231   std::vector<PressureElement> RegionCriticalPSets;
    232 
    233   /// The top of the unscheduled zone.
    234   MachineBasicBlock::iterator CurrentTop;
    235   IntervalPressure TopPressure;
    236   RegPressureTracker TopRPTracker;
    237 
    238   /// The bottom of the unscheduled zone.
    239   MachineBasicBlock::iterator CurrentBottom;
    240   IntervalPressure BotPressure;
    241   RegPressureTracker BotRPTracker;
    242 
    243   /// Record the next node in a scheduled cluster.
    244   const SUnit *NextClusterPred;
    245   const SUnit *NextClusterSucc;
    246 
    247 #ifndef NDEBUG
    248   /// The number of instructions scheduled so far. Used to cut off the
    249   /// scheduler at the point determined by misched-cutoff.
    250   unsigned NumInstrsScheduled;
    251 #endif
    252 
    253 public:
    254   ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S):
    255     ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
    256     AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0),
    257     Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(),
    258     TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure),
    259     NextClusterPred(NULL), NextClusterSucc(NULL) {
    260 #ifndef NDEBUG
    261     NumInstrsScheduled = 0;
    262 #endif
    263   }
    264 
    265   virtual ~ScheduleDAGMI();
    266 
    267   /// Add a postprocessing step to the DAG builder.
    268   /// Mutations are applied in the order that they are added after normal DAG
    269   /// building and before MachineSchedStrategy initialization.
    270   ///
    271   /// ScheduleDAGMI takes ownership of the Mutation object.
    272   void addMutation(ScheduleDAGMutation *Mutation) {
    273     Mutations.push_back(Mutation);
    274   }
    275 
    276   /// \brief True if an edge can be added from PredSU to SuccSU without creating
    277   /// a cycle.
    278   bool canAddEdge(SUnit *SuccSU, SUnit *PredSU);
    279 
    280   /// \brief Add a DAG edge to the given SU with the given predecessor
    281   /// dependence data.
    282   ///
    283   /// \returns true if the edge may be added without creating a cycle OR if an
    284   /// equivalent edge already existed (false indicates failure).
    285   bool addEdge(SUnit *SuccSU, const SDep &PredDep);
    286 
    287   MachineBasicBlock::iterator top() const { return CurrentTop; }
    288   MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
    289 
    290   /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
    291   /// region. This covers all instructions in a block, while schedule() may only
    292   /// cover a subset.
    293   void enterRegion(MachineBasicBlock *bb,
    294                    MachineBasicBlock::iterator begin,
    295                    MachineBasicBlock::iterator end,
    296                    unsigned endcount);
    297 
    298 
    299   /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
    300   /// reorderable instructions.
    301   virtual void schedule();
    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   /// Get current register pressure for the top scheduled instructions.
    308   const IntervalPressure &getTopPressure() const { return TopPressure; }
    309   const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
    310 
    311   /// Get current register pressure for the bottom scheduled instructions.
    312   const IntervalPressure &getBotPressure() const { return BotPressure; }
    313   const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
    314 
    315   /// Get register pressure for the entire scheduling region before scheduling.
    316   const IntervalPressure &getRegPressure() const { return RegPressure; }
    317 
    318   const std::vector<PressureElement> &getRegionCriticalPSets() const {
    319     return RegionCriticalPSets;
    320   }
    321 
    322   const SUnit *getNextClusterPred() const { return NextClusterPred; }
    323 
    324   const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
    325 
    326   /// Compute a DFSResult after DAG building is complete, and before any
    327   /// queue comparisons.
    328   void computeDFSResult();
    329 
    330   /// Return a non-null DFS result if the scheduling strategy initialized it.
    331   const SchedDFSResult *getDFSResult() const { return DFSResult; }
    332 
    333   BitVector &getScheduledTrees() { return ScheduledTrees; }
    334 
    335   void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE;
    336   void viewGraph() LLVM_OVERRIDE;
    337 
    338 protected:
    339   // Top-Level entry points for the schedule() driver...
    340 
    341   /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking
    342   /// enabled. This sets up three trackers. RPTracker will cover the entire DAG
    343   /// region, TopTracker and BottomTracker will be initialized to the top and
    344   /// bottom of the DAG region without covereing any unscheduled instruction.
    345   void buildDAGWithRegPressure();
    346 
    347   /// Apply each ScheduleDAGMutation step in order. This allows different
    348   /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
    349   void postprocessDAG();
    350 
    351   /// Release ExitSU predecessors and setup scheduler queues.
    352   void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
    353 
    354   /// Move an instruction and update register pressure.
    355   void scheduleMI(SUnit *SU, bool IsTopNode);
    356 
    357   /// Update scheduler DAG and queues after scheduling an instruction.
    358   void updateQueues(SUnit *SU, bool IsTopNode);
    359 
    360   /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
    361   void placeDebugValues();
    362 
    363   /// \brief dump the scheduled Sequence.
    364   void dumpSchedule() const;
    365 
    366   // Lesser helpers...
    367 
    368   void initRegPressure();
    369 
    370   void updateScheduledPressure(const std::vector<unsigned> &NewMaxPressure);
    371 
    372   bool checkSchedLimit();
    373 
    374   void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
    375                              SmallVectorImpl<SUnit*> &BotRoots);
    376 
    377   void releaseSucc(SUnit *SU, SDep *SuccEdge);
    378   void releaseSuccessors(SUnit *SU);
    379   void releasePred(SUnit *SU, SDep *PredEdge);
    380   void releasePredecessors(SUnit *SU);
    381 };
    382 
    383 } // namespace llvm
    384 
    385 #endif
    386