LLVM API Documentation

ScheduleDAGVLIW.cpp
Go to the documentation of this file.
00001 //===- ScheduleDAGVLIW.cpp - SelectionDAG list scheduler for VLIW -*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This implements a top-down list scheduler, using standard algorithms.
00011 // The basic approach uses a priority queue of available nodes to schedule.
00012 // One at a time, nodes are taken from the priority queue (thus in priority
00013 // order), checked for legality to schedule, and emitted if legal.
00014 //
00015 // Nodes may not be legal to schedule either due to structural hazards (e.g.
00016 // pipeline or resource constraints) or because an input to the instruction has
00017 // not completed execution.
00018 //
00019 //===----------------------------------------------------------------------===//
00020 
00021 #include "llvm/CodeGen/SchedulerRegistry.h"
00022 #include "ScheduleDAGSDNodes.h"
00023 #include "llvm/ADT/Statistic.h"
00024 #include "llvm/CodeGen/LatencyPriorityQueue.h"
00025 #include "llvm/CodeGen/ResourcePriorityQueue.h"
00026 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
00027 #include "llvm/CodeGen/SelectionDAGISel.h"
00028 #include "llvm/IR/DataLayout.h"
00029 #include "llvm/Support/Debug.h"
00030 #include "llvm/Support/ErrorHandling.h"
00031 #include "llvm/Support/raw_ostream.h"
00032 #include "llvm/Target/TargetInstrInfo.h"
00033 #include "llvm/Target/TargetRegisterInfo.h"
00034 #include "llvm/Target/TargetSubtargetInfo.h"
00035 #include <climits>
00036 using namespace llvm;
00037 
00038 #define DEBUG_TYPE "pre-RA-sched"
00039 
00040 STATISTIC(NumNoops , "Number of noops inserted");
00041 STATISTIC(NumStalls, "Number of pipeline stalls");
00042 
00043 static RegisterScheduler
00044   VLIWScheduler("vliw-td", "VLIW scheduler",
00045                 createVLIWDAGScheduler);
00046 
00047 namespace {
00048 //===----------------------------------------------------------------------===//
00049 /// ScheduleDAGVLIW - The actual DFA list scheduler implementation.  This
00050 /// supports / top-down scheduling.
00051 ///
00052 class ScheduleDAGVLIW : public ScheduleDAGSDNodes {
00053 private:
00054   /// AvailableQueue - The priority queue to use for the available SUnits.
00055   ///
00056   SchedulingPriorityQueue *AvailableQueue;
00057 
00058   /// PendingQueue - This contains all of the instructions whose operands have
00059   /// been issued, but their results are not ready yet (due to the latency of
00060   /// the operation).  Once the operands become available, the instruction is
00061   /// added to the AvailableQueue.
00062   std::vector<SUnit*> PendingQueue;
00063 
00064   /// HazardRec - The hazard recognizer to use.
00065   ScheduleHazardRecognizer *HazardRec;
00066 
00067   /// AA - AliasAnalysis for making memory reference queries.
00068   AliasAnalysis *AA;
00069 
00070 public:
00071   ScheduleDAGVLIW(MachineFunction &mf,
00072                   AliasAnalysis *aa,
00073                   SchedulingPriorityQueue *availqueue)
00074     : ScheduleDAGSDNodes(mf), AvailableQueue(availqueue), AA(aa) {
00075 
00076     const TargetMachine &tm = mf.getTarget();
00077     HazardRec =
00078         tm.getSubtargetImpl()->getInstrInfo()->CreateTargetHazardRecognizer(
00079             tm.getSubtargetImpl(), this);
00080   }
00081 
00082   ~ScheduleDAGVLIW() {
00083     delete HazardRec;
00084     delete AvailableQueue;
00085   }
00086 
00087   void Schedule() override;
00088 
00089 private:
00090   void releaseSucc(SUnit *SU, const SDep &D);
00091   void releaseSuccessors(SUnit *SU);
00092   void scheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
00093   void listScheduleTopDown();
00094 };
00095 }  // end anonymous namespace
00096 
00097 /// Schedule - Schedule the DAG using list scheduling.
00098 void ScheduleDAGVLIW::Schedule() {
00099   DEBUG(dbgs()
00100         << "********** List Scheduling BB#" << BB->getNumber()
00101         << " '" << BB->getName() << "' **********\n");
00102 
00103   // Build the scheduling graph.
00104   BuildSchedGraph(AA);
00105 
00106   AvailableQueue->initNodes(SUnits);
00107 
00108   listScheduleTopDown();
00109 
00110   AvailableQueue->releaseState();
00111 }
00112 
00113 //===----------------------------------------------------------------------===//
00114 //  Top-Down Scheduling
00115 //===----------------------------------------------------------------------===//
00116 
00117 /// releaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
00118 /// the PendingQueue if the count reaches zero. Also update its cycle bound.
00119 void ScheduleDAGVLIW::releaseSucc(SUnit *SU, const SDep &D) {
00120   SUnit *SuccSU = D.getSUnit();
00121 
00122 #ifndef NDEBUG
00123   if (SuccSU->NumPredsLeft == 0) {
00124     dbgs() << "*** Scheduling failed! ***\n";
00125     SuccSU->dump(this);
00126     dbgs() << " has been released too many times!\n";
00127     llvm_unreachable(nullptr);
00128   }
00129 #endif
00130   assert(!D.isWeak() && "unexpected artificial DAG edge");
00131 
00132   --SuccSU->NumPredsLeft;
00133 
00134   SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency());
00135 
00136   // If all the node's predecessors are scheduled, this node is ready
00137   // to be scheduled. Ignore the special ExitSU node.
00138   if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) {
00139     PendingQueue.push_back(SuccSU);
00140   }
00141 }
00142 
00143 void ScheduleDAGVLIW::releaseSuccessors(SUnit *SU) {
00144   // Top down: release successors.
00145   for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
00146        I != E; ++I) {
00147     assert(!I->isAssignedRegDep() &&
00148            "The list-td scheduler doesn't yet support physreg dependencies!");
00149 
00150     releaseSucc(SU, *I);
00151   }
00152 }
00153 
00154 /// scheduleNodeTopDown - Add the node to the schedule. Decrement the pending
00155 /// count of its successors. If a successor pending count is zero, add it to
00156 /// the Available queue.
00157 void ScheduleDAGVLIW::scheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
00158   DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
00159   DEBUG(SU->dump(this));
00160 
00161   Sequence.push_back(SU);
00162   assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!");
00163   SU->setDepthToAtLeast(CurCycle);
00164 
00165   releaseSuccessors(SU);
00166   SU->isScheduled = true;
00167   AvailableQueue->scheduledNode(SU);
00168 }
00169 
00170 /// listScheduleTopDown - The main loop of list scheduling for top-down
00171 /// schedulers.
00172 void ScheduleDAGVLIW::listScheduleTopDown() {
00173   unsigned CurCycle = 0;
00174 
00175   // Release any successors of the special Entry node.
00176   releaseSuccessors(&EntrySU);
00177 
00178   // All leaves to AvailableQueue.
00179   for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
00180     // It is available if it has no predecessors.
00181     if (SUnits[i].Preds.empty()) {
00182       AvailableQueue->push(&SUnits[i]);
00183       SUnits[i].isAvailable = true;
00184     }
00185   }
00186 
00187   // While AvailableQueue is not empty, grab the node with the highest
00188   // priority. If it is not ready put it back.  Schedule the node.
00189   std::vector<SUnit*> NotReady;
00190   Sequence.reserve(SUnits.size());
00191   while (!AvailableQueue->empty() || !PendingQueue.empty()) {
00192     // Check to see if any of the pending instructions are ready to issue.  If
00193     // so, add them to the available queue.
00194     for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
00195       if (PendingQueue[i]->getDepth() == CurCycle) {
00196         AvailableQueue->push(PendingQueue[i]);
00197         PendingQueue[i]->isAvailable = true;
00198         PendingQueue[i] = PendingQueue.back();
00199         PendingQueue.pop_back();
00200         --i; --e;
00201       }
00202       else {
00203         assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?");
00204       }
00205     }
00206 
00207     // If there are no instructions available, don't try to issue anything, and
00208     // don't advance the hazard recognizer.
00209     if (AvailableQueue->empty()) {
00210       // Reset DFA state.
00211       AvailableQueue->scheduledNode(nullptr);
00212       ++CurCycle;
00213       continue;
00214     }
00215 
00216     SUnit *FoundSUnit = nullptr;
00217 
00218     bool HasNoopHazards = false;
00219     while (!AvailableQueue->empty()) {
00220       SUnit *CurSUnit = AvailableQueue->pop();
00221 
00222       ScheduleHazardRecognizer::HazardType HT =
00223         HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
00224       if (HT == ScheduleHazardRecognizer::NoHazard) {
00225         FoundSUnit = CurSUnit;
00226         break;
00227       }
00228 
00229       // Remember if this is a noop hazard.
00230       HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
00231 
00232       NotReady.push_back(CurSUnit);
00233     }
00234 
00235     // Add the nodes that aren't ready back onto the available list.
00236     if (!NotReady.empty()) {
00237       AvailableQueue->push_all(NotReady);
00238       NotReady.clear();
00239     }
00240 
00241     // If we found a node to schedule, do it now.
00242     if (FoundSUnit) {
00243       scheduleNodeTopDown(FoundSUnit, CurCycle);
00244       HazardRec->EmitInstruction(FoundSUnit);
00245 
00246       // If this is a pseudo-op node, we don't want to increment the current
00247       // cycle.
00248       if (FoundSUnit->Latency)  // Don't increment CurCycle for pseudo-ops!
00249         ++CurCycle;
00250     } else if (!HasNoopHazards) {
00251       // Otherwise, we have a pipeline stall, but no other problem, just advance
00252       // the current cycle and try again.
00253       DEBUG(dbgs() << "*** Advancing cycle, no work to do\n");
00254       HazardRec->AdvanceCycle();
00255       ++NumStalls;
00256       ++CurCycle;
00257     } else {
00258       // Otherwise, we have no instructions to issue and we have instructions
00259       // that will fault if we don't do this right.  This is the case for
00260       // processors without pipeline interlocks and other cases.
00261       DEBUG(dbgs() << "*** Emitting noop\n");
00262       HazardRec->EmitNoop();
00263       Sequence.push_back(nullptr);   // NULL here means noop
00264       ++NumNoops;
00265       ++CurCycle;
00266     }
00267   }
00268 
00269 #ifndef NDEBUG
00270   VerifyScheduledSequence(/*isBottomUp=*/false);
00271 #endif
00272 }
00273 
00274 //===----------------------------------------------------------------------===//
00275 //                         Public Constructor Functions
00276 //===----------------------------------------------------------------------===//
00277 
00278 /// createVLIWDAGScheduler - This creates a top-down list scheduler.
00279 ScheduleDAGSDNodes *
00280 llvm::createVLIWDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
00281   return new ScheduleDAGVLIW(*IS->MF, IS->AA, new ResourcePriorityQueue(IS));
00282 }