typedef std::vector<NodeInfoPtr> NIVector;
typedef std::vector<NodeInfoPtr>::iterator NIIterator;
-
// Scheduling heuristics
enum SchedHeuristics {
- noScheduling, // No scheduling, emit breath first sequence.
+ defaultScheduling, // Let the target specify its preference.
+ noScheduling, // No scheduling, emit breadth first sequence.
simpleScheduling, // Two pass, min. critical path, max. utilization.
simpleNoItinScheduling, // Same as above exact using generic latency.
listSchedulingBURR, // Bottom up reg reduction list scheduling.
+ listSchedulingTD // Top-down list scheduler.
+ };
+
+ /// 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 *Node) {
+ return NoHazard;
+ }
+
+ /// EmitInstruction - This callback is invoked when an instruction is
+ /// emitted, to advance the hazard state.
+ virtual void EmitInstruction(SDNode *Node) {
+ }
+
+ /// 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() {
+ }
};
-
//===--------------------------------------------------------------------===//
///
/// Node group - This struct is used to manage flagged node groups.
///
class NodeGroup {
+ public:
+ NodeGroup *Next;
private:
NIVector Members; // Group member nodes
NodeInfo *Dominator; // Node with highest latency
public:
// Ctor.
- NodeGroup() : Dominator(NULL), Pending(0) {}
+ NodeGroup() : Next(NULL), Dominator(NULL), Pending(0) {}
// Accessors
inline void setDominator(NodeInfo *D) { Dominator = D; }
+ inline NodeInfo *getTop() { return Members.front(); }
+ inline NodeInfo *getBottom() { return Members.back(); }
inline NodeInfo *getDominator() { return Dominator; }
inline void setLatency(unsigned L) { Latency = L; }
inline unsigned getLatency() { return Latency; }
class NodeInfo {
private:
int Pending; // Number of visits pending before
- // adding to order
+ // adding to order
public:
SDNode *Node; // DAG node
InstrStage *StageBegin; // First stage in itinerary
bool IsStore : 1; // Is memory store
unsigned Slot; // Node's time slot
NodeGroup *Group; // Grouping information
- unsigned VRBase; // Virtual register base
#ifndef NDEBUG
unsigned Preorder; // Index before scheduling
#endif
, IsCall(false)
, Slot(0)
, Group(NULL)
- , VRBase(0)
#ifndef NDEBUG
, Preorder(0)
#endif
bool HasGroups; // True if there are any groups
NodeInfo *Info; // Info for nodes being scheduled
NIVector Ordering; // Emit ordering of nodes
+ NodeGroup *HeadNG, *TailNG; // Keep track of allocated NodeGroups
ScheduleDAG(SchedHeuristics hstc, SelectionDAG &dag, MachineBasicBlock *bb,
const TargetMachine &tm)
- : Heuristic(hstc), DAG(dag), BB(bb), TM(tm),
- NodeCount(0), HasGroups(false), Info(NULL) {}
-
- virtual ~ScheduleDAG() {};
+ : Heuristic(hstc), DAG(dag), BB(bb), TM(tm), NodeCount(0),
+ HasGroups(false), Info(NULL), HeadNG(NULL), TailNG(NULL) {}
+
+ virtual ~ScheduleDAG() {
+ if (Info)
+ delete[] Info;
+
+ NodeGroup *NG = HeadNG;
+ while (NG) {
+ NodeGroup *NextSU = NG->Next;
+ delete NG;
+ NG = NextSU;
+ }
+ };
/// Run - perform scheduling.
///
///
NodeInfo *getNI(SDNode *Node) { return Map[Node]; }
- /// getVR - Returns the virtual register number of the node.
- ///
- unsigned getVR(SDOperand Op) {
- NodeInfo *NI = getNI(Op.Val);
- assert(NI->VRBase != 0 && "Node emitted out of order - late");
- return NI->VRBase + Op.ResNo;
- }
-
/// isPassiveNode - Return true if the node is a non-scheduled leaf.
///
- bool isPassiveNode(SDNode *Node) {
+ static bool isPassiveNode(SDNode *Node) {
if (isa<ConstantSDNode>(Node)) return true;
if (isa<RegisterSDNode>(Node)) return true;
if (isa<GlobalAddressSDNode>(Node)) return true;
}
/// EmitNode - Generate machine code for an node and needed dependencies.
+ /// VRBaseMap contains, for each already emitted node, the first virtual
+ /// register number for the results of the node.
///
- void EmitNode(NodeInfo *NI);
-
- /// EmitAll - Emit all nodes in schedule sorted order.
+ void EmitNode(SDNode *Node, std::map<SDNode*, unsigned> &VRBaseMap);
+
+ /// EmitNoop - Emit a noop instruction.
///
- void EmitAll();
+ void EmitNoop();
+
/// Schedule - Order nodes according to selected style.
///
- virtual void Schedule() {};
-
- /// printNI - Print node info.
- ///
- void printNI(std::ostream &O, NodeInfo *NI) const;
-
- /// printChanges - Hilight changes in order caused by scheduling.
- ///
- void printChanges(unsigned Index) const;
-
- /// print - Print ordering to specified output stream.
- ///
- void print(std::ostream &O) const;
-
- void dump(const char *tag) const;
-
- void dump() const;
+ virtual void Schedule() {}
private:
- /// PrepareNodeInfo - Set up the basic minimum node info for scheduling.
- ///
- void PrepareNodeInfo();
-
- /// IdentifyGroups - Put flagged nodes into groups.
- ///
- void IdentifyGroups();
+ void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum,
+ const TargetInstrDescriptor *II,
+ std::map<SDNode*, unsigned> &VRBaseMap);
};
/// createSimpleDAGScheduler - This creates a simple two pass instruction
/// reduction list scheduler.
ScheduleDAG* createBURRListDAGScheduler(SelectionDAG &DAG,
MachineBasicBlock *BB);
+
+ /// createTDListDAGScheduler - This creates a top-down list scheduler with
+ /// the specified hazard recognizer. This takes ownership of the hazard
+ /// recognizer and deletes it when done.
+ ScheduleDAG* createTDListDAGScheduler(SelectionDAG &DAG,
+ MachineBasicBlock *BB,
+ HazardRecognizer *HR);
}
#endif