LLVM API Documentation
00001 //==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides an interface for customizing the standard MachineScheduler 00011 // pass. Note that the entire pass may be replaced as follows: 00012 // 00013 // <Target>TargetMachine::createPassConfig(PassManagerBase &PM) { 00014 // PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); 00015 // ...} 00016 // 00017 // The MachineScheduler pass is only responsible for choosing the regions to be 00018 // scheduled. Targets can override the DAG builder and scheduler without 00019 // replacing the pass as follows: 00020 // 00021 // ScheduleDAGInstrs *<Target>PassConfig:: 00022 // createMachineScheduler(MachineSchedContext *C) { 00023 // return new CustomMachineScheduler(C); 00024 // } 00025 // 00026 // The default scheduler, ScheduleDAGMILive, builds the DAG and drives list 00027 // scheduling while updating the instruction stream, register pressure, and live 00028 // intervals. Most targets don't need to override the DAG builder and list 00029 // schedulier, but subtargets that require custom scheduling heuristics may 00030 // plugin an alternate MachineSchedStrategy. The strategy is responsible for 00031 // selecting the highest priority node from the list: 00032 // 00033 // ScheduleDAGInstrs *<Target>PassConfig:: 00034 // createMachineScheduler(MachineSchedContext *C) { 00035 // return new ScheduleDAGMI(C, CustomStrategy(C)); 00036 // } 00037 // 00038 // The DAG builder can also be customized in a sense by adding DAG mutations 00039 // that will run after DAG building and before list scheduling. DAG mutations 00040 // can adjust dependencies based on target-specific knowledge or add weak edges 00041 // to aid heuristics: 00042 // 00043 // ScheduleDAGInstrs *<Target>PassConfig:: 00044 // createMachineScheduler(MachineSchedContext *C) { 00045 // ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C)); 00046 // DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI)); 00047 // return DAG; 00048 // } 00049 // 00050 // A target that supports alternative schedulers can use the 00051 // MachineSchedRegistry to allow command line selection. This can be done by 00052 // implementing the following boilerplate: 00053 // 00054 // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { 00055 // return new CustomMachineScheduler(C); 00056 // } 00057 // static MachineSchedRegistry 00058 // SchedCustomRegistry("custom", "Run my target's custom scheduler", 00059 // createCustomMachineSched); 00060 // 00061 // 00062 // Finally, subtargets that don't need to implement custom heuristics but would 00063 // like to configure the GenericScheduler's policy for a given scheduler region, 00064 // including scheduling direction and register pressure tracking policy, can do 00065 // this: 00066 // 00067 // void <SubTarget>Subtarget:: 00068 // overrideSchedPolicy(MachineSchedPolicy &Policy, 00069 // MachineInstr *begin, 00070 // MachineInstr *end, 00071 // unsigned NumRegionInstrs) const { 00072 // Policy.<Flag> = true; 00073 // } 00074 // 00075 //===----------------------------------------------------------------------===// 00076 00077 #ifndef LLVM_CODEGEN_MACHINESCHEDULER_H 00078 #define LLVM_CODEGEN_MACHINESCHEDULER_H 00079 00080 #include "llvm/CodeGen/MachinePassRegistry.h" 00081 #include "llvm/CodeGen/RegisterPressure.h" 00082 #include "llvm/CodeGen/ScheduleDAGInstrs.h" 00083 00084 #include <memory> 00085 00086 namespace llvm { 00087 00088 extern cl::opt<bool> ForceTopDown; 00089 extern cl::opt<bool> ForceBottomUp; 00090 00091 class AliasAnalysis; 00092 class LiveIntervals; 00093 class MachineDominatorTree; 00094 class MachineLoopInfo; 00095 class RegisterClassInfo; 00096 class ScheduleDAGInstrs; 00097 class SchedDFSResult; 00098 class ScheduleHazardRecognizer; 00099 00100 /// MachineSchedContext provides enough context from the MachineScheduler pass 00101 /// for the target to instantiate a scheduler. 00102 struct MachineSchedContext { 00103 MachineFunction *MF; 00104 const MachineLoopInfo *MLI; 00105 const MachineDominatorTree *MDT; 00106 const TargetPassConfig *PassConfig; 00107 AliasAnalysis *AA; 00108 LiveIntervals *LIS; 00109 00110 RegisterClassInfo *RegClassInfo; 00111 00112 MachineSchedContext(); 00113 virtual ~MachineSchedContext(); 00114 }; 00115 00116 /// MachineSchedRegistry provides a selection of available machine instruction 00117 /// schedulers. 00118 class MachineSchedRegistry : public MachinePassRegistryNode { 00119 public: 00120 typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *); 00121 00122 // RegisterPassParser requires a (misnamed) FunctionPassCtor type. 00123 typedef ScheduleDAGCtor FunctionPassCtor; 00124 00125 static MachinePassRegistry Registry; 00126 00127 MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) 00128 : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { 00129 Registry.Add(this); 00130 } 00131 ~MachineSchedRegistry() { Registry.Remove(this); } 00132 00133 // Accessors. 00134 // 00135 MachineSchedRegistry *getNext() const { 00136 return (MachineSchedRegistry *)MachinePassRegistryNode::getNext(); 00137 } 00138 static MachineSchedRegistry *getList() { 00139 return (MachineSchedRegistry *)Registry.getList(); 00140 } 00141 static void setListener(MachinePassRegistryListener *L) { 00142 Registry.setListener(L); 00143 } 00144 }; 00145 00146 class ScheduleDAGMI; 00147 00148 /// Define a generic scheduling policy for targets that don't provide their own 00149 /// MachineSchedStrategy. This can be overriden for each scheduling region 00150 /// before building the DAG. 00151 struct MachineSchedPolicy { 00152 // Allow the scheduler to disable register pressure tracking. 00153 bool ShouldTrackPressure; 00154 00155 // Allow the scheduler to force top-down or bottom-up scheduling. If neither 00156 // is true, the scheduler runs in both directions and converges. 00157 bool OnlyTopDown; 00158 bool OnlyBottomUp; 00159 00160 MachineSchedPolicy(): ShouldTrackPressure(false), OnlyTopDown(false), 00161 OnlyBottomUp(false) {} 00162 }; 00163 00164 /// MachineSchedStrategy - Interface to the scheduling algorithm used by 00165 /// ScheduleDAGMI. 00166 /// 00167 /// Initialization sequence: 00168 /// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots 00169 class MachineSchedStrategy { 00170 virtual void anchor(); 00171 public: 00172 virtual ~MachineSchedStrategy() {} 00173 00174 /// Optionally override the per-region scheduling policy. 00175 virtual void initPolicy(MachineBasicBlock::iterator Begin, 00176 MachineBasicBlock::iterator End, 00177 unsigned NumRegionInstrs) {} 00178 00179 /// Check if pressure tracking is needed before building the DAG and 00180 /// initializing this strategy. Called after initPolicy. 00181 virtual bool shouldTrackPressure() const { return true; } 00182 00183 /// Initialize the strategy after building the DAG for a new region. 00184 virtual void initialize(ScheduleDAGMI *DAG) = 0; 00185 00186 /// Notify this strategy that all roots have been released (including those 00187 /// that depend on EntrySU or ExitSU). 00188 virtual void registerRoots() {} 00189 00190 /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to 00191 /// schedule the node at the top of the unscheduled region. Otherwise it will 00192 /// be scheduled at the bottom. 00193 virtual SUnit *pickNode(bool &IsTopNode) = 0; 00194 00195 /// \brief Scheduler callback to notify that a new subtree is scheduled. 00196 virtual void scheduleTree(unsigned SubtreeID) {} 00197 00198 /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an 00199 /// instruction and updated scheduled/remaining flags in the DAG nodes. 00200 virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; 00201 00202 /// When all predecessor dependencies have been resolved, free this node for 00203 /// top-down scheduling. 00204 virtual void releaseTopNode(SUnit *SU) = 0; 00205 /// When all successor dependencies have been resolved, free this node for 00206 /// bottom-up scheduling. 00207 virtual void releaseBottomNode(SUnit *SU) = 0; 00208 }; 00209 00210 /// Mutate the DAG as a postpass after normal DAG building. 00211 class ScheduleDAGMutation { 00212 virtual void anchor(); 00213 public: 00214 virtual ~ScheduleDAGMutation() {} 00215 00216 virtual void apply(ScheduleDAGMI *DAG) = 0; 00217 }; 00218 00219 /// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply 00220 /// schedules machine instructions according to the given MachineSchedStrategy 00221 /// without much extra book-keeping. This is the common functionality between 00222 /// PreRA and PostRA MachineScheduler. 00223 class ScheduleDAGMI : public ScheduleDAGInstrs { 00224 protected: 00225 AliasAnalysis *AA; 00226 std::unique_ptr<MachineSchedStrategy> SchedImpl; 00227 00228 /// Topo - A topological ordering for SUnits which permits fast IsReachable 00229 /// and similar queries. 00230 ScheduleDAGTopologicalSort Topo; 00231 00232 /// Ordered list of DAG postprocessing steps. 00233 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations; 00234 00235 /// The top of the unscheduled zone. 00236 MachineBasicBlock::iterator CurrentTop; 00237 00238 /// The bottom of the unscheduled zone. 00239 MachineBasicBlock::iterator CurrentBottom; 00240 00241 /// Record the next node in a scheduled cluster. 00242 const SUnit *NextClusterPred; 00243 const SUnit *NextClusterSucc; 00244 00245 #ifndef NDEBUG 00246 /// The number of instructions scheduled so far. Used to cut off the 00247 /// scheduler at the point determined by misched-cutoff. 00248 unsigned NumInstrsScheduled; 00249 #endif 00250 public: 00251 ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, 00252 bool IsPostRA) 00253 : ScheduleDAGInstrs(*C->MF, C->MLI, IsPostRA, 00254 /*RemoveKillFlags=*/IsPostRA, C->LIS), 00255 AA(C->AA), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), CurrentTop(), 00256 CurrentBottom(), NextClusterPred(nullptr), NextClusterSucc(nullptr) { 00257 #ifndef NDEBUG 00258 NumInstrsScheduled = 0; 00259 #endif 00260 } 00261 00262 // Provide a vtable anchor 00263 ~ScheduleDAGMI() override; 00264 00265 /// Return true if this DAG supports VReg liveness and RegPressure. 00266 virtual bool hasVRegLiveness() const { return false; } 00267 00268 /// Add a postprocessing step to the DAG builder. 00269 /// Mutations are applied in the order that they are added after normal DAG 00270 /// building and before MachineSchedStrategy initialization. 00271 /// 00272 /// ScheduleDAGMI takes ownership of the Mutation object. 00273 void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) { 00274 Mutations.push_back(std::move(Mutation)); 00275 } 00276 00277 /// \brief True if an edge can be added from PredSU to SuccSU without creating 00278 /// a cycle. 00279 bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); 00280 00281 /// \brief Add a DAG edge to the given SU with the given predecessor 00282 /// dependence data. 00283 /// 00284 /// \returns true if the edge may be added without creating a cycle OR if an 00285 /// equivalent edge already existed (false indicates failure). 00286 bool addEdge(SUnit *SuccSU, const SDep &PredDep); 00287 00288 MachineBasicBlock::iterator top() const { return CurrentTop; } 00289 MachineBasicBlock::iterator bottom() const { return CurrentBottom; } 00290 00291 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling 00292 /// region. This covers all instructions in a block, while schedule() may only 00293 /// cover a subset. 00294 void enterRegion(MachineBasicBlock *bb, 00295 MachineBasicBlock::iterator begin, 00296 MachineBasicBlock::iterator end, 00297 unsigned regioninstrs) override; 00298 00299 /// Implement ScheduleDAGInstrs interface for scheduling a sequence of 00300 /// reorderable instructions. 00301 void schedule() override; 00302 00303 /// Change the position of an instruction within the basic block and update 00304 /// live ranges and region boundary iterators. 00305 void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); 00306 00307 const SUnit *getNextClusterPred() const { return NextClusterPred; } 00308 00309 const SUnit *getNextClusterSucc() const { return NextClusterSucc; } 00310 00311 void viewGraph(const Twine &Name, const Twine &Title) override; 00312 void viewGraph() override; 00313 00314 protected: 00315 // Top-Level entry points for the schedule() driver... 00316 00317 /// Apply each ScheduleDAGMutation step in order. This allows different 00318 /// instances of ScheduleDAGMI to perform custom DAG postprocessing. 00319 void postprocessDAG(); 00320 00321 /// Release ExitSU predecessors and setup scheduler queues. 00322 void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots); 00323 00324 /// Update scheduler DAG and queues after scheduling an instruction. 00325 void updateQueues(SUnit *SU, bool IsTopNode); 00326 00327 /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. 00328 void placeDebugValues(); 00329 00330 /// \brief dump the scheduled Sequence. 00331 void dumpSchedule() const; 00332 00333 // Lesser helpers... 00334 bool checkSchedLimit(); 00335 00336 void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, 00337 SmallVectorImpl<SUnit*> &BotRoots); 00338 00339 void releaseSucc(SUnit *SU, SDep *SuccEdge); 00340 void releaseSuccessors(SUnit *SU); 00341 void releasePred(SUnit *SU, SDep *PredEdge); 00342 void releasePredecessors(SUnit *SU); 00343 }; 00344 00345 /// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules 00346 /// machine instructions while updating LiveIntervals and tracking regpressure. 00347 class ScheduleDAGMILive : public ScheduleDAGMI { 00348 protected: 00349 RegisterClassInfo *RegClassInfo; 00350 00351 /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees 00352 /// will be empty. 00353 SchedDFSResult *DFSResult; 00354 BitVector ScheduledTrees; 00355 00356 MachineBasicBlock::iterator LiveRegionEnd; 00357 00358 // Map each SU to its summary of pressure changes. This array is updated for 00359 // liveness during bottom-up scheduling. Top-down scheduling may proceed but 00360 // has no affect on the pressure diffs. 00361 PressureDiffs SUPressureDiffs; 00362 00363 /// Register pressure in this region computed by initRegPressure. 00364 bool ShouldTrackPressure; 00365 IntervalPressure RegPressure; 00366 RegPressureTracker RPTracker; 00367 00368 /// List of pressure sets that exceed the target's pressure limit before 00369 /// scheduling, listed in increasing set ID order. Each pressure set is paired 00370 /// with its max pressure in the currently scheduled regions. 00371 std::vector<PressureChange> RegionCriticalPSets; 00372 00373 /// The top of the unscheduled zone. 00374 IntervalPressure TopPressure; 00375 RegPressureTracker TopRPTracker; 00376 00377 /// The bottom of the unscheduled zone. 00378 IntervalPressure BotPressure; 00379 RegPressureTracker BotRPTracker; 00380 00381 public: 00382 ScheduleDAGMILive(MachineSchedContext *C, 00383 std::unique_ptr<MachineSchedStrategy> S) 00384 : ScheduleDAGMI(C, std::move(S), /*IsPostRA=*/false), 00385 RegClassInfo(C->RegClassInfo), DFSResult(nullptr), 00386 ShouldTrackPressure(false), RPTracker(RegPressure), 00387 TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} 00388 00389 virtual ~ScheduleDAGMILive(); 00390 00391 /// Return true if this DAG supports VReg liveness and RegPressure. 00392 bool hasVRegLiveness() const override { return true; } 00393 00394 /// \brief Return true if register pressure tracking is enabled. 00395 bool isTrackingPressure() const { return ShouldTrackPressure; } 00396 00397 /// Get current register pressure for the top scheduled instructions. 00398 const IntervalPressure &getTopPressure() const { return TopPressure; } 00399 const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } 00400 00401 /// Get current register pressure for the bottom scheduled instructions. 00402 const IntervalPressure &getBotPressure() const { return BotPressure; } 00403 const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } 00404 00405 /// Get register pressure for the entire scheduling region before scheduling. 00406 const IntervalPressure &getRegPressure() const { return RegPressure; } 00407 00408 const std::vector<PressureChange> &getRegionCriticalPSets() const { 00409 return RegionCriticalPSets; 00410 } 00411 00412 PressureDiff &getPressureDiff(const SUnit *SU) { 00413 return SUPressureDiffs[SU->NodeNum]; 00414 } 00415 00416 /// Compute a DFSResult after DAG building is complete, and before any 00417 /// queue comparisons. 00418 void computeDFSResult(); 00419 00420 /// Return a non-null DFS result if the scheduling strategy initialized it. 00421 const SchedDFSResult *getDFSResult() const { return DFSResult; } 00422 00423 BitVector &getScheduledTrees() { return ScheduledTrees; } 00424 00425 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling 00426 /// region. This covers all instructions in a block, while schedule() may only 00427 /// cover a subset. 00428 void enterRegion(MachineBasicBlock *bb, 00429 MachineBasicBlock::iterator begin, 00430 MachineBasicBlock::iterator end, 00431 unsigned regioninstrs) override; 00432 00433 /// Implement ScheduleDAGInstrs interface for scheduling a sequence of 00434 /// reorderable instructions. 00435 void schedule() override; 00436 00437 /// Compute the cyclic critical path through the DAG. 00438 unsigned computeCyclicCriticalPath(); 00439 00440 protected: 00441 // Top-Level entry points for the schedule() driver... 00442 00443 /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking 00444 /// enabled. This sets up three trackers. RPTracker will cover the entire DAG 00445 /// region, TopTracker and BottomTracker will be initialized to the top and 00446 /// bottom of the DAG region without covereing any unscheduled instruction. 00447 void buildDAGWithRegPressure(); 00448 00449 /// Move an instruction and update register pressure. 00450 void scheduleMI(SUnit *SU, bool IsTopNode); 00451 00452 // Lesser helpers... 00453 00454 void initRegPressure(); 00455 00456 void updatePressureDiffs(ArrayRef<unsigned> LiveUses); 00457 00458 void updateScheduledPressure(const SUnit *SU, 00459 const std::vector<unsigned> &NewMaxPressure); 00460 }; 00461 00462 //===----------------------------------------------------------------------===// 00463 /// 00464 /// Helpers for implementing custom MachineSchedStrategy classes. These take 00465 /// care of the book-keeping associated with list scheduling heuristics. 00466 /// 00467 //===----------------------------------------------------------------------===// 00468 00469 /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience 00470 /// methods for pushing and removing nodes. ReadyQueue's are uniquely identified 00471 /// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. 00472 /// 00473 /// This is a convenience class that may be used by implementations of 00474 /// MachineSchedStrategy. 00475 class ReadyQueue { 00476 unsigned ID; 00477 std::string Name; 00478 std::vector<SUnit*> Queue; 00479 00480 public: 00481 ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} 00482 00483 unsigned getID() const { return ID; } 00484 00485 StringRef getName() const { return Name; } 00486 00487 // SU is in this queue if it's NodeQueueID is a superset of this ID. 00488 bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } 00489 00490 bool empty() const { return Queue.empty(); } 00491 00492 void clear() { Queue.clear(); } 00493 00494 unsigned size() const { return Queue.size(); } 00495 00496 typedef std::vector<SUnit*>::iterator iterator; 00497 00498 iterator begin() { return Queue.begin(); } 00499 00500 iterator end() { return Queue.end(); } 00501 00502 ArrayRef<SUnit*> elements() { return Queue; } 00503 00504 iterator find(SUnit *SU) { 00505 return std::find(Queue.begin(), Queue.end(), SU); 00506 } 00507 00508 void push(SUnit *SU) { 00509 Queue.push_back(SU); 00510 SU->NodeQueueId |= ID; 00511 } 00512 00513 iterator remove(iterator I) { 00514 (*I)->NodeQueueId &= ~ID; 00515 *I = Queue.back(); 00516 unsigned idx = I - Queue.begin(); 00517 Queue.pop_back(); 00518 return Queue.begin() + idx; 00519 } 00520 00521 void dump(); 00522 }; 00523 00524 /// Summarize the unscheduled region. 00525 struct SchedRemainder { 00526 // Critical path through the DAG in expected latency. 00527 unsigned CriticalPath; 00528 unsigned CyclicCritPath; 00529 00530 // Scaled count of micro-ops left to schedule. 00531 unsigned RemIssueCount; 00532 00533 bool IsAcyclicLatencyLimited; 00534 00535 // Unscheduled resources 00536 SmallVector<unsigned, 16> RemainingCounts; 00537 00538 void reset() { 00539 CriticalPath = 0; 00540 CyclicCritPath = 0; 00541 RemIssueCount = 0; 00542 IsAcyclicLatencyLimited = false; 00543 RemainingCounts.clear(); 00544 } 00545 00546 SchedRemainder() { reset(); } 00547 00548 void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel); 00549 }; 00550 00551 /// Each Scheduling boundary is associated with ready queues. It tracks the 00552 /// current cycle in the direction of movement, and maintains the state 00553 /// of "hazards" and other interlocks at the current cycle. 00554 class SchedBoundary { 00555 public: 00556 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) 00557 enum { 00558 TopQID = 1, 00559 BotQID = 2, 00560 LogMaxQID = 2 00561 }; 00562 00563 ScheduleDAGMI *DAG; 00564 const TargetSchedModel *SchedModel; 00565 SchedRemainder *Rem; 00566 00567 ReadyQueue Available; 00568 ReadyQueue Pending; 00569 00570 ScheduleHazardRecognizer *HazardRec; 00571 00572 private: 00573 /// True if the pending Q should be checked/updated before scheduling another 00574 /// instruction. 00575 bool CheckPending; 00576 00577 // For heuristics, keep a list of the nodes that immediately depend on the 00578 // most recently scheduled node. 00579 SmallPtrSet<const SUnit*, 8> NextSUs; 00580 00581 /// Number of cycles it takes to issue the instructions scheduled in this 00582 /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls. 00583 /// See getStalls(). 00584 unsigned CurrCycle; 00585 00586 /// Micro-ops issued in the current cycle 00587 unsigned CurrMOps; 00588 00589 /// MinReadyCycle - Cycle of the soonest available instruction. 00590 unsigned MinReadyCycle; 00591 00592 // The expected latency of the critical path in this scheduled zone. 00593 unsigned ExpectedLatency; 00594 00595 // The latency of dependence chains leading into this zone. 00596 // For each node scheduled bottom-up: DLat = max DLat, N.Depth. 00597 // For each cycle scheduled: DLat -= 1. 00598 unsigned DependentLatency; 00599 00600 /// Count the scheduled (issued) micro-ops that can be retired by 00601 /// time=CurrCycle assuming the first scheduled instr is retired at time=0. 00602 unsigned RetiredMOps; 00603 00604 // Count scheduled resources that have been executed. Resources are 00605 // considered executed if they become ready in the time that it takes to 00606 // saturate any resource including the one in question. Counts are scaled 00607 // for direct comparison with other resources. Counts can be compared with 00608 // MOps * getMicroOpFactor and Latency * getLatencyFactor. 00609 SmallVector<unsigned, 16> ExecutedResCounts; 00610 00611 /// Cache the max count for a single resource. 00612 unsigned MaxExecutedResCount; 00613 00614 // Cache the critical resources ID in this scheduled zone. 00615 unsigned ZoneCritResIdx; 00616 00617 // Is the scheduled region resource limited vs. latency limited. 00618 bool IsResourceLimited; 00619 00620 // Record the highest cycle at which each resource has been reserved by a 00621 // scheduled instruction. 00622 SmallVector<unsigned, 16> ReservedCycles; 00623 00624 #ifndef NDEBUG 00625 // Remember the greatest possible stall as an upper bound on the number of 00626 // times we should retry the pending queue because of a hazard. 00627 unsigned MaxObservedStall; 00628 #endif 00629 00630 public: 00631 /// Pending queues extend the ready queues with the same ID and the 00632 /// PendingFlag set. 00633 SchedBoundary(unsigned ID, const Twine &Name): 00634 DAG(nullptr), SchedModel(nullptr), Rem(nullptr), Available(ID, Name+".A"), 00635 Pending(ID << LogMaxQID, Name+".P"), 00636 HazardRec(nullptr) { 00637 reset(); 00638 } 00639 00640 ~SchedBoundary(); 00641 00642 void reset(); 00643 00644 void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, 00645 SchedRemainder *rem); 00646 00647 bool isTop() const { 00648 return Available.getID() == TopQID; 00649 } 00650 00651 /// Number of cycles to issue the instructions scheduled in this zone. 00652 unsigned getCurrCycle() const { return CurrCycle; } 00653 00654 /// Micro-ops issued in the current cycle 00655 unsigned getCurrMOps() const { return CurrMOps; } 00656 00657 /// Return true if the given SU is used by the most recently scheduled 00658 /// instruction. 00659 bool isNextSU(const SUnit *SU) const { return NextSUs.count(SU); } 00660 00661 // The latency of dependence chains leading into this zone. 00662 unsigned getDependentLatency() const { return DependentLatency; } 00663 00664 /// Get the number of latency cycles "covered" by the scheduled 00665 /// instructions. This is the larger of the critical path within the zone 00666 /// and the number of cycles required to issue the instructions. 00667 unsigned getScheduledLatency() const { 00668 return std::max(ExpectedLatency, CurrCycle); 00669 } 00670 00671 unsigned getUnscheduledLatency(SUnit *SU) const { 00672 return isTop() ? SU->getHeight() : SU->getDepth(); 00673 } 00674 00675 unsigned getResourceCount(unsigned ResIdx) const { 00676 return ExecutedResCounts[ResIdx]; 00677 } 00678 00679 /// Get the scaled count of scheduled micro-ops and resources, including 00680 /// executed resources. 00681 unsigned getCriticalCount() const { 00682 if (!ZoneCritResIdx) 00683 return RetiredMOps * SchedModel->getMicroOpFactor(); 00684 return getResourceCount(ZoneCritResIdx); 00685 } 00686 00687 /// Get a scaled count for the minimum execution time of the scheduled 00688 /// micro-ops that are ready to execute by getExecutedCount. Notice the 00689 /// feedback loop. 00690 unsigned getExecutedCount() const { 00691 return std::max(CurrCycle * SchedModel->getLatencyFactor(), 00692 MaxExecutedResCount); 00693 } 00694 00695 unsigned getZoneCritResIdx() const { return ZoneCritResIdx; } 00696 00697 // Is the scheduled region resource limited vs. latency limited. 00698 bool isResourceLimited() const { return IsResourceLimited; } 00699 00700 /// Get the difference between the given SUnit's ready time and the current 00701 /// cycle. 00702 unsigned getLatencyStallCycles(SUnit *SU); 00703 00704 unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles); 00705 00706 bool checkHazard(SUnit *SU); 00707 00708 unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs); 00709 00710 unsigned getOtherResourceCount(unsigned &OtherCritIdx); 00711 00712 void releaseNode(SUnit *SU, unsigned ReadyCycle); 00713 00714 void releaseTopNode(SUnit *SU); 00715 00716 void releaseBottomNode(SUnit *SU); 00717 00718 void bumpCycle(unsigned NextCycle); 00719 00720 void incExecutedResources(unsigned PIdx, unsigned Count); 00721 00722 unsigned countResource(unsigned PIdx, unsigned Cycles, unsigned ReadyCycle); 00723 00724 void bumpNode(SUnit *SU); 00725 00726 void releasePending(); 00727 00728 void removeReady(SUnit *SU); 00729 00730 /// Call this before applying any other heuristics to the Available queue. 00731 /// Updates the Available/Pending Q's if necessary and returns the single 00732 /// available instruction, or NULL if there are multiple candidates. 00733 SUnit *pickOnlyChoice(); 00734 00735 #ifndef NDEBUG 00736 void dumpScheduledState(); 00737 #endif 00738 }; 00739 00740 /// Base class for GenericScheduler. This class maintains information about 00741 /// scheduling candidates based on TargetSchedModel making it easy to implement 00742 /// heuristics for either preRA or postRA scheduling. 00743 class GenericSchedulerBase : public MachineSchedStrategy { 00744 public: 00745 /// Represent the type of SchedCandidate found within a single queue. 00746 /// pickNodeBidirectional depends on these listed by decreasing priority. 00747 enum CandReason { 00748 NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax, 00749 ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce, 00750 TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder}; 00751 00752 #ifndef NDEBUG 00753 static const char *getReasonStr(GenericSchedulerBase::CandReason Reason); 00754 #endif 00755 00756 /// Policy for scheduling the next instruction in the candidate's zone. 00757 struct CandPolicy { 00758 bool ReduceLatency; 00759 unsigned ReduceResIdx; 00760 unsigned DemandResIdx; 00761 00762 CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {} 00763 }; 00764 00765 /// Status of an instruction's critical resource consumption. 00766 struct SchedResourceDelta { 00767 // Count critical resources in the scheduled region required by SU. 00768 unsigned CritResources; 00769 00770 // Count critical resources from another region consumed by SU. 00771 unsigned DemandedResources; 00772 00773 SchedResourceDelta(): CritResources(0), DemandedResources(0) {} 00774 00775 bool operator==(const SchedResourceDelta &RHS) const { 00776 return CritResources == RHS.CritResources 00777 && DemandedResources == RHS.DemandedResources; 00778 } 00779 bool operator!=(const SchedResourceDelta &RHS) const { 00780 return !operator==(RHS); 00781 } 00782 }; 00783 00784 /// Store the state used by GenericScheduler heuristics, required for the 00785 /// lifetime of one invocation of pickNode(). 00786 struct SchedCandidate { 00787 CandPolicy Policy; 00788 00789 // The best SUnit candidate. 00790 SUnit *SU; 00791 00792 // The reason for this candidate. 00793 CandReason Reason; 00794 00795 // Set of reasons that apply to multiple candidates. 00796 uint32_t RepeatReasonSet; 00797 00798 // Register pressure values for the best candidate. 00799 RegPressureDelta RPDelta; 00800 00801 // Critical resource consumption of the best candidate. 00802 SchedResourceDelta ResDelta; 00803 00804 SchedCandidate(const CandPolicy &policy) 00805 : Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {} 00806 00807 bool isValid() const { return SU; } 00808 00809 // Copy the status of another candidate without changing policy. 00810 void setBest(SchedCandidate &Best) { 00811 assert(Best.Reason != NoCand && "uninitialized Sched candidate"); 00812 SU = Best.SU; 00813 Reason = Best.Reason; 00814 RPDelta = Best.RPDelta; 00815 ResDelta = Best.ResDelta; 00816 } 00817 00818 bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); } 00819 void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); } 00820 00821 void initResourceDelta(const ScheduleDAGMI *DAG, 00822 const TargetSchedModel *SchedModel); 00823 }; 00824 00825 protected: 00826 const MachineSchedContext *Context; 00827 const TargetSchedModel *SchedModel; 00828 const TargetRegisterInfo *TRI; 00829 00830 SchedRemainder Rem; 00831 protected: 00832 GenericSchedulerBase(const MachineSchedContext *C): 00833 Context(C), SchedModel(nullptr), TRI(nullptr) {} 00834 00835 void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, 00836 SchedBoundary *OtherZone); 00837 00838 #ifndef NDEBUG 00839 void traceCandidate(const SchedCandidate &Cand); 00840 #endif 00841 }; 00842 00843 /// GenericScheduler shrinks the unscheduled zone using heuristics to balance 00844 /// the schedule. 00845 class GenericScheduler : public GenericSchedulerBase { 00846 ScheduleDAGMILive *DAG; 00847 00848 // State of the top and bottom scheduled instruction boundaries. 00849 SchedBoundary Top; 00850 SchedBoundary Bot; 00851 00852 MachineSchedPolicy RegionPolicy; 00853 public: 00854 GenericScheduler(const MachineSchedContext *C): 00855 GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"), 00856 Bot(SchedBoundary::BotQID, "BotQ") {} 00857 00858 void initPolicy(MachineBasicBlock::iterator Begin, 00859 MachineBasicBlock::iterator End, 00860 unsigned NumRegionInstrs) override; 00861 00862 bool shouldTrackPressure() const override { 00863 return RegionPolicy.ShouldTrackPressure; 00864 } 00865 00866 void initialize(ScheduleDAGMI *dag) override; 00867 00868 SUnit *pickNode(bool &IsTopNode) override; 00869 00870 void schedNode(SUnit *SU, bool IsTopNode) override; 00871 00872 void releaseTopNode(SUnit *SU) override { 00873 Top.releaseTopNode(SU); 00874 } 00875 00876 void releaseBottomNode(SUnit *SU) override { 00877 Bot.releaseBottomNode(SU); 00878 } 00879 00880 void registerRoots() override; 00881 00882 protected: 00883 void checkAcyclicLatency(); 00884 00885 void tryCandidate(SchedCandidate &Cand, 00886 SchedCandidate &TryCand, 00887 SchedBoundary &Zone, 00888 const RegPressureTracker &RPTracker, 00889 RegPressureTracker &TempTracker); 00890 00891 SUnit *pickNodeBidirectional(bool &IsTopNode); 00892 00893 void pickNodeFromQueue(SchedBoundary &Zone, 00894 const RegPressureTracker &RPTracker, 00895 SchedCandidate &Candidate); 00896 00897 void reschedulePhysRegCopies(SUnit *SU, bool isTop); 00898 }; 00899 00900 /// PostGenericScheduler - Interface to the scheduling algorithm used by 00901 /// ScheduleDAGMI. 00902 /// 00903 /// Callbacks from ScheduleDAGMI: 00904 /// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... 00905 class PostGenericScheduler : public GenericSchedulerBase { 00906 ScheduleDAGMI *DAG; 00907 SchedBoundary Top; 00908 SmallVector<SUnit*, 8> BotRoots; 00909 public: 00910 PostGenericScheduler(const MachineSchedContext *C): 00911 GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} 00912 00913 virtual ~PostGenericScheduler() {} 00914 00915 void initPolicy(MachineBasicBlock::iterator Begin, 00916 MachineBasicBlock::iterator End, 00917 unsigned NumRegionInstrs) override { 00918 /* no configurable policy */ 00919 }; 00920 00921 /// PostRA scheduling does not track pressure. 00922 bool shouldTrackPressure() const override { return false; } 00923 00924 void initialize(ScheduleDAGMI *Dag) override; 00925 00926 void registerRoots() override; 00927 00928 SUnit *pickNode(bool &IsTopNode) override; 00929 00930 void scheduleTree(unsigned SubtreeID) override { 00931 llvm_unreachable("PostRA scheduler does not support subtree analysis."); 00932 } 00933 00934 void schedNode(SUnit *SU, bool IsTopNode) override; 00935 00936 void releaseTopNode(SUnit *SU) override { 00937 Top.releaseTopNode(SU); 00938 } 00939 00940 // Only called for roots. 00941 void releaseBottomNode(SUnit *SU) override { 00942 BotRoots.push_back(SU); 00943 } 00944 00945 protected: 00946 void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand); 00947 00948 void pickNodeFromQueue(SchedCandidate &Cand); 00949 }; 00950 00951 } // namespace llvm 00952 00953 #endif