Use the schedule itinerary operand use/def cycle information to adjust dependence edge latency for post-RA scheduling.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79425 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Goodwin
2009-08-19 16:08:58 +00:00
parent 774350a606
commit dc4bdcdef1
6 changed files with 107 additions and 19 deletions

View File

@@ -495,6 +495,12 @@ namespace llvm {
/// ///
virtual void ComputeLatency(SUnit *SU) = 0; virtual void ComputeLatency(SUnit *SU) = 0;
/// ComputeOperandLatency - Override dependence edge latency using
/// operand use/def information
///
virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use,
SDep& dep) const { };
/// Schedule - Order nodes according to selected style, filling /// Schedule - Order nodes according to selected style, filling
/// in the Sequence member. /// in the Sequence member.
/// ///

View File

@@ -118,20 +118,17 @@ struct InstrItineraryData {
return Stages + StageIdx; return Stages + StageIdx;
} }
/// getLatency - Return the scheduling latency of the given class. A /// getStageLatency - Return the total stage latency of the given
/// simple latency value for an instruction is an over-simplification /// class. The latency is the maximum completion time for any stage
/// for some architectures, but it's a reasonable first approximation. /// in the itinerary.
/// ///
unsigned getLatency(unsigned ItinClassIndx) const { unsigned getStageLatency(unsigned ItinClassIndx) const {
// If the target doesn't provide latency information, use a simple // If the target doesn't provide itinerary information, use a
// non-zero default value for all instructions. // simple non-zero default value for all instructions.
if (isEmpty()) if (isEmpty())
return 1; return 1;
// Caclulate the maximum completion time for any stage. The // Calculate the maximum completion time for any stage.
// assumption is that all inputs are consumed at the start of the
// first stage and that all outputs are produced at the end of the
// latest completing last stage.
unsigned Latency = 0, StartCycle = 0; unsigned Latency = 0, StartCycle = 0;
for (const InstrStage *IS = beginStage(ItinClassIndx), for (const InstrStage *IS = beginStage(ItinClassIndx),
*E = endStage(ItinClassIndx); IS != E; ++IS) { *E = endStage(ItinClassIndx); IS != E; ++IS) {
@@ -141,6 +138,21 @@ struct InstrItineraryData {
return Latency; return Latency;
} }
/// getOperandCycle - Return the cycle for the given class and
/// operand. Return -1 if no cycle is specified for the operand.
///
int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
if (isEmpty())
return -1;
unsigned FirstIdx = Itineratries[ItinClassIndx].FirstOperandCycle;
unsigned LastIdx = Itineratries[ItinClassIndx].LastOperandCycle;
if ((FirstIdx + OperandIdx) >= LastIdx)
return -1;
return (int)OperandCycles[FirstIdx + OperandIdx];
}
}; };

View File

@@ -17,6 +17,7 @@
namespace llvm { namespace llvm {
class SDep; class SDep;
class SUnit;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// ///
@@ -40,7 +41,8 @@ public:
// adjustSchedDependency - Perform target specific adjustments to // adjustSchedDependency - Perform target specific adjustments to
// the latency of a schedule dependency. // the latency of a schedule dependency.
virtual void adjustSchedDependency(SDep&) const { }; virtual void adjustSchedDependency(SUnit *def, SUnit *use,
SDep& dep) const { };
}; };
} // End llvm namespace } // End llvm namespace

View File

@@ -210,6 +210,10 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
// Optionally add in a special extra latency for nodes that // Optionally add in a special extra latency for nodes that
// feed addresses. // feed addresses.
// TODO: Do this for register aliases too. // TODO: Do this for register aliases too.
// TODO: Perhaps we should get rid of
// SpecialAddressLatency and just move this into
// adjustSchedDependency for the targets that care about
// it.
if (SpecialAddressLatency != 0 && !UnitLatencies) { if (SpecialAddressLatency != 0 && !UnitLatencies) {
MachineInstr *UseMI = UseSU->getInstr(); MachineInstr *UseMI = UseSU->getInstr();
const TargetInstrDesc &UseTID = UseMI->getDesc(); const TargetInstrDesc &UseTID = UseMI->getDesc();
@@ -220,8 +224,14 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
UseTID.OpInfo[RegUseIndex].isLookupPtrRegClass()) UseTID.OpInfo[RegUseIndex].isLookupPtrRegClass())
LDataLatency += SpecialAddressLatency; LDataLatency += SpecialAddressLatency;
} }
// Adjust the dependence latency using operand def/use
// information (if any), and then allow the target to
// perform its own adjustments.
const SDep& dep = SDep(SU, SDep::Data, LDataLatency, Reg); const SDep& dep = SDep(SU, SDep::Data, LDataLatency, Reg);
ST.adjustSchedDependency((SDep &)dep); if (!UnitLatencies) {
ComputeOperandLatency(SU, UseSU, (SDep &)dep);
ST.adjustSchedDependency(SU, UseSU, (SDep &)dep);
}
UseSU->addPred(dep); UseSU->addPred(dep);
} }
} }
@@ -231,7 +241,10 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
SUnit *UseSU = UseList[i]; SUnit *UseSU = UseList[i];
if (UseSU != SU) { if (UseSU != SU) {
const SDep& dep = SDep(SU, SDep::Data, DataLatency, *Alias); const SDep& dep = SDep(SU, SDep::Data, DataLatency, *Alias);
ST.adjustSchedDependency((SDep &)dep); if (!UnitLatencies) {
ComputeOperandLatency(SU, UseSU, (SDep &)dep);
ST.adjustSchedDependency(SU, UseSU, (SDep &)dep);
}
UseSU->addPred(dep); UseSU->addPred(dep);
} }
} }
@@ -410,7 +423,7 @@ void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) {
// Compute the latency for the node. // Compute the latency for the node.
SU->Latency = SU->Latency =
InstrItins.getLatency(SU->getInstr()->getDesc().getSchedClass()); InstrItins.getStageLatency(SU->getInstr()->getDesc().getSchedClass());
// Simplistic target-independent heuristic: assume that loads take // Simplistic target-independent heuristic: assume that loads take
// extra time. // extra time.
@@ -419,6 +432,50 @@ void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) {
SU->Latency += 2; SU->Latency += 2;
} }
void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use,
SDep& dep) const {
const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
if (InstrItins.isEmpty())
return;
// For a data dependency with a known register...
if ((dep.getKind() != SDep::Data) || (dep.getReg() == 0))
return;
const unsigned Reg = dep.getReg();
// ... find the definition of the register in the defining
// instruction
MachineInstr *DefMI = Def->getInstr();
int DefIdx = DefMI->findRegisterDefOperandIdx(Reg);
if (DefIdx != -1) {
int DefCycle = InstrItins.getOperandCycle(DefMI->getDesc().getSchedClass(), DefIdx);
if (DefCycle >= 0) {
MachineInstr *UseMI = Use->getInstr();
const unsigned UseClass = UseMI->getDesc().getSchedClass();
// For all uses of the register, calculate the maxmimum latency
int Latency = -1;
for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = UseMI->getOperand(i);
if (!MO.isReg() || !MO.isUse())
continue;
unsigned MOReg = MO.getReg();
if (MOReg != Reg)
continue;
int UseCycle = InstrItins.getOperandCycle(UseClass, i);
if (UseCycle >= 0)
Latency = std::max(Latency, DefCycle - UseCycle + 1);
}
// If we found a latency, then replace the existing dependence latency.
if (Latency >= 0)
dep.setLatency(Latency);
}
}
}
void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const { void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
SU->getInstr()->dump(); SU->getInstr()->dump();
} }

View File

@@ -160,6 +160,12 @@ namespace llvm {
/// ///
virtual void ComputeLatency(SUnit *SU); virtual void ComputeLatency(SUnit *SU);
/// ComputeOperandLatency - Override dependence edge latency using
/// operand use/def information
///
virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use,
SDep& dep) const;
virtual MachineBasicBlock *EmitSchedule(); virtual MachineBasicBlock *EmitSchedule();
/// StartBlock - Prepare to perform scheduling in the given block. /// StartBlock - Prepare to perform scheduling in the given block.

View File

@@ -155,6 +155,9 @@ void ScheduleDAGSDNodes::BuildSchedUnits() {
void ScheduleDAGSDNodes::AddSchedEdges() { void ScheduleDAGSDNodes::AddSchedEdges() {
const TargetSubtarget &ST = TM.getSubtarget<TargetSubtarget>(); const TargetSubtarget &ST = TM.getSubtarget<TargetSubtarget>();
// Check to see if the scheduler cares about latencies.
bool UnitLatencies = ForceUnitLatencies();
// Pass 2: add the preds, succs, etc. // Pass 2: add the preds, succs, etc.
for (unsigned su = 0, e = SUnits.size(); su != e; ++su) { for (unsigned su = 0, e = SUnits.size(); su != e; ++su) {
SUnit *SU = &SUnits[su]; SUnit *SU = &SUnits[su];
@@ -212,8 +215,10 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
const SDep& dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, const SDep& dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data,
OpSU->Latency, PhysReg); OpSU->Latency, PhysReg);
if (!isChain) if (!isChain && !UnitLatencies) {
ST.adjustSchedDependency((SDep &)dep); ComputeOperandLatency(OpSU, SU, (SDep &)dep);
ST.adjustSchedDependency(OpSU, SU, (SDep &)dep);
}
SU->addPred(dep); SU->addPred(dep);
} }
@@ -242,8 +247,8 @@ void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) {
for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode())
if (N->isMachineOpcode()) { if (N->isMachineOpcode()) {
SawMachineOpcode = true; SawMachineOpcode = true;
SU->Latency += SU->Latency += InstrItins.
InstrItins.getLatency(TII->get(N->getMachineOpcode()).getSchedClass()); getStageLatency(TII->get(N->getMachineOpcode()).getSchedClass());
} }
} }