diff options
Diffstat (limited to 'lib/CodeGen/ScoreboardHazardRecognizer.cpp')
| -rw-r--r-- | lib/CodeGen/ScoreboardHazardRecognizer.cpp | 243 | 
1 files changed, 243 insertions, 0 deletions
diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp new file mode 100644 index 000000000000..e6d7ded8a784 --- /dev/null +++ b/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -0,0 +1,243 @@ +//===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScoreboardHazardRecognizer class, which +// encapsultes hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrItineraries.h" + +using namespace llvm; + +#ifndef NDEBUG +const char *ScoreboardHazardRecognizer::DebugType = ""; +#endif + +ScoreboardHazardRecognizer:: +ScoreboardHazardRecognizer(const InstrItineraryData *II, +                           const ScheduleDAG *SchedDAG, +                           const char *ParentDebugType) : +  ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0), +  IssueCount(0) { + +#ifndef NDEBUG +  DebugType = ParentDebugType; +#endif + +  // Determine the maximum depth of any itinerary. This determines the +  // depth of the scoreboard. We always make the scoreboard at least 1 +  // cycle deep to avoid dealing with the boundary condition. +  unsigned ScoreboardDepth = 1; +  if (ItinData && !ItinData->isEmpty()) { +    IssueWidth = ItinData->IssueWidth; + +    for (unsigned idx = 0; ; ++idx) { +      if (ItinData->isEndMarker(idx)) +        break; + +      const InstrStage *IS = ItinData->beginStage(idx); +      const InstrStage *E = ItinData->endStage(idx); +      unsigned CurCycle = 0; +      unsigned ItinDepth = 0; +      for (; IS != E; ++IS) { +        unsigned StageDepth = CurCycle + IS->getCycles(); +        if (ItinDepth < StageDepth) ItinDepth = StageDepth; +        CurCycle += IS->getNextCycles(); +      } + +      // Find the next power-of-2 >= ItinDepth +      while (ItinDepth > ScoreboardDepth) { +        ScoreboardDepth *= 2; +      } +    } +    MaxLookAhead = ScoreboardDepth; +  } + +  ReservedScoreboard.reset(ScoreboardDepth); +  RequiredScoreboard.reset(ScoreboardDepth); + +  DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = " +               << ScoreboardDepth << '\n'); +} + +void ScoreboardHazardRecognizer::Reset() { +  IssueCount = 0; +  RequiredScoreboard.reset(); +  ReservedScoreboard.reset(); +} + +void ScoreboardHazardRecognizer::Scoreboard::dump() const { +  dbgs() << "Scoreboard:\n"; + +  unsigned last = Depth - 1; +  while ((last > 0) && ((*this)[last] == 0)) +    last--; + +  for (unsigned i = 0; i <= last; i++) { +    unsigned FUs = (*this)[i]; +    dbgs() << "\t"; +    for (int j = 31; j >= 0; j--) +      dbgs() << ((FUs & (1 << j)) ? '1' : '0'); +    dbgs() << '\n'; +  } +} + +bool ScoreboardHazardRecognizer::atIssueLimit() const { +  if (IssueWidth == 0) +    return false; + +  return IssueCount == IssueWidth; +} + +ScheduleHazardRecognizer::HazardType +ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { +  if (!ItinData || ItinData->isEmpty()) +    return NoHazard; + +  // Note that stalls will be negative for bottom-up scheduling. +  int cycle = Stalls; + +  // Use the itinerary for the underlying instruction to check for +  // free FU's in the scoreboard at the appropriate future cycles. + +  const TargetInstrDesc *TID = DAG->getInstrDesc(SU); +  if (TID == NULL) { +    // Don't check hazards for non-machineinstr Nodes. +    return NoHazard; +  } +  unsigned idx = TID->getSchedClass(); +  for (const InstrStage *IS = ItinData->beginStage(idx), +         *E = ItinData->endStage(idx); IS != E; ++IS) { +    // We must find one of the stage's units free for every cycle the +    // stage is occupied. FIXME it would be more accurate to find the +    // same unit free in all the cycles. +    for (unsigned int i = 0; i < IS->getCycles(); ++i) { +      int StageCycle = cycle + (int)i; +      if (StageCycle < 0) +        continue; + +      if (StageCycle >= (int)RequiredScoreboard.getDepth()) { +        assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() && +               "Scoreboard depth exceeded!"); +        // This stage was stalled beyond pipeline depth, so cannot conflict. +        break; +      } + +      unsigned freeUnits = IS->getUnits(); +      switch (IS->getReservationKind()) { +      default: +       assert(0 && "Invalid FU reservation"); +      case InstrStage::Required: +        // Required FUs conflict with both reserved and required ones +        freeUnits &= ~ReservedScoreboard[StageCycle]; +        // FALLTHROUGH +      case InstrStage::Reserved: +        // Reserved FUs can conflict only with required ones. +        freeUnits &= ~RequiredScoreboard[StageCycle]; +        break; +      } + +      if (!freeUnits) { +        DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", "); +        DEBUG(dbgs() << "SU(" << SU->NodeNum << "): "); +        DEBUG(DAG->dumpNode(SU)); +        return Hazard; +      } +    } + +    // Advance the cycle to the next stage. +    cycle += IS->getNextCycles(); +  } + +  return NoHazard; +} + +void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) { +  if (!ItinData || ItinData->isEmpty()) +    return; + +  // Use the itinerary for the underlying instruction to reserve FU's +  // in the scoreboard at the appropriate future cycles. +  const TargetInstrDesc *TID = DAG->getInstrDesc(SU); +  assert(TID && "The scheduler must filter non-machineinstrs"); +  if (DAG->TII->isZeroCost(TID->Opcode)) +    return; + +  ++IssueCount; + +  unsigned cycle = 0; + +  unsigned idx = TID->getSchedClass(); +  for (const InstrStage *IS = ItinData->beginStage(idx), +         *E = ItinData->endStage(idx); IS != E; ++IS) { +    // We must reserve one of the stage's units for every cycle the +    // stage is occupied. FIXME it would be more accurate to reserve +    // the same unit free in all the cycles. +    for (unsigned int i = 0; i < IS->getCycles(); ++i) { +      assert(((cycle + i) < RequiredScoreboard.getDepth()) && +             "Scoreboard depth exceeded!"); + +      unsigned freeUnits = IS->getUnits(); +      switch (IS->getReservationKind()) { +      default: +       assert(0 && "Invalid FU reservation"); +      case InstrStage::Required: +        // Required FUs conflict with both reserved and required ones +        freeUnits &= ~ReservedScoreboard[cycle + i]; +        // FALLTHROUGH +      case InstrStage::Reserved: +        // Reserved FUs can conflict only with required ones. +        freeUnits &= ~RequiredScoreboard[cycle + i]; +        break; +      } + +      // reduce to a single unit +      unsigned freeUnit = 0; +      do { +        freeUnit = freeUnits; +        freeUnits = freeUnit & (freeUnit - 1); +      } while (freeUnits); + +      assert(freeUnit && "No function unit available!"); +      if (IS->getReservationKind() == InstrStage::Required) +        RequiredScoreboard[cycle + i] |= freeUnit; +      else +        ReservedScoreboard[cycle + i] |= freeUnit; +    } + +    // Advance the cycle to the next stage. +    cycle += IS->getNextCycles(); +  } + +  DEBUG(ReservedScoreboard.dump()); +  DEBUG(RequiredScoreboard.dump()); +} + +void ScoreboardHazardRecognizer::AdvanceCycle() { +  IssueCount = 0; +  ReservedScoreboard[0] = 0; ReservedScoreboard.advance(); +  RequiredScoreboard[0] = 0; RequiredScoreboard.advance(); +} + +void ScoreboardHazardRecognizer::RecedeCycle() { +  IssueCount = 0; +  ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0; +  ReservedScoreboard.recede(); +  RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0; +  RequiredScoreboard.recede(); +}  | 
