mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +00:00
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:
parent
bacb24975d
commit
b86a0cdb67
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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 = ?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
;
|
;
|
||||||
|
@ -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).
|
||||||
|
@ -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())
|
||||||
|
Loading…
Reference in New Issue
Block a user