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