//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Evan Cheng and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#ifndef LLVM_CODEGEN_SCHEDULEDAG_H
#define LLVM_CODEGEN_SCHEDULEDAG_H
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
struct InstrStage;
struct SUnit;
class MachineConstantPool;
+ class MachineFunction;
class MachineModuleInfo;
+ class MachineRegisterInfo;
class MachineInstr;
- class MRegisterInfo;
+ class TargetRegisterInfo;
class SelectionDAG;
class SelectionDAGISel;
- class SSARegMap;
class TargetInstrInfo;
- class TargetInstrDescriptor;
+ class TargetInstrDesc;
+ class TargetLowering;
class TargetMachine;
class TargetRegisterClass;
/// 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) {
+ 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 *Node) {
- }
+ 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() {
- }
+ virtual void AdvanceCycle() {}
/// EmitNoop - This callback is invoked when a noop was added to the
/// instruction stream.
- virtual void EmitNoop() {
- }
+ virtual void EmitNoop() {}
};
/// SDep - Scheduling dependency. It keeps track of dependent nodes,
struct SUnit {
SDNode *Node; // Representative node.
SmallVector<SDNode*,4> FlaggedNodes;// All nodes flagged to Node.
- unsigned InstanceNo; // Instance#. One SDNode can be multiple
- // SUnit due to cloning.
+ SUnit *OrigNode; // If not this, the node from which
+ // this node was cloned.
// Preds/Succs - The SUnits before/after us in the graph. The boolean value
// is true if the edge is a token chain edge, false if it is a value edge.
typedef SmallVector<SDep, 4>::const_iterator const_succ_iterator;
unsigned NodeNum; // Entry # of node in the node vector.
+ unsigned NodeQueueId; // Queue id of node.
unsigned short Latency; // Node latency.
short NumPreds; // # of preds.
short NumSuccs; // # of sucss.
short NumSuccsLeft; // # of succs not scheduled.
bool isTwoAddress : 1; // Is a two-address instruction.
bool isCommutable : 1; // Is a commutable instruction.
- bool hasImplicitDefs : 1; // Has implicit physical reg defs.
+ bool hasPhysRegDefs : 1; // Has physreg defs that are being used.
bool isPending : 1; // True once pending.
bool isAvailable : 1; // True once available.
bool isScheduled : 1; // True once scheduled.
const TargetRegisterClass *CopySrcRC;
SUnit(SDNode *node, unsigned nodenum)
- : Node(node), InstanceNo(0), NodeNum(nodenum), Latency(0),
+ : Node(node), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), Latency(0),
NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
- isTwoAddress(false), isCommutable(false), hasImplicitDefs(false),
+ isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
isPending(false), isAvailable(false), isScheduled(false),
CycleBound(0), Cycle(0), Depth(0), Height(0),
CopyDstRC(NULL), CopySrcRC(NULL) {}
/// not already. This returns true if this is a new pred.
bool addPred(SUnit *N, bool isCtrl, bool isSpecial,
unsigned PhyReg = 0, int Cost = 1) {
- for (unsigned i = 0, e = Preds.size(); i != e; ++i)
+ for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i)
if (Preds[i].Dep == N &&
Preds[i].isCtrl == isCtrl && Preds[i].isSpecial == isSpecial)
return false;
}
bool isPred(SUnit *N) {
- for (unsigned i = 0, e = Preds.size(); i != e; ++i)
+ for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i)
if (Preds[i].Dep == N)
return true;
return false;
}
bool isSucc(SUnit *N) {
- for (unsigned i = 0, e = Succs.size(); i != e; ++i)
+ for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i)
if (Succs[i].Dep == N)
return true;
return false;
public:
virtual ~SchedulingPriorityQueue() {}
- virtual void initNodes(DenseMap<SDNode*, std::vector<SUnit*> > &SUMap,
- std::vector<SUnit> &SUnits) = 0;
+ virtual void initNodes(std::vector<SUnit> &SUnits) = 0;
virtual void addNode(const SUnit *SU) = 0;
virtual void updateNode(const SUnit *SU) = 0;
virtual void releaseState() = 0;
virtual void remove(SUnit *SU) = 0;
/// ScheduledNode - As each node is scheduled, this method is invoked. This
- /// allows the priority function to adjust the priority of node that have
- /// already been emitted.
- virtual void ScheduledNode(SUnit *Node) {}
+ /// allows the priority function to adjust the priority of related
+ /// unscheduled nodes, for example.
+ ///
+ virtual void ScheduledNode(SUnit *) {}
- virtual void UnscheduledNode(SUnit *Node) {}
+ virtual void UnscheduledNode(SUnit *) {}
};
class ScheduleDAG {
MachineBasicBlock *BB; // Current basic block
const TargetMachine &TM; // Target processor
const TargetInstrInfo *TII; // Target instruction information
- const MRegisterInfo *MRI; // Target processor register info
- SSARegMap *RegMap; // Virtual/real register map
+ const TargetRegisterInfo *TRI; // Target processor register info
+ TargetLowering *TLI; // Target lowering info
+ MachineFunction *MF; // Machine function
+ MachineRegisterInfo &MRI; // Virtual/real register map
MachineConstantPool *ConstPool; // Target constant pool
std::vector<SUnit*> Sequence; // The schedule. Null SUnit*'s
// represent noop instructions.
- DenseMap<SDNode*, std::vector<SUnit*> > SUnitMap;
- // SDNode to SUnit mapping (n -> n).
std::vector<SUnit> SUnits; // The scheduling units.
- SmallSet<SDNode*, 16> CommuteSet; // Nodes the should be commuted.
+ SmallSet<SDNode*, 16> CommuteSet; // Nodes that should be commuted.
ScheduleDAG(SelectionDAG &dag, MachineBasicBlock *bb,
- const TargetMachine &tm)
- : DAG(dag), BB(bb), TM(tm) {}
+ const TargetMachine &tm);
virtual ~ScheduleDAG() {}
/// Run - perform scheduling.
///
- MachineBasicBlock *Run();
+ void Run();
/// isPassiveNode - Return true if the node is a non-scheduled leaf.
///
static bool isPassiveNode(SDNode *Node) {
if (isa<ConstantSDNode>(Node)) return true;
+ if (isa<ConstantFPSDNode>(Node)) return true;
if (isa<RegisterSDNode>(Node)) return true;
if (isa<GlobalAddressSDNode>(Node)) return true;
if (isa<BasicBlockSDNode>(Node)) return true;
if (isa<ConstantPoolSDNode>(Node)) return true;
if (isa<JumpTableSDNode>(Node)) return true;
if (isa<ExternalSymbolSDNode>(Node)) return true;
+ if (isa<MemOperandSDNode>(Node)) return true;
+ if (Node->getOpcode() == ISD::EntryToken) return true;
return false;
}
/// NewSUnit - Creates a new SUnit and return a ptr to it.
///
SUnit *NewSUnit(SDNode *N) {
- SUnits.push_back(SUnit(N, SUnits.size()));
+ SUnits.push_back(SUnit(N, (unsigned)SUnits.size()));
+ SUnits.back().OrigNode = &SUnits.back();
return &SUnits.back();
}
/// together nodes with a single SUnit.
void BuildSchedUnits();
+ /// ComputeLatency - Compute node latency.
+ ///
+ void ComputeLatency(SUnit *SU);
+
/// CalculateDepths, CalculateHeights - Calculate node depth / height.
///
void CalculateDepths();
/// (which do not go into the machine instrs.)
static unsigned CountResults(SDNode *Node);
- /// CountOperands The inputs to target nodes have any actual inputs first,
- /// followed by an optional chain operand, then flag operands. Compute the
- /// number of actual operands that will go into the machine instr.
+ /// CountOperands - The inputs to target nodes have any actual inputs first,
+ /// followed by special operands that describe memory references, then an
+ /// optional chain operand, then flag operands. Compute the number of
+ /// actual operands that will go into the resulting MachineInstr.
static unsigned CountOperands(SDNode *Node);
+ /// ComputeMemOperandsEnd - Find the index one past the last
+ /// MemOperandSDNode operand
+ static unsigned ComputeMemOperandsEnd(SDNode *Node);
+
/// 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(SDNode *Node, unsigned InstNo,
- DenseMap<SDOperand, unsigned> &VRBaseMap);
+ void EmitNode(SDNode *Node, bool IsClone,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
/// EmitNoop - Emit a noop instruction.
///
void EmitNoop();
- void EmitCrossRCCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap);
-
- /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
- /// implicit physical register output.
- void EmitCopyFromReg(SDNode *Node, unsigned ResNo, unsigned InstNo,
- unsigned SrcReg,
- DenseMap<SDOperand, unsigned> &VRBaseMap);
-
- void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
- const TargetInstrDescriptor &II,
- DenseMap<SDOperand, unsigned> &VRBaseMap);
-
- void EmitSchedule();
+ MachineBasicBlock *EmitSchedule();
void dumpSchedule() const;
- /// Schedule - Order nodes according to selected style.
+ /// Schedule - Order nodes according to selected style, filling
+ /// in the Sequence member.
///
- virtual void Schedule() {}
+ virtual void Schedule() = 0;
private:
/// EmitSubregNode - Generate machine code for subreg nodes.
///
void EmitSubregNode(SDNode *Node,
- DenseMap<SDOperand, unsigned> &VRBaseMap);
-
- void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum,
- const TargetInstrDescriptor *II,
- DenseMap<SDOperand, unsigned> &VRBaseMap);
- };
+ DenseMap<SDValue, unsigned> &VRBaseMap);
- /// createBFS_DAGScheduler - This creates a simple breadth first instruction
- /// scheduler.
- ScheduleDAG *createBFS_DAGScheduler(SelectionDAGISel *IS,
- SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ /// getVR - Return the virtual register corresponding to the specified result
+ /// of the specified node.
+ unsigned getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap);
- /// createSimpleDAGScheduler - This creates a simple two pass instruction
- /// scheduler using instruction itinerary.
- ScheduleDAG* createSimpleDAGScheduler(SelectionDAGISel *IS,
- SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ /// getDstOfCopyToRegUse - If the only use of the specified result number of
+ /// node is a CopyToReg, return its destination register. Return 0 otherwise.
+ unsigned getDstOfOnlyCopyToRegUse(SDNode *Node, unsigned ResNo) const;
+
+ void AddOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum,
+ const TargetInstrDesc *II,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
+
+ void AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO);
+
+ void EmitCrossRCCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap);
- /// createNoItinsDAGScheduler - This creates a simple two pass instruction
- /// scheduler without using instruction itinerary.
- ScheduleDAG* createNoItinsDAGScheduler(SelectionDAGISel *IS,
- SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
+ /// implicit physical register output.
+ void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
+ unsigned SrcReg,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
+
+ void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
+ const TargetInstrDesc &II,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
+
+ /// EmitLiveInCopy - Emit a copy for a live in physical register. If the
+ /// physical register has only a single copy use, then coalesced the copy
+ /// if possible.
+ void EmitLiveInCopy(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator &InsertPos,
+ unsigned VirtReg, unsigned PhysReg,
+ const TargetRegisterClass *RC,
+ DenseMap<MachineInstr*, unsigned> &CopyRegMap);
+
+ /// EmitLiveInCopies - If this is the first basic block in the function,
+ /// and if it has live ins that need to be copied into vregs, emit the
+ /// copies into the top of the block.
+ void EmitLiveInCopies(MachineBasicBlock *MBB);
+ };
/// createBURRListDAGScheduler - This creates a bottom up register usage
/// reduction list scheduler.
ScheduleDAG* createBURRListDAGScheduler(SelectionDAGISel *IS,
SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ MachineBasicBlock *BB,
+ bool Fast);
/// createTDRRListDAGScheduler - This creates a top down register usage
/// reduction list scheduler.
ScheduleDAG* createTDRRListDAGScheduler(SelectionDAGISel *IS,
SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ MachineBasicBlock *BB,
+ bool Fast);
/// createTDListDAGScheduler - This creates a top-down list scheduler with
/// a hazard recognizer.
ScheduleDAG* createTDListDAGScheduler(SelectionDAGISel *IS,
SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ MachineBasicBlock *BB,
+ bool Fast);
/// createDefaultScheduler - This creates an instruction scheduler appropriate
/// for the target.
ScheduleDAG* createDefaultScheduler(SelectionDAGISel *IS,
SelectionDAG *DAG,
- MachineBasicBlock *BB);
+ MachineBasicBlock *BB,
+ bool Fast);
class SUnitIterator : public forward_iterator<SUnit, ptrdiff_t> {
SUnit *Node;
static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); }
static SUnitIterator end (SUnit *N) {
- return SUnitIterator(N, N->Preds.size());
+ return SUnitIterator(N, (unsigned)N->Preds.size());
}
unsigned getOperand() const { return Operand; }
const SUnit *getNode() const { return Node; }
bool isCtrlDep() const { return Node->Preds[Operand].isCtrl; }
+ bool isSpecialDep() const { return Node->Preds[Operand].isSpecial; }
};
template <> struct GraphTraits<SUnit*> {