Generalize the HazardRecognizer interface so that it can be used

to support MachineInstr-based scheduling in addition to
SDNode-based scheduling.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62284 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2009-01-15 22:18:12 +00:00
parent c475c3608a
commit fc54c55296
13 changed files with 122 additions and 84 deletions

View File

@ -19,45 +19,6 @@
#include "llvm/CodeGen/SelectionDAG.h"
namespace llvm {
/// HazardRecognizer - This determines whether or not an instruction can be
/// issued this cycle, and whether or not a noop needs to be inserted to handle
/// the hazard.
class HazardRecognizer {
public:
virtual ~HazardRecognizer();
enum HazardType {
NoHazard, // This instruction can be emitted at this cycle.
Hazard, // This instruction can't be emitted at this cycle.
NoopHazard // This instruction can't be emitted, and needs noops.
};
/// getHazardType - Return the hazard type of emitting this node. There are
/// three possible results. Either:
/// * NoHazard: it is legal to issue this instruction on this cycle.
/// * Hazard: issuing this instruction would stall the machine. If some
/// other instruction is available, issue it first.
/// * NoopHazard: issuing this instruction would break the program. If
/// some other instruction can be issued, do so, otherwise issue a noop.
virtual HazardType getHazardType(SDNode *) {
return NoHazard;
}
/// EmitInstruction - This callback is invoked when an instruction is
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SDNode *) {}
/// AdvanceCycle - This callback is invoked when no instructions can be
/// issued on this cycle without a hazard. This should increment the
/// internal state of the hazard recognizer so that previously "Hazard"
/// instructions will now not be hazards.
virtual void AdvanceCycle() {}
/// EmitNoop - This callback is invoked when a noop was added to the
/// instruction stream.
virtual void EmitNoop() {}
};
/// ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
///
/// Edges between SUnits are initially based on edges in the SelectionDAG,

View File

@ -0,0 +1,63 @@
//=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ScheduleHazardRecognizer class, which implements
// hazard-avoidance heuristics for scheduling.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H
#define LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H
namespace llvm {
class SUnit;
/// HazardRecognizer - This determines whether or not an instruction can be
/// issued this cycle, and whether or not a noop needs to be inserted to handle
/// the hazard.
class ScheduleHazardRecognizer {
public:
virtual ~ScheduleHazardRecognizer();
enum HazardType {
NoHazard, // This instruction can be emitted at this cycle.
Hazard, // This instruction can't be emitted at this cycle.
NoopHazard // This instruction can't be emitted, and needs noops.
};
/// getHazardType - Return the hazard type of emitting this node. There are
/// three possible results. Either:
/// * NoHazard: it is legal to issue this instruction on this cycle.
/// * Hazard: issuing this instruction would stall the machine. If some
/// other instruction is available, issue it first.
/// * NoopHazard: issuing this instruction would break the program. If
/// some other instruction can be issued, do so, otherwise issue a noop.
virtual HazardType getHazardType(SUnit *) {
return NoHazard;
}
/// EmitInstruction - This callback is invoked when an instruction is
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SUnit *) {}
/// AdvanceCycle - This callback is invoked when no instructions can be
/// issued on this cycle without a hazard. This should increment the
/// internal state of the hazard recognizer so that previously "Hazard"
/// instructions will now not be hazards.
virtual void AdvanceCycle() {}
/// EmitNoop - This callback is invoked when a noop was added to the
/// instruction stream.
virtual void EmitNoop() {}
};
}
#endif

View File

@ -33,7 +33,7 @@ namespace llvm {
class TargetLowering;
class TargetInstrInfo;
class FunctionLoweringInfo;
class HazardRecognizer;
class ScheduleHazardRecognizer;
class GCFunctionInfo;
class ScheduleDAG;
@ -93,7 +93,7 @@ public:
/// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer
/// to use for this target when scheduling the DAG.
virtual HazardRecognizer *CreateTargetHazardRecognizer();
virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer();
protected:
/// DAGSize - Size of DAG being instruction selected.

View File

@ -1293,7 +1293,23 @@ public:
return getOperand(getNumOperands()-1).getNode();
return 0;
}
// If this is a pseudo op, like copyfromreg, look to see if there is a
// real target node flagged to it. If so, return the target node.
const SDNode *getFlaggedMachineNode() const {
const SDNode *FoundNode = this;
// Climb up flag edges until a machine-opcode node is found, or the
// end of the chain is reached.
while (!FoundNode->isMachineOpcode()) {
const SDNode *N = FoundNode->getFlaggedNode();
if (!N) break;
FoundNode = N;
}
return FoundNode;
}
/// getNumValues - Return the number of values defined/returned by this
/// operator.
///

View File

@ -14,6 +14,7 @@
#define DEBUG_TYPE "pre-RA-sched"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
@ -561,3 +562,5 @@ void ScheduleDAGTopologicalSort::Allocate(int n, int index) {
ScheduleDAGTopologicalSort::ScheduleDAGTopologicalSort(
std::vector<SUnit> &sunits)
: SUnits(sunits) {}
ScheduleHazardRecognizer::~ScheduleHazardRecognizer() {}

View File

@ -21,6 +21,7 @@
#define DEBUG_TYPE "pre-RA-sched"
#include "llvm/CodeGen/LatencyPriorityQueue.h"
#include "llvm/CodeGen/ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetRegisterInfo.h"
@ -58,12 +59,12 @@ private:
std::vector<SUnit*> PendingQueue;
/// HazardRec - The hazard recognizer to use.
HazardRecognizer *HazardRec;
ScheduleHazardRecognizer *HazardRec;
public:
ScheduleDAGList(MachineFunction &mf,
SchedulingPriorityQueue *availqueue,
HazardRecognizer *HR)
ScheduleHazardRecognizer *HR)
: ScheduleDAGSDNodes(mf),
AvailableQueue(availqueue), HazardRec(HR) {
}
@ -82,9 +83,6 @@ private:
};
} // end anonymous namespace
HazardRecognizer::~HazardRecognizer() {}
/// Schedule - Schedule the DAG using list scheduling.
void ScheduleDAGList::Schedule() {
DOUT << "********** List Scheduling **********\n";
@ -190,31 +188,20 @@ void ScheduleDAGList::ListScheduleTopDown() {
}
SUnit *FoundSUnit = 0;
SDNode *FoundNode = 0;
bool HasNoopHazards = false;
while (!AvailableQueue->empty()) {
SUnit *CurSUnit = AvailableQueue->pop();
// Get the node represented by this SUnit.
FoundNode = CurSUnit->getNode();
// If this is a pseudo op, like copyfromreg, look to see if there is a
// real target node flagged to it. If so, use the target node.
while (!FoundNode->isMachineOpcode()) {
SDNode *N = FoundNode->getFlaggedNode();
if (!N) break;
FoundNode = N;
}
HazardRecognizer::HazardType HT = HazardRec->getHazardType(FoundNode);
if (HT == HazardRecognizer::NoHazard) {
ScheduleHazardRecognizer::HazardType HT =
HazardRec->getHazardType(CurSUnit);
if (HT == ScheduleHazardRecognizer::NoHazard) {
FoundSUnit = CurSUnit;
break;
}
// Remember if this is a noop hazard.
HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
NotReady.push_back(CurSUnit);
}
@ -228,7 +215,7 @@ void ScheduleDAGList::ListScheduleTopDown() {
// If we found a node to schedule, do it now.
if (FoundSUnit) {
ScheduleNodeTopDown(FoundSUnit, CurCycle);
HazardRec->EmitInstruction(FoundNode);
HazardRec->EmitInstruction(FoundSUnit);
// If this is a pseudo-op node, we don't want to increment the current
// cycle.

View File

@ -34,6 +34,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/DwarfWriter.h"
@ -1079,8 +1080,8 @@ ScheduleDAG *SelectionDAGISel::Schedule() {
}
HazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
return new HazardRecognizer();
ScheduleHazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
return new ScheduleHazardRecognizer();
}
//===----------------------------------------------------------------------===//

View File

@ -17,6 +17,8 @@
#include "SPUHazardRecognizers.h"
#include "SPU.h"
#include "SPUInstrInfo.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@ -38,14 +40,15 @@ SPUHazardRecognizer::SPUHazardRecognizer(const TargetInstrInfo &tii) :
/// instruction. Currently returns NoHazard.
///
/// \return NoHazard
HazardRecognizer::HazardType
SPUHazardRecognizer::getHazardType(SDNode *Node)
ScheduleHazardRecognizer::HazardType
SPUHazardRecognizer::getHazardType(SUnit *SU)
{
// Initial thoughts on how to do this, but this code cannot work unless the
// function's prolog and epilog code are also being scheduled so that we can
// accurately determine which pipeline is being scheduled.
#if 0
HazardRecognizer::HazardType retval = NoHazard;
const SDNode *Node = SU->getNode()->getFlaggedMachineNode();
ScheduleHazardRecognizer::HazardType retval = NoHazard;
bool mustBeOdd = false;
switch (Node->getOpcode()) {
@ -120,7 +123,7 @@ SPUHazardRecognizer::getHazardType(SDNode *Node)
#endif
}
void SPUHazardRecognizer::EmitInstruction(SDNode *Node)
void SPUHazardRecognizer::EmitInstruction(SUnit *SU)
{
}

View File

@ -15,13 +15,14 @@
#ifndef SPUHAZRECS_H
#define SPUHAZRECS_H
#include "llvm/CodeGen/ScheduleDAGSDNodes.h"
#include "SPUInstrInfo.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
namespace llvm {
class TargetInstrInfo;
/// SPUHazardRecognizer
class SPUHazardRecognizer : public HazardRecognizer
class SPUHazardRecognizer : public ScheduleHazardRecognizer
{
private:
const TargetInstrInfo &TII;
@ -29,8 +30,8 @@ private:
public:
SPUHazardRecognizer(const TargetInstrInfo &TII);
virtual HazardType getHazardType(SDNode *Node);
virtual void EmitInstruction(SDNode *Node);
virtual HazardType getHazardType(SUnit *SU);
virtual void EmitInstruction(SUnit *SU);
virtual void AdvanceCycle();
virtual void EmitNoop();
};
@ -38,4 +39,3 @@ public:
} // end namespace llvm
#endif

View File

@ -353,7 +353,7 @@ public:
/// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
/// this target when scheduling the DAG.
virtual HazardRecognizer *CreateTargetHazardRecognizer() {
virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() {
const TargetInstrInfo *II = TM.getInstrInfo();
assert(II && "No InstrInfo?");
return new SPUHazardRecognizer(*II);

View File

@ -15,6 +15,7 @@
#include "PPCHazardRecognizers.h"
#include "PPC.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@ -118,8 +119,9 @@ isLoadOfStoredAddress(unsigned LoadSize, SDValue Ptr1, SDValue Ptr2) const {
/// terminate terminate the dispatch group. We turn NoopHazard for any
/// instructions that wouldn't terminate the dispatch group that would cause a
/// pipeline flush.
HazardRecognizer::HazardType PPCHazardRecognizer970::
getHazardType(SDNode *Node) {
ScheduleHazardRecognizer::HazardType PPCHazardRecognizer970::
getHazardType(SUnit *SU) {
const SDNode *Node = SU->getNode()->getFlaggedMachineNode();
bool isFirst, isSingle, isCracked, isLoad, isStore;
PPCII::PPC970_Unit InstrType =
GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked,
@ -217,7 +219,8 @@ getHazardType(SDNode *Node) {
return NoHazard;
}
void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) {
void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) {
const SDNode *Node = SU->getNode()->getFlaggedMachineNode();
bool isFirst, isSingle, isCracked, isLoad, isStore;
PPCII::PPC970_Unit InstrType =
GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked,

View File

@ -14,7 +14,8 @@
#ifndef PPCHAZRECS_H
#define PPCHAZRECS_H
#include "llvm/CodeGen/ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "PPCInstrInfo.h"
namespace llvm {
@ -25,7 +26,7 @@ namespace llvm {
/// avoid structural hazards that cause significant performance penalties (e.g.
/// setting the CTR register then branching through it within a dispatch group),
/// or storing then loading from the same address within a dispatch group.
class PPCHazardRecognizer970 : public HazardRecognizer {
class PPCHazardRecognizer970 : public ScheduleHazardRecognizer {
const TargetInstrInfo &TII;
unsigned NumIssued; // Number of insts issued, including advanced cycles.
@ -47,8 +48,8 @@ class PPCHazardRecognizer970 : public HazardRecognizer {
public:
PPCHazardRecognizer970(const TargetInstrInfo &TII);
virtual HazardType getHazardType(SDNode *Node);
virtual void EmitInstruction(SDNode *Node);
virtual HazardType getHazardType(SUnit *SU);
virtual void EmitInstruction(SUnit *SU);
virtual void AdvanceCycle();
virtual void EmitNoop();

View File

@ -181,7 +181,7 @@ namespace {
/// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
/// this target when scheduling the DAG.
virtual HazardRecognizer *CreateTargetHazardRecognizer() {
virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() {
// Should use subtarget info to pick the right hazard recognizer. For
// now, always return a PPC970 recognizer.
const TargetInstrInfo *II = TM.getInstrInfo();