//===----- ExactHazardRecognizer.cpp - hazard recognizer -------- ---------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This implements a a hazard recognizer using the instructions itineraries // defined for the current target. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "exact-hazards" #include "ExactHazardRecognizer.h" #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetInstrItineraries.h" namespace llvm { ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData) : ScheduleHazardRecognizer(), ItinData(LItinData) { // Determine the maximum depth of any itinerary. This determines the // depth of the scoreboard. We always make the scoreboard at least 1 // cycle deep to avoid dealing with the boundary condition. ScoreboardDepth = 1; if (!ItinData.isEmpty()) { for (unsigned idx = 0; ; ++idx) { // If the begin stage of an itinerary has 0 cycles and units, // then we have reached the end of the itineraries. const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); if ((IS->Cycles == 0) && (IS->Units == 0)) break; unsigned ItinDepth = 0; for (; IS != E; ++IS) ItinDepth += IS->Cycles; ScoreboardDepth = std::max(ScoreboardDepth, ItinDepth); } } Scoreboard = new unsigned[ScoreboardDepth]; ScoreboardHead = 0; DOUT << "Using exact hazard recognizer: ScoreboardDepth = " << ScoreboardDepth << '\n'; } ExactHazardRecognizer::~ExactHazardRecognizer() { delete Scoreboard; } void ExactHazardRecognizer::Reset() { memset(Scoreboard, 0, ScoreboardDepth * sizeof(unsigned)); ScoreboardHead = 0; } unsigned ExactHazardRecognizer::getFutureIndex(unsigned offset) { return (ScoreboardHead + offset) % ScoreboardDepth; } void ExactHazardRecognizer::dumpScoreboard() { DOUT << "Scoreboard:\n"; unsigned last = ScoreboardDepth - 1; while ((last > 0) && (Scoreboard[getFutureIndex(last)] == 0)) last--; for (unsigned i = 0; i <= last; i++) { unsigned FUs = Scoreboard[getFutureIndex(i)]; DOUT << "\t"; for (int j = 31; j >= 0; j--) DOUT << ((FUs & (1 << j)) ? '1' : '0'); DOUT << '\n'; } } ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU) { unsigned cycle = 0; // Use the itinerary for the underlying instruction to check for // free FU's in the scoreboard at the appropriate future cycles. unsigned idx = SU->getInstr()->getDesc().getSchedClass(); for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); IS != E; ++IS) { // We must find one of the stage's units free for every cycle the // stage is occupied. for (unsigned int i = 0; i < IS->Cycles; ++i) { assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!"); unsigned index = getFutureIndex(cycle); unsigned freeUnits = IS->Units & ~Scoreboard[index]; if (!freeUnits) { DOUT << "*** Hazard in cycle " << cycle << ", "; DOUT << "SU(" << SU->NodeNum << "): "; DEBUG(SU->getInstr()->dump()); return Hazard; } ++cycle; } } return NoHazard; } void ExactHazardRecognizer::EmitInstruction(SUnit *SU) { unsigned cycle = 0; // Use the itinerary for the underlying instruction to reserve FU's // in the scoreboard at the appropriate future cycles. unsigned idx = SU->getInstr()->getDesc().getSchedClass(); for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx); IS != E; ++IS) { // We must reserve one of the stage's units for every cycle the // stage is occupied. for (unsigned int i = 0; i < IS->Cycles; ++i) { assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!"); unsigned index = getFutureIndex(cycle); unsigned freeUnits = IS->Units & ~Scoreboard[index]; // reduce to a single unit unsigned freeUnit = 0; do { freeUnit = freeUnits; freeUnits = freeUnit & (freeUnit - 1); } while (freeUnits); assert(freeUnit && "No function unit available!"); Scoreboard[index] |= freeUnit; ++cycle; } } DEBUG(dumpScoreboard()); } void ExactHazardRecognizer::AdvanceCycle() { Scoreboard[ScoreboardHead] = 0; ScoreboardHead = getFutureIndex(1); } } /* namespace llvm */