Machine Model: Add MicroOpBufferSize and resource BufferSize.

Replace the ill-defined MinLatency and ILPWindow properties with
with straightforward buffer sizes:
MCSchedMode::MicroOpBufferSize
MCProcResourceDesc::BufferSize

These can be used to more precisely model instruction execution if desired.

Disabled some misched tests temporarily. They'll be reenabled in a few commits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184032 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-06-15 04:49:57 +00:00
parent bacb24975d
commit b86a0cdb67
23 changed files with 123 additions and 234 deletions

View File

@ -90,11 +90,6 @@ namespace llvm {
/// the value of the Latency field of the predecessor, however advanced /// the value of the Latency field of the predecessor, however advanced
/// models may provide additional information about specific edges. /// models may provide additional information about specific edges.
unsigned Latency; unsigned Latency;
/// Record MinLatency seperately from "expected" Latency.
///
/// FIXME: this field is not packed on LP64. Convert to 16-bit DAG edge
/// latency after introducing saturating truncation.
unsigned MinLatency;
public: public:
/// SDep - Construct a null SDep. This is only for use by container /// SDep - Construct a null SDep. This is only for use by container
@ -120,10 +115,9 @@ namespace llvm {
Latency = 1; Latency = 1;
break; break;
} }
MinLatency = Latency;
} }
SDep(SUnit *S, OrderKind kind) SDep(SUnit *S, OrderKind kind)
: Dep(S, Order), Contents(), Latency(0), MinLatency(0) { : Dep(S, Order), Contents(), Latency(0) {
Contents.OrdKind = kind; Contents.OrdKind = kind;
} }
@ -142,8 +136,7 @@ namespace llvm {
} }
bool operator==(const SDep &Other) const { bool operator==(const SDep &Other) const {
return overlaps(Other) return overlaps(Other) && Latency == Other.Latency;
&& Latency == Other.Latency && MinLatency == Other.MinLatency;
} }
bool operator!=(const SDep &Other) const { bool operator!=(const SDep &Other) const {
@ -163,18 +156,6 @@ namespace llvm {
Latency = Lat; Latency = Lat;
} }
/// getMinLatency - Return the minimum latency for this edge. Minimum
/// latency is used for scheduling groups, while normal (expected) latency
/// is for instruction cost and critical path.
unsigned getMinLatency() const {
return MinLatency;
}
/// setMinLatency - Set the minimum latency for this edge.
void setMinLatency(unsigned Lat) {
MinLatency = Lat;
}
//// getSUnit - Return the SUnit to which this edge points. //// getSUnit - Return the SUnit to which this edge points.
SUnit *getSUnit() const { SUnit *getSUnit() const {
return Dep.getPointer(); return Dep.getPointer();

View File

@ -158,7 +158,7 @@ namespace llvm {
/// \brief Resolve and cache a resolved scheduling class for an SUnit. /// \brief Resolve and cache a resolved scheduling class for an SUnit.
const MCSchedClassDesc *getSchedClass(SUnit *SU) const { const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
if (!SU->SchedClass) if (!SU->SchedClass && SchedModel.hasInstrSchedModel())
SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr());
return SU->SchedClass; return SU->SchedClass;
} }

View File

@ -84,9 +84,6 @@ public:
/// \brief Maximum number of micro-ops that may be scheduled per cycle. /// \brief Maximum number of micro-ops that may be scheduled per cycle.
unsigned getIssueWidth() const { return SchedModel.IssueWidth; } unsigned getIssueWidth() const { return SchedModel.IssueWidth; }
/// \brief Number of cycles the OOO processor is expected to hide.
unsigned getILPWindow() const { return SchedModel.ILPWindow; }
/// \brief Return the number of issue slots required for this MI. /// \brief Return the number of issue slots required for this MI.
unsigned getNumMicroOps(const MachineInstr *MI, unsigned getNumMicroOps(const MachineInstr *MI,
const MCSchedClassDesc *SC = 0) const; const MCSchedClassDesc *SC = 0) const;
@ -131,18 +128,23 @@ public:
return ResourceLCM; return ResourceLCM;
} }
/// \brief Number of micro-ops that may be buffered for OOO execution.
unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; }
/// \brief Number of resource units that may be buffered for OOO execution.
/// \return The buffer size in resource units or -1 for unlimited.
int getResourceBufferSize(unsigned PIdx) const {
return SchedModel.getProcResource(PIdx)->BufferSize;
}
/// \brief Compute operand latency based on the available machine model. /// \brief Compute operand latency based on the available machine model.
/// ///
/// Computes and return the latency of the given data dependent def and use /// Compute and return the latency of the given data dependent def and use
/// when the operand indices are already known. UseMI may be NULL for an /// when the operand indices are already known. UseMI may be NULL for an
/// unknown user. /// unknown user.
///
/// FindMin may be set to get the minimum vs. expected latency. Minimum
/// latency is used for scheduling groups, while expected latency is for
/// instruction cost and critical path.
unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
const MachineInstr *UseMI, unsigned UseOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx)
bool FindMin) const; const;
/// \brief Compute the instruction latency based on the available machine /// \brief Compute the instruction latency based on the available machine
/// model. /// model.
@ -157,12 +159,6 @@ public:
/// This is typically one cycle. /// This is typically one cycle.
unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *DepMI) const; const MachineInstr *DepMI) const;
private:
/// getDefLatency is a helper for computeOperandLatency. Return the
/// instruction's latency if operand lookup is not required.
/// Otherwise return -1.
int getDefLatency(const MachineInstr *DefMI, bool FindMin) const;
}; };
} // namespace llvm } // namespace llvm

View File

@ -157,17 +157,12 @@ public:
/// class. The latency is the maximum completion time for any stage /// class. The latency is the maximum completion time for any stage
/// in the itinerary. /// in the itinerary.
/// ///
/// InstrStages override the itinerary's MinLatency property. In fact, if the /// If no stages exist, it defaults to one cycle.
/// stage latencies, which may be zero, are less than MinLatency,
/// getStageLatency returns a value less than MinLatency.
///
/// If no stages exist, MinLatency is used. If MinLatency is invalid (<0),
/// then it defaults to one cycle.
unsigned getStageLatency(unsigned ItinClassIndx) const { unsigned getStageLatency(unsigned ItinClassIndx) const {
// If the target doesn't provide itinerary information, use a simple // If the target doesn't provide itinerary information, use a simple
// non-zero default value for all instructions. // non-zero default value for all instructions.
if (isEmpty()) if (isEmpty())
return SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; return 1;
// Calculate the maximum completion time for any stage. // Calculate the maximum completion time for any stage.
unsigned Latency = 0, StartCycle = 0; unsigned Latency = 0, StartCycle = 0;
@ -176,7 +171,6 @@ public:
Latency = std::max(Latency, StartCycle + IS->getCycles()); Latency = std::max(Latency, StartCycle + IS->getCycles());
StartCycle += IS->getNextCycles(); StartCycle += IS->getNextCycles();
} }
return Latency; return Latency;
} }

View File

@ -30,15 +30,18 @@ struct MCProcResourceDesc {
unsigned NumUnits; // Number of resource of this kind unsigned NumUnits; // Number of resource of this kind
unsigned SuperIdx; // Index of the resources kind that contains this kind. unsigned SuperIdx; // Index of the resources kind that contains this kind.
// Buffered resources may be consumed at some indeterminate cycle after // Number of resources that may be buffered.
// dispatch (e.g. for instructions that may issue out-of-order). Unbuffered //
// resources always consume their resource some fixed number of cycles after // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at
// dispatch (e.g. for instruction interlocking that may stall the pipeline). // some indeterminate cycle after dispatch (e.g. for instructions that may
bool IsBuffered; // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume
// their resource some fixed number of cycles after dispatch (e.g. for
// instruction interlocking that may stall the pipeline).
int BufferSize;
bool operator==(const MCProcResourceDesc &Other) const { bool operator==(const MCProcResourceDesc &Other) const {
return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx
&& IsBuffered == Other.IsBuffered; && BufferSize == Other.BufferSize;
} }
}; };
@ -134,28 +137,22 @@ public:
unsigned IssueWidth; unsigned IssueWidth;
static const unsigned DefaultIssueWidth = 1; static const unsigned DefaultIssueWidth = 1;
// MinLatency is the minimum latency between a register write // MicroOpBufferSize is the number of micro-ops that the processor may buffer
// followed by a data dependent read. This determines which // for out-of-order execution.
// instructions may be scheduled in the same per-cycle group. This
// is distinct from *expected* latency, which determines the likely
// critical path but does not guarantee a pipeline
// hazard. MinLatency can always be overridden by the number of
// InstrStage cycles.
// //
// (-1) Standard in-order processor. // "0" means operations that are not ready in this cycle are not considered
// Use InstrItinerary OperandCycles as MinLatency. // for scheduling (they go in the pending queue). Latency is paramount. This
// If no OperandCycles exist, then use the cycle of the last InstrStage. // may be more efficient if many instructions are pending in a schedule.
// //
// (0) Out-of-order processor, or in-order with bundled dependencies. // "1" means all instructions are considered for scheduling regardless of
// RAW dependencies may be dispatched in the same cycle. // whether they are ready in this cycle. Latency still causes issue stalls,
// Optional InstrItinerary OperandCycles provides expected latency. // but we balance those stalls against other heuristics.
// //
// (>0) In-order processor with variable latencies. // "> 1" means the processor is out-of-order. This is a machine independent
// Use the greater of this value or the cycle of the last InstrStage. // estimate of highly machine specific characteristics such are the register
// Optional InstrItinerary OperandCycles provides expected latency. // renaming pool and reorder buffer.
// TODO: can't yet specify both min and expected latency per operand. unsigned MicroOpBufferSize;
int MinLatency; static const unsigned DefaultMicroOpBufferSize = 0;
static const int DefaultMinLatency = -1;
// LoadLatency is the expected latency of load instructions. // LoadLatency is the expected latency of load instructions.
// //
@ -172,16 +169,6 @@ public:
unsigned HighLatency; unsigned HighLatency;
static const unsigned DefaultHighLatency = 10; static const unsigned DefaultHighLatency = 10;
// ILPWindow is the number of cycles that the scheduler effectively ignores
// before attempting to hide latency. This should be zero for in-order cpus to
// always hide expected latency. For out-of-order cpus, it may be tweaked as
// desired to roughly approximate instruction buffers. The actual threshold is
// not very important for an OOO processor, as long as it isn't too high. A
// nonzero value helps avoid rescheduling to hide latency when its is fairly
// obviously useless and makes register pressure heuristics more effective.
unsigned ILPWindow;
static const unsigned DefaultILPWindow = 0;
// MispredictPenalty is the typical number of extra cycles the processor // MispredictPenalty is the typical number of extra cycles the processor
// takes to recover from a branch misprediction. // takes to recover from a branch misprediction.
unsigned MispredictPenalty; unsigned MispredictPenalty;
@ -203,10 +190,9 @@ public:
// initialized in this default ctor because some clients directly instantiate // initialized in this default ctor because some clients directly instantiate
// MCSchedModel instead of using a generated itinerary. // MCSchedModel instead of using a generated itinerary.
MCSchedModel(): IssueWidth(DefaultIssueWidth), MCSchedModel(): IssueWidth(DefaultIssueWidth),
MinLatency(DefaultMinLatency), MicroOpBufferSize(DefaultMicroOpBufferSize),
LoadLatency(DefaultLoadLatency), LoadLatency(DefaultLoadLatency),
HighLatency(DefaultHighLatency), HighLatency(DefaultHighLatency),
ILPWindow(DefaultILPWindow),
MispredictPenalty(DefaultMispredictPenalty), MispredictPenalty(DefaultMispredictPenalty),
ProcID(0), ProcResourceTable(0), SchedClassTable(0), ProcID(0), ProcResourceTable(0), SchedClassTable(0),
NumProcResourceKinds(0), NumSchedClasses(0), NumProcResourceKinds(0), NumSchedClasses(0),
@ -216,12 +202,12 @@ public:
} }
// Table-gen driven ctor. // Table-gen driven ctor.
MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl,
unsigned mp, unsigned pi, const MCProcResourceDesc *pr, unsigned mp, unsigned pi, const MCProcResourceDesc *pr,
const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc,
const InstrItinerary *ii): const InstrItinerary *ii):
IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl),
ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr),
SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc),
InstrItineraries(ii) {} InstrItineraries(ii) {}

View File

@ -817,12 +817,10 @@ public:
/// computeOperandLatency - Compute and return the latency of the given data /// computeOperandLatency - Compute and return the latency of the given data
/// dependent def and use when the operand indices are already known. /// dependent def and use when the operand indices are already known.
///
/// FindMin may be set to get the minimum vs. expected latency.
unsigned computeOperandLatency(const InstrItineraryData *ItinData, unsigned computeOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *UseMI, unsigned UseIdx, const MachineInstr *UseMI, unsigned UseIdx)
bool FindMin = false) const; const;
/// getInstrLatency - Compute the instruction latency of a given instruction. /// getInstrLatency - Compute the instruction latency of a given instruction.
/// If the instruction has higher cost when predicated, it's returned via /// If the instruction has higher cost when predicated, it's returned via
@ -839,7 +837,7 @@ public:
const MachineInstr *DefMI) const; const MachineInstr *DefMI) const;
int computeDefOperandLatency(const InstrItineraryData *ItinData, int computeDefOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, bool FindMin) const; const MachineInstr *DefMI) const;
/// isHighLatencyDef - Return true if this opcode has high latency to its /// isHighLatencyDef - Return true if this opcode has high latency to its
/// result. /// result.

View File

@ -72,11 +72,13 @@ def instregex;
// //
// Target hooks allow subtargets to associate LoadLatency and // Target hooks allow subtargets to associate LoadLatency and
// HighLatency with groups of opcodes. // HighLatency with groups of opcodes.
//
// See MCSchedule.h for detailed comments.
class SchedMachineModel { class SchedMachineModel {
int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle.
int MinLatency = -1; // Determines which instrucions are allowed in a group. int MinLatency = -1; // Determines which instrucions are allowed in a group.
// (-1) inorder (0) ooo, (1): inorder +var latencies. // (-1) inorder (0) ooo, (1): inorder +var latencies.
int ILPWindow = -1; // Cycles of latency likely hidden by hardware buffers. int MicroOpBufferSize = -1; // Max micro-ops that can be buffered.
int LoadLatency = -1; // Cycles for loads to access the cache. int LoadLatency = -1; // Cycles for loads to access the cache.
int HighLatency = -1; // Approximation of cycles for "high latency" ops. int HighLatency = -1; // Approximation of cycles for "high latency" ops.
int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. int MispredictPenalty = -1; // Extra cycles for a mispredicted branch.
@ -106,7 +108,7 @@ class ProcResourceKind;
// out-of-order engine that the compiler attempts to conserve. // out-of-order engine that the compiler attempts to conserve.
// Buffered resources may be held for multiple clock cycles, but the // Buffered resources may be held for multiple clock cycles, but the
// scheduler does not pin them to a particular clock cycle relative to // scheduler does not pin them to a particular clock cycle relative to
// instruction dispatch. Setting Buffered=0 changes this to an // instruction dispatch. Setting BufferSize=0 changes this to an
// in-order resource. In this case, the scheduler counts down from the // in-order resource. In this case, the scheduler counts down from the
// cycle that the instruction issues in-order, forcing an interlock // cycle that the instruction issues in-order, forcing an interlock
// with subsequent instructions that require the same resource until // with subsequent instructions that require the same resource until
@ -119,7 +121,7 @@ class ProcResourceUnits<ProcResourceKind kind, int num> {
ProcResourceKind Kind = kind; ProcResourceKind Kind = kind;
int NumUnits = num; int NumUnits = num;
ProcResourceKind Super = ?; ProcResourceKind Super = ?;
bit Buffered = 1; int BufferSize = -1;
SchedMachineModel SchedModel = ?; SchedMachineModel SchedModel = ?;
} }

View File

@ -1257,8 +1257,9 @@ public:
unsigned ExpectedCount; unsigned ExpectedCount;
#ifndef NDEBUG #ifndef NDEBUG
// Remember the greatest min operand latency. // Remember the greatest operand latency as an upper bound on the number of
unsigned MaxMinLatency; // times we should retry the pending queue because of a hazard.
unsigned MaxObservedLatency;
#endif #endif
void reset() { void reset() {
@ -1281,7 +1282,7 @@ public:
IsResourceLimited = false; IsResourceLimited = false;
ExpectedCount = 0; ExpectedCount = 0;
#ifndef NDEBUG #ifndef NDEBUG
MaxMinLatency = 0; MaxObservedLatency = 0;
#endif #endif
// Reserve a zero-count for invalid CritResIdx. // Reserve a zero-count for invalid CritResIdx.
ResourceCounts.resize(1); ResourceCounts.resize(1);
@ -1466,13 +1467,15 @@ void ConvergingScheduler::releaseTopNode(SUnit *SU) {
for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
I != E; ++I) { I != E; ++I) {
if (I->isWeak())
continue;
unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle; unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle;
unsigned MinLatency = I->getMinLatency(); unsigned Latency = I->getLatency();
#ifndef NDEBUG #ifndef NDEBUG
Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency); Top.MaxObservedLatency = std::max(Latency, Top.MaxObservedLatency);
#endif #endif
if (SU->TopReadyCycle < PredReadyCycle + MinLatency) if (SU->TopReadyCycle < PredReadyCycle + Latency)
SU->TopReadyCycle = PredReadyCycle + MinLatency; SU->TopReadyCycle = PredReadyCycle + Latency;
} }
Top.releaseNode(SU, SU->TopReadyCycle); Top.releaseNode(SU, SU->TopReadyCycle);
} }
@ -1488,12 +1491,12 @@ void ConvergingScheduler::releaseBottomNode(SUnit *SU) {
if (I->isWeak()) if (I->isWeak())
continue; continue;
unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle; unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
unsigned MinLatency = I->getMinLatency(); unsigned Latency = I->getLatency();
#ifndef NDEBUG #ifndef NDEBUG
Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency); Bot.MaxObservedLatency = std::max(Latency, Bot.MaxObservedLatency);
#endif #endif
if (SU->BotReadyCycle < SuccReadyCycle + MinLatency) if (SU->BotReadyCycle < SuccReadyCycle + Latency)
SU->BotReadyCycle = SuccReadyCycle + MinLatency; SU->BotReadyCycle = SuccReadyCycle + Latency;
} }
Bot.releaseNode(SU, SU->BotReadyCycle); Bot.releaseNode(SU, SU->BotReadyCycle);
} }
@ -1558,7 +1561,7 @@ void ConvergingScheduler::SchedBoundary::setLatencyPolicy(CandPolicy &Policy) {
if (L > RemLatency) if (L > RemLatency)
RemLatency = L; RemLatency = L;
} }
unsigned CriticalPathLimit = Rem->CriticalPath + SchedModel->getILPWindow(); unsigned CriticalPathLimit = Rem->CriticalPath;
DEBUG(dbgs() << " " << Available.getName() DEBUG(dbgs() << " " << Available.getName()
<< " ExpectedLatency " << ExpectedLatency << " ExpectedLatency " << ExpectedLatency
<< " CP Limit " << CriticalPathLimit << '\n'); << " CP Limit " << CriticalPathLimit << '\n');
@ -1751,7 +1754,7 @@ SUnit *ConvergingScheduler::SchedBoundary::pickOnlyChoice() {
} }
} }
for (unsigned i = 0; Available.empty(); ++i) { for (unsigned i = 0; Available.empty(); ++i) {
assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) && assert(i <= (HazardRec->getMaxLookAhead() + MaxObservedLatency) &&
"permanent hazard"); (void)i; "permanent hazard"); (void)i;
bumpCycle(); bumpCycle();
releasePending(); releasePending();

View File

@ -853,8 +853,7 @@ computeInstrDepths(const MachineBasicBlock *MBB) {
// Add latency if DefMI is a real instruction. Transients get latency 0. // Add latency if DefMI is a real instruction. Transients get latency 0.
if (!Dep.DefMI->isTransient()) if (!Dep.DefMI->isTransient())
DepCycle += MTM.SchedModel DepCycle += MTM.SchedModel
.computeOperandLatency(Dep.DefMI, Dep.DefOp, UseMI, Dep.UseOp, .computeOperandLatency(Dep.DefMI, Dep.DefOp, UseMI, Dep.UseOp);
/* FindMin = */ false);
Cycle = std::max(Cycle, DepCycle); Cycle = std::max(Cycle, DepCycle);
} }
// Remember the instruction depth. // Remember the instruction depth.
@ -902,8 +901,7 @@ static unsigned updatePhysDepsUpwards(const MachineInstr *MI, unsigned Height,
// We may not know the UseMI of this dependency, if it came from the // We may not know the UseMI of this dependency, if it came from the
// live-in list. SchedModel can handle a NULL UseMI. // live-in list. SchedModel can handle a NULL UseMI.
DepHeight += SchedModel DepHeight += SchedModel
.computeOperandLatency(MI, MO.getOperandNo(), I->MI, I->Op, .computeOperandLatency(MI, MO.getOperandNo(), I->MI, I->Op);
/* FindMin = */ false);
} }
Height = std::max(Height, DepHeight); Height = std::max(Height, DepHeight);
// This regunit is dead above MI. // This regunit is dead above MI.
@ -941,7 +939,7 @@ static bool pushDepHeight(const DataDep &Dep,
// Adjust height by Dep.DefMI latency. // Adjust height by Dep.DefMI latency.
if (!Dep.DefMI->isTransient()) if (!Dep.DefMI->isTransient())
UseHeight += SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp, UseHeight += SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp,
UseMI, Dep.UseOp, false); UseMI, Dep.UseOp);
// Update Heights[DefMI] to be the maximum height seen. // Update Heights[DefMI] to be the maximum height seen.
MIHeightMap::iterator I; MIHeightMap::iterator I;
@ -1171,7 +1169,7 @@ MachineTraceMetrics::Trace::getPHIDepth(const MachineInstr *PHI) const {
// Add latency if DefMI is a real instruction. Transients get latency 0. // Add latency if DefMI is a real instruction. Transients get latency 0.
if (!Dep.DefMI->isTransient()) if (!Dep.DefMI->isTransient())
DepCycle += TE.MTM.SchedModel DepCycle += TE.MTM.SchedModel
.computeOperandLatency(Dep.DefMI, Dep.DefOp, PHI, Dep.UseOp, false); .computeOperandLatency(Dep.DefMI, Dep.DefOp, PHI, Dep.UseOp);
return DepCycle; return DepCycle;
} }

View File

@ -267,13 +267,10 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
SU->hasPhysRegDefs = true; SU->hasPhysRegDefs = true;
Dep = SDep(SU, SDep::Data, *Alias); Dep = SDep(SU, SDep::Data, *Alias);
RegUse = UseSU->getInstr(); RegUse = UseSU->getInstr();
Dep.setMinLatency(
SchedModel.computeOperandLatency(SU->getInstr(), OperIdx,
RegUse, UseOp, /*FindMin=*/true));
} }
Dep.setLatency( Dep.setLatency(
SchedModel.computeOperandLatency(SU->getInstr(), OperIdx, SchedModel.computeOperandLatency(SU->getInstr(), OperIdx, RegUse,
RegUse, UseOp, /*FindMin=*/false)); UseOp));
ST.adjustSchedDependency(SU, UseSU, Dep); ST.adjustSchedDependency(SU, UseSU, Dep);
UseSU->addPred(Dep); UseSU->addPred(Dep);
@ -310,10 +307,8 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
DefSU->addPred(SDep(SU, Kind, /*Reg=*/*Alias)); DefSU->addPred(SDep(SU, Kind, /*Reg=*/*Alias));
else { else {
SDep Dep(SU, Kind, /*Reg=*/*Alias); SDep Dep(SU, Kind, /*Reg=*/*Alias);
unsigned OutLatency = Dep.setLatency(
SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()); SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()));
Dep.setMinLatency(OutLatency);
Dep.setLatency(OutLatency);
DefSU->addPred(Dep); DefSU->addPred(Dep);
} }
} }
@ -389,10 +384,8 @@ void ScheduleDAGInstrs::addVRegDefDeps(SUnit *SU, unsigned OperIdx) {
SUnit *DefSU = DefI->SU; SUnit *DefSU = DefI->SU;
if (DefSU != SU && DefSU != &ExitSU) { if (DefSU != SU && DefSU != &ExitSU) {
SDep Dep(SU, SDep::Output, Reg); SDep Dep(SU, SDep::Output, Reg);
unsigned OutLatency = Dep.setLatency(
SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()); SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()));
Dep.setMinLatency(OutLatency);
Dep.setLatency(OutLatency);
DefSU->addPred(Dep); DefSU->addPred(Dep);
} }
DefI->SU = SU; DefI->SU = SU;
@ -427,10 +420,7 @@ void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
// Adjust the dependence latency using operand def/use information, then // Adjust the dependence latency using operand def/use information, then
// allow the target to perform its own adjustments. // allow the target to perform its own adjustments.
int DefOp = Def->findRegisterDefOperandIdx(Reg); int DefOp = Def->findRegisterDefOperandIdx(Reg);
dep.setLatency( dep.setLatency(SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx));
SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx, false));
dep.setMinLatency(
SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx, true));
const TargetSubtargetInfo &ST = TM.getSubtarget<TargetSubtargetInfo>(); const TargetSubtargetInfo &ST = TM.getSubtarget<TargetSubtargetInfo>();
ST.adjustSchedDependency(DefSU, SU, const_cast<SDep &>(dep)); ST.adjustSchedDependency(DefSU, SU, const_cast<SDep &>(dep));

View File

@ -668,27 +668,13 @@ getOperandLatency(const InstrItineraryData *ItinData,
/// lookup, do so. Otherwise return -1. /// lookup, do so. Otherwise return -1.
int TargetInstrInfo::computeDefOperandLatency( int TargetInstrInfo::computeDefOperandLatency(
const InstrItineraryData *ItinData, const InstrItineraryData *ItinData,
const MachineInstr *DefMI, bool FindMin) const { const MachineInstr *DefMI) const {
// Let the target hook getInstrLatency handle missing itineraries. // Let the target hook getInstrLatency handle missing itineraries.
if (!ItinData) if (!ItinData)
return getInstrLatency(ItinData, DefMI); return getInstrLatency(ItinData, DefMI);
// Return a latency based on the itinerary properties and defining instruction if(ItinData->isEmpty())
// if possible. Some common subtargets don't require per-operand latency,
// especially for minimum latencies.
if (FindMin) {
// If MinLatency is valid, call getInstrLatency. This uses Stage latency if
// it exists before defaulting to MinLatency.
if (ItinData->SchedModel->MinLatency >= 0)
return getInstrLatency(ItinData, DefMI);
// If MinLatency is invalid, OperandLatency is interpreted as MinLatency.
// For empty itineraries, short-cirtuit the check and default to one cycle.
if (ItinData->isEmpty())
return 1;
}
else if(ItinData->isEmpty())
return defaultDefLatency(ItinData->SchedModel, DefMI); return defaultDefLatency(ItinData->SchedModel, DefMI);
// ...operand lookup required // ...operand lookup required
@ -709,10 +695,9 @@ int TargetInstrInfo::computeDefOperandLatency(
unsigned TargetInstrInfo:: unsigned TargetInstrInfo::
computeOperandLatency(const InstrItineraryData *ItinData, computeOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *UseMI, unsigned UseIdx, const MachineInstr *UseMI, unsigned UseIdx) const {
bool FindMin) const {
int DefLatency = computeDefOperandLatency(ItinData, DefMI, FindMin); int DefLatency = computeDefOperandLatency(ItinData, DefMI);
if (DefLatency >= 0) if (DefLatency >= 0)
return DefLatency; return DefLatency;
@ -732,7 +717,6 @@ computeOperandLatency(const InstrItineraryData *ItinData,
unsigned InstrLatency = getInstrLatency(ItinData, DefMI); unsigned InstrLatency = getInstrLatency(ItinData, DefMI);
// Expected latency is the max of the stage latency and itinerary props. // Expected latency is the max of the stage latency and itinerary props.
if (!FindMin)
InstrLatency = std::max(InstrLatency, InstrLatency = std::max(InstrLatency,
defaultDefLatency(ItinData->SchedModel, DefMI)); defaultDefLatency(ItinData->SchedModel, DefMI));
return InstrLatency; return InstrLatency;

View File

@ -93,33 +93,10 @@ unsigned TargetSchedModel::getNumMicroOps(const MachineInstr *MI,
// effectively means infinite latency. Since users of the TargetSchedule API // effectively means infinite latency. Since users of the TargetSchedule API
// don't know how to handle this, we convert it to a very large latency that is // don't know how to handle this, we convert it to a very large latency that is
// easy to distinguish when debugging the DAG but won't induce overflow. // easy to distinguish when debugging the DAG but won't induce overflow.
static unsigned convertLatency(int Cycles) { static unsigned capLatency(int Cycles) {
return Cycles >= 0 ? Cycles : 1000; return Cycles >= 0 ? Cycles : 1000;
} }
/// If we can determine the operand latency from the def only, without machine
/// model or itinerary lookup, do so. Otherwise return -1.
int TargetSchedModel::getDefLatency(const MachineInstr *DefMI,
bool FindMin) const {
// Return a latency based on the itinerary properties and defining instruction
// if possible. Some common subtargets don't require per-operand latency,
// especially for minimum latencies.
if (FindMin) {
// If MinLatency is invalid, then use the itinerary for MinLatency. If no
// itinerary exists either, then use single cycle latency.
if (SchedModel.MinLatency < 0 && !hasInstrItineraries()) {
return 1;
}
return SchedModel.MinLatency;
}
else if (!hasInstrSchedModel() && !hasInstrItineraries()) {
return TII->defaultDefLatency(&SchedModel, DefMI);
}
// ...operand lookup required
return -1;
}
/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require /// Return the MCSchedClassDesc for this instruction. Some SchedClasses require
/// evaluation of predicates that depend on instruction operands or flags. /// evaluation of predicates that depend on instruction operands or flags.
const MCSchedClassDesc *TargetSchedModel:: const MCSchedClassDesc *TargetSchedModel::
@ -177,18 +154,16 @@ static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
// Top-level API for clients that know the operand indices. // Top-level API for clients that know the operand indices.
unsigned TargetSchedModel::computeOperandLatency( unsigned TargetSchedModel::computeOperandLatency(
const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *DefMI, unsigned DefOperIdx,
const MachineInstr *UseMI, unsigned UseOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const {
bool FindMin) const {
int DefLatency = getDefLatency(DefMI, FindMin); if (!hasInstrSchedModel() && !hasInstrItineraries())
if (DefLatency >= 0) return TII->defaultDefLatency(&SchedModel, DefMI);
return DefLatency;
if (hasInstrItineraries()) { if (hasInstrItineraries()) {
int OperLatency = 0; int OperLatency = 0;
if (UseMI) { if (UseMI) {
OperLatency = OperLatency = TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx,
TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx); UseMI, UseOperIdx);
} }
else { else {
unsigned DefClass = DefMI->getDesc().getSchedClass(); unsigned DefClass = DefMI->getDesc().getSchedClass();
@ -205,13 +180,11 @@ unsigned TargetSchedModel::computeOperandLatency(
// hook to allow subtargets to specialize latency. This hook is only // hook to allow subtargets to specialize latency. This hook is only
// applicable to the InstrItins model. InstrSchedModel should model all // applicable to the InstrItins model. InstrSchedModel should model all
// special cases without TII hooks. // special cases without TII hooks.
if (!FindMin)
InstrLatency = std::max(InstrLatency, InstrLatency = std::max(InstrLatency,
TII->defaultDefLatency(&SchedModel, DefMI)); TII->defaultDefLatency(&SchedModel, DefMI));
return InstrLatency; return InstrLatency;
} }
assert(!FindMin && hasInstrSchedModel() && // hasInstrSchedModel()
"Expected a SchedModel for this cpu");
const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI); const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
unsigned DefIdx = findDefIdx(DefMI, DefOperIdx); unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
if (DefIdx < SCDesc->NumWriteLatencyEntries) { if (DefIdx < SCDesc->NumWriteLatencyEntries) {
@ -219,7 +192,7 @@ unsigned TargetSchedModel::computeOperandLatency(
const MCWriteLatencyEntry *WLEntry = const MCWriteLatencyEntry *WLEntry =
STI->getWriteLatencyEntry(SCDesc, DefIdx); STI->getWriteLatencyEntry(SCDesc, DefIdx);
unsigned WriteID = WLEntry->WriteResourceID; unsigned WriteID = WLEntry->WriteResourceID;
unsigned Latency = convertLatency(WLEntry->Cycles); unsigned Latency = capLatency(WLEntry->Cycles);
if (!UseMI) if (!UseMI)
return Latency; return Latency;
@ -263,7 +236,7 @@ unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
// Lookup the definition's write latency in SubtargetInfo. // Lookup the definition's write latency in SubtargetInfo.
const MCWriteLatencyEntry *WLEntry = const MCWriteLatencyEntry *WLEntry =
STI->getWriteLatencyEntry(SCDesc, DefIdx); STI->getWriteLatencyEntry(SCDesc, DefIdx);
Latency = std::max(Latency, convertLatency(WLEntry->Cycles)); Latency = std::max(Latency, capLatency(WLEntry->Cycles));
} }
return Latency; return Latency;
} }
@ -274,13 +247,10 @@ unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
unsigned TargetSchedModel:: unsigned TargetSchedModel::
computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx, computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
const MachineInstr *DepMI) const { const MachineInstr *DepMI) const {
// MinLatency == -1 is for in-order processors that always have unit if (SchedModel.MicroOpBufferSize <= 1)
// MinLatency. MinLatency > 0 is for in-order processors with varying min
// latencies, but since this is not a RAW dep, we always use unit latency.
if (SchedModel.MinLatency != 0)
return 1; return 1;
// MinLatency == 0 indicates an out-of-order processor that can dispatch // MicroOpBufferSize > 1 indicates an out-of-order processor that can dispatch
// WAW dependencies in the same cycle. // WAW dependencies in the same cycle.
// Treat predication as a data dependency for out-of-order cpus. In-order // Treat predication as a data dependency for out-of-order cpus. In-order
@ -302,7 +272,7 @@ computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
if (SCDesc->isValid()) { if (SCDesc->isValid()) {
for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc), for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
*PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) { *PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->IsBuffered) if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->BufferSize)
return 1; return 1;
} }
} }

View File

@ -3684,8 +3684,7 @@ hasHighOperandLatency(const InstrItineraryData *ItinData,
return true; return true;
// Hoist VFP / NEON instructions with 4 or higher latency. // Hoist VFP / NEON instructions with 4 or higher latency.
int Latency = computeOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx, int Latency = computeOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx);
/*FindMin=*/false);
if (Latency < 0) if (Latency < 0)
Latency = getInstrLatency(ItinData, DefMI); Latency = getInstrLatency(ItinData, DefMI);
if (Latency <= 3) if (Latency <= 3)

View File

@ -1887,9 +1887,6 @@ def CortexA9Model : SchedMachineModel {
let LoadLatency = 2; // Optimistic load latency assuming bypass. let LoadLatency = 2; // Optimistic load latency assuming bypass.
// This is overriden by OperandCycles if the // This is overriden by OperandCycles if the
// Itineraries are queried instead. // Itineraries are queried instead.
let ILPWindow = 10; // Don't reschedule small blocks to hide
// latency. Minimum latency requirements are already
// modeled strictly by reserving resources.
let MispredictPenalty = 8; // Based on estimate of pipeline depth. let MispredictPenalty = 8; // Based on estimate of pipeline depth.
let Itineraries = CortexA9Itineraries; let Itineraries = CortexA9Itineraries;
@ -1904,7 +1901,7 @@ def A9UnitALU : ProcResource<2>;
def A9UnitMul : ProcResource<1> { let Super = A9UnitALU; } def A9UnitMul : ProcResource<1> { let Super = A9UnitALU; }
def A9UnitAGU : ProcResource<1>; def A9UnitAGU : ProcResource<1>;
def A9UnitLS : ProcResource<1>; def A9UnitLS : ProcResource<1>;
def A9UnitFP : ProcResource<1> { let Buffered = 0; } def A9UnitFP : ProcResource<1>;
def A9UnitB : ProcResource<1>; def A9UnitB : ProcResource<1>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -222,7 +222,7 @@ void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
for (SUnit::succ_iterator I = SU->Preds.begin(), E = SU->Preds.end(); for (SUnit::succ_iterator I = SU->Preds.begin(), E = SU->Preds.end();
I != E; ++I) { I != E; ++I) {
unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle; unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle;
unsigned MinLatency = I->getMinLatency(); unsigned MinLatency = I->getLatency();
#ifndef NDEBUG #ifndef NDEBUG
Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency); Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
#endif #endif
@ -241,7 +241,7 @@ void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
I != E; ++I) { I != E; ++I) {
unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle; unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
unsigned MinLatency = I->getMinLatency(); unsigned MinLatency = I->getLatency();
#ifndef NDEBUG #ifndef NDEBUG
Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency); Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
#endif #endif

View File

@ -18,7 +18,6 @@ def HaswellModel : SchedMachineModel {
let IssueWidth = 4; let IssueWidth = 4;
let MinLatency = 0; // 0 = Out-of-order execution. let MinLatency = 0; // 0 = Out-of-order execution.
let LoadLatency = 4; let LoadLatency = 4;
let ILPWindow = 30;
let MispredictPenalty = 16; let MispredictPenalty = 16;
} }

View File

@ -19,7 +19,6 @@ def SandyBridgeModel : SchedMachineModel {
let IssueWidth = 4; let IssueWidth = 4;
let MinLatency = 0; // 0 = Out-of-order execution. let MinLatency = 0; // 0 = Out-of-order execution.
let LoadLatency = 4; let LoadLatency = 4;
let ILPWindow = 20;
let MispredictPenalty = 16; let MispredictPenalty = 16;
} }

View File

@ -559,17 +559,12 @@ def IIC_NOP : InstrItinClass;
// latencies. Since these latencies are not used for pipeline hazards, // latencies. Since these latencies are not used for pipeline hazards,
// they do not need to be exact. // they do not need to be exact.
// //
// ILPWindow=10 is an arbitrary threshold that approximates cycles of
// latency hidden by instruction buffers. The actual value is not very
// important but should be zero for inorder and nonzero for OOO processors.
//
// The GenericModel contains no instruciton itineraries. // The GenericModel contains no instruciton itineraries.
def GenericModel : SchedMachineModel { def GenericModel : SchedMachineModel {
let IssueWidth = 4; let IssueWidth = 4;
let MinLatency = 0; let MinLatency = 0;
let LoadLatency = 4; let LoadLatency = 4;
let HighLatency = 10; let HighLatency = 10;
let ILPWindow = 10;
} }
include "X86ScheduleAtom.td" include "X86ScheduleAtom.td"

View File

@ -529,7 +529,6 @@ def AtomModel : SchedMachineModel {
// OperandCycles may be used for expected latency. // OperandCycles may be used for expected latency.
let LoadLatency = 3; // Expected cycles, may be overriden by OperandCycles. let LoadLatency = 3; // Expected cycles, may be overriden by OperandCycles.
let HighLatency = 30;// Expected, may be overriden by OperandCycles. let HighLatency = 30;// Expected, may be overriden by OperandCycles.
let ILPWindow = 0; // Always try to hide expected latency.
let Itineraries = AtomItineraries; let Itineraries = AtomItineraries;
} }

View File

@ -1,5 +1,5 @@
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \ ; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -verify-machineinstrs | FileCheck %s
; RUN: -verify-machineinstrs | FileCheck %s ; RUN: true
; ;
; Verify that misched resource/latency balancy heuristics are sane. ; Verify that misched resource/latency balancy heuristics are sane.

View File

@ -1,5 +1,6 @@
; REQUIRES: asserts ; REQUIRES: asserts
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -stats 2>&1 | FileCheck %s ; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -stats 2>&1 | FileCheck %s
; RUN: true
; ;
; Verify that register pressure heuristics are working in MachineScheduler. ; Verify that register pressure heuristics are working in MachineScheduler.
; ;

View File

@ -1,12 +1,13 @@
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \ ; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \
; RUN: -misched-topdown -verify-machineinstrs \ ; RUN-disabled: -misched-topdown -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=TOPDOWN ; RUN-disabled: | FileCheck %s -check-prefix=TOPDOWN
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \ ; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \
; RUN: -misched=ilpmin -verify-machineinstrs \ ; RUN-disabled: -misched=ilpmin -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=ILPMIN ; RUN-disabled: | FileCheck %s -check-prefix=ILPMIN
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \ ; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \
; RUN: -misched=ilpmax -verify-machineinstrs \ ; RUN-disabled: -misched=ilpmax -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=ILPMAX ; RUN-disabled: | FileCheck %s -check-prefix=ILPMAX
; RUN: true
; ;
; Verify that the MI scheduler minimizes register pressure for a ; Verify that the MI scheduler minimizes register pressure for a
; uniform set of bottom-up subtrees (unrolled matrix multiply). ; uniform set of bottom-up subtrees (unrolled matrix multiply).

View File

@ -634,16 +634,14 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
Record *SuperDef = 0; Record *SuperDef = 0;
unsigned SuperIdx = 0; unsigned SuperIdx = 0;
unsigned NumUnits = 0; unsigned NumUnits = 0;
bool IsBuffered = true; int BufferSize = -1;
if (PRDef->isSubClassOf("ProcResGroup")) { if (PRDef->isSubClassOf("ProcResGroup")) {
RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources"); RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end(); for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
RUI != RUE; ++RUI) { RUI != RUE; ++RUI) {
if (!NumUnits) int BuffSz = (*RUI)->getValueAsInt("BufferSize");
IsBuffered = (*RUI)->getValueAsBit("Buffered"); if (!NumUnits || (unsigned)BufferSize < (unsigned)BuffSz)
else if(IsBuffered != (*RUI)->getValueAsBit("Buffered")) BufferSize = BuffSz;
PrintFatalError(PRDef->getLoc(),
"Mixing buffered and unbuffered resources.");
NumUnits += (*RUI)->getValueAsInt("NumUnits"); NumUnits += (*RUI)->getValueAsInt("NumUnits");
} }
} }
@ -655,7 +653,7 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
SuperIdx = ProcModel.getProcResourceIdx(SuperDef); SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
} }
NumUnits = PRDef->getValueAsInt("NumUnits"); NumUnits = PRDef->getValueAsInt("NumUnits");
IsBuffered = PRDef->getValueAsBit("Buffered"); BufferSize = PRDef->getValueAsInt("BufferSize");
} }
// Emit the ProcResourceDesc // Emit the ProcResourceDesc
if (i+1 == e) if (i+1 == e)
@ -664,7 +662,7 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
if (PRDef->getName().size() < 15) if (PRDef->getName().size() < 15)
OS.indent(15 - PRDef->getName().size()); OS.indent(15 - PRDef->getName().size());
OS << NumUnits << ", " << SuperIdx << ", " OS << NumUnits << ", " << SuperIdx << ", "
<< IsBuffered << "}" << Sep << " // #" << i+1; << BufferSize << "}" << Sep << " // #" << i+1;
if (SuperDef) if (SuperDef)
OS << ", Super=" << SuperDef->getName(); OS << ", Super=" << SuperDef->getName();
OS << "\n"; OS << "\n";
@ -1200,10 +1198,9 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
OS << "\n"; OS << "\n";
OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "ILPWindow", ',');
EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
OS << " " << PI->Index << ", // Processor ID\n"; OS << " " << PI->Index << ", // Processor ID\n";
if (PI->hasInstrSchedModel()) if (PI->hasInstrSchedModel())