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