blob: d78b5d3ecbdd4a4df5d2306db322b7acda4a86ad [file] [log] [blame]
Andrew Trick00067fb2010-12-08 20:04:29 +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#define DEBUG_TYPE "sched-hazard"
17#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
Evan Cheng078f4ce2010-06-14 21:06:53 +000018#include "llvm/CodeGen/ScheduleDAG.h"
David Goodwin6021b4d2009-08-10 15:55:25 +000019#include "llvm/Support/Debug.h"
20#include "llvm/Support/ErrorHandling.h"
David Goodwinf20236a2009-08-11 01:44:26 +000021#include "llvm/Support/raw_ostream.h"
David Goodwin6021b4d2009-08-10 15:55:25 +000022#include "llvm/Target/TargetInstrItineraries.h"
23
Bill Wendlinga2c45942009-08-22 20:08:44 +000024using namespace llvm;
David Goodwin6021b4d2009-08-10 15:55:25 +000025
Andrew Trick00067fb2010-12-08 20:04:29 +000026ScoreboardHazardRecognizer::
27ScoreboardHazardRecognizer(const InstrItineraryData *LItinData) :
Evan Cheng078f4ce2010-06-14 21:06:53 +000028 ScheduleHazardRecognizer(), ItinData(LItinData) {
David Goodwin6021b4d2009-08-10 15:55:25 +000029 // Determine the maximum depth of any itinerary. This determines the
30 // depth of the scoreboard. We always make the scoreboard at least 1
31 // cycle deep to avoid dealing with the boundary condition.
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000032 unsigned ScoreboardDepth = 1;
Evan Chengbf407072010-09-10 01:29:16 +000033 if (ItinData && !ItinData->isEmpty()) {
David Goodwin6021b4d2009-08-10 15:55:25 +000034 for (unsigned idx = 0; ; ++idx) {
Evan Chengbf407072010-09-10 01:29:16 +000035 if (ItinData->isEndMarker(idx))
David Goodwin6021b4d2009-08-10 15:55:25 +000036 break;
37
Evan Chengbf407072010-09-10 01:29:16 +000038 const InstrStage *IS = ItinData->beginStage(idx);
39 const InstrStage *E = ItinData->endStage(idx);
David Goodwin6021b4d2009-08-10 15:55:25 +000040 unsigned ItinDepth = 0;
41 for (; IS != E; ++IS)
David Goodwinb369ee42009-08-12 18:31:53 +000042 ItinDepth += IS->getCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +000043
Andrew Trick00067fb2010-12-08 20:04:29 +000044 // Find the next power-of-2 >= ItinDepth
45 while (ItinDepth > ScoreboardDepth) {
46 ScoreboardDepth *= 2;
47 }
David Goodwin6021b4d2009-08-10 15:55:25 +000048 }
49 }
50
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000051 ReservedScoreboard.reset(ScoreboardDepth);
52 RequiredScoreboard.reset(ScoreboardDepth);
David Goodwin6021b4d2009-08-10 15:55:25 +000053
Andrew Trick00067fb2010-12-08 20:04:29 +000054 DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
Bill Wendlinga2c45942009-08-22 20:08:44 +000055 << ScoreboardDepth << '\n');
David Goodwin6021b4d2009-08-10 15:55:25 +000056}
57
Andrew Trick00067fb2010-12-08 20:04:29 +000058void ScoreboardHazardRecognizer::Reset() {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000059 RequiredScoreboard.reset();
60 ReservedScoreboard.reset();
David Goodwin6021b4d2009-08-10 15:55:25 +000061}
62
Andrew Trick00067fb2010-12-08 20:04:29 +000063void ScoreboardHazardRecognizer::Scoreboard::dump() const {
David Greene964a9822010-01-04 21:26:07 +000064 dbgs() << "Scoreboard:\n";
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000065
66 unsigned last = Depth - 1;
67 while ((last > 0) && ((*this)[last] == 0))
David Goodwin6021b4d2009-08-10 15:55:25 +000068 last--;
69
70 for (unsigned i = 0; i <= last; i++) {
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000071 unsigned FUs = (*this)[i];
David Greene964a9822010-01-04 21:26:07 +000072 dbgs() << "\t";
David Goodwin6021b4d2009-08-10 15:55:25 +000073 for (int j = 31; j >= 0; j--)
David Greene964a9822010-01-04 21:26:07 +000074 dbgs() << ((FUs & (1 << j)) ? '1' : '0');
75 dbgs() << '\n';
David Goodwin6021b4d2009-08-10 15:55:25 +000076 }
77}
78
Evan Chengf128bdc2010-06-16 07:35:02 +000079ScheduleHazardRecognizer::HazardType
Andrew Trick00067fb2010-12-08 20:04:29 +000080ScoreboardHazardRecognizer::getHazardType(SUnit *SU) {
Evan Chengbf407072010-09-10 01:29:16 +000081 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +000082 return NoHazard;
David Goodwin6021b4d2009-08-10 15:55:25 +000083
David Goodwin74b79562009-09-22 16:47:52 +000084 unsigned cycle = 0;
85
86 // Use the itinerary for the underlying instruction to check for
87 // free FU's in the scoreboard at the appropriate future cycles.
88 unsigned idx = SU->getInstr()->getDesc().getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +000089 for (const InstrStage *IS = ItinData->beginStage(idx),
90 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +000091 // We must find one of the stage's units free for every cycle the
92 // stage is occupied. FIXME it would be more accurate to find the
93 // same unit free in all the cycles.
94 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000095 assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
David Goodwin74b79562009-09-22 16:47:52 +000096 "Scoreboard depth exceeded!");
Anton Korobeynikov9a348a92010-04-07 18:19:24 +000097
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +000098 unsigned freeUnits = IS->getUnits();
99 switch (IS->getReservationKind()) {
100 default:
101 assert(0 && "Invalid FU reservation");
102 case InstrStage::Required:
103 // Required FUs conflict with both reserved and required ones
104 freeUnits &= ~ReservedScoreboard[cycle + i];
105 // FALLTHROUGH
106 case InstrStage::Reserved:
107 // Reserved FUs can conflict only with required ones.
108 freeUnits &= ~RequiredScoreboard[cycle + i];
109 break;
110 }
111
David Goodwin74b79562009-09-22 16:47:52 +0000112 if (!freeUnits) {
David Greene964a9822010-01-04 21:26:07 +0000113 DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", ");
114 DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
David Goodwin74b79562009-09-22 16:47:52 +0000115 DEBUG(SU->getInstr()->dump());
116 return Hazard;
117 }
David Goodwin6021b4d2009-08-10 15:55:25 +0000118 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000119
David Goodwin74b79562009-09-22 16:47:52 +0000120 // Advance the cycle to the next stage.
121 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000122 }
123
124 return NoHazard;
125}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000126
Andrew Trick00067fb2010-12-08 20:04:29 +0000127void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
Evan Chengbf407072010-09-10 01:29:16 +0000128 if (!ItinData || ItinData->isEmpty())
David Goodwin74b79562009-09-22 16:47:52 +0000129 return;
David Goodwin6021b4d2009-08-10 15:55:25 +0000130
David Goodwin74b79562009-09-22 16:47:52 +0000131 unsigned cycle = 0;
David Goodwin6021b4d2009-08-10 15:55:25 +0000132
David Goodwin74b79562009-09-22 16:47:52 +0000133 // Use the itinerary for the underlying instruction to reserve FU's
134 // in the scoreboard at the appropriate future cycles.
135 unsigned idx = SU->getInstr()->getDesc().getSchedClass();
Evan Chengbf407072010-09-10 01:29:16 +0000136 for (const InstrStage *IS = ItinData->beginStage(idx),
137 *E = ItinData->endStage(idx); IS != E; ++IS) {
David Goodwin74b79562009-09-22 16:47:52 +0000138 // We must reserve one of the stage's units for every cycle the
139 // stage is occupied. FIXME it would be more accurate to reserve
140 // the same unit free in all the cycles.
141 for (unsigned int i = 0; i < IS->getCycles(); ++i) {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000142 assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
David Goodwin74b79562009-09-22 16:47:52 +0000143 "Scoreboard depth exceeded!");
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000144
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000145 unsigned freeUnits = IS->getUnits();
146 switch (IS->getReservationKind()) {
147 default:
148 assert(0 && "Invalid FU reservation");
149 case InstrStage::Required:
150 // Required FUs conflict with both reserved and required ones
151 freeUnits &= ~ReservedScoreboard[cycle + i];
152 // FALLTHROUGH
153 case InstrStage::Reserved:
154 // Reserved FUs can conflict only with required ones.
155 freeUnits &= ~RequiredScoreboard[cycle + i];
156 break;
157 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000158
David Goodwin74b79562009-09-22 16:47:52 +0000159 // reduce to a single unit
160 unsigned freeUnit = 0;
161 do {
162 freeUnit = freeUnits;
163 freeUnits = freeUnit & (freeUnit - 1);
164 } while (freeUnits);
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000165
David Goodwin74b79562009-09-22 16:47:52 +0000166 assert(freeUnit && "No function unit available!");
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000167 if (IS->getReservationKind() == InstrStage::Required)
168 RequiredScoreboard[cycle + i] |= freeUnit;
169 else
170 ReservedScoreboard[cycle + i] |= freeUnit;
David Goodwin6021b4d2009-08-10 15:55:25 +0000171 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000172
David Goodwin74b79562009-09-22 16:47:52 +0000173 // Advance the cycle to the next stage.
174 cycle += IS->getNextCycles();
David Goodwin6021b4d2009-08-10 15:55:25 +0000175 }
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000176
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000177 DEBUG(ReservedScoreboard.dump());
178 DEBUG(RequiredScoreboard.dump());
David Goodwin6021b4d2009-08-10 15:55:25 +0000179}
Anton Korobeynikov9a348a92010-04-07 18:19:24 +0000180
Andrew Trick00067fb2010-12-08 20:04:29 +0000181void ScoreboardHazardRecognizer::AdvanceCycle() {
Anton Korobeynikov0bdc6342010-04-07 18:19:32 +0000182 ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
183 RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
David Goodwin6021b4d2009-08-10 15:55:25 +0000184}
Andrew Trick00067fb2010-12-08 20:04:29 +0000185
186void ScoreboardHazardRecognizer::RecedeCycle() {
187 ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
188 ReservedScoreboard.recede();
189 RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
190 RequiredScoreboard.recede();
191}