Skip to content

Commit

Permalink
Enhance the InstrStage object to enable the specification of an Itine…
Browse files Browse the repository at this point in the history
…rary with overlapping stages. The default is to maintain the current behavior that the "next" stage immediately follows the previous one.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78827 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
David Goodwin committed Aug 12, 2009
1 parent 4e97a0f commit 1a8f36e
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 118 deletions.
70 changes: 57 additions & 13 deletions include/llvm/Target/TargetInstrItineraries.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,65 @@
//===----------------------------------------------------------------------===//
//
// This file describes the structures used for instruction itineraries and
// states. This is used by schedulers to determine instruction states and
// stages. This is used by schedulers to determine instruction stages and
// latencies.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H
#define LLVM_TARGET_TARGETINSTRITINERARIES_H

#include <algorithm>

namespace llvm {

//===----------------------------------------------------------------------===//
/// Instruction stage - These values represent a step in the execution of an
/// 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.
/// Instruction stage - These values represent a non-pipelined step in
/// the execution of an instruction. Cycles 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. NextCycles indicates how many
/// cycles should elapse from the start of this stage to the start of
/// the next stage in the itinerary. A value of -1 indicates that the
/// next stage should start immediately after the current one.
/// For example:
///
/// { 1, x, -1 }
/// indicates that the stage occupies FU x for 1 cycle and that
/// the next stage starts immediately after this one.
///
/// { 2, x|y, 1 }
/// indicates that the stage occupies either FU x or FU y for 2
/// consecuative cycles and that the next stage starts one cycle
/// after this stage starts. That is, the stage requirements
/// overlap in time.
///
/// { 1, x, 0 }
/// indicates that the stage occupies FU x for 1 cycle and that
/// the next stage starts in this same cycle. This can be used to
/// indicate that the instruction requires multiple stages at the
/// same time.
///
struct InstrStage {
unsigned Cycles; ///< Length of stage in machine cycles
unsigned Units; ///< Choice of functional units
unsigned Cycles_; ///< Length of stage in machine cycles
unsigned Units_; ///< Choice of functional units
int NextCycles_; ///< Number of machine cycles to next stage

/// getCycles - returns the number of cycles the stage is occupied
unsigned getCycles() const {
return Cycles_;
}

/// getUnits - returns the choice of FUs
unsigned getUnits() const {
return Units_;
}

/// getNextCycles - returns the number of cycles from the start of
/// this stage to the start of the next stage in the itinerary
unsigned getNextCycles() const {
return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_;
}
};


Expand Down Expand Up @@ -84,13 +124,17 @@ struct InstrItineraryData {
if (isEmpty())
return 1;

// 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;
// Caclulate the maximum completion time for any 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
// latest completing last stage.
unsigned Latency = 0, StartCycle = 0;
for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx);
IS != E; ++IS)
Latency += IS->Cycles;
IS != E; ++IS) {
Latency = std::max(Latency, StartCycle + IS->getCycles());
StartCycle += IS->getNextCycles();
}

return Latency;
}
};
Expand Down
19 changes: 14 additions & 5 deletions include/llvm/Target/TargetSchedule.td
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,23 @@
class FuncUnit;

//===----------------------------------------------------------------------===//
// 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 stage - These values represent a non-pipelined step in
// the execution of an instruction. Cycles 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. NextCycles indicates how many
// cycles should elapse from the start of this stage to the start of
// the next stage in the itinerary. For example:
//
class InstrStage<int cycles, list<FuncUnit> units> {
// A stage is specified in one of two ways:
//
// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles
// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit
//
class InstrStage<int cycles, list<FuncUnit> units, int timeinc = -1> {
int Cycles = cycles; // length of stage in machine cycles
list<FuncUnit> Units = units; // choice of functional units
int TimeInc = timeinc; // cycles till start of next stage
}

//===----------------------------------------------------------------------===//
Expand Down
54 changes: 25 additions & 29 deletions lib/CodeGen/ExactHazardRecognizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData
// 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))
if ((IS->getCycles() == 0) && (IS->getUnits() == 0))
break;

unsigned ItinDepth = 0;
for (; IS != E; ++IS)
ItinDepth += std::max(1U, IS->Cycles);
ItinDepth += IS->getCycles();

ScoreboardDepth = std::max(ScoreboardDepth, ItinDepth);
}
Expand Down Expand Up @@ -89,27 +89,25 @@ ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU
unsigned idx = SU->getInstr()->getDesc().getSchedClass();
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
IS != E; ++IS) {
// If the stages cycles are 0, then we must have the FU free in
// the current cycle, but we don't advance the cycle time .
unsigned StageCycles = std::max(1U, IS->Cycles);

// We must find one of the stage's units free for every cycle the
// stage is occupied.
for (unsigned int i = 0; i < StageCycles; ++i) {
assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!");

unsigned index = getFutureIndex(cycle);
unsigned freeUnits = IS->Units & ~Scoreboard[index];
// stage is occupied. FIXME it would be more accurate to find the
// same unit free in all the cycles.
for (unsigned int i = 0; i < IS->getCycles(); ++i) {
assert(((cycle + i) < ScoreboardDepth) &&
"Scoreboard depth exceeded!");

unsigned index = getFutureIndex(cycle + i);
unsigned freeUnits = IS->getUnits() & ~Scoreboard[index];
if (!freeUnits) {
DEBUG(errs() << "*** Hazard in cycle " << cycle << ", ");
DEBUG(errs() << "*** Hazard in cycle " << (cycle + i) << ", ");
DEBUG(errs() << "SU(" << SU->NodeNum << "): ");
DEBUG(SU->getInstr()->dump());
return Hazard;
}

if (IS->Cycles > 0)
++cycle;
}

// Advance the cycle to the next stage.
cycle += IS->getNextCycles();
}

return NoHazard;
Expand All @@ -123,17 +121,15 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
unsigned idx = SU->getInstr()->getDesc().getSchedClass();
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
IS != E; ++IS) {
// If the stages cycles are 0, then we must reserve the FU in the
// current cycle, but we don't advance the cycle time .
unsigned StageCycles = std::max(1U, IS->Cycles);

// We must reserve one of the stage's units for every cycle the
// stage is occupied.
for (unsigned int i = 0; i < StageCycles; ++i) {
assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!");

unsigned index = getFutureIndex(cycle);
unsigned freeUnits = IS->Units & ~Scoreboard[index];
// stage is occupied. FIXME it would be more accurate to reserve
// the same unit free in all the cycles.
for (unsigned int i = 0; i < IS->getCycles(); ++i) {
assert(((cycle + i) < ScoreboardDepth) &&
"Scoreboard depth exceeded!");

unsigned index = getFutureIndex(cycle + i);
unsigned freeUnits = IS->getUnits() & ~Scoreboard[index];

// reduce to a single unit
unsigned freeUnit = 0;
Expand All @@ -144,10 +140,10 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {

assert(freeUnit && "No function unit available!");
Scoreboard[index] |= freeUnit;

if (IS->Cycles > 0)
++cycle;
}

// Advance the cycle to the next stage.
cycle += IS->getNextCycles();
}

DEBUG(dumpScoreboard());
Expand Down
Loading

0 comments on commit 1a8f36e

Please sign in to comment.