LLVM API Documentation
00001 //===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the ScoreboardHazardRecognizer class, which 00011 // encapsultes hazard-avoidance heuristics for scheduling, based on the 00012 // scheduling itineraries specified for the target. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "llvm/CodeGen/ScoreboardHazardRecognizer.h" 00017 #include "llvm/CodeGen/ScheduleDAG.h" 00018 #include "llvm/MC/MCInstrItineraries.h" 00019 #include "llvm/Support/Debug.h" 00020 #include "llvm/Support/ErrorHandling.h" 00021 #include "llvm/Support/raw_ostream.h" 00022 #include "llvm/Target/TargetInstrInfo.h" 00023 00024 using namespace llvm; 00025 00026 #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType 00027 00028 #ifndef NDEBUG 00029 const char *ScoreboardHazardRecognizer::DebugType = ""; 00030 #endif 00031 00032 ScoreboardHazardRecognizer:: 00033 ScoreboardHazardRecognizer(const InstrItineraryData *II, 00034 const ScheduleDAG *SchedDAG, 00035 const char *ParentDebugType) : 00036 ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0), 00037 IssueCount(0) { 00038 00039 #ifndef NDEBUG 00040 DebugType = ParentDebugType; 00041 #endif 00042 00043 // Determine the maximum depth of any itinerary. This determines the depth of 00044 // the scoreboard. We always make the scoreboard at least 1 cycle deep to 00045 // avoid dealing with the boundary condition. 00046 unsigned ScoreboardDepth = 1; 00047 if (ItinData && !ItinData->isEmpty()) { 00048 for (unsigned idx = 0; ; ++idx) { 00049 if (ItinData->isEndMarker(idx)) 00050 break; 00051 00052 const InstrStage *IS = ItinData->beginStage(idx); 00053 const InstrStage *E = ItinData->endStage(idx); 00054 unsigned CurCycle = 0; 00055 unsigned ItinDepth = 0; 00056 for (; IS != E; ++IS) { 00057 unsigned StageDepth = CurCycle + IS->getCycles(); 00058 if (ItinDepth < StageDepth) ItinDepth = StageDepth; 00059 CurCycle += IS->getNextCycles(); 00060 } 00061 00062 // Find the next power-of-2 >= ItinDepth 00063 while (ItinDepth > ScoreboardDepth) { 00064 ScoreboardDepth *= 2; 00065 // Don't set MaxLookAhead until we find at least one nonzero stage. 00066 // This way, an itinerary with no stages has MaxLookAhead==0, which 00067 // completely bypasses the scoreboard hazard logic. 00068 MaxLookAhead = ScoreboardDepth; 00069 } 00070 } 00071 } 00072 00073 ReservedScoreboard.reset(ScoreboardDepth); 00074 RequiredScoreboard.reset(ScoreboardDepth); 00075 00076 // If MaxLookAhead is not set above, then we are not enabled. 00077 if (!isEnabled()) 00078 DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n"); 00079 else { 00080 // A nonempty itinerary must have a SchedModel. 00081 IssueWidth = ItinData->SchedModel.IssueWidth; 00082 DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = " 00083 << ScoreboardDepth << '\n'); 00084 } 00085 } 00086 00087 void ScoreboardHazardRecognizer::Reset() { 00088 IssueCount = 0; 00089 RequiredScoreboard.reset(); 00090 ReservedScoreboard.reset(); 00091 } 00092 00093 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 00094 void ScoreboardHazardRecognizer::Scoreboard::dump() const { 00095 dbgs() << "Scoreboard:\n"; 00096 00097 unsigned last = Depth - 1; 00098 while ((last > 0) && ((*this)[last] == 0)) 00099 last--; 00100 00101 for (unsigned i = 0; i <= last; i++) { 00102 unsigned FUs = (*this)[i]; 00103 dbgs() << "\t"; 00104 for (int j = 31; j >= 0; j--) 00105 dbgs() << ((FUs & (1 << j)) ? '1' : '0'); 00106 dbgs() << '\n'; 00107 } 00108 } 00109 #endif 00110 00111 bool ScoreboardHazardRecognizer::atIssueLimit() const { 00112 if (IssueWidth == 0) 00113 return false; 00114 00115 return IssueCount == IssueWidth; 00116 } 00117 00118 ScheduleHazardRecognizer::HazardType 00119 ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { 00120 if (!ItinData || ItinData->isEmpty()) 00121 return NoHazard; 00122 00123 // Note that stalls will be negative for bottom-up scheduling. 00124 int cycle = Stalls; 00125 00126 // Use the itinerary for the underlying instruction to check for 00127 // free FU's in the scoreboard at the appropriate future cycles. 00128 00129 const MCInstrDesc *MCID = DAG->getInstrDesc(SU); 00130 if (!MCID) { 00131 // Don't check hazards for non-machineinstr Nodes. 00132 return NoHazard; 00133 } 00134 unsigned idx = MCID->getSchedClass(); 00135 for (const InstrStage *IS = ItinData->beginStage(idx), 00136 *E = ItinData->endStage(idx); IS != E; ++IS) { 00137 // We must find one of the stage's units free for every cycle the 00138 // stage is occupied. FIXME it would be more accurate to find the 00139 // same unit free in all the cycles. 00140 for (unsigned int i = 0; i < IS->getCycles(); ++i) { 00141 int StageCycle = cycle + (int)i; 00142 if (StageCycle < 0) 00143 continue; 00144 00145 if (StageCycle >= (int)RequiredScoreboard.getDepth()) { 00146 assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() && 00147 "Scoreboard depth exceeded!"); 00148 // This stage was stalled beyond pipeline depth, so cannot conflict. 00149 break; 00150 } 00151 00152 unsigned freeUnits = IS->getUnits(); 00153 switch (IS->getReservationKind()) { 00154 case InstrStage::Required: 00155 // Required FUs conflict with both reserved and required ones 00156 freeUnits &= ~ReservedScoreboard[StageCycle]; 00157 // FALLTHROUGH 00158 case InstrStage::Reserved: 00159 // Reserved FUs can conflict only with required ones. 00160 freeUnits &= ~RequiredScoreboard[StageCycle]; 00161 break; 00162 } 00163 00164 if (!freeUnits) { 00165 DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", "); 00166 DEBUG(dbgs() << "SU(" << SU->NodeNum << "): "); 00167 DEBUG(DAG->dumpNode(SU)); 00168 return Hazard; 00169 } 00170 } 00171 00172 // Advance the cycle to the next stage. 00173 cycle += IS->getNextCycles(); 00174 } 00175 00176 return NoHazard; 00177 } 00178 00179 void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) { 00180 if (!ItinData || ItinData->isEmpty()) 00181 return; 00182 00183 // Use the itinerary for the underlying instruction to reserve FU's 00184 // in the scoreboard at the appropriate future cycles. 00185 const MCInstrDesc *MCID = DAG->getInstrDesc(SU); 00186 assert(MCID && "The scheduler must filter non-machineinstrs"); 00187 if (DAG->TII->isZeroCost(MCID->Opcode)) 00188 return; 00189 00190 ++IssueCount; 00191 00192 unsigned cycle = 0; 00193 00194 unsigned idx = MCID->getSchedClass(); 00195 for (const InstrStage *IS = ItinData->beginStage(idx), 00196 *E = ItinData->endStage(idx); IS != E; ++IS) { 00197 // We must reserve one of the stage's units for every cycle the 00198 // stage is occupied. FIXME it would be more accurate to reserve 00199 // the same unit free in all the cycles. 00200 for (unsigned int i = 0; i < IS->getCycles(); ++i) { 00201 assert(((cycle + i) < RequiredScoreboard.getDepth()) && 00202 "Scoreboard depth exceeded!"); 00203 00204 unsigned freeUnits = IS->getUnits(); 00205 switch (IS->getReservationKind()) { 00206 case InstrStage::Required: 00207 // Required FUs conflict with both reserved and required ones 00208 freeUnits &= ~ReservedScoreboard[cycle + i]; 00209 // FALLTHROUGH 00210 case InstrStage::Reserved: 00211 // Reserved FUs can conflict only with required ones. 00212 freeUnits &= ~RequiredScoreboard[cycle + i]; 00213 break; 00214 } 00215 00216 // reduce to a single unit 00217 unsigned freeUnit = 0; 00218 do { 00219 freeUnit = freeUnits; 00220 freeUnits = freeUnit & (freeUnit - 1); 00221 } while (freeUnits); 00222 00223 if (IS->getReservationKind() == InstrStage::Required) 00224 RequiredScoreboard[cycle + i] |= freeUnit; 00225 else 00226 ReservedScoreboard[cycle + i] |= freeUnit; 00227 } 00228 00229 // Advance the cycle to the next stage. 00230 cycle += IS->getNextCycles(); 00231 } 00232 00233 DEBUG(ReservedScoreboard.dump()); 00234 DEBUG(RequiredScoreboard.dump()); 00235 } 00236 00237 void ScoreboardHazardRecognizer::AdvanceCycle() { 00238 IssueCount = 0; 00239 ReservedScoreboard[0] = 0; ReservedScoreboard.advance(); 00240 RequiredScoreboard[0] = 0; RequiredScoreboard.advance(); 00241 } 00242 00243 void ScoreboardHazardRecognizer::RecedeCycle() { 00244 IssueCount = 0; 00245 ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0; 00246 ReservedScoreboard.recede(); 00247 RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0; 00248 RequiredScoreboard.recede(); 00249 }