blob: b3d83d5313aff75bce8fb7c9aa0ae7601fbf9ae4 [file] [log] [blame]
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001//===- ScoreboardHazardRecognizer.cpp - Scheduler Support -----------------===//
David Goodwin6021b4d2009-08-10 15:55:25 +00002//
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//
Andrew Trick00067fb2010-12-08 20:04:29 +000010// This file implements the ScoreboardHazardRecognizer class, which
11// encapsultes hazard-avoidance heuristics for scheduling, based on the
12// scheduling itineraries specified for the target.
David Goodwin6021b4d2009-08-10 15:55:25 +000013//
14//===----------------------------------------------------------------------===//
15
Andrew Trick00067fb2010-12-08 20:04:29 +000016#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
Evan Cheng078f4ce2010-06-14 21:06:53 +000017#include "llvm/CodeGen/ScheduleDAG.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000018#include "llvm/MC/MCInstrDesc.h"
Evan Cheng8264e272011-06-29 01:14:12 +000019#include "llvm/MC/MCInstrItineraries.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000020#include "llvm/Support/Compiler.h"
David Goodwin6021b4d2009-08-10 15:55:25 +000021#include "llvm/Support/Debug.h"
David Goodwinf20236a2009-08-11 01:44:26 +000022#include "llvm/Support/raw_ostream.h"
Andrew Trick47ff14b2011-01-21 05:51:33 +000023#include "llvm/Target/TargetInstrInfo.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000024#include <cassert>
David Goodwin6021b4d2009-08-10 15:55:25 +000025
Bill Wendlinga2c45942009-08-22 20:08:44 +000026using namespace llvm;
David Goodwin6021b4d2009-08-10 15:55:25 +000027
Mehdi Aminiea0b1e72016-04-20 00:21:24 +000028#define DEBUG_TYPE DebugType
Chandler Carruth1b9dde02014-04-22 02:02:50 +000029
Mehdi Aminiea0b1e72016-04-20 00:21:24 +000030ScoreboardHazardRecognizer::ScoreboardHazardRecognizer(
31 const InstrItineraryData *II, const ScheduleDAG *SchedDAG,
32 const char *ParentDebugType)
33 : ScheduleHazardRecognizer(), DebugType(ParentDebugType), ItinData(II),
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000034 DAG(SchedDAG) {
Andrew Tricked7c96d2012-06-05 03:44:32 +000035 // Determine the maximum depth of any itinerary. This determines the depth of
36 // the scoreboard. We always make the scoreboard at least 1 cycle deep to
37 // avoid dealing with the boundary condition.
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000038 unsigned ScoreboardDepth = 1;
Evan Chengbf407072010-09-10 01:29:16 +000039 if (ItinData && !ItinData->isEmpty()) {
David Goodwin6021b4d2009-08-10 15:55:25 +000040 for (unsigned idx = 0; ; ++idx) {
Evan Chengbf407072010-09-10 01:29:16 +000041 if (ItinData->isEndMarker(idx))
David Goodwin6021b4d2009-08-10 15:55:25 +000042 break;
43
Evan Chengbf407072010-09-10 01:29:16 +000044 const InstrStage *IS = ItinData->beginStage(idx);
45 const InstrStage *E = ItinData->endStage(idx);
Andrew Trick10ffc2b2010-12-24 05:03:26 +000046 unsigned CurCycle = 0;
David Goodwin6021b4d2009-08-10 15:55:25 +000047 unsigned ItinDepth = 0;
Andrew Trick10ffc2b2010-12-24 05:03:26 +000048 for (; IS != E; ++IS) {
49 unsigned StageDepth = CurCycle + IS->getCycles();
50 if (ItinDepth < StageDepth) ItinDepth = StageDepth;
51 CurCycle += IS->getNextCycles();
52 }
David Goodwin6021b4d2009-08-10 15:55:25 +000053
Andrew Trick00067fb2010-12-08 20:04:29 +000054 // Find the next power-of-2 >= ItinDepth
55 while (ItinDepth > ScoreboardDepth) {
56 ScoreboardDepth *= 2;
Andrew Tricked7c96d2012-06-05 03:44:32 +000057 // Don't set MaxLookAhead until we find at least one nonzero stage.
58 // This way, an itinerary with no stages has MaxLookAhead==0, which
59 // completely bypasses the scoreboard hazard logic.
60 MaxLookAhead = ScoreboardDepth;
Andrew Trick00067fb2010-12-08 20:04:29 +000061 }
David Goodwin6021b4d2009-08-10 15:55:25 +000062 }
63 }
64
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000065 ReservedScoreboard.reset(ScoreboardDepth);
66 RequiredScoreboard.reset(ScoreboardDepth);
David Goodwin6021b4d2009-08-10 15:55:25 +000067
Andrew Trick87255e32012-07-07 04:00:00 +000068 // If MaxLookAhead is not set above, then we are not enabled.
Andrew Trick73d77362012-06-05 03:44:40 +000069 if (!isEnabled())
Andrew Tricked7c96d2012-06-05 03:44:32 +000070 DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
Andrew Trick73d77362012-06-05 03:44:40 +000071 else {
Andrew Trick87255e32012-07-07 04:00:00 +000072 // A nonempty itinerary must have a SchedModel.
Pete Cooper11759452014-09-02 17:43:54 +000073 IssueWidth = ItinData->SchedModel.IssueWidth;
Andrew Tricked7c96d2012-06-05 03:44:32 +000074 DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
75 << ScoreboardDepth << '\n');
Andrew Trick73d77362012-06-05 03:44:40 +000076 }
David Goodwin6021b4d2009-08-10 15:55:25 +000077}
78
Andrew Trick00067fb2010-12-08 20:04:29 +000079void ScoreboardHazardRecognizer::Reset() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +000080 IssueCount = 0;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000081 RequiredScoreboard.reset();
82 ReservedScoreboard.reset();
David Goodwin6021b4d2009-08-10 15:55:25 +000083}
84
Manman Ren19f49ac2012-09-11 22:23:19 +000085#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Yaron Kereneb2a2542016-01-29 20:50:44 +000086LLVM_DUMP_METHOD void ScoreboardHazardRecognizer::Scoreboard::dump() const {
David Greene964a9822010-01-04 21:26:07 +000087 dbgs() << "Scoreboard:\n";
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000088
89 unsigned last = Depth - 1;
90 while ((last > 0) && ((*this)[last] == 0))
David Goodwin6021b4d2009-08-10 15:55:25 +000091 last--;
92
93 for (unsigned i = 0; i <= last; i++) {
Hal Finkel8db55472012-06-22 20:27:13 +000094 unsigned FUs = (*this)[i];
David Greene964a9822010-01-04 21:26:07 +000095 dbgs() << "\t";
Hal Finkel8db55472012-06-22 20:27:13 +000096 for (int j = 31; j >= 0; j--)
97 dbgs() << ((FUs & (1 << j)) ? '1' : '0');
David Greene964a9822010-01-04 21:26:07 +000098 dbgs() << '\n';
David Goodwin6021b4d2009-08-10 15:55:25 +000099 }
100}
Manman Ren742534c2012-09-06 19:06:06 +0000101#endif
David Goodwin6021b4d2009-08-10 15:55:25 +0000102
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000103bool ScoreboardHazardRecognizer::atIssueLimit() const {
104 if (IssueWidth == 0)
105 return false;
106
107 return IssueCount == IssueWidth;
108}
109
Evan Chengf128bdc2010-06-16 07:35:02 +0000110ScheduleHazardRecognizer::HazardType
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000111ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
Evan Chengbf407072010-09-10 01:29:16 +0000112 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +0000113 return NoHazard;
David Goodwin6021b4d2009-08-10 15:55:25 +0000114
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000115 // Note that stalls will be negative for bottom-up scheduling.
116 int cycle = Stalls;
David Goodwin74b79562009-09-22 16:47:52 +0000117
118 // Use the itinerary for the underlying instruction to check for
119 // free FU's in the scoreboard at the appropriate future cycles.
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000120
Evan Cheng6cc775f2011-06-28 19:10:37 +0000121 const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
Craig Topperc0196b12014-04-14 00:51:57 +0000122 if (!MCID) {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000123 // Don't check hazards for non-machineinstr Nodes.
124 return NoHazard;
125 }
Evan Cheng6cc775f2011-06-28 19:10:37 +0000126 unsigned idx = MCID->getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +0000127 for (const InstrStage *IS = ItinData->beginStage(idx),
128 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +0000129 // We must find one of the stage's units free for every cycle the
130 // stage is occupied. FIXME it would be more accurate to find the
131 // same unit free in all the cycles.
132 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000133 int StageCycle = cycle + (int)i;
134 if (StageCycle < 0)
135 continue;
136
137 if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
138 assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
139 "Scoreboard depth exceeded!");
140 // This stage was stalled beyond pipeline depth, so cannot conflict.
141 break;
142 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000143
Hal Finkel8db55472012-06-22 20:27:13 +0000144 unsigned freeUnits = IS->getUnits();
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000145 switch (IS->getReservationKind()) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000146 case InstrStage::Required:
147 // Required FUs conflict with both reserved and required ones
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000148 freeUnits &= ~ReservedScoreboard[StageCycle];
Justin Bognerb03fd122016-08-17 05:10:15 +0000149 LLVM_FALLTHROUGH;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000150 case InstrStage::Reserved:
151 // Reserved FUs can conflict only with required ones.
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000152 freeUnits &= ~RequiredScoreboard[StageCycle];
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000153 break;
154 }
155
David Goodwin74b79562009-09-22 16:47:52 +0000156 if (!freeUnits) {
Benjamin Kramer484f4242012-05-26 11:37:37 +0000157 DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
David Greene964a9822010-01-04 21:26:07 +0000158 DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000159 DEBUG(DAG->dumpNode(SU));
David Goodwin74b79562009-09-22 16:47:52 +0000160 return Hazard;
161 }
David Goodwin6021b4d2009-08-10 15:55:25 +0000162 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000163
David Goodwin74b79562009-09-22 16:47:52 +0000164 // Advance the cycle to the next stage.
165 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000166 }
167
168 return NoHazard;
169}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000170
Andrew Trick00067fb2010-12-08 20:04:29 +0000171void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
Evan Chengbf407072010-09-10 01:29:16 +0000172 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +0000173 return;
David Goodwin6021b4d2009-08-10 15:55:25 +0000174
David Goodwin74b79562009-09-22 16:47:52 +0000175 // Use the itinerary for the underlying instruction to reserve FU's
176 // in the scoreboard at the appropriate future cycles.
Evan Cheng6cc775f2011-06-28 19:10:37 +0000177 const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
178 assert(MCID && "The scheduler must filter non-machineinstrs");
179 if (DAG->TII->isZeroCost(MCID->Opcode))
Andrew Trick47ff14b2011-01-21 05:51:33 +0000180 return;
181
182 ++IssueCount;
183
184 unsigned cycle = 0;
185
Evan Cheng6cc775f2011-06-28 19:10:37 +0000186 unsigned idx = MCID->getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +0000187 for (const InstrStage *IS = ItinData->beginStage(idx),
188 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +0000189 // We must reserve one of the stage's units for every cycle the
190 // stage is occupied. FIXME it would be more accurate to reserve
191 // the same unit free in all the cycles.
192 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000193 assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
David Goodwin74b79562009-09-22 16:47:52 +0000194 "Scoreboard depth exceeded!");
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000195
Hal Finkel8db55472012-06-22 20:27:13 +0000196 unsigned freeUnits = IS->getUnits();
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000197 switch (IS->getReservationKind()) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000198 case InstrStage::Required:
199 // Required FUs conflict with both reserved and required ones
200 freeUnits &= ~ReservedScoreboard[cycle + i];
Justin Bognerb03fd122016-08-17 05:10:15 +0000201 LLVM_FALLTHROUGH;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000202 case InstrStage::Reserved:
203 // Reserved FUs can conflict only with required ones.
204 freeUnits &= ~RequiredScoreboard[cycle + i];
205 break;
206 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000207
David Goodwin74b79562009-09-22 16:47:52 +0000208 // reduce to a single unit
Hal Finkel8db55472012-06-22 20:27:13 +0000209 unsigned freeUnit = 0;
David Goodwin74b79562009-09-22 16:47:52 +0000210 do {
211 freeUnit = freeUnits;
212 freeUnits = freeUnit & (freeUnit - 1);
213 } while (freeUnits);
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000214
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000215 if (IS->getReservationKind() == InstrStage::Required)
216 RequiredScoreboard[cycle + i] |= freeUnit;
217 else
218 ReservedScoreboard[cycle + i] |= freeUnit;
David Goodwin6021b4d2009-08-10 15:55:25 +0000219 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000220
David Goodwin74b79562009-09-22 16:47:52 +0000221 // Advance the cycle to the next stage.
222 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000223 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000224
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000225 DEBUG(ReservedScoreboard.dump());
226 DEBUG(RequiredScoreboard.dump());
David Goodwin6021b4d2009-08-10 15:55:25 +0000227}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000228
Andrew Trick00067fb2010-12-08 20:04:29 +0000229void ScoreboardHazardRecognizer::AdvanceCycle() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000230 IssueCount = 0;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000231 ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
232 RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
David Goodwin6021b4d2009-08-10 15:55:25 +0000233}
Andrew Trick00067fb2010-12-08 20:04:29 +0000234
235void ScoreboardHazardRecognizer::RecedeCycle() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000236 IssueCount = 0;
Andrew Trick00067fb2010-12-08 20:04:29 +0000237 ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
238 ReservedScoreboard.recede();
239 RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
240 RequiredScoreboard.recede();
241}