1 //===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
17 #include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
18 #include "llvm/CodeGen/ScheduleDAG.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Target/TargetInstrInfo.h"
23 #include "llvm/Target/TargetInstrItineraries.h"
28 const char *ScoreboardHazardRecognizer::DebugType
= "";
31 ScoreboardHazardRecognizer::
32 ScoreboardHazardRecognizer(const InstrItineraryData
*II
,
33 const ScheduleDAG
*SchedDAG
,
34 const char *ParentDebugType
) :
35 ScheduleHazardRecognizer(), ItinData(II
), DAG(SchedDAG
), IssueWidth(0),
39 DebugType
= ParentDebugType
;
42 // Determine the maximum depth of any itinerary. This determines the
43 // depth of the scoreboard. We always make the scoreboard at least 1
44 // cycle deep to avoid dealing with the boundary condition.
45 unsigned ScoreboardDepth
= 1;
46 if (ItinData
&& !ItinData
->isEmpty()) {
47 IssueWidth
= ItinData
->IssueWidth
;
49 for (unsigned idx
= 0; ; ++idx
) {
50 if (ItinData
->isEndMarker(idx
))
53 const InstrStage
*IS
= ItinData
->beginStage(idx
);
54 const InstrStage
*E
= ItinData
->endStage(idx
);
55 unsigned CurCycle
= 0;
56 unsigned ItinDepth
= 0;
57 for (; IS
!= E
; ++IS
) {
58 unsigned StageDepth
= CurCycle
+ IS
->getCycles();
59 if (ItinDepth
< StageDepth
) ItinDepth
= StageDepth
;
60 CurCycle
+= IS
->getNextCycles();
63 // Find the next power-of-2 >= ItinDepth
64 while (ItinDepth
> ScoreboardDepth
) {
68 MaxLookAhead
= ScoreboardDepth
;
71 ReservedScoreboard
.reset(ScoreboardDepth
);
72 RequiredScoreboard
.reset(ScoreboardDepth
);
74 DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
75 << ScoreboardDepth
<< '\n');
78 void ScoreboardHazardRecognizer::Reset() {
80 RequiredScoreboard
.reset();
81 ReservedScoreboard
.reset();
84 void ScoreboardHazardRecognizer::Scoreboard::dump() const {
85 dbgs() << "Scoreboard:\n";
87 unsigned last
= Depth
- 1;
88 while ((last
> 0) && ((*this)[last
] == 0))
91 for (unsigned i
= 0; i
<= last
; i
++) {
92 unsigned FUs
= (*this)[i
];
94 for (int j
= 31; j
>= 0; j
--)
95 dbgs() << ((FUs
& (1 << j
)) ? '1' : '0');
100 bool ScoreboardHazardRecognizer::atIssueLimit() const {
104 return IssueCount
== IssueWidth
;
107 ScheduleHazardRecognizer::HazardType
108 ScoreboardHazardRecognizer::getHazardType(SUnit
*SU
, int Stalls
) {
109 if (!ItinData
|| ItinData
->isEmpty())
112 // Note that stalls will be negative for bottom-up scheduling.
115 // Use the itinerary for the underlying instruction to check for
116 // free FU's in the scoreboard at the appropriate future cycles.
118 const TargetInstrDesc
*TID
= DAG
->getInstrDesc(SU
);
120 // Don't check hazards for non-machineinstr Nodes.
123 unsigned idx
= TID
->getSchedClass();
124 for (const InstrStage
*IS
= ItinData
->beginStage(idx
),
125 *E
= ItinData
->endStage(idx
); IS
!= E
; ++IS
) {
126 // We must find one of the stage's units free for every cycle the
127 // stage is occupied. FIXME it would be more accurate to find the
128 // same unit free in all the cycles.
129 for (unsigned int i
= 0; i
< IS
->getCycles(); ++i
) {
130 int StageCycle
= cycle
+ (int)i
;
134 if (StageCycle
>= (int)RequiredScoreboard
.getDepth()) {
135 assert((StageCycle
- Stalls
) < (int)RequiredScoreboard
.getDepth() &&
136 "Scoreboard depth exceeded!");
137 // This stage was stalled beyond pipeline depth, so cannot conflict.
141 unsigned freeUnits
= IS
->getUnits();
142 switch (IS
->getReservationKind()) {
144 assert(0 && "Invalid FU reservation");
145 case InstrStage::Required
:
146 // Required FUs conflict with both reserved and required ones
147 freeUnits
&= ~ReservedScoreboard
[StageCycle
];
149 case InstrStage::Reserved
:
150 // Reserved FUs can conflict only with required ones.
151 freeUnits
&= ~RequiredScoreboard
[StageCycle
];
156 DEBUG(dbgs() << "*** Hazard in cycle " << (cycle
+ i
) << ", ");
157 DEBUG(dbgs() << "SU(" << SU
->NodeNum
<< "): ");
158 DEBUG(DAG
->dumpNode(SU
));
163 // Advance the cycle to the next stage.
164 cycle
+= IS
->getNextCycles();
170 void ScoreboardHazardRecognizer::EmitInstruction(SUnit
*SU
) {
171 if (!ItinData
|| ItinData
->isEmpty())
174 // Use the itinerary for the underlying instruction to reserve FU's
175 // in the scoreboard at the appropriate future cycles.
176 const TargetInstrDesc
*TID
= DAG
->getInstrDesc(SU
);
177 assert(TID
&& "The scheduler must filter non-machineinstrs");
178 if (DAG
->TII
->isZeroCost(TID
->Opcode
))
185 unsigned idx
= TID
->getSchedClass();
186 for (const InstrStage
*IS
= ItinData
->beginStage(idx
),
187 *E
= ItinData
->endStage(idx
); IS
!= E
; ++IS
) {
188 // We must reserve one of the stage's units for every cycle the
189 // stage is occupied. FIXME it would be more accurate to reserve
190 // the same unit free in all the cycles.
191 for (unsigned int i
= 0; i
< IS
->getCycles(); ++i
) {
192 assert(((cycle
+ i
) < RequiredScoreboard
.getDepth()) &&
193 "Scoreboard depth exceeded!");
195 unsigned freeUnits
= IS
->getUnits();
196 switch (IS
->getReservationKind()) {
198 assert(0 && "Invalid FU reservation");
199 case InstrStage::Required
:
200 // Required FUs conflict with both reserved and required ones
201 freeUnits
&= ~ReservedScoreboard
[cycle
+ i
];
203 case InstrStage::Reserved
:
204 // Reserved FUs can conflict only with required ones.
205 freeUnits
&= ~RequiredScoreboard
[cycle
+ i
];
209 // reduce to a single unit
210 unsigned freeUnit
= 0;
212 freeUnit
= freeUnits
;
213 freeUnits
= freeUnit
& (freeUnit
- 1);
216 assert(freeUnit
&& "No function unit available!");
217 if (IS
->getReservationKind() == InstrStage::Required
)
218 RequiredScoreboard
[cycle
+ i
] |= freeUnit
;
220 ReservedScoreboard
[cycle
+ i
] |= freeUnit
;
223 // Advance the cycle to the next stage.
224 cycle
+= IS
->getNextCycles();
227 DEBUG(ReservedScoreboard
.dump());
228 DEBUG(RequiredScoreboard
.dump());
231 void ScoreboardHazardRecognizer::AdvanceCycle() {
233 ReservedScoreboard
[0] = 0; ReservedScoreboard
.advance();
234 RequiredScoreboard
[0] = 0; RequiredScoreboard
.advance();
237 void ScoreboardHazardRecognizer::RecedeCycle() {
239 ReservedScoreboard
[ReservedScoreboard
.getDepth()-1] = 0;
240 ReservedScoreboard
.recede();
241 RequiredScoreboard
[RequiredScoreboard
.getDepth()-1] = 0;
242 RequiredScoreboard
.recede();