diff options
author | David Goodwin <david_goodwin@apple.com> | 2009-08-10 15:55:25 +0000 |
---|---|---|
committer | David Goodwin <david_goodwin@apple.com> | 2009-08-10 15:55:25 +0000 |
commit | d94a4e5d8de1145be200ff7223f98b0928462b94 (patch) | |
tree | f3fbcecfdc7ed2e3a84989c12cedc5a15db93215 /lib/CodeGen/ExactHazardRecognizer.cpp | |
parent | 65f2e7887a8b70b3ee63ef535a6bcfe8a170c074 (diff) |
Post RA scheduler changes. Introduce a hazard recognizer that uses the target schedule information to accurately model the pipeline. Update the scheduler to correctly handle multi-issue targets.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78563 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ExactHazardRecognizer.cpp')
-rw-r--r-- | lib/CodeGen/ExactHazardRecognizer.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/lib/CodeGen/ExactHazardRecognizer.cpp b/lib/CodeGen/ExactHazardRecognizer.cpp new file mode 100644 index 0000000000..a7fcf918a3 --- /dev/null +++ b/lib/CodeGen/ExactHazardRecognizer.cpp @@ -0,0 +1,149 @@ +//===----- 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 */ |