1 //===- HexagonMachineScheduler.cpp - MI Scheduler for Hexagon -------------===// 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 #include "HexagonMachineScheduler.h" 16 #include "HexagonInstrInfo.h" 17 #include "HexagonSubtarget.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/CodeGen/DFAPacketizer.h" 20 #include "llvm/CodeGen/MachineBasicBlock.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineInstr.h" 23 #include "llvm/CodeGen/MachineLoopInfo.h" 24 #include "llvm/CodeGen/RegisterClassInfo.h" 25 #include "llvm/CodeGen/RegisterPressure.h" 26 #include "llvm/CodeGen/ScheduleDAG.h" 27 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 28 #include "llvm/CodeGen/TargetInstrInfo.h" 29 #include "llvm/CodeGen/TargetOpcodes.h" 30 #include "llvm/CodeGen/TargetRegisterInfo.h" 31 #include "llvm/CodeGen/TargetSchedule.h" 32 #include "llvm/CodeGen/TargetSubtargetInfo.h" 33 #include "llvm/IR/Function.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include <algorithm> 38 #include <cassert> 39 #include <iomanip> 40 #include <limits> 41 #include <memory> 42 #include <sstream> 43 44 using namespace llvm; 45 46 #define DEBUG_TYPE "machine-scheduler" 47 48 static cl::opt<bool> IgnoreBBRegPressure("ignore-bb-reg-pressure", 49 cl::Hidden, cl::ZeroOrMore, cl::init(false)); 50 51 static cl::opt<bool> UseNewerCandidate("use-newer-candidate", 52 cl::Hidden, cl::ZeroOrMore, cl::init(true)); 53 54 static cl::opt<unsigned> SchedDebugVerboseLevel("misched-verbose-level", 55 cl::Hidden, cl::ZeroOrMore, cl::init(1)); 56 57 // Check if the scheduler should penalize instructions that are available to 58 // early due to a zero-latency dependence. 59 static cl::opt<bool> CheckEarlyAvail("check-early-avail", cl::Hidden, 60 cl::ZeroOrMore, cl::init(true)); 61 62 // This value is used to determine if a register class is a high pressure set. 63 // We compute the maximum number of registers needed and divided by the total 64 // available. Then, we compare the result to this value. 65 static cl::opt<float> RPThreshold("hexagon-reg-pressure", cl::Hidden, 66 cl::init(0.75f), cl::desc("High register pressure threhold.")); 67 68 /// Return true if there is a dependence between SUd and SUu. 69 static bool hasDependence(const SUnit *SUd, const SUnit *SUu, 70 const HexagonInstrInfo &QII) { 71 if (SUd->Succs.size() == 0) 72 return false; 73 74 // Enable .cur formation. 75 if (QII.mayBeCurLoad(*SUd->getInstr())) 76 return false; 77 78 if (QII.canExecuteInBundle(*SUd->getInstr(), *SUu->getInstr())) 79 return false; 80 81 for (const auto &S : SUd->Succs) { 82 // Since we do not add pseudos to packets, might as well 83 // ignore order dependencies. 84 if (S.isCtrl()) 85 continue; 86 87 if (S.getSUnit() == SUu && S.getLatency() > 0) 88 return true; 89 } 90 return false; 91 } 92 93 /// Check if scheduling of this SU is possible 94 /// in the current packet. 95 /// It is _not_ precise (statefull), it is more like 96 /// another heuristic. Many corner cases are figured 97 /// empirically. 98 bool VLIWResourceModel::isResourceAvailable(SUnit *SU, bool IsTop) { 99 if (!SU || !SU->getInstr()) 100 return false; 101 102 // First see if the pipeline could receive this instruction 103 // in the current cycle. 104 switch (SU->getInstr()->getOpcode()) { 105 default: 106 if (!ResourcesModel->canReserveResources(*SU->getInstr())) 107 return false; 108 case TargetOpcode::EXTRACT_SUBREG: 109 case TargetOpcode::INSERT_SUBREG: 110 case TargetOpcode::SUBREG_TO_REG: 111 case TargetOpcode::REG_SEQUENCE: 112 case TargetOpcode::IMPLICIT_DEF: 113 case TargetOpcode::COPY: 114 case TargetOpcode::INLINEASM: 115 break; 116 } 117 118 MachineBasicBlock *MBB = SU->getInstr()->getParent(); 119 auto &QST = MBB->getParent()->getSubtarget<HexagonSubtarget>(); 120 const auto &QII = *QST.getInstrInfo(); 121 122 // Now see if there are no other dependencies to instructions already 123 // in the packet. 124 if (IsTop) { 125 for (unsigned i = 0, e = Packet.size(); i != e; ++i) 126 if (hasDependence(Packet[i], SU, QII)) 127 return false; 128 } else { 129 for (unsigned i = 0, e = Packet.size(); i != e; ++i) 130 if (hasDependence(SU, Packet[i], QII)) 131 return false; 132 } 133 return true; 134 } 135 136 /// Keep track of available resources. 137 bool VLIWResourceModel::reserveResources(SUnit *SU, bool IsTop) { 138 bool startNewCycle = false; 139 // Artificially reset state. 140 if (!SU) { 141 ResourcesModel->clearResources(); 142 Packet.clear(); 143 TotalPackets++; 144 return false; 145 } 146 // If this SU does not fit in the packet or the packet is now full 147 // start a new one. 148 if (!isResourceAvailable(SU, IsTop) || 149 Packet.size() >= SchedModel->getIssueWidth()) { 150 ResourcesModel->clearResources(); 151 Packet.clear(); 152 TotalPackets++; 153 startNewCycle = true; 154 } 155 156 switch (SU->getInstr()->getOpcode()) { 157 default: 158 ResourcesModel->reserveResources(*SU->getInstr()); 159 break; 160 case TargetOpcode::EXTRACT_SUBREG: 161 case TargetOpcode::INSERT_SUBREG: 162 case TargetOpcode::SUBREG_TO_REG: 163 case TargetOpcode::REG_SEQUENCE: 164 case TargetOpcode::IMPLICIT_DEF: 165 case TargetOpcode::KILL: 166 case TargetOpcode::CFI_INSTRUCTION: 167 case TargetOpcode::EH_LABEL: 168 case TargetOpcode::COPY: 169 case TargetOpcode::INLINEASM: 170 break; 171 } 172 Packet.push_back(SU); 173 174 #ifndef NDEBUG 175 DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n"); 176 for (unsigned i = 0, e = Packet.size(); i != e; ++i) { 177 DEBUG(dbgs() << "\t[" << i << "] SU("); 178 DEBUG(dbgs() << Packet[i]->NodeNum << ")\t"); 179 DEBUG(Packet[i]->getInstr()->dump()); 180 } 181 #endif 182 183 return startNewCycle; 184 } 185 186 /// schedule - Called back from MachineScheduler::runOnMachineFunction 187 /// after setting up the current scheduling region. [RegionBegin, RegionEnd) 188 /// only includes instructions that have DAG nodes, not scheduling boundaries. 189 void VLIWMachineScheduler::schedule() { 190 DEBUG(dbgs() << "********** MI Converging Scheduling VLIW " 191 << printMBBReference(*BB) << " " << BB->getName() << " in_func " 192 << BB->getParent()->getName() << " at loop depth " 193 << MLI->getLoopDepth(BB) << " \n"); 194 195 buildDAGWithRegPressure(); 196 197 Topo.InitDAGTopologicalSorting(); 198 199 // Postprocess the DAG to add platform-specific artificial dependencies. 200 postprocessDAG(); 201 202 SmallVector<SUnit*, 8> TopRoots, BotRoots; 203 findRootsAndBiasEdges(TopRoots, BotRoots); 204 205 // Initialize the strategy before modifying the DAG. 206 SchedImpl->initialize(this); 207 208 DEBUG(unsigned maxH = 0; 209 for (unsigned su = 0, e = SUnits.size(); su != e; ++su) 210 if (SUnits[su].getHeight() > maxH) 211 maxH = SUnits[su].getHeight(); 212 dbgs() << "Max Height " << maxH << "\n";); 213 DEBUG(unsigned maxD = 0; 214 for (unsigned su = 0, e = SUnits.size(); su != e; ++su) 215 if (SUnits[su].getDepth() > maxD) 216 maxD = SUnits[su].getDepth(); 217 dbgs() << "Max Depth " << maxD << "\n";); 218 DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) 219 SUnits[su].dumpAll(this)); 220 221 initQueues(TopRoots, BotRoots); 222 223 bool IsTopNode = false; 224 while (true) { 225 DEBUG(dbgs() << "** VLIWMachineScheduler::schedule picking next node\n"); 226 SUnit *SU = SchedImpl->pickNode(IsTopNode); 227 if (!SU) break; 228 229 if (!checkSchedLimit()) 230 break; 231 232 scheduleMI(SU, IsTopNode); 233 234 // Notify the scheduling strategy after updating the DAG. 235 SchedImpl->schedNode(SU, IsTopNode); 236 237 updateQueues(SU, IsTopNode); 238 } 239 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone."); 240 241 placeDebugValues(); 242 243 DEBUG({ 244 dbgs() << "*** Final schedule for " 245 << printMBBReference(*begin()->getParent()) << " ***\n"; 246 dumpSchedule(); 247 dbgs() << '\n'; 248 }); 249 } 250 251 void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) { 252 DAG = static_cast<VLIWMachineScheduler*>(dag); 253 SchedModel = DAG->getSchedModel(); 254 255 Top.init(DAG, SchedModel); 256 Bot.init(DAG, SchedModel); 257 258 // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or 259 // are disabled, then these HazardRecs will be disabled. 260 const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries(); 261 const TargetSubtargetInfo &STI = DAG->MF.getSubtarget(); 262 const TargetInstrInfo *TII = STI.getInstrInfo(); 263 delete Top.HazardRec; 264 delete Bot.HazardRec; 265 Top.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG); 266 Bot.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG); 267 268 delete Top.ResourceModel; 269 delete Bot.ResourceModel; 270 Top.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel()); 271 Bot.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel()); 272 273 const std::vector<unsigned> &MaxPressure = 274 DAG->getRegPressure().MaxSetPressure; 275 HighPressureSets.assign(MaxPressure.size(), 0); 276 for (unsigned i = 0, e = MaxPressure.size(); i < e; ++i) { 277 unsigned Limit = DAG->getRegClassInfo()->getRegPressureSetLimit(i); 278 HighPressureSets[i] = 279 ((float) MaxPressure[i] > ((float) Limit * RPThreshold)); 280 } 281 282 assert((!ForceTopDown || !ForceBottomUp) && 283 "-misched-topdown incompatible with -misched-bottomup"); 284 } 285 286 void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) { 287 if (SU->isScheduled) 288 return; 289 290 for (const SDep &PI : SU->Preds) { 291 unsigned PredReadyCycle = PI.getSUnit()->TopReadyCycle; 292 unsigned MinLatency = PI.getLatency(); 293 #ifndef NDEBUG 294 Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency); 295 #endif 296 if (SU->TopReadyCycle < PredReadyCycle + MinLatency) 297 SU->TopReadyCycle = PredReadyCycle + MinLatency; 298 } 299 Top.releaseNode(SU, SU->TopReadyCycle); 300 } 301 302 void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) { 303 if (SU->isScheduled) 304 return; 305 306 assert(SU->getInstr() && "Scheduled SUnit must have instr"); 307 308 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); 309 I != E; ++I) { 310 unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle; 311 unsigned MinLatency = I->getLatency(); 312 #ifndef NDEBUG 313 Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency); 314 #endif 315 if (SU->BotReadyCycle < SuccReadyCycle + MinLatency) 316 SU->BotReadyCycle = SuccReadyCycle + MinLatency; 317 } 318 Bot.releaseNode(SU, SU->BotReadyCycle); 319 } 320 321 /// Does this SU have a hazard within the current instruction group. 322 /// 323 /// The scheduler supports two modes of hazard recognition. The first is the 324 /// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that 325 /// supports highly complicated in-order reservation tables 326 /// (ScoreboardHazardRecognizer) and arbitrary target-specific logic. 327 /// 328 /// The second is a streamlined mechanism that checks for hazards based on 329 /// simple counters that the scheduler itself maintains. It explicitly checks 330 /// for instruction dispatch limitations, including the number of micro-ops that 331 /// can dispatch per cycle. 332 /// 333 /// TODO: Also check whether the SU must start a new group. 334 bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(SUnit *SU) { 335 if (HazardRec->isEnabled()) 336 return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard; 337 338 unsigned uops = SchedModel->getNumMicroOps(SU->getInstr()); 339 if (IssueCount + uops > SchedModel->getIssueWidth()) 340 return true; 341 342 return false; 343 } 344 345 void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(SUnit *SU, 346 unsigned ReadyCycle) { 347 if (ReadyCycle < MinReadyCycle) 348 MinReadyCycle = ReadyCycle; 349 350 // Check for interlocks first. For the purpose of other heuristics, an 351 // instruction that cannot issue appears as if it's not in the ReadyQueue. 352 if (ReadyCycle > CurrCycle || checkHazard(SU)) 353 354 Pending.push(SU); 355 else 356 Available.push(SU); 357 } 358 359 /// Move the boundary of scheduled code by one cycle. 360 void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() { 361 unsigned Width = SchedModel->getIssueWidth(); 362 IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width; 363 364 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() && 365 "MinReadyCycle uninitialized"); 366 unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle); 367 368 if (!HazardRec->isEnabled()) { 369 // Bypass HazardRec virtual calls. 370 CurrCycle = NextCycle; 371 } else { 372 // Bypass getHazardType calls in case of long latency. 373 for (; CurrCycle != NextCycle; ++CurrCycle) { 374 if (isTop()) 375 HazardRec->AdvanceCycle(); 376 else 377 HazardRec->RecedeCycle(); 378 } 379 } 380 CheckPending = true; 381 382 DEBUG(dbgs() << "*** Next cycle " << Available.getName() << " cycle " 383 << CurrCycle << '\n'); 384 } 385 386 /// Move the boundary of scheduled code by one SUnit. 387 void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(SUnit *SU) { 388 bool startNewCycle = false; 389 390 // Update the reservation table. 391 if (HazardRec->isEnabled()) { 392 if (!isTop() && SU->isCall) { 393 // Calls are scheduled with their preceding instructions. For bottom-up 394 // scheduling, clear the pipeline state before emitting. 395 HazardRec->Reset(); 396 } 397 HazardRec->EmitInstruction(SU); 398 } 399 400 // Update DFA model. 401 startNewCycle = ResourceModel->reserveResources(SU, isTop()); 402 403 // Check the instruction group dispatch limit. 404 // TODO: Check if this SU must end a dispatch group. 405 IssueCount += SchedModel->getNumMicroOps(SU->getInstr()); 406 if (startNewCycle) { 407 DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n'); 408 bumpCycle(); 409 } 410 else 411 DEBUG(dbgs() << "*** IssueCount " << IssueCount 412 << " at cycle " << CurrCycle << '\n'); 413 } 414 415 /// Release pending ready nodes in to the available queue. This makes them 416 /// visible to heuristics. 417 void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() { 418 // If the available queue is empty, it is safe to reset MinReadyCycle. 419 if (Available.empty()) 420 MinReadyCycle = std::numeric_limits<unsigned>::max(); 421 422 // Check to see if any of the pending instructions are ready to issue. If 423 // so, add them to the available queue. 424 for (unsigned i = 0, e = Pending.size(); i != e; ++i) { 425 SUnit *SU = *(Pending.begin()+i); 426 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle; 427 428 if (ReadyCycle < MinReadyCycle) 429 MinReadyCycle = ReadyCycle; 430 431 if (ReadyCycle > CurrCycle) 432 continue; 433 434 if (checkHazard(SU)) 435 continue; 436 437 Available.push(SU); 438 Pending.remove(Pending.begin()+i); 439 --i; --e; 440 } 441 CheckPending = false; 442 } 443 444 /// Remove SU from the ready set for this boundary. 445 void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(SUnit *SU) { 446 if (Available.isInQueue(SU)) 447 Available.remove(Available.find(SU)); 448 else { 449 assert(Pending.isInQueue(SU) && "bad ready count"); 450 Pending.remove(Pending.find(SU)); 451 } 452 } 453 454 static unsigned getWeakLeft(const SUnit *SU, bool IsTop) { 455 return (IsTop) ? SU->WeakPredsLeft : SU->WeakSuccsLeft; 456 } 457 458 /// If this queue only has one ready candidate, return it. As a side effect, 459 /// advance the cycle until at least one node is ready. If multiple instructions 460 /// are ready, return NULL. 461 SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() { 462 if (CheckPending) 463 releasePending(); 464 465 auto AdvanceCycle = [this]() { 466 if (Available.empty()) 467 return true; 468 if (Available.size() == 1 && Pending.size() > 0) 469 return !ResourceModel->isResourceAvailable(*Available.begin(), isTop()) || 470 getWeakLeft(*Available.begin(), isTop()) != 0; 471 return false; 472 }; 473 for (unsigned i = 0; AdvanceCycle(); ++i) { 474 assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) && 475 "permanent hazard"); (void)i; 476 ResourceModel->reserveResources(nullptr, isTop()); 477 bumpCycle(); 478 releasePending(); 479 } 480 if (Available.size() == 1) 481 return *Available.begin(); 482 return nullptr; 483 } 484 485 #ifndef NDEBUG 486 void ConvergingVLIWScheduler::traceCandidate(const char *Label, 487 const ReadyQueue &Q, SUnit *SU, int Cost, PressureChange P) { 488 dbgs() << Label << " " << Q.getName() << " "; 489 if (P.isValid()) 490 dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":" 491 << P.getUnitInc() << " "; 492 else 493 dbgs() << " "; 494 dbgs() << "cost(" << Cost << ")\t"; 495 SU->dump(DAG); 496 } 497 498 // Very detailed queue dump, to be used with higher verbosity levels. 499 void ConvergingVLIWScheduler::readyQueueVerboseDump( 500 const RegPressureTracker &RPTracker, SchedCandidate &Candidate, 501 ReadyQueue &Q) { 502 RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker); 503 504 dbgs() << ">>> " << Q.getName() << "\n"; 505 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) { 506 RegPressureDelta RPDelta; 507 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta, 508 DAG->getRegionCriticalPSets(), 509 DAG->getRegPressure().MaxSetPressure); 510 std::stringstream dbgstr; 511 dbgstr << "SU(" << std::setw(3) << (*I)->NodeNum << ")"; 512 dbgs() << dbgstr.str(); 513 SchedulingCost(Q, *I, Candidate, RPDelta, true); 514 dbgs() << "\t"; 515 (*I)->getInstr()->dump(); 516 } 517 dbgs() << "\n"; 518 } 519 #endif 520 521 /// isSingleUnscheduledPred - If SU2 is the only unscheduled predecessor 522 /// of SU, return true (we may have duplicates) 523 static inline bool isSingleUnscheduledPred(SUnit *SU, SUnit *SU2) { 524 if (SU->NumPredsLeft == 0) 525 return false; 526 527 for (auto &Pred : SU->Preds) { 528 // We found an available, but not scheduled, predecessor. 529 if (!Pred.getSUnit()->isScheduled && (Pred.getSUnit() != SU2)) 530 return false; 531 } 532 533 return true; 534 } 535 536 /// isSingleUnscheduledSucc - If SU2 is the only unscheduled successor 537 /// of SU, return true (we may have duplicates) 538 static inline bool isSingleUnscheduledSucc(SUnit *SU, SUnit *SU2) { 539 if (SU->NumSuccsLeft == 0) 540 return false; 541 542 for (auto &Succ : SU->Succs) { 543 // We found an available, but not scheduled, successor. 544 if (!Succ.getSUnit()->isScheduled && (Succ.getSUnit() != SU2)) 545 return false; 546 } 547 return true; 548 } 549 550 /// Check if the instruction changes the register pressure of a register in the 551 /// high pressure set. The function returns a negative value if the pressure 552 /// decreases and a positive value is the pressure increases. If the instruction 553 /// doesn't use a high pressure register or doesn't change the register 554 /// pressure, then return 0. 555 int ConvergingVLIWScheduler::pressureChange(const SUnit *SU, bool isBotUp) { 556 PressureDiff &PD = DAG->getPressureDiff(SU); 557 for (auto &P : PD) { 558 if (!P.isValid()) 559 continue; 560 // The pressure differences are computed bottom-up, so the comparision for 561 // an increase is positive in the bottom direction, but negative in the 562 // top-down direction. 563 if (HighPressureSets[P.getPSet()]) 564 return (isBotUp ? P.getUnitInc() : -P.getUnitInc()); 565 } 566 return 0; 567 } 568 569 // Constants used to denote relative importance of 570 // heuristic components for cost computation. 571 static const unsigned PriorityOne = 200; 572 static const unsigned PriorityTwo = 50; 573 static const unsigned PriorityThree = 75; 574 static const unsigned ScaleTwo = 10; 575 576 /// Single point to compute overall scheduling cost. 577 /// TODO: More heuristics will be used soon. 578 int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU, 579 SchedCandidate &Candidate, 580 RegPressureDelta &Delta, 581 bool verbose) { 582 // Initial trivial priority. 583 int ResCount = 1; 584 585 // Do not waste time on a node that is already scheduled. 586 if (!SU || SU->isScheduled) 587 return ResCount; 588 589 DEBUG(if (verbose) dbgs() << ((Q.getID() == TopQID) ? "(top|" : "(bot|")); 590 // Forced priority is high. 591 if (SU->isScheduleHigh) { 592 ResCount += PriorityOne; 593 DEBUG(dbgs() << "H|"); 594 } 595 596 unsigned IsAvailableAmt = 0; 597 // Critical path first. 598 if (Q.getID() == TopQID) { 599 if (Top.isLatencyBound(SU)) { 600 DEBUG(if (verbose) dbgs() << "LB|"); 601 ResCount += (SU->getHeight() * ScaleTwo); 602 } 603 604 DEBUG(if (verbose) { 605 std::stringstream dbgstr; 606 dbgstr << "h" << std::setw(3) << SU->getHeight() << "|"; 607 dbgs() << dbgstr.str(); 608 }); 609 610 // If resources are available for it, multiply the 611 // chance of scheduling. 612 if (Top.ResourceModel->isResourceAvailable(SU, true)) { 613 IsAvailableAmt = (PriorityTwo + PriorityThree); 614 ResCount += IsAvailableAmt; 615 DEBUG(if (verbose) dbgs() << "A|"); 616 } else 617 DEBUG(if (verbose) dbgs() << " |"); 618 } else { 619 if (Bot.isLatencyBound(SU)) { 620 DEBUG(if (verbose) dbgs() << "LB|"); 621 ResCount += (SU->getDepth() * ScaleTwo); 622 } 623 624 DEBUG(if (verbose) { 625 std::stringstream dbgstr; 626 dbgstr << "d" << std::setw(3) << SU->getDepth() << "|"; 627 dbgs() << dbgstr.str(); 628 }); 629 630 // If resources are available for it, multiply the 631 // chance of scheduling. 632 if (Bot.ResourceModel->isResourceAvailable(SU, false)) { 633 IsAvailableAmt = (PriorityTwo + PriorityThree); 634 ResCount += IsAvailableAmt; 635 DEBUG(if (verbose) dbgs() << "A|"); 636 } else 637 DEBUG(if (verbose) dbgs() << " |"); 638 } 639 640 unsigned NumNodesBlocking = 0; 641 if (Q.getID() == TopQID) { 642 // How many SUs does it block from scheduling? 643 // Look at all of the successors of this node. 644 // Count the number of nodes that 645 // this node is the sole unscheduled node for. 646 if (Top.isLatencyBound(SU)) 647 for (const SDep &SI : SU->Succs) 648 if (isSingleUnscheduledPred(SI.getSUnit(), SU)) 649 ++NumNodesBlocking; 650 } else { 651 // How many unscheduled predecessors block this node? 652 if (Bot.isLatencyBound(SU)) 653 for (const SDep &PI : SU->Preds) 654 if (isSingleUnscheduledSucc(PI.getSUnit(), SU)) 655 ++NumNodesBlocking; 656 } 657 ResCount += (NumNodesBlocking * ScaleTwo); 658 659 DEBUG(if (verbose) { 660 std::stringstream dbgstr; 661 dbgstr << "blk " << std::setw(2) << NumNodesBlocking << ")|"; 662 dbgs() << dbgstr.str(); 663 }); 664 665 // Factor in reg pressure as a heuristic. 666 if (!IgnoreBBRegPressure) { 667 // Decrease priority by the amount that register pressure exceeds the limit. 668 ResCount -= (Delta.Excess.getUnitInc()*PriorityOne); 669 // Decrease priority if register pressure exceeds the limit. 670 ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityOne); 671 // Decrease priority slightly if register pressure would increase over the 672 // current maximum. 673 ResCount -= (Delta.CurrentMax.getUnitInc()*PriorityTwo); 674 // If there are register pressure issues, then we remove the value added for 675 // the instruction being available. The rationale is that we really don't 676 // want to schedule an instruction that causes a spill. 677 if (IsAvailableAmt && pressureChange(SU, Q.getID() != TopQID) > 0 && 678 (Delta.Excess.getUnitInc() || Delta.CriticalMax.getUnitInc() || 679 Delta.CurrentMax.getUnitInc())) 680 ResCount -= IsAvailableAmt; 681 DEBUG(if (verbose) { 682 dbgs() << "RP " << Delta.Excess.getUnitInc() << "/" 683 << Delta.CriticalMax.getUnitInc() <<"/" 684 << Delta.CurrentMax.getUnitInc() << ")|"; 685 }); 686 } 687 688 // Give a little extra priority to a .cur instruction if there is a resource 689 // available for it. 690 auto &QST = DAG->MF.getSubtarget<HexagonSubtarget>(); 691 auto &QII = *QST.getInstrInfo(); 692 if (SU->isInstr() && QII.mayBeCurLoad(*SU->getInstr())) { 693 if (Q.getID() == TopQID && 694 Top.ResourceModel->isResourceAvailable(SU, true)) { 695 ResCount += PriorityTwo; 696 DEBUG(if (verbose) dbgs() << "C|"); 697 } else if (Q.getID() == BotQID && 698 Bot.ResourceModel->isResourceAvailable(SU, false)) { 699 ResCount += PriorityTwo; 700 DEBUG(if (verbose) dbgs() << "C|"); 701 } 702 } 703 704 // Give preference to a zero latency instruction if the dependent 705 // instruction is in the current packet. 706 if (Q.getID() == TopQID && getWeakLeft(SU, true) == 0) { 707 for (const SDep &PI : SU->Preds) { 708 if (!PI.getSUnit()->getInstr()->isPseudo() && PI.isAssignedRegDep() && 709 PI.getLatency() == 0 && 710 Top.ResourceModel->isInPacket(PI.getSUnit())) { 711 ResCount += PriorityThree; 712 DEBUG(if (verbose) dbgs() << "Z|"); 713 } 714 } 715 } else if (Q.getID() == BotQID && getWeakLeft(SU, false) == 0) { 716 for (const SDep &SI : SU->Succs) { 717 if (!SI.getSUnit()->getInstr()->isPseudo() && SI.isAssignedRegDep() && 718 SI.getLatency() == 0 && 719 Bot.ResourceModel->isInPacket(SI.getSUnit())) { 720 ResCount += PriorityThree; 721 DEBUG(if (verbose) dbgs() << "Z|"); 722 } 723 } 724 } 725 726 // If the instruction has a non-zero latency dependence with an instruction in 727 // the current packet, then it should not be scheduled yet. The case occurs 728 // when the dependent instruction is scheduled in a new packet, so the 729 // scheduler updates the current cycle and pending instructions become 730 // available. 731 if (CheckEarlyAvail) { 732 if (Q.getID() == TopQID) { 733 for (const auto &PI : SU->Preds) { 734 if (PI.getLatency() > 0 && 735 Top.ResourceModel->isInPacket(PI.getSUnit())) { 736 ResCount -= PriorityOne; 737 DEBUG(if (verbose) dbgs() << "D|"); 738 } 739 } 740 } else { 741 for (const auto &SI : SU->Succs) { 742 if (SI.getLatency() > 0 && 743 Bot.ResourceModel->isInPacket(SI.getSUnit())) { 744 ResCount -= PriorityOne; 745 DEBUG(if (verbose) dbgs() << "D|"); 746 } 747 } 748 } 749 } 750 751 DEBUG(if (verbose) { 752 std::stringstream dbgstr; 753 dbgstr << "Total " << std::setw(4) << ResCount << ")"; 754 dbgs() << dbgstr.str(); 755 }); 756 757 return ResCount; 758 } 759 760 /// Pick the best candidate from the top queue. 761 /// 762 /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during 763 /// DAG building. To adjust for the current scheduling location we need to 764 /// maintain the number of vreg uses remaining to be top-scheduled. 765 ConvergingVLIWScheduler::CandResult ConvergingVLIWScheduler:: 766 pickNodeFromQueue(VLIWSchedBoundary &Zone, const RegPressureTracker &RPTracker, 767 SchedCandidate &Candidate) { 768 ReadyQueue &Q = Zone.Available; 769 DEBUG(if (SchedDebugVerboseLevel > 1) 770 readyQueueVerboseDump(RPTracker, Candidate, Q); 771 else Q.dump();); 772 773 // getMaxPressureDelta temporarily modifies the tracker. 774 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker); 775 776 // BestSU remains NULL if no top candidates beat the best existing candidate. 777 CandResult FoundCandidate = NoCand; 778 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) { 779 RegPressureDelta RPDelta; 780 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta, 781 DAG->getRegionCriticalPSets(), 782 DAG->getRegPressure().MaxSetPressure); 783 784 int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false); 785 786 // Initialize the candidate if needed. 787 if (!Candidate.SU) { 788 DEBUG(traceCandidate("DCAND", Q, *I, CurrentCost)); 789 Candidate.SU = *I; 790 Candidate.RPDelta = RPDelta; 791 Candidate.SCost = CurrentCost; 792 FoundCandidate = NodeOrder; 793 continue; 794 } 795 796 // Choose node order for negative cost candidates. There is no good 797 // candidate in this case. 798 if (CurrentCost < 0 && Candidate.SCost < 0) { 799 if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) 800 || (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) { 801 DEBUG(traceCandidate("NCAND", Q, *I, CurrentCost)); 802 Candidate.SU = *I; 803 Candidate.RPDelta = RPDelta; 804 Candidate.SCost = CurrentCost; 805 FoundCandidate = NodeOrder; 806 } 807 continue; 808 } 809 810 // Best cost. 811 if (CurrentCost > Candidate.SCost) { 812 DEBUG(traceCandidate("CCAND", Q, *I, CurrentCost)); 813 Candidate.SU = *I; 814 Candidate.RPDelta = RPDelta; 815 Candidate.SCost = CurrentCost; 816 FoundCandidate = BestCost; 817 continue; 818 } 819 820 // Choose an instruction that does not depend on an artificial edge. 821 unsigned CurrWeak = getWeakLeft(*I, (Q.getID() == TopQID)); 822 unsigned CandWeak = getWeakLeft(Candidate.SU, (Q.getID() == TopQID)); 823 if (CurrWeak != CandWeak) { 824 if (CurrWeak < CandWeak) { 825 DEBUG(traceCandidate("WCAND", Q, *I, CurrentCost)); 826 Candidate.SU = *I; 827 Candidate.RPDelta = RPDelta; 828 Candidate.SCost = CurrentCost; 829 FoundCandidate = Weak; 830 } 831 continue; 832 } 833 834 if (CurrentCost == Candidate.SCost && Zone.isLatencyBound(*I)) { 835 unsigned CurrSize, CandSize; 836 if (Q.getID() == TopQID) { 837 CurrSize = (*I)->Succs.size(); 838 CandSize = Candidate.SU->Succs.size(); 839 } else { 840 CurrSize = (*I)->Preds.size(); 841 CandSize = Candidate.SU->Preds.size(); 842 } 843 if (CurrSize > CandSize) { 844 DEBUG(traceCandidate("SPCAND", Q, *I, CurrentCost)); 845 Candidate.SU = *I; 846 Candidate.RPDelta = RPDelta; 847 Candidate.SCost = CurrentCost; 848 FoundCandidate = BestCost; 849 } 850 // Keep the old candidate if it's a better candidate. That is, don't use 851 // the subsequent tie breaker. 852 if (CurrSize != CandSize) 853 continue; 854 } 855 856 // Tie breaker. 857 // To avoid scheduling indeterminism, we need a tie breaker 858 // for the case when cost is identical for two nodes. 859 if (UseNewerCandidate && CurrentCost == Candidate.SCost) { 860 if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) 861 || (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) { 862 DEBUG(traceCandidate("TCAND", Q, *I, CurrentCost)); 863 Candidate.SU = *I; 864 Candidate.RPDelta = RPDelta; 865 Candidate.SCost = CurrentCost; 866 FoundCandidate = NodeOrder; 867 continue; 868 } 869 } 870 871 // Fall through to original instruction order. 872 // Only consider node order if Candidate was chosen from this Q. 873 if (FoundCandidate == NoCand) 874 continue; 875 } 876 return FoundCandidate; 877 } 878 879 /// Pick the best candidate node from either the top or bottom queue. 880 SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) { 881 // Schedule as far as possible in the direction of no choice. This is most 882 // efficient, but also provides the best heuristics for CriticalPSets. 883 if (SUnit *SU = Bot.pickOnlyChoice()) { 884 DEBUG(dbgs() << "Picked only Bottom\n"); 885 IsTopNode = false; 886 return SU; 887 } 888 if (SUnit *SU = Top.pickOnlyChoice()) { 889 DEBUG(dbgs() << "Picked only Top\n"); 890 IsTopNode = true; 891 return SU; 892 } 893 SchedCandidate BotCand; 894 // Prefer bottom scheduling when heuristics are silent. 895 CandResult BotResult = pickNodeFromQueue(Bot, 896 DAG->getBotRPTracker(), BotCand); 897 assert(BotResult != NoCand && "failed to find the first candidate"); 898 899 // If either Q has a single candidate that provides the least increase in 900 // Excess pressure, we can immediately schedule from that Q. 901 // 902 // RegionCriticalPSets summarizes the pressure within the scheduled region and 903 // affects picking from either Q. If scheduling in one direction must 904 // increase pressure for one of the excess PSets, then schedule in that 905 // direction first to provide more freedom in the other direction. 906 if (BotResult == SingleExcess || BotResult == SingleCritical) { 907 DEBUG(dbgs() << "Prefered Bottom Node\n"); 908 IsTopNode = false; 909 return BotCand.SU; 910 } 911 // Check if the top Q has a better candidate. 912 SchedCandidate TopCand; 913 CandResult TopResult = pickNodeFromQueue(Top, 914 DAG->getTopRPTracker(), TopCand); 915 assert(TopResult != NoCand && "failed to find the first candidate"); 916 917 if (TopResult == SingleExcess || TopResult == SingleCritical) { 918 DEBUG(dbgs() << "Prefered Top Node\n"); 919 IsTopNode = true; 920 return TopCand.SU; 921 } 922 // If either Q has a single candidate that minimizes pressure above the 923 // original region's pressure pick it. 924 if (BotResult == SingleMax) { 925 DEBUG(dbgs() << "Prefered Bottom Node SingleMax\n"); 926 IsTopNode = false; 927 return BotCand.SU; 928 } 929 if (TopResult == SingleMax) { 930 DEBUG(dbgs() << "Prefered Top Node SingleMax\n"); 931 IsTopNode = true; 932 return TopCand.SU; 933 } 934 if (TopCand.SCost > BotCand.SCost) { 935 DEBUG(dbgs() << "Prefered Top Node Cost\n"); 936 IsTopNode = true; 937 return TopCand.SU; 938 } 939 // Otherwise prefer the bottom candidate in node order. 940 DEBUG(dbgs() << "Prefered Bottom in Node order\n"); 941 IsTopNode = false; 942 return BotCand.SU; 943 } 944 945 /// Pick the best node to balance the schedule. Implements MachineSchedStrategy. 946 SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) { 947 if (DAG->top() == DAG->bottom()) { 948 assert(Top.Available.empty() && Top.Pending.empty() && 949 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage"); 950 return nullptr; 951 } 952 SUnit *SU; 953 if (ForceTopDown) { 954 SU = Top.pickOnlyChoice(); 955 if (!SU) { 956 SchedCandidate TopCand; 957 CandResult TopResult = 958 pickNodeFromQueue(Top, DAG->getTopRPTracker(), TopCand); 959 assert(TopResult != NoCand && "failed to find the first candidate"); 960 (void)TopResult; 961 SU = TopCand.SU; 962 } 963 IsTopNode = true; 964 } else if (ForceBottomUp) { 965 SU = Bot.pickOnlyChoice(); 966 if (!SU) { 967 SchedCandidate BotCand; 968 CandResult BotResult = 969 pickNodeFromQueue(Bot, DAG->getBotRPTracker(), BotCand); 970 assert(BotResult != NoCand && "failed to find the first candidate"); 971 (void)BotResult; 972 SU = BotCand.SU; 973 } 974 IsTopNode = false; 975 } else { 976 SU = pickNodeBidrectional(IsTopNode); 977 } 978 if (SU->isTopReady()) 979 Top.removeReady(SU); 980 if (SU->isBottomReady()) 981 Bot.removeReady(SU); 982 983 DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom") 984 << " Scheduling instruction in cycle " 985 << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << " (" << 986 reportPackets() << ")\n"; 987 SU->dump(DAG)); 988 return SU; 989 } 990 991 /// Update the scheduler's state after scheduling a node. This is the same node 992 /// that was just returned by pickNode(). However, VLIWMachineScheduler needs 993 /// to update it's state based on the current cycle before MachineSchedStrategy 994 /// does. 995 void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) { 996 if (IsTopNode) { 997 Top.bumpNode(SU); 998 SU->TopReadyCycle = Top.CurrCycle; 999 } else { 1000 Bot.bumpNode(SU); 1001 SU->BotReadyCycle = Bot.CurrCycle; 1002 } 1003 } 1004