LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ScoreboardHazardRecognizer.cpp
Go to the documentation of this file.
1 //===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===//
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 // This file implements the ScoreboardHazardRecognizer class, which
11 // encapsultes hazard-avoidance heuristics for scheduling, based on the
12 // scheduling itineraries specified for the target.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
20 #include "llvm/Support/Debug.h"
24 
25 using namespace llvm;
26 
27 #ifndef NDEBUG
29 #endif
30 
33  const ScheduleDAG *SchedDAG,
34  const char *ParentDebugType) :
35  ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
36  IssueCount(0) {
37 
38 #ifndef NDEBUG
39  DebugType = ParentDebugType;
40 #endif
41 
42  // Determine the maximum depth of any itinerary. This determines the depth of
43  // the scoreboard. We always make the scoreboard at least 1 cycle deep to
44  // avoid dealing with the boundary condition.
45  unsigned ScoreboardDepth = 1;
46  if (ItinData && !ItinData->isEmpty()) {
47  for (unsigned idx = 0; ; ++idx) {
48  if (ItinData->isEndMarker(idx))
49  break;
50 
51  const InstrStage *IS = ItinData->beginStage(idx);
52  const InstrStage *E = ItinData->endStage(idx);
53  unsigned CurCycle = 0;
54  unsigned ItinDepth = 0;
55  for (; IS != E; ++IS) {
56  unsigned StageDepth = CurCycle + IS->getCycles();
57  if (ItinDepth < StageDepth) ItinDepth = StageDepth;
58  CurCycle += IS->getNextCycles();
59  }
60 
61  // Find the next power-of-2 >= ItinDepth
62  while (ItinDepth > ScoreboardDepth) {
63  ScoreboardDepth *= 2;
64  // Don't set MaxLookAhead until we find at least one nonzero stage.
65  // This way, an itinerary with no stages has MaxLookAhead==0, which
66  // completely bypasses the scoreboard hazard logic.
67  MaxLookAhead = ScoreboardDepth;
68  }
69  }
70  }
71 
72  ReservedScoreboard.reset(ScoreboardDepth);
73  RequiredScoreboard.reset(ScoreboardDepth);
74 
75  // If MaxLookAhead is not set above, then we are not enabled.
76  if (!isEnabled())
77  DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
78  else {
79  // A nonempty itinerary must have a SchedModel.
80  IssueWidth = ItinData->SchedModel->IssueWidth;
81  DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
82  << ScoreboardDepth << '\n');
83  }
84 }
85 
87  IssueCount = 0;
88  RequiredScoreboard.reset();
89  ReservedScoreboard.reset();
90 }
91 
92 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
94  dbgs() << "Scoreboard:\n";
95 
96  unsigned last = Depth - 1;
97  while ((last > 0) && ((*this)[last] == 0))
98  last--;
99 
100  for (unsigned i = 0; i <= last; i++) {
101  unsigned FUs = (*this)[i];
102  dbgs() << "\t";
103  for (int j = 31; j >= 0; j--)
104  dbgs() << ((FUs & (1 << j)) ? '1' : '0');
105  dbgs() << '\n';
106  }
107 }
108 #endif
109 
111  if (IssueWidth == 0)
112  return false;
113 
114  return IssueCount == IssueWidth;
115 }
116 
119  if (!ItinData || ItinData->isEmpty())
120  return NoHazard;
121 
122  // Note that stalls will be negative for bottom-up scheduling.
123  int cycle = Stalls;
124 
125  // Use the itinerary for the underlying instruction to check for
126  // free FU's in the scoreboard at the appropriate future cycles.
127 
128  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
129  if (MCID == NULL) {
130  // Don't check hazards for non-machineinstr Nodes.
131  return NoHazard;
132  }
133  unsigned idx = MCID->getSchedClass();
134  for (const InstrStage *IS = ItinData->beginStage(idx),
135  *E = ItinData->endStage(idx); IS != E; ++IS) {
136  // We must find one of the stage's units free for every cycle the
137  // stage is occupied. FIXME it would be more accurate to find the
138  // same unit free in all the cycles.
139  for (unsigned int i = 0; i < IS->getCycles(); ++i) {
140  int StageCycle = cycle + (int)i;
141  if (StageCycle < 0)
142  continue;
143 
144  if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
145  assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
146  "Scoreboard depth exceeded!");
147  // This stage was stalled beyond pipeline depth, so cannot conflict.
148  break;
149  }
150 
151  unsigned freeUnits = IS->getUnits();
152  switch (IS->getReservationKind()) {
154  // Required FUs conflict with both reserved and required ones
155  freeUnits &= ~ReservedScoreboard[StageCycle];
156  // FALLTHROUGH
158  // Reserved FUs can conflict only with required ones.
159  freeUnits &= ~RequiredScoreboard[StageCycle];
160  break;
161  }
162 
163  if (!freeUnits) {
164  DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
165  DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
166  DEBUG(DAG->dumpNode(SU));
167  return Hazard;
168  }
169  }
170 
171  // Advance the cycle to the next stage.
172  cycle += IS->getNextCycles();
173  }
174 
175  return NoHazard;
176 }
177 
179  if (!ItinData || ItinData->isEmpty())
180  return;
181 
182  // Use the itinerary for the underlying instruction to reserve FU's
183  // in the scoreboard at the appropriate future cycles.
184  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
185  assert(MCID && "The scheduler must filter non-machineinstrs");
186  if (DAG->TII->isZeroCost(MCID->Opcode))
187  return;
188 
189  ++IssueCount;
190 
191  unsigned cycle = 0;
192 
193  unsigned idx = MCID->getSchedClass();
194  for (const InstrStage *IS = ItinData->beginStage(idx),
195  *E = ItinData->endStage(idx); IS != E; ++IS) {
196  // We must reserve one of the stage's units for every cycle the
197  // stage is occupied. FIXME it would be more accurate to reserve
198  // the same unit free in all the cycles.
199  for (unsigned int i = 0; i < IS->getCycles(); ++i) {
200  assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
201  "Scoreboard depth exceeded!");
202 
203  unsigned freeUnits = IS->getUnits();
204  switch (IS->getReservationKind()) {
206  // Required FUs conflict with both reserved and required ones
207  freeUnits &= ~ReservedScoreboard[cycle + i];
208  // FALLTHROUGH
210  // Reserved FUs can conflict only with required ones.
211  freeUnits &= ~RequiredScoreboard[cycle + i];
212  break;
213  }
214 
215  // reduce to a single unit
216  unsigned freeUnit = 0;
217  do {
218  freeUnit = freeUnits;
219  freeUnits = freeUnit & (freeUnit - 1);
220  } while (freeUnits);
221 
222  if (IS->getReservationKind() == InstrStage::Required)
223  RequiredScoreboard[cycle + i] |= freeUnit;
224  else
225  ReservedScoreboard[cycle + i] |= freeUnit;
226  }
227 
228  // Advance the cycle to the next stage.
229  cycle += IS->getNextCycles();
230  }
231 
232  DEBUG(ReservedScoreboard.dump());
233  DEBUG(RequiredScoreboard.dump());
234 }
235 
237  IssueCount = 0;
238  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
239  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
240 }
241 
243  IssueCount = 0;
244  ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
245  ReservedScoreboard.recede();
246  RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
247  RequiredScoreboard.recede();
248 }
virtual HazardType getHazardType(SUnit *SU, int Stalls)
unsigned getCycles() const
getCycles - returns the number of cycles the stage is occupied
const MCSchedModel * SchedModel
Basic machine properties.
bool isEndMarker(unsigned ItinClassIndx) const
const InstrStage * beginStage(unsigned ItinClassIndx) const
ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, const ScheduleDAG *DAG, const char *ParentDebugType="")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned getNextCycles() const
bool isZeroCost(unsigned Opcode) const
const InstrStage * endStage(unsigned ItinClassIndx) const
unsigned IssueWidth
Definition: MCSchedule.h:137
unsigned short Opcode
Definition: MCInstrDesc.h:139
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Definition: Debug.cpp:101
unsigned getSchedClass() const
Return the scheduling class for this instruction. The scheduling class is an index into the InstrItin...
Definition: MCInstrDesc.h:570
const TargetInstrInfo * TII
Definition: ScheduleDAG.h:541
unsigned NodeNum
Definition: ScheduleDAG.h:271
virtual void dumpNode(const SUnit *SU) const =0
#define DEBUG(X)
Definition: Debug.h:97
const MCInstrDesc * getInstrDesc(const SUnit *SU) const
Definition: ScheduleDAG.h:564
SUnit - Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:249