LLVM API Documentation

ScoreboardHazardRecognizer.cpp
Go to the documentation of this file.
00001 //===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===//
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 file implements the ScoreboardHazardRecognizer class, which
00011 // encapsultes hazard-avoidance heuristics for scheduling, based on the
00012 // scheduling itineraries specified for the target.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
00017 #include "llvm/CodeGen/ScheduleDAG.h"
00018 #include "llvm/MC/MCInstrItineraries.h"
00019 #include "llvm/Support/Debug.h"
00020 #include "llvm/Support/ErrorHandling.h"
00021 #include "llvm/Support/raw_ostream.h"
00022 #include "llvm/Target/TargetInstrInfo.h"
00023 
00024 using namespace llvm;
00025 
00026 #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
00027 
00028 #ifndef NDEBUG
00029 const char *ScoreboardHazardRecognizer::DebugType = "";
00030 #endif
00031 
00032 ScoreboardHazardRecognizer::
00033 ScoreboardHazardRecognizer(const InstrItineraryData *II,
00034                            const ScheduleDAG *SchedDAG,
00035                            const char *ParentDebugType) :
00036   ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
00037   IssueCount(0) {
00038 
00039 #ifndef NDEBUG
00040   DebugType = ParentDebugType;
00041 #endif
00042 
00043   // Determine the maximum depth of any itinerary. This determines the depth of
00044   // the scoreboard. We always make the scoreboard at least 1 cycle deep to
00045   // avoid dealing with the boundary condition.
00046   unsigned ScoreboardDepth = 1;
00047   if (ItinData && !ItinData->isEmpty()) {
00048     for (unsigned idx = 0; ; ++idx) {
00049       if (ItinData->isEndMarker(idx))
00050         break;
00051 
00052       const InstrStage *IS = ItinData->beginStage(idx);
00053       const InstrStage *E = ItinData->endStage(idx);
00054       unsigned CurCycle = 0;
00055       unsigned ItinDepth = 0;
00056       for (; IS != E; ++IS) {
00057         unsigned StageDepth = CurCycle + IS->getCycles();
00058         if (ItinDepth < StageDepth) ItinDepth = StageDepth;
00059         CurCycle += IS->getNextCycles();
00060       }
00061 
00062       // Find the next power-of-2 >= ItinDepth
00063       while (ItinDepth > ScoreboardDepth) {
00064         ScoreboardDepth *= 2;
00065         // Don't set MaxLookAhead until we find at least one nonzero stage.
00066         // This way, an itinerary with no stages has MaxLookAhead==0, which
00067         // completely bypasses the scoreboard hazard logic.
00068         MaxLookAhead = ScoreboardDepth;
00069       }
00070     }
00071   }
00072 
00073   ReservedScoreboard.reset(ScoreboardDepth);
00074   RequiredScoreboard.reset(ScoreboardDepth);
00075 
00076   // If MaxLookAhead is not set above, then we are not enabled.
00077   if (!isEnabled())
00078     DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
00079   else {
00080     // A nonempty itinerary must have a SchedModel.
00081     IssueWidth = ItinData->SchedModel.IssueWidth;
00082     DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
00083           << ScoreboardDepth << '\n');
00084   }
00085 }
00086 
00087 void ScoreboardHazardRecognizer::Reset() {
00088   IssueCount = 0;
00089   RequiredScoreboard.reset();
00090   ReservedScoreboard.reset();
00091 }
00092 
00093 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
00094 void ScoreboardHazardRecognizer::Scoreboard::dump() const {
00095   dbgs() << "Scoreboard:\n";
00096 
00097   unsigned last = Depth - 1;
00098   while ((last > 0) && ((*this)[last] == 0))
00099     last--;
00100 
00101   for (unsigned i = 0; i <= last; i++) {
00102     unsigned FUs = (*this)[i];
00103     dbgs() << "\t";
00104     for (int j = 31; j >= 0; j--)
00105       dbgs() << ((FUs & (1 << j)) ? '1' : '0');
00106     dbgs() << '\n';
00107   }
00108 }
00109 #endif
00110 
00111 bool ScoreboardHazardRecognizer::atIssueLimit() const {
00112   if (IssueWidth == 0)
00113     return false;
00114 
00115   return IssueCount == IssueWidth;
00116 }
00117 
00118 ScheduleHazardRecognizer::HazardType
00119 ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
00120   if (!ItinData || ItinData->isEmpty())
00121     return NoHazard;
00122 
00123   // Note that stalls will be negative for bottom-up scheduling.
00124   int cycle = Stalls;
00125 
00126   // Use the itinerary for the underlying instruction to check for
00127   // free FU's in the scoreboard at the appropriate future cycles.
00128 
00129   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
00130   if (!MCID) {
00131     // Don't check hazards for non-machineinstr Nodes.
00132     return NoHazard;
00133   }
00134   unsigned idx = MCID->getSchedClass();
00135   for (const InstrStage *IS = ItinData->beginStage(idx),
00136          *E = ItinData->endStage(idx); IS != E; ++IS) {
00137     // We must find one of the stage's units free for every cycle the
00138     // stage is occupied. FIXME it would be more accurate to find the
00139     // same unit free in all the cycles.
00140     for (unsigned int i = 0; i < IS->getCycles(); ++i) {
00141       int StageCycle = cycle + (int)i;
00142       if (StageCycle < 0)
00143         continue;
00144 
00145       if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
00146         assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
00147                "Scoreboard depth exceeded!");
00148         // This stage was stalled beyond pipeline depth, so cannot conflict.
00149         break;
00150       }
00151 
00152       unsigned freeUnits = IS->getUnits();
00153       switch (IS->getReservationKind()) {
00154       case InstrStage::Required:
00155         // Required FUs conflict with both reserved and required ones
00156         freeUnits &= ~ReservedScoreboard[StageCycle];
00157         // FALLTHROUGH
00158       case InstrStage::Reserved:
00159         // Reserved FUs can conflict only with required ones.
00160         freeUnits &= ~RequiredScoreboard[StageCycle];
00161         break;
00162       }
00163 
00164       if (!freeUnits) {
00165         DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
00166         DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
00167         DEBUG(DAG->dumpNode(SU));
00168         return Hazard;
00169       }
00170     }
00171 
00172     // Advance the cycle to the next stage.
00173     cycle += IS->getNextCycles();
00174   }
00175 
00176   return NoHazard;
00177 }
00178 
00179 void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
00180   if (!ItinData || ItinData->isEmpty())
00181     return;
00182 
00183   // Use the itinerary for the underlying instruction to reserve FU's
00184   // in the scoreboard at the appropriate future cycles.
00185   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
00186   assert(MCID && "The scheduler must filter non-machineinstrs");
00187   if (DAG->TII->isZeroCost(MCID->Opcode))
00188     return;
00189 
00190   ++IssueCount;
00191 
00192   unsigned cycle = 0;
00193 
00194   unsigned idx = MCID->getSchedClass();
00195   for (const InstrStage *IS = ItinData->beginStage(idx),
00196          *E = ItinData->endStage(idx); IS != E; ++IS) {
00197     // We must reserve one of the stage's units for every cycle the
00198     // stage is occupied. FIXME it would be more accurate to reserve
00199     // the same unit free in all the cycles.
00200     for (unsigned int i = 0; i < IS->getCycles(); ++i) {
00201       assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
00202              "Scoreboard depth exceeded!");
00203 
00204       unsigned freeUnits = IS->getUnits();
00205       switch (IS->getReservationKind()) {
00206       case InstrStage::Required:
00207         // Required FUs conflict with both reserved and required ones
00208         freeUnits &= ~ReservedScoreboard[cycle + i];
00209         // FALLTHROUGH
00210       case InstrStage::Reserved:
00211         // Reserved FUs can conflict only with required ones.
00212         freeUnits &= ~RequiredScoreboard[cycle + i];
00213         break;
00214       }
00215 
00216       // reduce to a single unit
00217       unsigned freeUnit = 0;
00218       do {
00219         freeUnit = freeUnits;
00220         freeUnits = freeUnit & (freeUnit - 1);
00221       } while (freeUnits);
00222 
00223       if (IS->getReservationKind() == InstrStage::Required)
00224         RequiredScoreboard[cycle + i] |= freeUnit;
00225       else
00226         ReservedScoreboard[cycle + i] |= freeUnit;
00227     }
00228 
00229     // Advance the cycle to the next stage.
00230     cycle += IS->getNextCycles();
00231   }
00232 
00233   DEBUG(ReservedScoreboard.dump());
00234   DEBUG(RequiredScoreboard.dump());
00235 }
00236 
00237 void ScoreboardHazardRecognizer::AdvanceCycle() {
00238   IssueCount = 0;
00239   ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
00240   RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
00241 }
00242 
00243 void ScoreboardHazardRecognizer::RecedeCycle() {
00244   IssueCount = 0;
00245   ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
00246   ReservedScoreboard.recede();
00247   RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
00248   RequiredScoreboard.recede();
00249 }