LLVM  3.7.0
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 
19 #include "llvm/Support/Debug.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
27 
28 #ifndef NDEBUG
29 const char *ScoreboardHazardRecognizer::DebugType = "";
30 #endif
31 
34  const ScheduleDAG *SchedDAG,
35  const char *ParentDebugType) :
36  ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
37  IssueCount(0) {
38 
39 #ifndef NDEBUG
40  DebugType = ParentDebugType;
41 #endif
42 
43  // Determine the maximum depth of any itinerary. This determines the depth of
44  // the scoreboard. We always make the scoreboard at least 1 cycle deep to
45  // avoid dealing with the boundary condition.
46  unsigned ScoreboardDepth = 1;
47  if (ItinData && !ItinData->isEmpty()) {
48  for (unsigned idx = 0; ; ++idx) {
49  if (ItinData->isEndMarker(idx))
50  break;
51 
52  const InstrStage *IS = ItinData->beginStage(idx);
53  const InstrStage *E = ItinData->endStage(idx);
54  unsigned CurCycle = 0;
55  unsigned ItinDepth = 0;
56  for (; IS != E; ++IS) {
57  unsigned StageDepth = CurCycle + IS->getCycles();
58  if (ItinDepth < StageDepth) ItinDepth = StageDepth;
59  CurCycle += IS->getNextCycles();
60  }
61 
62  // Find the next power-of-2 >= ItinDepth
63  while (ItinDepth > ScoreboardDepth) {
64  ScoreboardDepth *= 2;
65  // Don't set MaxLookAhead until we find at least one nonzero stage.
66  // This way, an itinerary with no stages has MaxLookAhead==0, which
67  // completely bypasses the scoreboard hazard logic.
68  MaxLookAhead = ScoreboardDepth;
69  }
70  }
71  }
72 
73  ReservedScoreboard.reset(ScoreboardDepth);
74  RequiredScoreboard.reset(ScoreboardDepth);
75 
76  // If MaxLookAhead is not set above, then we are not enabled.
77  if (!isEnabled())
78  DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
79  else {
80  // A nonempty itinerary must have a SchedModel.
81  IssueWidth = ItinData->SchedModel.IssueWidth;
82  DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
83  << ScoreboardDepth << '\n');
84  }
85 }
86 
88  IssueCount = 0;
89  RequiredScoreboard.reset();
90  ReservedScoreboard.reset();
91 }
92 
93 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
95  dbgs() << "Scoreboard:\n";
96 
97  unsigned last = Depth - 1;
98  while ((last > 0) && ((*this)[last] == 0))
99  last--;
100 
101  for (unsigned i = 0; i <= last; i++) {
102  unsigned FUs = (*this)[i];
103  dbgs() << "\t";
104  for (int j = 31; j >= 0; j--)
105  dbgs() << ((FUs & (1 << j)) ? '1' : '0');
106  dbgs() << '\n';
107  }
108 }
109 #endif
110 
112  if (IssueWidth == 0)
113  return false;
114 
115  return IssueCount == IssueWidth;
116 }
117 
120  if (!ItinData || ItinData->isEmpty())
121  return NoHazard;
122 
123  // Note that stalls will be negative for bottom-up scheduling.
124  int cycle = Stalls;
125 
126  // Use the itinerary for the underlying instruction to check for
127  // free FU's in the scoreboard at the appropriate future cycles.
128 
129  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
130  if (!MCID) {
131  // Don't check hazards for non-machineinstr Nodes.
132  return NoHazard;
133  }
134  unsigned idx = MCID->getSchedClass();
135  for (const InstrStage *IS = ItinData->beginStage(idx),
136  *E = ItinData->endStage(idx); IS != E; ++IS) {
137  // We must find one of the stage's units free for every cycle the
138  // stage is occupied. FIXME it would be more accurate to find the
139  // same unit free in all the cycles.
140  for (unsigned int i = 0; i < IS->getCycles(); ++i) {
141  int StageCycle = cycle + (int)i;
142  if (StageCycle < 0)
143  continue;
144 
145  if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
146  assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
147  "Scoreboard depth exceeded!");
148  // This stage was stalled beyond pipeline depth, so cannot conflict.
149  break;
150  }
151 
152  unsigned freeUnits = IS->getUnits();
153  switch (IS->getReservationKind()) {
155  // Required FUs conflict with both reserved and required ones
156  freeUnits &= ~ReservedScoreboard[StageCycle];
157  // FALLTHROUGH
159  // Reserved FUs can conflict only with required ones.
160  freeUnits &= ~RequiredScoreboard[StageCycle];
161  break;
162  }
163 
164  if (!freeUnits) {
165  DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
166  DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
167  DEBUG(DAG->dumpNode(SU));
168  return Hazard;
169  }
170  }
171 
172  // Advance the cycle to the next stage.
173  cycle += IS->getNextCycles();
174  }
175 
176  return NoHazard;
177 }
178 
180  if (!ItinData || ItinData->isEmpty())
181  return;
182 
183  // Use the itinerary for the underlying instruction to reserve FU's
184  // in the scoreboard at the appropriate future cycles.
185  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
186  assert(MCID && "The scheduler must filter non-machineinstrs");
187  if (DAG->TII->isZeroCost(MCID->Opcode))
188  return;
189 
190  ++IssueCount;
191 
192  unsigned cycle = 0;
193 
194  unsigned idx = MCID->getSchedClass();
195  for (const InstrStage *IS = ItinData->beginStage(idx),
196  *E = ItinData->endStage(idx); IS != E; ++IS) {
197  // We must reserve one of the stage's units for every cycle the
198  // stage is occupied. FIXME it would be more accurate to reserve
199  // the same unit free in all the cycles.
200  for (unsigned int i = 0; i < IS->getCycles(); ++i) {
201  assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
202  "Scoreboard depth exceeded!");
203 
204  unsigned freeUnits = IS->getUnits();
205  switch (IS->getReservationKind()) {
207  // Required FUs conflict with both reserved and required ones
208  freeUnits &= ~ReservedScoreboard[cycle + i];
209  // FALLTHROUGH
211  // Reserved FUs can conflict only with required ones.
212  freeUnits &= ~RequiredScoreboard[cycle + i];
213  break;
214  }
215 
216  // reduce to a single unit
217  unsigned freeUnit = 0;
218  do {
219  freeUnit = freeUnits;
220  freeUnits = freeUnit & (freeUnit - 1);
221  } while (freeUnits);
222 
223  if (IS->getReservationKind() == InstrStage::Required)
224  RequiredScoreboard[cycle + i] |= freeUnit;
225  else
226  ReservedScoreboard[cycle + i] |= freeUnit;
227  }
228 
229  // Advance the cycle to the next stage.
230  cycle += IS->getNextCycles();
231  }
232 
233  DEBUG(ReservedScoreboard.dump());
234  DEBUG(RequiredScoreboard.dump());
235 }
236 
238  IssueCount = 0;
239  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
240  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
241 }
242 
244  IssueCount = 0;
245  ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
246  ReservedScoreboard.recede();
247  RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
248  RequiredScoreboard.recede();
249 }
unsigned IssueWidth
Definition: MCSchedule.h:139
void RecedeCycle() override
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:138
unsigned getCycles() const
Returns the number of cycles the stage is occupied.
bool isEndMarker(unsigned ItinClassIndx) const
Returns true if the index is for the end marker itinerary.
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
bool atIssueLimit() const override
atIssueLimit - Return true if no more instructions may be issued in this cycle.
void EmitInstruction(SUnit *SU) override
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
Itinerary data supplied by a subtarget to be used by a target.
unsigned MaxLookAhead
MaxLookAhead - Indicate the number of cycles in the scoreboard state.
ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, const ScheduleDAG *DAG, const char *ParentDebugType="")
HazardType getHazardType(SUnit *SU, int Stalls) override
getHazardType - Return the hazard type of emitting this node.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
HazardRecognizer - This determines whether or not an instruction can be issued this cycle...
unsigned getNextCycles() const
Returns the number of cycles from the start of this stage to the start of the next stage in the itine...
bool isZeroCost(unsigned Opcode) const
Return true for pseudo instructions that don't consume any machine resources in their current form...
void Reset() override
Reset - This callback is invoked when a new block of instructions is about to be schedule.
const InstrStage * endStage(unsigned ItinClassIndx) const
Return the last+1 stage of the itinerary.
void AdvanceCycle() override
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
unsigned short Opcode
Definition: MCInstrDesc.h:140
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:123
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:528
MCSchedModel SchedModel
Basic machine properties.
These values represent a non-pipelined step in the execution of an instruction.
const TargetInstrInfo * TII
Definition: ScheduleDAG.h:561
unsigned NodeNum
Definition: ScheduleDAG.h:283
virtual void dumpNode(const SUnit *SU) const =0
#define DEBUG(X)
Definition: Debug.h:92
const MCInstrDesc * getInstrDesc(const SUnit *SU) const
getInstrDesc - Return the MCInstrDesc of this SUnit.
Definition: ScheduleDAG.h:584
bool isEmpty() const
Returns true if there are no itineraries.
SUnit - Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:261