blob: 1364c9d8de8a83c6ab4f01e58548d168692993af [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"
David Blaikie3f833ed2017-11-08 01:01:31 +000018#include "llvm/CodeGen/TargetInstrInfo.h"
Nico Weber432a3882018-04-30 14:59:11 +000019#include "llvm/Config/llvm-config.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000020#include "llvm/MC/MCInstrDesc.h"
Evan Cheng8264e272011-06-29 01:14:12 +000021#include "llvm/MC/MCInstrItineraries.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000022#include "llvm/Support/Compiler.h"
David Goodwin6021b4d2009-08-10 15:55:25 +000023#include "llvm/Support/Debug.h"
David Goodwinf20236a2009-08-11 01:44:26 +000024#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000025#include <cassert>
David Goodwin6021b4d2009-08-10 15:55:25 +000026
Bill Wendlinga2c45942009-08-22 20:08:44 +000027using namespace llvm;
David Goodwin6021b4d2009-08-10 15:55:25 +000028
Mehdi Aminiea0b1e72016-04-20 00:21:24 +000029#define DEBUG_TYPE DebugType
Chandler Carruth1b9dde02014-04-22 02:02:50 +000030
Mehdi Aminiea0b1e72016-04-20 00:21:24 +000031ScoreboardHazardRecognizer::ScoreboardHazardRecognizer(
32 const InstrItineraryData *II, const ScheduleDAG *SchedDAG,
33 const char *ParentDebugType)
34 : ScheduleHazardRecognizer(), DebugType(ParentDebugType), ItinData(II),
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000035 DAG(SchedDAG) {
Don Hinton53eb6372017-09-27 21:19:56 +000036 (void)DebugType;
Andrew Tricked7c96d2012-06-05 03:44:32 +000037 // Determine the maximum depth of any itinerary. This determines the depth of
38 // the scoreboard. We always make the scoreboard at least 1 cycle deep to
39 // avoid dealing with the boundary condition.
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000040 unsigned ScoreboardDepth = 1;
Evan Chengbf407072010-09-10 01:29:16 +000041 if (ItinData && !ItinData->isEmpty()) {
David Goodwin6021b4d2009-08-10 15:55:25 +000042 for (unsigned idx = 0; ; ++idx) {
Evan Chengbf407072010-09-10 01:29:16 +000043 if (ItinData->isEndMarker(idx))
David Goodwin6021b4d2009-08-10 15:55:25 +000044 break;
45
Evan Chengbf407072010-09-10 01:29:16 +000046 const InstrStage *IS = ItinData->beginStage(idx);
47 const InstrStage *E = ItinData->endStage(idx);
Andrew Trick10ffc2b2010-12-24 05:03:26 +000048 unsigned CurCycle = 0;
David Goodwin6021b4d2009-08-10 15:55:25 +000049 unsigned ItinDepth = 0;
Andrew Trick10ffc2b2010-12-24 05:03:26 +000050 for (; IS != E; ++IS) {
51 unsigned StageDepth = CurCycle + IS->getCycles();
52 if (ItinDepth < StageDepth) ItinDepth = StageDepth;
53 CurCycle += IS->getNextCycles();
54 }
David Goodwin6021b4d2009-08-10 15:55:25 +000055
Andrew Trick00067fb2010-12-08 20:04:29 +000056 // Find the next power-of-2 >= ItinDepth
57 while (ItinDepth > ScoreboardDepth) {
58 ScoreboardDepth *= 2;
Andrew Tricked7c96d2012-06-05 03:44:32 +000059 // Don't set MaxLookAhead until we find at least one nonzero stage.
60 // This way, an itinerary with no stages has MaxLookAhead==0, which
61 // completely bypasses the scoreboard hazard logic.
62 MaxLookAhead = ScoreboardDepth;
Andrew Trick00067fb2010-12-08 20:04:29 +000063 }
David Goodwin6021b4d2009-08-10 15:55:25 +000064 }
65 }
66
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000067 ReservedScoreboard.reset(ScoreboardDepth);
68 RequiredScoreboard.reset(ScoreboardDepth);
David Goodwin6021b4d2009-08-10 15:55:25 +000069
Andrew Trick87255e32012-07-07 04:00:00 +000070 // If MaxLookAhead is not set above, then we are not enabled.
Andrew Trick73d77362012-06-05 03:44:40 +000071 if (!isEnabled())
Andrew Tricked7c96d2012-06-05 03:44:32 +000072 DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
Andrew Trick73d77362012-06-05 03:44:40 +000073 else {
Andrew Trick87255e32012-07-07 04:00:00 +000074 // A nonempty itinerary must have a SchedModel.
Pete Cooper11759452014-09-02 17:43:54 +000075 IssueWidth = ItinData->SchedModel.IssueWidth;
Andrew Tricked7c96d2012-06-05 03:44:32 +000076 DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
77 << ScoreboardDepth << '\n');
Andrew Trick73d77362012-06-05 03:44:40 +000078 }
David Goodwin6021b4d2009-08-10 15:55:25 +000079}
80
Andrew Trick00067fb2010-12-08 20:04:29 +000081void ScoreboardHazardRecognizer::Reset() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +000082 IssueCount = 0;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000083 RequiredScoreboard.reset();
84 ReservedScoreboard.reset();
David Goodwin6021b4d2009-08-10 15:55:25 +000085}
86
Aaron Ballman615eb472017-10-15 14:32:27 +000087#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Yaron Kereneb2a2542016-01-29 20:50:44 +000088LLVM_DUMP_METHOD void ScoreboardHazardRecognizer::Scoreboard::dump() const {
David Greene964a9822010-01-04 21:26:07 +000089 dbgs() << "Scoreboard:\n";
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000090
91 unsigned last = Depth - 1;
92 while ((last > 0) && ((*this)[last] == 0))
David Goodwin6021b4d2009-08-10 15:55:25 +000093 last--;
94
95 for (unsigned i = 0; i <= last; i++) {
Hal Finkel8db55472012-06-22 20:27:13 +000096 unsigned FUs = (*this)[i];
David Greene964a9822010-01-04 21:26:07 +000097 dbgs() << "\t";
Hal Finkel8db55472012-06-22 20:27:13 +000098 for (int j = 31; j >= 0; j--)
99 dbgs() << ((FUs & (1 << j)) ? '1' : '0');
David Greene964a9822010-01-04 21:26:07 +0000100 dbgs() << '\n';
David Goodwin6021b4d2009-08-10 15:55:25 +0000101 }
102}
Manman Ren742534c2012-09-06 19:06:06 +0000103#endif
David Goodwin6021b4d2009-08-10 15:55:25 +0000104
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000105bool ScoreboardHazardRecognizer::atIssueLimit() const {
106 if (IssueWidth == 0)
107 return false;
108
109 return IssueCount == IssueWidth;
110}
111
Evan Chengf128bdc2010-06-16 07:35:02 +0000112ScheduleHazardRecognizer::HazardType
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000113ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
Evan Chengbf407072010-09-10 01:29:16 +0000114 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +0000115 return NoHazard;
David Goodwin6021b4d2009-08-10 15:55:25 +0000116
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000117 // Note that stalls will be negative for bottom-up scheduling.
118 int cycle = Stalls;
David Goodwin74b79562009-09-22 16:47:52 +0000119
120 // Use the itinerary for the underlying instruction to check for
121 // free FU's in the scoreboard at the appropriate future cycles.
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000122
Evan Cheng6cc775f2011-06-28 19:10:37 +0000123 const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
Craig Topperc0196b12014-04-14 00:51:57 +0000124 if (!MCID) {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000125 // Don't check hazards for non-machineinstr Nodes.
126 return NoHazard;
127 }
Evan Cheng6cc775f2011-06-28 19:10:37 +0000128 unsigned idx = MCID->getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +0000129 for (const InstrStage *IS = ItinData->beginStage(idx),
130 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +0000131 // We must find one of the stage's units free for every cycle the
132 // stage is occupied. FIXME it would be more accurate to find the
133 // same unit free in all the cycles.
134 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000135 int StageCycle = cycle + (int)i;
136 if (StageCycle < 0)
137 continue;
138
139 if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
140 assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
141 "Scoreboard depth exceeded!");
142 // This stage was stalled beyond pipeline depth, so cannot conflict.
143 break;
144 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000145
Hal Finkel8db55472012-06-22 20:27:13 +0000146 unsigned freeUnits = IS->getUnits();
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000147 switch (IS->getReservationKind()) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000148 case InstrStage::Required:
149 // Required FUs conflict with both reserved and required ones
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000150 freeUnits &= ~ReservedScoreboard[StageCycle];
Justin Bognerb03fd122016-08-17 05:10:15 +0000151 LLVM_FALLTHROUGH;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000152 case InstrStage::Reserved:
153 // Reserved FUs can conflict only with required ones.
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000154 freeUnits &= ~RequiredScoreboard[StageCycle];
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000155 break;
156 }
157
David Goodwin74b79562009-09-22 16:47:52 +0000158 if (!freeUnits) {
Benjamin Kramer484f4242012-05-26 11:37:37 +0000159 DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
David Greene964a9822010-01-04 21:26:07 +0000160 DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000161 DEBUG(DAG->dumpNode(SU));
David Goodwin74b79562009-09-22 16:47:52 +0000162 return Hazard;
163 }
David Goodwin6021b4d2009-08-10 15:55:25 +0000164 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000165
David Goodwin74b79562009-09-22 16:47:52 +0000166 // Advance the cycle to the next stage.
167 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000168 }
169
170 return NoHazard;
171}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000172
Andrew Trick00067fb2010-12-08 20:04:29 +0000173void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
Evan Chengbf407072010-09-10 01:29:16 +0000174 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +0000175 return;
David Goodwin6021b4d2009-08-10 15:55:25 +0000176
David Goodwin74b79562009-09-22 16:47:52 +0000177 // Use the itinerary for the underlying instruction to reserve FU's
178 // in the scoreboard at the appropriate future cycles.
Evan Cheng6cc775f2011-06-28 19:10:37 +0000179 const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
180 assert(MCID && "The scheduler must filter non-machineinstrs");
181 if (DAG->TII->isZeroCost(MCID->Opcode))
Andrew Trick47ff14b2011-01-21 05:51:33 +0000182 return;
183
184 ++IssueCount;
185
186 unsigned cycle = 0;
187
Evan Cheng6cc775f2011-06-28 19:10:37 +0000188 unsigned idx = MCID->getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +0000189 for (const InstrStage *IS = ItinData->beginStage(idx),
190 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +0000191 // We must reserve one of the stage's units for every cycle the
192 // stage is occupied. FIXME it would be more accurate to reserve
193 // the same unit free in all the cycles.
194 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000195 assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
David Goodwin74b79562009-09-22 16:47:52 +0000196 "Scoreboard depth exceeded!");
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000197
Hal Finkel8db55472012-06-22 20:27:13 +0000198 unsigned freeUnits = IS->getUnits();
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000199 switch (IS->getReservationKind()) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000200 case InstrStage::Required:
201 // Required FUs conflict with both reserved and required ones
202 freeUnits &= ~ReservedScoreboard[cycle + i];
Justin Bognerb03fd122016-08-17 05:10:15 +0000203 LLVM_FALLTHROUGH;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000204 case InstrStage::Reserved:
205 // Reserved FUs can conflict only with required ones.
206 freeUnits &= ~RequiredScoreboard[cycle + i];
207 break;
208 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000209
David Goodwin74b79562009-09-22 16:47:52 +0000210 // reduce to a single unit
Hal Finkel8db55472012-06-22 20:27:13 +0000211 unsigned freeUnit = 0;
David Goodwin74b79562009-09-22 16:47:52 +0000212 do {
213 freeUnit = freeUnits;
214 freeUnits = freeUnit & (freeUnit - 1);
215 } while (freeUnits);
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000216
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000217 if (IS->getReservationKind() == InstrStage::Required)
218 RequiredScoreboard[cycle + i] |= freeUnit;
219 else
220 ReservedScoreboard[cycle + i] |= freeUnit;
David Goodwin6021b4d2009-08-10 15:55:25 +0000221 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000222
David Goodwin74b79562009-09-22 16:47:52 +0000223 // Advance the cycle to the next stage.
224 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000225 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000226
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000227 DEBUG(ReservedScoreboard.dump());
228 DEBUG(RequiredScoreboard.dump());
David Goodwin6021b4d2009-08-10 15:55:25 +0000229}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000230
Andrew Trick00067fb2010-12-08 20:04:29 +0000231void ScoreboardHazardRecognizer::AdvanceCycle() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000232 IssueCount = 0;
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000233 ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
234 RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
David Goodwin6021b4d2009-08-10 15:55:25 +0000235}
Andrew Trick00067fb2010-12-08 20:04:29 +0000236
237void ScoreboardHazardRecognizer::RecedeCycle() {
Andrew Trick10ffc2b2010-12-24 05:03:26 +0000238 IssueCount = 0;
Andrew Trick00067fb2010-12-08 20:04:29 +0000239 ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
240 ReservedScoreboard.recede();
241 RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
242 RequiredScoreboard.recede();
243}