summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2013-06-15 04:49:57 +0000
committerAndrew Trick <atrick@apple.com>2013-06-15 04:49:57 +0000
commitb86a0cdb674549d8493043331cecd9cbf53b80da (patch)
tree8690d4a95ff7cf02b6f840632086b62aa1ed17fc /lib/CodeGen
parentbacb24975d7a8a6ccff0e16057a581b3831c4c7d (diff)
downloadllvm-b86a0cdb674549d8493043331cecd9cbf53b80da.tar.gz
llvm-b86a0cdb674549d8493043331cecd9cbf53b80da.tar.bz2
llvm-b86a0cdb674549d8493043331cecd9cbf53b80da.tar.xz
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/MachineScheduler.cpp29
-rw-r--r--lib/CodeGen/MachineTraceMetrics.cpp10
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.cpp24
-rw-r--r--lib/CodeGen/TargetInstrInfo.cpp28
-rw-r--r--lib/CodeGen/TargetSchedule.cpp58
5 files changed, 47 insertions, 102 deletions
diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp
index 3840473a9a..c87a1be720 100644
--- a/lib/CodeGen/MachineScheduler.cpp
+++ b/lib/CodeGen/MachineScheduler.cpp
@@ -1257,8 +1257,9 @@ public:
unsigned ExpectedCount;
#ifndef NDEBUG
- // Remember the greatest min operand latency.
- unsigned MaxMinLatency;
+ // Remember the greatest operand latency as an upper bound on the number of
+ // times we should retry the pending queue because of a hazard.
+ unsigned MaxObservedLatency;
#endif
void reset() {
@@ -1281,7 +1282,7 @@ public:
IsResourceLimited = false;
ExpectedCount = 0;
#ifndef NDEBUG
- MaxMinLatency = 0;
+ MaxObservedLatency = 0;
#endif
// Reserve a zero-count for invalid CritResIdx.
ResourceCounts.resize(1);
@@ -1466,13 +1467,15 @@ void ConvergingScheduler::releaseTopNode(SUnit *SU) {
for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
I != E; ++I) {
+ if (I->isWeak())
+ continue;
unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle;
- unsigned MinLatency = I->getMinLatency();
+ unsigned Latency = I->getLatency();
#ifndef NDEBUG
- Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
+ Top.MaxObservedLatency = std::max(Latency, Top.MaxObservedLatency);
#endif
- if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
- SU->TopReadyCycle = PredReadyCycle + MinLatency;
+ if (SU->TopReadyCycle < PredReadyCycle + Latency)
+ SU->TopReadyCycle = PredReadyCycle + Latency;
}
Top.releaseNode(SU, SU->TopReadyCycle);
}
@@ -1488,12 +1491,12 @@ void ConvergingScheduler::releaseBottomNode(SUnit *SU) {
if (I->isWeak())
continue;
unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
- unsigned MinLatency = I->getMinLatency();
+ unsigned Latency = I->getLatency();
#ifndef NDEBUG
- Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
+ Bot.MaxObservedLatency = std::max(Latency, Bot.MaxObservedLatency);
#endif
- if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
- SU->BotReadyCycle = SuccReadyCycle + MinLatency;
+ if (SU->BotReadyCycle < SuccReadyCycle + Latency)
+ SU->BotReadyCycle = SuccReadyCycle + Latency;
}
Bot.releaseNode(SU, SU->BotReadyCycle);
}
@@ -1558,7 +1561,7 @@ void ConvergingScheduler::SchedBoundary::setLatencyPolicy(CandPolicy &Policy) {
if (L > RemLatency)
RemLatency = L;
}
- unsigned CriticalPathLimit = Rem->CriticalPath + SchedModel->getILPWindow();
+ unsigned CriticalPathLimit = Rem->CriticalPath;
DEBUG(dbgs() << " " << Available.getName()
<< " ExpectedLatency " << ExpectedLatency
<< " CP Limit " << CriticalPathLimit << '\n');
@@ -1751,7 +1754,7 @@ SUnit *ConvergingScheduler::SchedBoundary::pickOnlyChoice() {
}
}
for (unsigned i = 0; Available.empty(); ++i) {
- assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
+ assert(i <= (HazardRec->getMaxLookAhead() + MaxObservedLatency) &&
"permanent hazard"); (void)i;
bumpCycle();
releasePending();
diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp
index 00f702c846..6aa3f67962 100644
--- a/lib/CodeGen/MachineTraceMetrics.cpp
+++ b/lib/CodeGen/MachineTraceMetrics.cpp
@@ -853,8 +853,7 @@ computeInstrDepths(const MachineBasicBlock *MBB) {
// Add latency if DefMI is a real instruction. Transients get latency 0.
if (!Dep.DefMI->isTransient())
DepCycle += MTM.SchedModel
- .computeOperandLatency(Dep.DefMI, Dep.DefOp, UseMI, Dep.UseOp,
- /* FindMin = */ false);
+ .computeOperandLatency(Dep.DefMI, Dep.DefOp, UseMI, Dep.UseOp);
Cycle = std::max(Cycle, DepCycle);
}
// 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
// live-in list. SchedModel can handle a NULL UseMI.
DepHeight += SchedModel
- .computeOperandLatency(MI, MO.getOperandNo(), I->MI, I->Op,
- /* FindMin = */ false);
+ .computeOperandLatency(MI, MO.getOperandNo(), I->MI, I->Op);
}
Height = std::max(Height, DepHeight);
// This regunit is dead above MI.
@@ -941,7 +939,7 @@ static bool pushDepHeight(const DataDep &Dep,
// Adjust height by Dep.DefMI latency.
if (!Dep.DefMI->isTransient())
UseHeight += SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp,
- UseMI, Dep.UseOp, false);
+ UseMI, Dep.UseOp);
// Update Heights[DefMI] to be the maximum height seen.
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.
if (!Dep.DefMI->isTransient())
DepCycle += TE.MTM.SchedModel
- .computeOperandLatency(Dep.DefMI, Dep.DefOp, PHI, Dep.UseOp, false);
+ .computeOperandLatency(Dep.DefMI, Dep.DefOp, PHI, Dep.UseOp);
return DepCycle;
}
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index e4da6a41ee..aaf5c88a83 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -267,13 +267,10 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
SU->hasPhysRegDefs = true;
Dep = SDep(SU, SDep::Data, *Alias);
RegUse = UseSU->getInstr();
- Dep.setMinLatency(
- SchedModel.computeOperandLatency(SU->getInstr(), OperIdx,
- RegUse, UseOp, /*FindMin=*/true));
}
Dep.setLatency(
- SchedModel.computeOperandLatency(SU->getInstr(), OperIdx,
- RegUse, UseOp, /*FindMin=*/false));
+ SchedModel.computeOperandLatency(SU->getInstr(), OperIdx, RegUse,
+ UseOp));
ST.adjustSchedDependency(SU, UseSU, Dep);
UseSU->addPred(Dep);
@@ -310,10 +307,8 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
DefSU->addPred(SDep(SU, Kind, /*Reg=*/*Alias));
else {
SDep Dep(SU, Kind, /*Reg=*/*Alias);
- unsigned OutLatency =
- SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr());
- Dep.setMinLatency(OutLatency);
- Dep.setLatency(OutLatency);
+ Dep.setLatency(
+ SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()));
DefSU->addPred(Dep);
}
}
@@ -389,10 +384,8 @@ void ScheduleDAGInstrs::addVRegDefDeps(SUnit *SU, unsigned OperIdx) {
SUnit *DefSU = DefI->SU;
if (DefSU != SU && DefSU != &ExitSU) {
SDep Dep(SU, SDep::Output, Reg);
- unsigned OutLatency =
- SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr());
- Dep.setMinLatency(OutLatency);
- Dep.setLatency(OutLatency);
+ Dep.setLatency(
+ SchedModel.computeOutputLatency(MI, OperIdx, DefSU->getInstr()));
DefSU->addPred(Dep);
}
DefI->SU = SU;
@@ -427,10 +420,7 @@ void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
// Adjust the dependence latency using operand def/use information, then
// allow the target to perform its own adjustments.
int DefOp = Def->findRegisterDefOperandIdx(Reg);
- dep.setLatency(
- SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx, false));
- dep.setMinLatency(
- SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx, true));
+ dep.setLatency(SchedModel.computeOperandLatency(Def, DefOp, MI, OperIdx));
const TargetSubtargetInfo &ST = TM.getSubtarget<TargetSubtargetInfo>();
ST.adjustSchedDependency(DefSU, SU, const_cast<SDep &>(dep));
diff --git a/lib/CodeGen/TargetInstrInfo.cpp b/lib/CodeGen/TargetInstrInfo.cpp
index 20eb918793..bb8bd426a9 100644
--- a/lib/CodeGen/TargetInstrInfo.cpp
+++ b/lib/CodeGen/TargetInstrInfo.cpp
@@ -668,27 +668,13 @@ getOperandLatency(const InstrItineraryData *ItinData,
/// lookup, do so. Otherwise return -1.
int TargetInstrInfo::computeDefOperandLatency(
const InstrItineraryData *ItinData,
- const MachineInstr *DefMI, bool FindMin) const {
+ const MachineInstr *DefMI) const {
// Let the target hook getInstrLatency handle missing itineraries.
if (!ItinData)
return getInstrLatency(ItinData, DefMI);
- // 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 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())
+ if(ItinData->isEmpty())
return defaultDefLatency(ItinData->SchedModel, DefMI);
// ...operand lookup required
@@ -709,10 +695,9 @@ int TargetInstrInfo::computeDefOperandLatency(
unsigned TargetInstrInfo::
computeOperandLatency(const InstrItineraryData *ItinData,
const MachineInstr *DefMI, unsigned DefIdx,
- const MachineInstr *UseMI, unsigned UseIdx,
- bool FindMin) const {
+ const MachineInstr *UseMI, unsigned UseIdx) const {
- int DefLatency = computeDefOperandLatency(ItinData, DefMI, FindMin);
+ int DefLatency = computeDefOperandLatency(ItinData, DefMI);
if (DefLatency >= 0)
return DefLatency;
@@ -732,8 +717,7 @@ computeOperandLatency(const InstrItineraryData *ItinData,
unsigned InstrLatency = getInstrLatency(ItinData, DefMI);
// Expected latency is the max of the stage latency and itinerary props.
- if (!FindMin)
- InstrLatency = std::max(InstrLatency,
- defaultDefLatency(ItinData->SchedModel, DefMI));
+ InstrLatency = std::max(InstrLatency,
+ defaultDefLatency(ItinData->SchedModel, DefMI));
return InstrLatency;
}
diff --git a/lib/CodeGen/TargetSchedule.cpp b/lib/CodeGen/TargetSchedule.cpp
index 1bf14dbcef..53cd11c5da 100644
--- a/lib/CodeGen/TargetSchedule.cpp
+++ b/lib/CodeGen/TargetSchedule.cpp
@@ -93,33 +93,10 @@ unsigned TargetSchedModel::getNumMicroOps(const MachineInstr *MI,
// 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
// 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;
}
-/// 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
/// evaluation of predicates that depend on instruction operands or flags.
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.
unsigned TargetSchedModel::computeOperandLatency(
const MachineInstr *DefMI, unsigned DefOperIdx,
- const MachineInstr *UseMI, unsigned UseOperIdx,
- bool FindMin) const {
+ const MachineInstr *UseMI, unsigned UseOperIdx) const {
- int DefLatency = getDefLatency(DefMI, FindMin);
- if (DefLatency >= 0)
- return DefLatency;
+ if (!hasInstrSchedModel() && !hasInstrItineraries())
+ return TII->defaultDefLatency(&SchedModel, DefMI);
if (hasInstrItineraries()) {
int OperLatency = 0;
if (UseMI) {
- OperLatency =
- TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx);
+ OperLatency = TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx,
+ UseMI, UseOperIdx);
}
else {
unsigned DefClass = DefMI->getDesc().getSchedClass();
@@ -205,13 +180,11 @@ unsigned TargetSchedModel::computeOperandLatency(
// hook to allow subtargets to specialize latency. This hook is only
// applicable to the InstrItins model. InstrSchedModel should model all
// special cases without TII hooks.
- if (!FindMin)
- InstrLatency = std::max(InstrLatency,
- TII->defaultDefLatency(&SchedModel, DefMI));
+ InstrLatency = std::max(InstrLatency,
+ TII->defaultDefLatency(&SchedModel, DefMI));
return InstrLatency;
}
- assert(!FindMin && hasInstrSchedModel() &&
- "Expected a SchedModel for this cpu");
+ // hasInstrSchedModel()
const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
if (DefIdx < SCDesc->NumWriteLatencyEntries) {
@@ -219,7 +192,7 @@ unsigned TargetSchedModel::computeOperandLatency(
const MCWriteLatencyEntry *WLEntry =
STI->getWriteLatencyEntry(SCDesc, DefIdx);
unsigned WriteID = WLEntry->WriteResourceID;
- unsigned Latency = convertLatency(WLEntry->Cycles);
+ unsigned Latency = capLatency(WLEntry->Cycles);
if (!UseMI)
return Latency;
@@ -263,7 +236,7 @@ unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
// Lookup the definition's write latency in SubtargetInfo.
const MCWriteLatencyEntry *WLEntry =
STI->getWriteLatencyEntry(SCDesc, DefIdx);
- Latency = std::max(Latency, convertLatency(WLEntry->Cycles));
+ Latency = std::max(Latency, capLatency(WLEntry->Cycles));
}
return Latency;
}
@@ -274,13 +247,10 @@ unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
unsigned TargetSchedModel::
computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
const MachineInstr *DepMI) const {
- // MinLatency == -1 is for in-order processors that always have unit
- // 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)
+ if (SchedModel.MicroOpBufferSize <= 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.
// 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()) {
for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
*PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
- if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->IsBuffered)
+ if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->BufferSize)
return 1;
}
}