31 #define DEBUG_TYPE "pre-RA-sched" 33 STATISTIC(NumUnfolds,
"Number of nodes unfolded");
34 STATISTIC(NumDups,
"Number of duplicated nodes");
35 STATISTIC(NumPRCopies,
"Number of physical copies");
49 struct FastPriorityQueue {
59 if (
empty())
return nullptr;
72 FastPriorityQueue AvailableQueue;
78 std::vector<SUnit*> LiveRegDefs;
79 std::vector<unsigned> LiveRegCycles;
85 void Schedule()
override;
95 void RemovePred(
SUnit *SU,
const SDep &D) {
100 void ReleasePred(
SUnit *SU,
SDep *PredEdge);
101 void ReleasePredecessors(
SUnit *SU,
unsigned CurCycle);
102 void ScheduleNodeBottomUp(
SUnit*,
unsigned);
104 void InsertCopiesAndMoveSuccs(
SUnit*,
unsigned,
109 void ListScheduleBottomUp();
112 bool forceUnitLatencies()
const override {
return true; }
118 void ScheduleDAGFast::Schedule() {
122 LiveRegDefs.resize(
TRI->getNumRegs(),
nullptr);
123 LiveRegCycles.resize(
TRI->getNumRegs(), 0);
126 BuildSchedGraph(
nullptr);
131 ListScheduleBottomUp();
140 void ScheduleDAGFast::ReleasePred(
SUnit *SU,
SDep *PredEdge) {
145 dbgs() <<
"*** Scheduling failed! ***\n";
147 dbgs() <<
" has been released too many times!\n";
157 AvailableQueue.push(PredSU);
161 void ScheduleDAGFast::ReleasePredecessors(
SUnit *SU,
unsigned CurCycle) {
164 ReleasePred(SU, &Pred);
170 if (!LiveRegDefs[Pred.
getReg()]) {
173 LiveRegCycles[Pred.
getReg()] = CurCycle;
182 void ScheduleDAGFast::ScheduleNodeBottomUp(
SUnit *SU,
unsigned CurCycle) {
186 assert(CurCycle >= SU->
getHeight() &&
"Node scheduled below its height!");
190 ReleasePredecessors(SU, CurCycle);
196 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
198 "Physical register dependency violated?");
200 LiveRegDefs[Succ.
getReg()] =
nullptr;
201 LiveRegCycles[Succ.
getReg()] = 0;
211 SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(
SUnit *SU) {
220 bool TryUnfold =
false;
221 for (
unsigned i = 0, e = N->
getNumValues(); i != e; ++i) {
229 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
236 if (!
TII->unfoldMemoryOperand(*DAG, N, NewNodes))
240 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
243 SDNode *LoadNode = NewNodes[0];
244 unsigned NumVals = N->getNumValues();
246 for (
unsigned i = 0; i != NumVals; ++i)
248 DAG->ReplaceAllUsesOfValueWith(
SDValue(SU->
getNode(), OldNumVals-1),
251 SUnit *NewSU = newSUnit(N);
252 assert(N->getNodeId() == -1 &&
"Node already inserted!");
268 bool isNewLoad =
true;
274 LoadSU = newSUnit(LoadNode);
300 RemovePred(SU, ChainPred);
302 AddPred(LoadSU, ChainPred);
304 for (
unsigned i = 0, e = LoadPreds.
size(); i != e; ++i) {
305 const SDep &Pred = LoadPreds[i];
306 RemovePred(SU, Pred);
308 AddPred(LoadSU, Pred);
311 for (
unsigned i = 0, e = NodePreds.
size(); i != e; ++i) {
312 const SDep &Pred = NodePreds[i];
313 RemovePred(SU, Pred);
314 AddPred(NewSU, Pred);
316 for (
unsigned i = 0, e = NodeSuccs.
size(); i != e; ++i) {
317 SDep D = NodeSuccs[i];
320 RemovePred(SuccDep, D);
324 for (
unsigned i = 0, e = ChainSuccs.
size(); i != e; ++i) {
325 SDep D = ChainSuccs[i];
328 RemovePred(SuccDep, D);
355 AddPred(NewSU, Pred);
369 DelDeps.
push_back(std::make_pair(SuccSU, D));
372 for (
unsigned i = 0, e = DelDeps.
size(); i != e; ++i)
381 void ScheduleDAGFast::InsertCopiesAndMoveSuccs(
SUnit *SU,
unsigned Reg,
385 SUnit *CopyFromSU = newSUnit(static_cast<SDNode *>(
nullptr));
389 SUnit *CopyToSU = newSUnit(static_cast<SDNode *>(
nullptr));
404 DelDeps.
push_back(std::make_pair(SuccSU, Succ));
407 for (
unsigned i = 0, e = DelDeps.
size(); i != e; ++i) {
411 FromDep.setLatency(SU->
Latency);
412 AddPred(CopyFromSU, FromDep);
414 ToDep.setLatency(CopyFromSU->
Latency);
415 AddPred(CopyToSU, ToDep);
448 std::vector<SUnit*> &LiveRegDefs,
454 if (LiveRegDefs[*AI] && LiveRegDefs[*AI] != SU) {
455 if (RegAdded.
insert(*AI).second) {
468 bool ScheduleDAGFast::DelayForLiveRegsBottomUp(
SUnit *SU,
470 if (NumLiveRegs == 0)
478 RegAdded, LRegs,
TRI);
482 for (
SDNode *Node = SU->
getNode(); Node; Node = Node->getGluedNode()) {
485 unsigned NumOps = Node->getNumOperands();
486 if (Node->getOperand(NumOps-1).getValueType() ==
MVT::Glue)
491 cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
499 for (; NumVals; --NumVals, ++i) {
500 unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->
getReg();
509 if (!Node->isMachineOpcode())
518 return !LRegs.
empty();
524 void ScheduleDAGFast::ListScheduleBottomUp() {
525 unsigned CurCycle = 0;
528 ReleasePredecessors(&ExitSU, CurCycle);
531 if (!SUnits.empty()) {
532 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
533 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
535 AvailableQueue.push(RootSU);
543 while (!AvailableQueue.empty()) {
544 bool Delayed =
false;
546 SUnit *CurSU = AvailableQueue.pop();
549 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
552 LRegsMap.
insert(std::make_pair(CurSU, LRegs));
556 CurSU = AvailableQueue.pop();
562 if (Delayed && !CurSU) {
567 SUnit *TrySU = NotReady[0];
569 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
570 unsigned Reg = LRegs[0];
574 TRI->getMinimalPhysRegClass(Reg, VT);
584 SUnit *NewDef =
nullptr;
586 NewDef = CopyAndMoveSuccessors(LRDef);
587 if (!DestRC && !NewDef)
589 "register dependency!");
594 InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies);
598 NewDef = Copies.
back();
602 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
603 LiveRegDefs[
Reg] = NewDef;
615 for (
unsigned i = 0, e = NotReady.
size(); i != e; ++i) {
616 NotReady[i]->isPending =
false;
619 AvailableQueue.push(NotReady[i]);
624 ScheduleNodeBottomUp(CurSU, CurCycle);
632 VerifyScheduledSequence(
true);
647 void Schedule()
override;
656 void ScheduleNode(
SDNode *N);
660 void ScheduleDAGLinearize::ScheduleNode(
SDNode *N) {
674 if (
unsigned NumLeft = NumOps) {
675 SDNode *GluedOpN =
nullptr;
694 if (DI != GluedMap.
end() && DI->second !=
N)
699 assert(Degree > 0 &&
"Predecessor over-released!");
715 void ScheduleDAGLinearize::Schedule() {
716 LLVM_DEBUG(
dbgs() <<
"********** DAG Linearization **********\n");
719 unsigned DAGSize = 0;
720 for (
SDNode &Node : DAG->allnodes()) {
732 GluedMap.insert(std::make_pair(N, User));
741 for (
unsigned i = 0, e = Glues.
size(); i != e; ++i) {
743 SDNode *GUser = GluedMap[Glue];
758 ScheduleNode(DAG->getRoot().getNode());
768 unsigned NumNodes =
Sequence.size();
770 for (
unsigned i = 0; i != NumNodes; ++i) {
773 Emitter.
EmitNode(N,
false,
false, VRBaseMap);
778 for (
auto DV : DAG->GetDbgValues(N)) {
779 if (!DV->isEmitted())
781 BB->
insert(InsertPos, DbgMI);
798 return new ScheduleDAGFast(*IS->
MF);
803 return new ScheduleDAGLinearize(*IS->
MF);
EVT getValueType() const
Return the ValueType of the referenced return value.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
bool isCommutable() const
Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z, ..."), which produces the same result if Y and Z are exchanged.
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void push_back(const T &Elt)
bool isTwoAddress
Is a two-address instruction.
Describe properties that are true of each instruction in the target description file.
static bool isClobberKind(unsigned Flag)
static bool CheckForLiveRegDef(SUnit *SU, unsigned Reg, std::vector< SUnit *> &LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI)
CheckForLiveRegDef - Return true and update live register vector if the specified register def of the...
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
void setNodeId(int Id)
Set unique node id.
unsigned getReg() const
Returns the register associated with this edge.
SDNode * getNode() const
get the SDNode which holds the desired result
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
const TargetRegisterClass * CopyDstRC
Is a special copy node if != nullptr.
EntryToken - This is the marker used to indicate the start of a region.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineBasicBlock * getBlock()
getBlock - Return the current basic block.
bool isScheduled
True once scheduled.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
unsigned NumSuccsLeft
of succs not scheduled.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const HexagonInstrInfo * TII
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Regular data dependence (aka true-dependence).
static bool isRegDefEarlyClobberKind(unsigned Flag)
INLINEASM - Represents an inline asm block.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
ScheduleDAGSDNodes * createDAGLinearizer(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
createDAGLinearizer - This creates a "no-scheduling" scheduler which linearize the DAG using topologi...
bool isOperandOf(const SDNode *N) const
Return true if this node is an operand of N.
bool isPending
True once pending.
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
static bool isRegDefKind(unsigned Flag)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
bool getHasDebugValue() const
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
TargetInstrInfo - Interface to description of machine instruction set.
iterator find(const_arg_type_t< KeyT > Val)
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
void setHeightToAtLeast(unsigned NewHeight)
If NewDepth is greater than this node's depth value, set it to be the new height value.
const MCPhysReg * getImplicitDefs() const
Return a list of registers that are potentially written by any instance of this machine instruction...
ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
unsigned short Latency
Node latency.
bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
iterator_range< value_op_iterator > op_values() const
SDNode * getGluedUser() const
If this node has a glue value with a user, return the user (there is at most one).
const SDValue & getOperand(unsigned Num) const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const MCPhysReg * ImplicitDefs
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
MCRegAliasIterator enumerates all registers aliasing Reg.
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
unsigned getNumOperands() const
Return the number of values used by this operation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
An unknown scheduling barrier.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set.
void dump() const
Dump this node, for debugging.
bool isCommutable
Is a commutable instruction.
static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII)
getPhysicalRegisterVT - Returns the ValueType of the physical register definition of the specified no...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
const TargetRegisterClass * CopySrcRC
static SDNode * findGluedUser(SDNode *N)
findGluedUser - Find the representative use of a glue value by walking the use chain.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
size_t use_size() const
Return the number of uses of this node.
iterator_range< use_iterator > uses()
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
void setLatency(unsigned Lat)
Sets the latency for this edge.
int getNodeId() const
Return the unique node id.
static RegisterScheduler fastDAGScheduler("fast", "Fast suboptimal list scheduling", createFastDAGScheduler)
bool isAvailable
True once available.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
void EmitNode(SDNode *Node, bool IsClone, bool IsCloned, DenseMap< SDValue, unsigned > &VRBaseMap)
EmitNode - Generate machine code for a node and needed dependencies.
LLVM_NODISCARD bool empty() const
static RegisterScheduler linearizeDAGScheduler("linearize", "Linearize DAG, no scheduling", createDAGLinearizer)
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
unsigned NodeNum
Entry # of node in the node vector.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineInstr * EmitDbgValue(SDDbgValue *SD, DenseMap< SDValue, unsigned > &VRBaseMap)
EmitDbgValue - Generate machine instruction for a dbg_value node.
bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
MachineBasicBlock::iterator getInsertPos()
getInsertPos - Return the current insertion position.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
SmallVector< SDep, 4 > Succs
All sunit successors.
Arbitrary strong DAG edge (no real dependence).
ScheduleDAGSDNodes * createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
createFastDAGScheduler - This creates a "fast" scheduler.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
Scheduling unit. This is a node in the scheduling DAG.