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