1 //===- MachineScheduler.cpp - Machine Instruction Scheduler ---------------===// 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 // MachineScheduler schedules machine instructions after phi elimination. It 11 // preserves LiveIntervals so it can be invoked before register allocation. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #define DEBUG_TYPE "misched" 16 17 #include "llvm/CodeGen/LiveIntervalAnalysis.h" 18 #include "llvm/CodeGen/MachineScheduler.h" 19 #include "llvm/CodeGen/Passes.h" 20 #include "llvm/CodeGen/RegisterClassInfo.h" 21 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 22 #include "llvm/Analysis/AliasAnalysis.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include "llvm/ADT/OwningPtr.h" 28 #include "llvm/ADT/PriorityQueue.h" 29 30 #include <queue> 31 32 using namespace llvm; 33 34 namespace llvm { 35 cl::opt<bool> ForceTopDown("misched-topdown", cl::Hidden, 36 cl::desc("Force top-down list scheduling")); 37 cl::opt<bool> ForceBottomUp("misched-bottomup", cl::Hidden, 38 cl::desc("Force bottom-up list scheduling")); 39 } 40 41 #ifndef NDEBUG 42 static cl::opt<bool> ViewMISchedDAGs("view-misched-dags", cl::Hidden, 43 cl::desc("Pop up a window to show MISched dags after they are processed")); 44 45 static cl::opt<unsigned> MISchedCutoff("misched-cutoff", cl::Hidden, 46 cl::desc("Stop scheduling after N instructions"), cl::init(~0U)); 47 #else 48 static bool ViewMISchedDAGs = false; 49 #endif // NDEBUG 50 51 //===----------------------------------------------------------------------===// 52 // Machine Instruction Scheduling Pass and Registry 53 //===----------------------------------------------------------------------===// 54 55 MachineSchedContext::MachineSchedContext(): 56 MF(0), MLI(0), MDT(0), PassConfig(0), AA(0), LIS(0) { 57 RegClassInfo = new RegisterClassInfo(); 58 } 59 60 MachineSchedContext::~MachineSchedContext() { 61 delete RegClassInfo; 62 } 63 64 namespace { 65 /// MachineScheduler runs after coalescing and before register allocation. 66 class MachineScheduler : public MachineSchedContext, 67 public MachineFunctionPass { 68 public: 69 MachineScheduler(); 70 71 virtual void getAnalysisUsage(AnalysisUsage &AU) const; 72 73 virtual void releaseMemory() {} 74 75 virtual bool runOnMachineFunction(MachineFunction&); 76 77 virtual void print(raw_ostream &O, const Module* = 0) const; 78 79 static char ID; // Class identification, replacement for typeinfo 80 }; 81 } // namespace 82 83 char MachineScheduler::ID = 0; 84 85 char &llvm::MachineSchedulerID = MachineScheduler::ID; 86 87 INITIALIZE_PASS_BEGIN(MachineScheduler, "misched", 88 "Machine Instruction Scheduler", false, false) 89 INITIALIZE_AG_DEPENDENCY(AliasAnalysis) 90 INITIALIZE_PASS_DEPENDENCY(SlotIndexes) 91 INITIALIZE_PASS_DEPENDENCY(LiveIntervals) 92 INITIALIZE_PASS_END(MachineScheduler, "misched", 93 "Machine Instruction Scheduler", false, false) 94 95 MachineScheduler::MachineScheduler() 96 : MachineFunctionPass(ID) { 97 initializeMachineSchedulerPass(*PassRegistry::getPassRegistry()); 98 } 99 100 void MachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const { 101 AU.setPreservesCFG(); 102 AU.addRequiredID(MachineDominatorsID); 103 AU.addRequired<MachineLoopInfo>(); 104 AU.addRequired<AliasAnalysis>(); 105 AU.addRequired<TargetPassConfig>(); 106 AU.addRequired<SlotIndexes>(); 107 AU.addPreserved<SlotIndexes>(); 108 AU.addRequired<LiveIntervals>(); 109 AU.addPreserved<LiveIntervals>(); 110 MachineFunctionPass::getAnalysisUsage(AU); 111 } 112 113 MachinePassRegistry MachineSchedRegistry::Registry; 114 115 /// A dummy default scheduler factory indicates whether the scheduler 116 /// is overridden on the command line. 117 static ScheduleDAGInstrs *useDefaultMachineSched(MachineSchedContext *C) { 118 return 0; 119 } 120 121 /// MachineSchedOpt allows command line selection of the scheduler. 122 static cl::opt<MachineSchedRegistry::ScheduleDAGCtor, false, 123 RegisterPassParser<MachineSchedRegistry> > 124 MachineSchedOpt("misched", 125 cl::init(&useDefaultMachineSched), cl::Hidden, 126 cl::desc("Machine instruction scheduler to use")); 127 128 static MachineSchedRegistry 129 DefaultSchedRegistry("default", "Use the target's default scheduler choice.", 130 useDefaultMachineSched); 131 132 /// Forward declare the standard machine scheduler. This will be used as the 133 /// default scheduler if the target does not set a default. 134 static ScheduleDAGInstrs *createConvergingSched(MachineSchedContext *C); 135 136 137 /// Decrement this iterator until reaching the top or a non-debug instr. 138 static MachineBasicBlock::iterator 139 priorNonDebug(MachineBasicBlock::iterator I, MachineBasicBlock::iterator Beg) { 140 assert(I != Beg && "reached the top of the region, cannot decrement"); 141 while (--I != Beg) { 142 if (!I->isDebugValue()) 143 break; 144 } 145 return I; 146 } 147 148 /// If this iterator is a debug value, increment until reaching the End or a 149 /// non-debug instruction. 150 static MachineBasicBlock::iterator 151 nextIfDebug(MachineBasicBlock::iterator I, MachineBasicBlock::iterator End) { 152 for(; I != End; ++I) { 153 if (!I->isDebugValue()) 154 break; 155 } 156 return I; 157 } 158 159 /// Top-level MachineScheduler pass driver. 160 /// 161 /// Visit blocks in function order. Divide each block into scheduling regions 162 /// and visit them bottom-up. Visiting regions bottom-up is not required, but is 163 /// consistent with the DAG builder, which traverses the interior of the 164 /// scheduling regions bottom-up. 165 /// 166 /// This design avoids exposing scheduling boundaries to the DAG builder, 167 /// simplifying the DAG builder's support for "special" target instructions. 168 /// At the same time the design allows target schedulers to operate across 169 /// scheduling boundaries, for example to bundle the boudary instructions 170 /// without reordering them. This creates complexity, because the target 171 /// scheduler must update the RegionBegin and RegionEnd positions cached by 172 /// ScheduleDAGInstrs whenever adding or removing instructions. A much simpler 173 /// design would be to split blocks at scheduling boundaries, but LLVM has a 174 /// general bias against block splitting purely for implementation simplicity. 175 bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { 176 DEBUG(dbgs() << "Before MISsched:\n"; mf.print(dbgs())); 177 178 // Initialize the context of the pass. 179 MF = &mf; 180 MLI = &getAnalysis<MachineLoopInfo>(); 181 MDT = &getAnalysis<MachineDominatorTree>(); 182 PassConfig = &getAnalysis<TargetPassConfig>(); 183 AA = &getAnalysis<AliasAnalysis>(); 184 185 LIS = &getAnalysis<LiveIntervals>(); 186 const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); 187 188 RegClassInfo->runOnMachineFunction(*MF); 189 190 // Select the scheduler, or set the default. 191 MachineSchedRegistry::ScheduleDAGCtor Ctor = MachineSchedOpt; 192 if (Ctor == useDefaultMachineSched) { 193 // Get the default scheduler set by the target. 194 Ctor = MachineSchedRegistry::getDefault(); 195 if (!Ctor) { 196 Ctor = createConvergingSched; 197 MachineSchedRegistry::setDefault(Ctor); 198 } 199 } 200 // Instantiate the selected scheduler. 201 OwningPtr<ScheduleDAGInstrs> Scheduler(Ctor(this)); 202 203 // Visit all machine basic blocks. 204 // 205 // TODO: Visit blocks in global postorder or postorder within the bottom-up 206 // loop tree. Then we can optionally compute global RegPressure. 207 for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end(); 208 MBB != MBBEnd; ++MBB) { 209 210 Scheduler->startBlock(MBB); 211 212 // Break the block into scheduling regions [I, RegionEnd), and schedule each 213 // region as soon as it is discovered. RegionEnd points the scheduling 214 // boundary at the bottom of the region. The DAG does not include RegionEnd, 215 // but the region does (i.e. the next RegionEnd is above the previous 216 // RegionBegin). If the current block has no terminator then RegionEnd == 217 // MBB->end() for the bottom region. 218 // 219 // The Scheduler may insert instructions during either schedule() or 220 // exitRegion(), even for empty regions. So the local iterators 'I' and 221 // 'RegionEnd' are invalid across these calls. 222 unsigned RemainingCount = MBB->size(); 223 for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 224 RegionEnd != MBB->begin(); RegionEnd = Scheduler->begin()) { 225 226 // Avoid decrementing RegionEnd for blocks with no terminator. 227 if (RegionEnd != MBB->end() 228 || TII->isSchedulingBoundary(llvm::prior(RegionEnd), MBB, *MF)) { 229 --RegionEnd; 230 // Count the boundary instruction. 231 --RemainingCount; 232 } 233 234 // The next region starts above the previous region. Look backward in the 235 // instruction stream until we find the nearest boundary. 236 MachineBasicBlock::iterator I = RegionEnd; 237 for(;I != MBB->begin(); --I, --RemainingCount) { 238 if (TII->isSchedulingBoundary(llvm::prior(I), MBB, *MF)) 239 break; 240 } 241 // Notify the scheduler of the region, even if we may skip scheduling 242 // it. Perhaps it still needs to be bundled. 243 Scheduler->enterRegion(MBB, I, RegionEnd, RemainingCount); 244 245 // Skip empty scheduling regions (0 or 1 schedulable instructions). 246 if (I == RegionEnd || I == llvm::prior(RegionEnd)) { 247 // Close the current region. Bundle the terminator if needed. 248 // This invalidates 'RegionEnd' and 'I'. 249 Scheduler->exitRegion(); 250 continue; 251 } 252 DEBUG(dbgs() << "********** MI Scheduling **********\n"); 253 DEBUG(dbgs() << MF->getName() 254 << ":BB#" << MBB->getNumber() << "\n From: " << *I << " To: "; 255 if (RegionEnd != MBB->end()) dbgs() << *RegionEnd; 256 else dbgs() << "End"; 257 dbgs() << " Remaining: " << RemainingCount << "\n"); 258 259 // Schedule a region: possibly reorder instructions. 260 // This invalidates 'RegionEnd' and 'I'. 261 Scheduler->schedule(); 262 263 // Close the current region. 264 Scheduler->exitRegion(); 265 266 // Scheduling has invalidated the current iterator 'I'. Ask the 267 // scheduler for the top of it's scheduled region. 268 RegionEnd = Scheduler->begin(); 269 } 270 assert(RemainingCount == 0 && "Instruction count mismatch!"); 271 Scheduler->finishBlock(); 272 } 273 Scheduler->finalizeSchedule(); 274 DEBUG(LIS->print(dbgs())); 275 return true; 276 } 277 278 void MachineScheduler::print(raw_ostream &O, const Module* m) const { 279 // unimplemented 280 } 281 282 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 283 void ReadyQueue::dump() { 284 dbgs() << Name << ": "; 285 for (unsigned i = 0, e = Queue.size(); i < e; ++i) 286 dbgs() << Queue[i]->NodeNum << " "; 287 dbgs() << "\n"; 288 } 289 #endif 290 291 //===----------------------------------------------------------------------===// 292 // ScheduleDAGMI - Base class for MachineInstr scheduling with LiveIntervals 293 // preservation. 294 //===----------------------------------------------------------------------===// 295 296 /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When 297 /// NumPredsLeft reaches zero, release the successor node. 298 /// 299 /// FIXME: Adjust SuccSU height based on MinLatency. 300 void ScheduleDAGMI::releaseSucc(SUnit *SU, SDep *SuccEdge) { 301 SUnit *SuccSU = SuccEdge->getSUnit(); 302 303 #ifndef NDEBUG 304 if (SuccSU->NumPredsLeft == 0) { 305 dbgs() << "*** Scheduling failed! ***\n"; 306 SuccSU->dump(this); 307 dbgs() << " has been released too many times!\n"; 308 llvm_unreachable(0); 309 } 310 #endif 311 --SuccSU->NumPredsLeft; 312 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) 313 SchedImpl->releaseTopNode(SuccSU); 314 } 315 316 /// releaseSuccessors - Call releaseSucc on each of SU's successors. 317 void ScheduleDAGMI::releaseSuccessors(SUnit *SU) { 318 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); 319 I != E; ++I) { 320 releaseSucc(SU, &*I); 321 } 322 } 323 324 /// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. When 325 /// NumSuccsLeft reaches zero, release the predecessor node. 326 /// 327 /// FIXME: Adjust PredSU height based on MinLatency. 328 void ScheduleDAGMI::releasePred(SUnit *SU, SDep *PredEdge) { 329 SUnit *PredSU = PredEdge->getSUnit(); 330 331 #ifndef NDEBUG 332 if (PredSU->NumSuccsLeft == 0) { 333 dbgs() << "*** Scheduling failed! ***\n"; 334 PredSU->dump(this); 335 dbgs() << " has been released too many times!\n"; 336 llvm_unreachable(0); 337 } 338 #endif 339 --PredSU->NumSuccsLeft; 340 if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) 341 SchedImpl->releaseBottomNode(PredSU); 342 } 343 344 /// releasePredecessors - Call releasePred on each of SU's predecessors. 345 void ScheduleDAGMI::releasePredecessors(SUnit *SU) { 346 for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 347 I != E; ++I) { 348 releasePred(SU, &*I); 349 } 350 } 351 352 void ScheduleDAGMI::moveInstruction(MachineInstr *MI, 353 MachineBasicBlock::iterator InsertPos) { 354 // Advance RegionBegin if the first instruction moves down. 355 if (&*RegionBegin == MI) 356 ++RegionBegin; 357 358 // Update the instruction stream. 359 BB->splice(InsertPos, BB, MI); 360 361 // Update LiveIntervals 362 LIS->handleMove(MI); 363 364 // Recede RegionBegin if an instruction moves above the first. 365 if (RegionBegin == InsertPos) 366 RegionBegin = MI; 367 } 368 369 bool ScheduleDAGMI::checkSchedLimit() { 370 #ifndef NDEBUG 371 if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) { 372 CurrentTop = CurrentBottom; 373 return false; 374 } 375 ++NumInstrsScheduled; 376 #endif 377 return true; 378 } 379 380 /// enterRegion - Called back from MachineScheduler::runOnMachineFunction after 381 /// crossing a scheduling boundary. [begin, end) includes all instructions in 382 /// the region, including the boundary itself and single-instruction regions 383 /// that don't get scheduled. 384 void ScheduleDAGMI::enterRegion(MachineBasicBlock *bb, 385 MachineBasicBlock::iterator begin, 386 MachineBasicBlock::iterator end, 387 unsigned endcount) 388 { 389 ScheduleDAGInstrs::enterRegion(bb, begin, end, endcount); 390 391 // For convenience remember the end of the liveness region. 392 LiveRegionEnd = 393 (RegionEnd == bb->end()) ? RegionEnd : llvm::next(RegionEnd); 394 } 395 396 // Setup the register pressure trackers for the top scheduled top and bottom 397 // scheduled regions. 398 void ScheduleDAGMI::initRegPressure() { 399 TopRPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin); 400 BotRPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd); 401 402 // Close the RPTracker to finalize live ins. 403 RPTracker.closeRegion(); 404 405 DEBUG(RPTracker.getPressure().dump(TRI)); 406 407 // Initialize the live ins and live outs. 408 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs); 409 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs); 410 411 // Close one end of the tracker so we can call 412 // getMaxUpward/DownwardPressureDelta before advancing across any 413 // instructions. This converts currently live regs into live ins/outs. 414 TopRPTracker.closeTop(); 415 BotRPTracker.closeBottom(); 416 417 // Account for liveness generated by the region boundary. 418 if (LiveRegionEnd != RegionEnd) 419 BotRPTracker.recede(); 420 421 assert(BotRPTracker.getPos() == RegionEnd && "Can't find the region bottom"); 422 423 // Cache the list of excess pressure sets in this region. This will also track 424 // the max pressure in the scheduled code for these sets. 425 RegionCriticalPSets.clear(); 426 std::vector<unsigned> RegionPressure = RPTracker.getPressure().MaxSetPressure; 427 for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) { 428 unsigned Limit = TRI->getRegPressureSetLimit(i); 429 DEBUG(dbgs() << TRI->getRegPressureSetName(i) 430 << "Limit " << Limit 431 << " Actual " << RegionPressure[i] << "\n"); 432 if (RegionPressure[i] > Limit) 433 RegionCriticalPSets.push_back(PressureElement(i, 0)); 434 } 435 DEBUG(dbgs() << "Excess PSets: "; 436 for (unsigned i = 0, e = RegionCriticalPSets.size(); i != e; ++i) 437 dbgs() << TRI->getRegPressureSetName( 438 RegionCriticalPSets[i].PSetID) << " "; 439 dbgs() << "\n"); 440 } 441 442 // FIXME: When the pressure tracker deals in pressure differences then we won't 443 // iterate over all RegionCriticalPSets[i]. 444 void ScheduleDAGMI:: 445 updateScheduledPressure(std::vector<unsigned> NewMaxPressure) { 446 for (unsigned i = 0, e = RegionCriticalPSets.size(); i < e; ++i) { 447 unsigned ID = RegionCriticalPSets[i].PSetID; 448 int &MaxUnits = RegionCriticalPSets[i].UnitIncrease; 449 if ((int)NewMaxPressure[ID] > MaxUnits) 450 MaxUnits = NewMaxPressure[ID]; 451 } 452 } 453 454 // Release all DAG roots for scheduling. 455 void ScheduleDAGMI::releaseRoots() { 456 SmallVector<SUnit*, 16> BotRoots; 457 458 for (std::vector<SUnit>::iterator 459 I = SUnits.begin(), E = SUnits.end(); I != E; ++I) { 460 // A SUnit is ready to top schedule if it has no predecessors. 461 if (I->Preds.empty()) 462 SchedImpl->releaseTopNode(&(*I)); 463 // A SUnit is ready to bottom schedule if it has no successors. 464 if (I->Succs.empty()) 465 BotRoots.push_back(&(*I)); 466 } 467 // Release bottom roots in reverse order so the higher priority nodes appear 468 // first. This is more natural and slightly more efficient. 469 for (SmallVectorImpl<SUnit*>::const_reverse_iterator 470 I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I) 471 SchedImpl->releaseBottomNode(*I); 472 } 473 474 /// schedule - Called back from MachineScheduler::runOnMachineFunction 475 /// after setting up the current scheduling region. [RegionBegin, RegionEnd) 476 /// only includes instructions that have DAG nodes, not scheduling boundaries. 477 /// 478 /// This is a skeletal driver, with all the functionality pushed into helpers, 479 /// so that it can be easilly extended by experimental schedulers. Generally, 480 /// implementing MachineSchedStrategy should be sufficient to implement a new 481 /// scheduling algorithm. However, if a scheduler further subclasses 482 /// ScheduleDAGMI then it will want to override this virtual method in order to 483 /// update any specialized state. 484 void ScheduleDAGMI::schedule() { 485 buildDAGWithRegPressure(); 486 487 postprocessDAG(); 488 489 DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) 490 SUnits[su].dumpAll(this)); 491 492 if (ViewMISchedDAGs) viewGraph(); 493 494 initQueues(); 495 496 bool IsTopNode = false; 497 while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) { 498 if (!checkSchedLimit()) 499 break; 500 501 scheduleMI(SU, IsTopNode); 502 503 updateQueues(SU, IsTopNode); 504 } 505 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone."); 506 507 placeDebugValues(); 508 } 509 510 /// Build the DAG and setup three register pressure trackers. 511 void ScheduleDAGMI::buildDAGWithRegPressure() { 512 // Initialize the register pressure tracker used by buildSchedGraph. 513 RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd); 514 515 // Account for liveness generate by the region boundary. 516 if (LiveRegionEnd != RegionEnd) 517 RPTracker.recede(); 518 519 // Build the DAG, and compute current register pressure. 520 buildSchedGraph(AA, &RPTracker); 521 if (ViewMISchedDAGs) viewGraph(); 522 523 // Initialize top/bottom trackers after computing region pressure. 524 initRegPressure(); 525 } 526 527 /// Apply each ScheduleDAGMutation step in order. 528 void ScheduleDAGMI::postprocessDAG() { 529 for (unsigned i = 0, e = Mutations.size(); i < e; ++i) { 530 Mutations[i]->apply(this); 531 } 532 } 533 534 /// Identify DAG roots and setup scheduler queues. 535 void ScheduleDAGMI::initQueues() { 536 // Initialize the strategy before modifying the DAG. 537 SchedImpl->initialize(this); 538 539 // Release edges from the special Entry node or to the special Exit node. 540 releaseSuccessors(&EntrySU); 541 releasePredecessors(&ExitSU); 542 543 // Release all DAG roots for scheduling. 544 releaseRoots(); 545 546 CurrentTop = nextIfDebug(RegionBegin, RegionEnd); 547 CurrentBottom = RegionEnd; 548 } 549 550 /// Move an instruction and update register pressure. 551 void ScheduleDAGMI::scheduleMI(SUnit *SU, bool IsTopNode) { 552 // Move the instruction to its new location in the instruction stream. 553 MachineInstr *MI = SU->getInstr(); 554 555 if (IsTopNode) { 556 assert(SU->isTopReady() && "node still has unscheduled dependencies"); 557 if (&*CurrentTop == MI) 558 CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom); 559 else { 560 moveInstruction(MI, CurrentTop); 561 TopRPTracker.setPos(MI); 562 } 563 564 // Update top scheduled pressure. 565 TopRPTracker.advance(); 566 assert(TopRPTracker.getPos() == CurrentTop && "out of sync"); 567 updateScheduledPressure(TopRPTracker.getPressure().MaxSetPressure); 568 } 569 else { 570 assert(SU->isBottomReady() && "node still has unscheduled dependencies"); 571 MachineBasicBlock::iterator priorII = 572 priorNonDebug(CurrentBottom, CurrentTop); 573 if (&*priorII == MI) 574 CurrentBottom = priorII; 575 else { 576 if (&*CurrentTop == MI) { 577 CurrentTop = nextIfDebug(++CurrentTop, priorII); 578 TopRPTracker.setPos(CurrentTop); 579 } 580 moveInstruction(MI, CurrentBottom); 581 CurrentBottom = MI; 582 } 583 // Update bottom scheduled pressure. 584 BotRPTracker.recede(); 585 assert(BotRPTracker.getPos() == CurrentBottom && "out of sync"); 586 updateScheduledPressure(BotRPTracker.getPressure().MaxSetPressure); 587 } 588 } 589 590 /// Update scheduler queues after scheduling an instruction. 591 void ScheduleDAGMI::updateQueues(SUnit *SU, bool IsTopNode) { 592 // Release dependent instructions for scheduling. 593 if (IsTopNode) 594 releaseSuccessors(SU); 595 else 596 releasePredecessors(SU); 597 598 SU->isScheduled = true; 599 600 // Notify the scheduling strategy after updating the DAG. 601 SchedImpl->schedNode(SU, IsTopNode); 602 } 603 604 /// Reinsert any remaining debug_values, just like the PostRA scheduler. 605 void ScheduleDAGMI::placeDebugValues() { 606 // If first instruction was a DBG_VALUE then put it back. 607 if (FirstDbgValue) { 608 BB->splice(RegionBegin, BB, FirstDbgValue); 609 RegionBegin = FirstDbgValue; 610 } 611 612 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator 613 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) { 614 std::pair<MachineInstr *, MachineInstr *> P = *prior(DI); 615 MachineInstr *DbgValue = P.first; 616 MachineBasicBlock::iterator OrigPrevMI = P.second; 617 BB->splice(++OrigPrevMI, BB, DbgValue); 618 if (OrigPrevMI == llvm::prior(RegionEnd)) 619 RegionEnd = DbgValue; 620 } 621 DbgValues.clear(); 622 FirstDbgValue = NULL; 623 } 624 625 //===----------------------------------------------------------------------===// 626 // ConvergingScheduler - Implementation of the standard MachineSchedStrategy. 627 //===----------------------------------------------------------------------===// 628 629 namespace { 630 /// ConvergingScheduler shrinks the unscheduled zone using heuristics to balance 631 /// the schedule. 632 class ConvergingScheduler : public MachineSchedStrategy { 633 634 /// Store the state used by ConvergingScheduler heuristics, required for the 635 /// lifetime of one invocation of pickNode(). 636 struct SchedCandidate { 637 // The best SUnit candidate. 638 SUnit *SU; 639 640 // Register pressure values for the best candidate. 641 RegPressureDelta RPDelta; 642 643 SchedCandidate(): SU(NULL) {} 644 }; 645 /// Represent the type of SchedCandidate found within a single queue. 646 enum CandResult { 647 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure }; 648 649 /// Each Scheduling boundary is associated with ready queues. It tracks the 650 /// current cycle in whichever direction at has moved, and maintains the state 651 /// of "hazards" and other interlocks at the current cycle. 652 struct SchedBoundary { 653 ScheduleDAGMI *DAG; 654 655 ReadyQueue Available; 656 ReadyQueue Pending; 657 bool CheckPending; 658 659 ScheduleHazardRecognizer *HazardRec; 660 661 unsigned CurrCycle; 662 unsigned IssueCount; 663 664 /// MinReadyCycle - Cycle of the soonest available instruction. 665 unsigned MinReadyCycle; 666 667 // Remember the greatest min operand latency. 668 unsigned MaxMinLatency; 669 670 /// Pending queues extend the ready queues with the same ID and the 671 /// PendingFlag set. 672 SchedBoundary(unsigned ID, const Twine &Name): 673 DAG(0), Available(ID, Name+".A"), 674 Pending(ID << ConvergingScheduler::LogMaxQID, Name+".P"), 675 CheckPending(false), HazardRec(0), CurrCycle(0), IssueCount(0), 676 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {} 677 678 ~SchedBoundary() { delete HazardRec; } 679 680 bool isTop() const { 681 return Available.getID() == ConvergingScheduler::TopQID; 682 } 683 684 bool checkHazard(SUnit *SU); 685 686 void releaseNode(SUnit *SU, unsigned ReadyCycle); 687 688 void bumpCycle(); 689 690 void bumpNode(SUnit *SU); 691 692 void releasePending(); 693 694 void removeReady(SUnit *SU); 695 696 SUnit *pickOnlyChoice(); 697 }; 698 699 ScheduleDAGMI *DAG; 700 const TargetRegisterInfo *TRI; 701 702 // State of the top and bottom scheduled instruction boundaries. 703 SchedBoundary Top; 704 SchedBoundary Bot; 705 706 public: 707 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) 708 enum { 709 TopQID = 1, 710 BotQID = 2, 711 LogMaxQID = 2 712 }; 713 714 ConvergingScheduler(): 715 DAG(0), TRI(0), Top(TopQID, "TopQ"), Bot(BotQID, "BotQ") {} 716 717 virtual void initialize(ScheduleDAGMI *dag); 718 719 virtual SUnit *pickNode(bool &IsTopNode); 720 721 virtual void schedNode(SUnit *SU, bool IsTopNode); 722 723 virtual void releaseTopNode(SUnit *SU); 724 725 virtual void releaseBottomNode(SUnit *SU); 726 727 protected: 728 SUnit *pickNodeBidrectional(bool &IsTopNode); 729 730 CandResult pickNodeFromQueue(ReadyQueue &Q, 731 const RegPressureTracker &RPTracker, 732 SchedCandidate &Candidate); 733 #ifndef NDEBUG 734 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU, 735 PressureElement P = PressureElement()); 736 #endif 737 }; 738 } // namespace 739 740 void ConvergingScheduler::initialize(ScheduleDAGMI *dag) { 741 DAG = dag; 742 TRI = DAG->TRI; 743 Top.DAG = dag; 744 Bot.DAG = dag; 745 746 // Initialize the HazardRecognizers. 747 const TargetMachine &TM = DAG->MF.getTarget(); 748 const InstrItineraryData *Itin = TM.getInstrItineraryData(); 749 Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); 750 Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); 751 752 assert((!ForceTopDown || !ForceBottomUp) && 753 "-misched-topdown incompatible with -misched-bottomup"); 754 } 755 756 void ConvergingScheduler::releaseTopNode(SUnit *SU) { 757 if (SU->isScheduled) 758 return; 759 760 for (SUnit::succ_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 761 I != E; ++I) { 762 unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle; 763 unsigned MinLatency = I->getMinLatency(); 764 #ifndef NDEBUG 765 Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency); 766 #endif 767 if (SU->TopReadyCycle < PredReadyCycle + MinLatency) 768 SU->TopReadyCycle = PredReadyCycle + MinLatency; 769 } 770 Top.releaseNode(SU, SU->TopReadyCycle); 771 } 772 773 void ConvergingScheduler::releaseBottomNode(SUnit *SU) { 774 if (SU->isScheduled) 775 return; 776 777 assert(SU->getInstr() && "Scheduled SUnit must have instr"); 778 779 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); 780 I != E; ++I) { 781 unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle; 782 unsigned MinLatency = I->getMinLatency(); 783 #ifndef NDEBUG 784 Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency); 785 #endif 786 if (SU->BotReadyCycle < SuccReadyCycle + MinLatency) 787 SU->BotReadyCycle = SuccReadyCycle + MinLatency; 788 } 789 Bot.releaseNode(SU, SU->BotReadyCycle); 790 } 791 792 /// Does this SU have a hazard within the current instruction group. 793 /// 794 /// The scheduler supports two modes of hazard recognition. The first is the 795 /// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that 796 /// supports highly complicated in-order reservation tables 797 /// (ScoreboardHazardRecognizer) and arbitraty target-specific logic. 798 /// 799 /// The second is a streamlined mechanism that checks for hazards based on 800 /// simple counters that the scheduler itself maintains. It explicitly checks 801 /// for instruction dispatch limitations, including the number of micro-ops that 802 /// can dispatch per cycle. 803 /// 804 /// TODO: Also check whether the SU must start a new group. 805 bool ConvergingScheduler::SchedBoundary::checkHazard(SUnit *SU) { 806 if (HazardRec->isEnabled()) 807 return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard; 808 809 if (IssueCount + DAG->getNumMicroOps(SU->getInstr()) > DAG->getIssueWidth()) 810 return true; 811 812 return false; 813 } 814 815 void ConvergingScheduler::SchedBoundary::releaseNode(SUnit *SU, 816 unsigned ReadyCycle) { 817 if (ReadyCycle < MinReadyCycle) 818 MinReadyCycle = ReadyCycle; 819 820 // Check for interlocks first. For the purpose of other heuristics, an 821 // instruction that cannot issue appears as if it's not in the ReadyQueue. 822 if (ReadyCycle > CurrCycle || checkHazard(SU)) 823 Pending.push(SU); 824 else 825 Available.push(SU); 826 } 827 828 /// Move the boundary of scheduled code by one cycle. 829 void ConvergingScheduler::SchedBoundary::bumpCycle() { 830 unsigned Width = DAG->getIssueWidth(); 831 IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width; 832 833 assert(MinReadyCycle < UINT_MAX && "MinReadyCycle uninitialized"); 834 unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle); 835 836 if (!HazardRec->isEnabled()) { 837 // Bypass HazardRec virtual calls. 838 CurrCycle = NextCycle; 839 } 840 else { 841 // Bypass getHazardType calls in case of long latency. 842 for (; CurrCycle != NextCycle; ++CurrCycle) { 843 if (isTop()) 844 HazardRec->AdvanceCycle(); 845 else 846 HazardRec->RecedeCycle(); 847 } 848 } 849 CheckPending = true; 850 851 DEBUG(dbgs() << "*** " << Available.getName() << " cycle " 852 << CurrCycle << '\n'); 853 } 854 855 /// Move the boundary of scheduled code by one SUnit. 856 void ConvergingScheduler::SchedBoundary::bumpNode(SUnit *SU) { 857 // Update the reservation table. 858 if (HazardRec->isEnabled()) { 859 if (!isTop() && SU->isCall) { 860 // Calls are scheduled with their preceding instructions. For bottom-up 861 // scheduling, clear the pipeline state before emitting. 862 HazardRec->Reset(); 863 } 864 HazardRec->EmitInstruction(SU); 865 } 866 // Check the instruction group dispatch limit. 867 // TODO: Check if this SU must end a dispatch group. 868 IssueCount += DAG->getNumMicroOps(SU->getInstr()); 869 if (IssueCount >= DAG->getIssueWidth()) { 870 DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n'); 871 bumpCycle(); 872 } 873 } 874 875 /// Release pending ready nodes in to the available queue. This makes them 876 /// visible to heuristics. 877 void ConvergingScheduler::SchedBoundary::releasePending() { 878 // If the available queue is empty, it is safe to reset MinReadyCycle. 879 if (Available.empty()) 880 MinReadyCycle = UINT_MAX; 881 882 // Check to see if any of the pending instructions are ready to issue. If 883 // so, add them to the available queue. 884 for (unsigned i = 0, e = Pending.size(); i != e; ++i) { 885 SUnit *SU = *(Pending.begin()+i); 886 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle; 887 888 if (ReadyCycle < MinReadyCycle) 889 MinReadyCycle = ReadyCycle; 890 891 if (ReadyCycle > CurrCycle) 892 continue; 893 894 if (checkHazard(SU)) 895 continue; 896 897 Available.push(SU); 898 Pending.remove(Pending.begin()+i); 899 --i; --e; 900 } 901 CheckPending = false; 902 } 903 904 /// Remove SU from the ready set for this boundary. 905 void ConvergingScheduler::SchedBoundary::removeReady(SUnit *SU) { 906 if (Available.isInQueue(SU)) 907 Available.remove(Available.find(SU)); 908 else { 909 assert(Pending.isInQueue(SU) && "bad ready count"); 910 Pending.remove(Pending.find(SU)); 911 } 912 } 913 914 /// If this queue only has one ready candidate, return it. As a side effect, 915 /// advance the cycle until at least one node is ready. If multiple instructions 916 /// are ready, return NULL. 917 SUnit *ConvergingScheduler::SchedBoundary::pickOnlyChoice() { 918 if (CheckPending) 919 releasePending(); 920 921 for (unsigned i = 0; Available.empty(); ++i) { 922 assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) && 923 "permanent hazard"); (void)i; 924 bumpCycle(); 925 releasePending(); 926 } 927 if (Available.size() == 1) 928 return *Available.begin(); 929 return NULL; 930 } 931 932 #ifndef NDEBUG 933 void ConvergingScheduler::traceCandidate(const char *Label, const ReadyQueue &Q, 934 SUnit *SU, PressureElement P) { 935 dbgs() << Label << " " << Q.getName() << " "; 936 if (P.isValid()) 937 dbgs() << TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease 938 << " "; 939 else 940 dbgs() << " "; 941 SU->dump(DAG); 942 } 943 #endif 944 945 /// pickNodeFromQueue helper that returns true if the LHS reg pressure effect is 946 /// more desirable than RHS from scheduling standpoint. 947 static bool compareRPDelta(const RegPressureDelta &LHS, 948 const RegPressureDelta &RHS) { 949 // Compare each component of pressure in decreasing order of importance 950 // without checking if any are valid. Invalid PressureElements are assumed to 951 // have UnitIncrease==0, so are neutral. 952 953 // Avoid increasing the max critical pressure in the scheduled region. 954 if (LHS.Excess.UnitIncrease != RHS.Excess.UnitIncrease) 955 return LHS.Excess.UnitIncrease < RHS.Excess.UnitIncrease; 956 957 // Avoid increasing the max critical pressure in the scheduled region. 958 if (LHS.CriticalMax.UnitIncrease != RHS.CriticalMax.UnitIncrease) 959 return LHS.CriticalMax.UnitIncrease < RHS.CriticalMax.UnitIncrease; 960 961 // Avoid increasing the max pressure of the entire region. 962 if (LHS.CurrentMax.UnitIncrease != RHS.CurrentMax.UnitIncrease) 963 return LHS.CurrentMax.UnitIncrease < RHS.CurrentMax.UnitIncrease; 964 965 return false; 966 } 967 968 /// Pick the best candidate from the top queue. 969 /// 970 /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during 971 /// DAG building. To adjust for the current scheduling location we need to 972 /// maintain the number of vreg uses remaining to be top-scheduled. 973 ConvergingScheduler::CandResult ConvergingScheduler:: 974 pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker, 975 SchedCandidate &Candidate) { 976 DEBUG(Q.dump()); 977 978 // getMaxPressureDelta temporarily modifies the tracker. 979 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker); 980 981 // BestSU remains NULL if no top candidates beat the best existing candidate. 982 CandResult FoundCandidate = NoCand; 983 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) { 984 RegPressureDelta RPDelta; 985 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta, 986 DAG->getRegionCriticalPSets(), 987 DAG->getRegPressure().MaxSetPressure); 988 989 // Initialize the candidate if needed. 990 if (!Candidate.SU) { 991 Candidate.SU = *I; 992 Candidate.RPDelta = RPDelta; 993 FoundCandidate = NodeOrder; 994 continue; 995 } 996 // Avoid exceeding the target's limit. 997 if (RPDelta.Excess.UnitIncrease < Candidate.RPDelta.Excess.UnitIncrease) { 998 DEBUG(traceCandidate("ECAND", Q, *I, RPDelta.Excess)); 999 Candidate.SU = *I; 1000 Candidate.RPDelta = RPDelta; 1001 FoundCandidate = SingleExcess; 1002 continue; 1003 } 1004 if (RPDelta.Excess.UnitIncrease > Candidate.RPDelta.Excess.UnitIncrease) 1005 continue; 1006 if (FoundCandidate == SingleExcess) 1007 FoundCandidate = MultiPressure; 1008 1009 // Avoid increasing the max critical pressure in the scheduled region. 1010 if (RPDelta.CriticalMax.UnitIncrease 1011 < Candidate.RPDelta.CriticalMax.UnitIncrease) { 1012 DEBUG(traceCandidate("PCAND", Q, *I, RPDelta.CriticalMax)); 1013 Candidate.SU = *I; 1014 Candidate.RPDelta = RPDelta; 1015 FoundCandidate = SingleCritical; 1016 continue; 1017 } 1018 if (RPDelta.CriticalMax.UnitIncrease 1019 > Candidate.RPDelta.CriticalMax.UnitIncrease) 1020 continue; 1021 if (FoundCandidate == SingleCritical) 1022 FoundCandidate = MultiPressure; 1023 1024 // Avoid increasing the max pressure of the entire region. 1025 if (RPDelta.CurrentMax.UnitIncrease 1026 < Candidate.RPDelta.CurrentMax.UnitIncrease) { 1027 DEBUG(traceCandidate("MCAND", Q, *I, RPDelta.CurrentMax)); 1028 Candidate.SU = *I; 1029 Candidate.RPDelta = RPDelta; 1030 FoundCandidate = SingleMax; 1031 continue; 1032 } 1033 if (RPDelta.CurrentMax.UnitIncrease 1034 > Candidate.RPDelta.CurrentMax.UnitIncrease) 1035 continue; 1036 if (FoundCandidate == SingleMax) 1037 FoundCandidate = MultiPressure; 1038 1039 // Fall through to original instruction order. 1040 // Only consider node order if Candidate was chosen from this Q. 1041 if (FoundCandidate == NoCand) 1042 continue; 1043 1044 if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) 1045 || (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) { 1046 DEBUG(traceCandidate("NCAND", Q, *I)); 1047 Candidate.SU = *I; 1048 Candidate.RPDelta = RPDelta; 1049 FoundCandidate = NodeOrder; 1050 } 1051 } 1052 return FoundCandidate; 1053 } 1054 1055 /// Pick the best candidate node from either the top or bottom queue. 1056 SUnit *ConvergingScheduler::pickNodeBidrectional(bool &IsTopNode) { 1057 // Schedule as far as possible in the direction of no choice. This is most 1058 // efficient, but also provides the best heuristics for CriticalPSets. 1059 if (SUnit *SU = Bot.pickOnlyChoice()) { 1060 IsTopNode = false; 1061 return SU; 1062 } 1063 if (SUnit *SU = Top.pickOnlyChoice()) { 1064 IsTopNode = true; 1065 return SU; 1066 } 1067 SchedCandidate BotCand; 1068 // Prefer bottom scheduling when heuristics are silent. 1069 CandResult BotResult = pickNodeFromQueue(Bot.Available, 1070 DAG->getBotRPTracker(), BotCand); 1071 assert(BotResult != NoCand && "failed to find the first candidate"); 1072 1073 // If either Q has a single candidate that provides the least increase in 1074 // Excess pressure, we can immediately schedule from that Q. 1075 // 1076 // RegionCriticalPSets summarizes the pressure within the scheduled region and 1077 // affects picking from either Q. If scheduling in one direction must 1078 // increase pressure for one of the excess PSets, then schedule in that 1079 // direction first to provide more freedom in the other direction. 1080 if (BotResult == SingleExcess || BotResult == SingleCritical) { 1081 IsTopNode = false; 1082 return BotCand.SU; 1083 } 1084 // Check if the top Q has a better candidate. 1085 SchedCandidate TopCand; 1086 CandResult TopResult = pickNodeFromQueue(Top.Available, 1087 DAG->getTopRPTracker(), TopCand); 1088 assert(TopResult != NoCand && "failed to find the first candidate"); 1089 1090 if (TopResult == SingleExcess || TopResult == SingleCritical) { 1091 IsTopNode = true; 1092 return TopCand.SU; 1093 } 1094 // If either Q has a single candidate that minimizes pressure above the 1095 // original region's pressure pick it. 1096 if (BotResult == SingleMax) { 1097 IsTopNode = false; 1098 return BotCand.SU; 1099 } 1100 if (TopResult == SingleMax) { 1101 IsTopNode = true; 1102 return TopCand.SU; 1103 } 1104 // Check for a salient pressure difference and pick the best from either side. 1105 if (compareRPDelta(TopCand.RPDelta, BotCand.RPDelta)) { 1106 IsTopNode = true; 1107 return TopCand.SU; 1108 } 1109 // Otherwise prefer the bottom candidate in node order. 1110 IsTopNode = false; 1111 return BotCand.SU; 1112 } 1113 1114 /// Pick the best node to balance the schedule. Implements MachineSchedStrategy. 1115 SUnit *ConvergingScheduler::pickNode(bool &IsTopNode) { 1116 if (DAG->top() == DAG->bottom()) { 1117 assert(Top.Available.empty() && Top.Pending.empty() && 1118 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage"); 1119 return NULL; 1120 } 1121 SUnit *SU; 1122 if (ForceTopDown) { 1123 SU = Top.pickOnlyChoice(); 1124 if (!SU) { 1125 SchedCandidate TopCand; 1126 CandResult TopResult = 1127 pickNodeFromQueue(Top.Available, DAG->getTopRPTracker(), TopCand); 1128 assert(TopResult != NoCand && "failed to find the first candidate"); 1129 (void)TopResult; 1130 SU = TopCand.SU; 1131 } 1132 IsTopNode = true; 1133 } 1134 else if (ForceBottomUp) { 1135 SU = Bot.pickOnlyChoice(); 1136 if (!SU) { 1137 SchedCandidate BotCand; 1138 CandResult BotResult = 1139 pickNodeFromQueue(Bot.Available, DAG->getBotRPTracker(), BotCand); 1140 assert(BotResult != NoCand && "failed to find the first candidate"); 1141 (void)BotResult; 1142 SU = BotCand.SU; 1143 } 1144 IsTopNode = false; 1145 } 1146 else { 1147 SU = pickNodeBidrectional(IsTopNode); 1148 } 1149 if (SU->isTopReady()) 1150 Top.removeReady(SU); 1151 if (SU->isBottomReady()) 1152 Bot.removeReady(SU); 1153 1154 DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom") 1155 << " Scheduling Instruction in cycle " 1156 << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << '\n'; 1157 SU->dump(DAG)); 1158 return SU; 1159 } 1160 1161 /// Update the scheduler's state after scheduling a node. This is the same node 1162 /// that was just returned by pickNode(). However, ScheduleDAGMI needs to update 1163 /// it's state based on the current cycle before MachineSchedStrategy does. 1164 void ConvergingScheduler::schedNode(SUnit *SU, bool IsTopNode) { 1165 if (IsTopNode) { 1166 SU->TopReadyCycle = Top.CurrCycle; 1167 Top.bumpNode(SU); 1168 } 1169 else { 1170 SU->BotReadyCycle = Bot.CurrCycle; 1171 Bot.bumpNode(SU); 1172 } 1173 } 1174 1175 /// Create the standard converging machine scheduler. This will be used as the 1176 /// default scheduler if the target does not set a default. 1177 static ScheduleDAGInstrs *createConvergingSched(MachineSchedContext *C) { 1178 assert((!ForceTopDown || !ForceBottomUp) && 1179 "-misched-topdown incompatible with -misched-bottomup"); 1180 return new ScheduleDAGMI(C, new ConvergingScheduler()); 1181 } 1182 static MachineSchedRegistry 1183 ConvergingSchedRegistry("converge", "Standard converging scheduler.", 1184 createConvergingSched); 1185 1186 //===----------------------------------------------------------------------===// 1187 // Machine Instruction Shuffler for Correctness Testing 1188 //===----------------------------------------------------------------------===// 1189 1190 #ifndef NDEBUG 1191 namespace { 1192 /// Apply a less-than relation on the node order, which corresponds to the 1193 /// instruction order prior to scheduling. IsReverse implements greater-than. 1194 template<bool IsReverse> 1195 struct SUnitOrder { 1196 bool operator()(SUnit *A, SUnit *B) const { 1197 if (IsReverse) 1198 return A->NodeNum > B->NodeNum; 1199 else 1200 return A->NodeNum < B->NodeNum; 1201 } 1202 }; 1203 1204 /// Reorder instructions as much as possible. 1205 class InstructionShuffler : public MachineSchedStrategy { 1206 bool IsAlternating; 1207 bool IsTopDown; 1208 1209 // Using a less-than relation (SUnitOrder<false>) for the TopQ priority 1210 // gives nodes with a higher number higher priority causing the latest 1211 // instructions to be scheduled first. 1212 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false> > 1213 TopQ; 1214 // When scheduling bottom-up, use greater-than as the queue priority. 1215 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true> > 1216 BottomQ; 1217 public: 1218 InstructionShuffler(bool alternate, bool topdown) 1219 : IsAlternating(alternate), IsTopDown(topdown) {} 1220 1221 virtual void initialize(ScheduleDAGMI *) { 1222 TopQ.clear(); 1223 BottomQ.clear(); 1224 } 1225 1226 /// Implement MachineSchedStrategy interface. 1227 /// ----------------------------------------- 1228 1229 virtual SUnit *pickNode(bool &IsTopNode) { 1230 SUnit *SU; 1231 if (IsTopDown) { 1232 do { 1233 if (TopQ.empty()) return NULL; 1234 SU = TopQ.top(); 1235 TopQ.pop(); 1236 } while (SU->isScheduled); 1237 IsTopNode = true; 1238 } 1239 else { 1240 do { 1241 if (BottomQ.empty()) return NULL; 1242 SU = BottomQ.top(); 1243 BottomQ.pop(); 1244 } while (SU->isScheduled); 1245 IsTopNode = false; 1246 } 1247 if (IsAlternating) 1248 IsTopDown = !IsTopDown; 1249 return SU; 1250 } 1251 1252 virtual void schedNode(SUnit *SU, bool IsTopNode) {} 1253 1254 virtual void releaseTopNode(SUnit *SU) { 1255 TopQ.push(SU); 1256 } 1257 virtual void releaseBottomNode(SUnit *SU) { 1258 BottomQ.push(SU); 1259 } 1260 }; 1261 } // namespace 1262 1263 static ScheduleDAGInstrs *createInstructionShuffler(MachineSchedContext *C) { 1264 bool Alternate = !ForceTopDown && !ForceBottomUp; 1265 bool TopDown = !ForceBottomUp; 1266 assert((TopDown || !ForceTopDown) && 1267 "-misched-topdown incompatible with -misched-bottomup"); 1268 return new ScheduleDAGMI(C, new InstructionShuffler(Alternate, TopDown)); 1269 } 1270 static MachineSchedRegistry ShufflerRegistry( 1271 "shuffle", "Shuffle machine instructions alternating directions", 1272 createInstructionShuffler); 1273 #endif // !NDEBUG 1274