Skip to content

Commit

Permalink
Post RA scheduler changes. Introduce a hazard recognizer that uses th…
Browse files Browse the repository at this point in the history
…e 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
  • Loading branch information
David Goodwin committed Aug 10, 2009
1 parent 65f2e78 commit d94a4e5
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 82 deletions.
5 changes: 5 additions & 0 deletions include/llvm/CodeGen/ScheduleHazardRecognizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class ScheduleHazardRecognizer {
return NoHazard;
}

/// Reset - This callback is invoked when a new block of
/// instructions is about to be schedule. The hazard state should be
/// set to an initialized state.
virtual void Reset() {}

/// EmitInstruction - This callback is invoked when an instruction is
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SUnit *) {}
Expand Down
10 changes: 6 additions & 4 deletions include/llvm/Target/TargetInstrItineraries.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace llvm {

//===----------------------------------------------------------------------===//
/// Instruction stage - These values represent a step in the execution of an
/// instruction. The latency represents the number of discrete time slots used
/// need to complete the stage. Units represent the choice of functional units
/// that can be used to complete the stage. Eg. IntUnit1, IntUnit2.
/// instruction. The latency represents the number of discrete time slots
/// needed to complete the stage. Units represent the choice of functional
/// units that can be used to complete the stage. Eg. IntUnit1, IntUnit2.
///
struct InstrStage {
unsigned Cycles; ///< Length of stage in machine cycles
Expand Down Expand Up @@ -84,7 +84,9 @@ struct InstrItineraryData {
if (isEmpty())
return 1;

// Just sum the cycle count for each stage.
// Just sum the cycle count for each stage. The assumption is that all
// inputs are consumed at the start of the first stage and that all
// outputs are produced at the end of the last stage.
unsigned Latency = 0;
for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx);
IS != E; ++IS)
Expand Down
1 change: 1 addition & 0 deletions lib/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_llvm_library(LLVMCodeGen
DwarfEHPrepare.cpp
ELFCodeEmitter.cpp
ELFWriter.cpp
ExactHazardRecognizer.cpp
GCMetadata.cpp
GCMetadataPrinter.cpp
GCStrategy.cpp
Expand Down
149 changes: 149 additions & 0 deletions lib/CodeGen/ExactHazardRecognizer.cpp
Original file line number Diff line number Diff line change
@@ -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 */
61 changes: 61 additions & 0 deletions lib/CodeGen/ExactHazardRecognizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//=- llvm/CodeGen/ExactHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ExactHazardRecognizer class, which
// implements hazard-avoidance heuristics for scheduling, based on the
// scheduling itineraries specified for the target.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H

#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Target/TargetInstrItineraries.h"

namespace llvm {
class ExactHazardRecognizer : public ScheduleHazardRecognizer {
// Itinerary data for the target.
const InstrItineraryData &ItinData;

// Scoreboard to track function unit usage. Scoreboard[0] is a
// mask of the FUs in use in the cycle currently being
// schedule. Scoreboard[1] is a mask for the next cycle. The
// Scoreboard is used as a circular buffer with the current cycle
// indicated by ScoreboardHead.
unsigned *Scoreboard;

// The maximum number of cycles monitored by the Scoreboard. This
// value is determined based on the target itineraries to ensure
// that all hazards can be tracked.
unsigned ScoreboardDepth;

// Indices into the Scoreboard that represent the current cycle.
unsigned ScoreboardHead;

// Return the scoreboard index to use for 'offset' cycles in the
// future. 'offset' of 0 returns ScoreboardHead.
unsigned getFutureIndex(unsigned offset);

// Print the scoreboard.
void dumpScoreboard();

public:
ExactHazardRecognizer(const InstrItineraryData &ItinData);
~ExactHazardRecognizer();

virtual HazardType getHazardType(SUnit *SU);
virtual void Reset();
virtual void EmitInstruction(SUnit *SU);
virtual void AdvanceCycle();
};
}

#endif
Loading

0 comments on commit d94a4e5

Please sign in to comment.