28#define DEBUG_TYPE "pre-RA-sched"
46 struct FastPriorityQueue {
49 bool empty()
const {
return Queue.empty(); }
56 if (empty())
return nullptr;
57 return Queue.pop_back_val();
67 FastPriorityQueue AvailableQueue;
72 unsigned NumLiveRegs = 0
u;
73 std::vector<SUnit*> LiveRegDefs;
74 std::vector<unsigned> LiveRegCycles;
89 void ReleasePred(
SUnit *SU,
SDep *PredEdge);
90 void ReleasePredecessors(
SUnit *SU,
unsigned CurCycle);
91 void ScheduleNodeBottomUp(
SUnit*,
unsigned);
93 void InsertCopiesAndMoveSuccs(
SUnit*,
unsigned,
98 void ListScheduleBottomUp();
107void ScheduleDAGFast::Schedule() {
111 LiveRegDefs.resize(
TRI->getNumRegs(),
nullptr);
112 LiveRegCycles.resize(
TRI->getNumRegs(), 0);
120 ListScheduleBottomUp();
129void ScheduleDAGFast::ReleasePred(
SUnit *SU,
SDep *PredEdge) {
134 dbgs() <<
"*** Scheduling failed! ***\n";
136 dbgs() <<
" has been released too many times!\n";
146 AvailableQueue.push(PredSU);
150void ScheduleDAGFast::ReleasePredecessors(
SUnit *SU,
unsigned CurCycle) {
153 ReleasePred(SU, &Pred);
159 if (!LiveRegDefs[Pred.
getReg()]) {
162 LiveRegCycles[Pred.
getReg()] = CurCycle;
171void ScheduleDAGFast::ScheduleNodeBottomUp(
SUnit *SU,
unsigned CurCycle) {
175 assert(CurCycle >= SU->
getHeight() &&
"Node scheduled below its height!");
179 ReleasePredecessors(SU, CurCycle);
185 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
187 "Physical register dependency violated?");
189 LiveRegDefs[Succ.
getReg()] =
nullptr;
190 LiveRegCycles[Succ.
getReg()] = 0;
200SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(
SUnit *SU) {
209 bool TryUnfold =
false;
210 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
211 MVT VT =
N->getSimpleValueType(i);
214 else if (VT == MVT::Other)
218 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
225 if (!
TII->unfoldMemoryOperand(*DAG,
N, NewNodes))
229 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
232 SDNode *LoadNode = NewNodes[0];
233 unsigned NumVals =
N->getNumValues();
235 for (
unsigned i = 0; i != NumVals; ++i)
237 DAG->ReplaceAllUsesOfValueWith(
SDValue(SU->
getNode(), OldNumVals-1),
240 SUnit *NewSU = newSUnit(
N);
241 assert(
N->getNodeId() == -1 &&
"Node already inserted!");
257 bool isNewLoad =
true;
263 LoadSU = newSUnit(LoadNode);
289 RemovePred(SU, ChainPred);
291 AddPred(LoadSU, ChainPred);
293 for (
const SDep &Pred : LoadPreds) {
294 RemovePred(SU, Pred);
296 AddPred(LoadSU, Pred);
299 for (
const SDep &Pred : NodePreds) {
300 RemovePred(SU, Pred);
301 AddPred(NewSU, Pred);
303 for (
SDep D : NodeSuccs) {
304 SUnit *SuccDep =
D.getSUnit();
306 RemovePred(SuccDep,
D);
310 for (
SDep D : ChainSuccs) {
311 SUnit *SuccDep =
D.getSUnit();
313 RemovePred(SuccDep,
D);
340 AddPred(NewSU, Pred);
357 for (
const auto &[Del, Dep] : DelDeps)
358 RemovePred(Del, Dep);
366void ScheduleDAGFast::InsertCopiesAndMoveSuccs(
SUnit *SU,
unsigned Reg,
370 SUnit *CopyFromSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
374 SUnit *CopyToSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
387 D.setSUnit(CopyToSU);
389 DelDeps.
push_back(std::make_pair(SuccSU, Succ));
392 for (
const auto &[Del, Dep] : DelDeps)
393 RemovePred(Del, Dep);
395 FromDep.setLatency(SU->
Latency);
396 AddPred(CopyFromSU, FromDep);
398 ToDep.setLatency(CopyFromSU->
Latency);
399 AddPred(CopyToSU, ToDep);
401 Copies.push_back(CopyFromSU);
402 Copies.push_back(CopyToSU);
419 "Physical reg def must be in implicit def list!");
427 return N->getSimpleValueType(NumRes);
433 std::vector<SUnit *> &LiveRegDefs,
441 if (!LiveRegDefs[*AI])
445 if (LiveRegDefs[*AI] == SU)
453 if (RegAdded.
insert(*AI).second) {
465bool ScheduleDAGFast::DelayForLiveRegsBottomUp(
SUnit *SU,
467 if (NumLiveRegs == 0)
475 RegAdded, LRegs,
TRI);
483 unsigned NumOps =
Node->getNumOperands();
484 if (
Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
488 unsigned Flags =
Node->getConstantOperandVal(i);
490 unsigned NumVals =
F.getNumOperandRegisters();
493 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
496 for (; NumVals; --NumVals, ++i) {
498 if (
Reg.isPhysical())
509 if (
Reg.isPhysical()) {
510 SDNode *SrcNode =
Node->getOperand(2).getNode();
515 if (!
Node->isMachineOpcode())
521 return !LRegs.
empty();
527void ScheduleDAGFast::ListScheduleBottomUp() {
528 unsigned CurCycle = 0;
531 ReleasePredecessors(&ExitSU, CurCycle);
534 if (!SUnits.empty()) {
535 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
536 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
538 AvailableQueue.push(RootSU);
546 while (!AvailableQueue.empty()) {
547 bool Delayed =
false;
549 SUnit *CurSU = AvailableQueue.pop();
552 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
555 LRegsMap.
insert(std::make_pair(CurSU, LRegs));
559 CurSU = AvailableQueue.pop();
565 if (Delayed && !CurSU) {
570 SUnit *TrySU = NotReady[0];
572 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
573 unsigned Reg = LRegs[0];
577 TRI->getMinimalPhysRegClass(Reg, VT);
587 SUnit *NewDef =
nullptr;
589 NewDef = CopyAndMoveSuccessors(LRDef);
590 if (!DestRC && !NewDef)
592 "register dependency!");
597 InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC,
Copies);
599 <<
" to SU #" <<
Copies.front()->NodeNum <<
"\n");
605 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
606 LiveRegDefs[
Reg] = NewDef;
618 for (
SUnit *SU : NotReady) {
622 AvailableQueue.push(SU);
627 ScheduleNodeBottomUp(CurSU, CurCycle);
635 VerifyScheduledSequence(
true);
663void ScheduleDAGLinearize::ScheduleNode(
SDNode *
N) {
664 if (
N->getNodeId() != 0)
667 if (!
N->isMachineOpcode() &&
676 unsigned NumOps =
N->getNumOperands();
677 if (
unsigned NumLeft = NumOps) {
678 SDNode *GluedOpN =
nullptr;
683 if (NumLeft == NumOps &&
Op.getValueType() == MVT::Glue) {
697 if (DI != GluedMap.end() && DI->second !=
N)
702 assert(Degree > 0 &&
"Predecessor over-released!");
713 while (
SDNode *Glued =
N->getGluedUser())
718void ScheduleDAGLinearize::Schedule() {
719 LLVM_DEBUG(
dbgs() <<
"********** DAG Linearization **********\n");
722 unsigned DAGSize = 0;
727 unsigned Degree =
N->use_size();
728 N->setNodeId(Degree);
729 unsigned NumVals =
N->getNumValues();
730 if (NumVals &&
N->getValueType(NumVals-1) == MVT::Glue &&
731 N->hasAnyUseOfValue(NumVals-1)) {
735 GluedMap.insert(std::make_pair(
N,
User));
739 if (
N->isMachineOpcode() ||
744 for (
SDNode *Glue : Glues) {
745 SDNode *GUser = GluedMap[Glue];
746 unsigned Degree = Glue->getNodeId();
760 ScheduleNode(DAG->getRoot().getNode());
770 unsigned NumNodes =
Sequence.size();
772 for (
unsigned i = 0; i != NumNodes; ++i) {
775 Emitter.EmitNode(
N,
false,
false, VRBaseMap);
778 if (
N->getHasDebugValue()) {
780 for (
auto *DV : DAG->GetDbgValues(
N)) {
781 if (!DV->isEmitted())
782 if (
auto *DbgMI =
Emitter.EmitDbgValue(DV, VRBaseMap))
783 BB->
insert(InsertPos, DbgMI);
790 InsertPos =
Emitter.getInsertPos();
800 return new ScheduleDAGFast(*IS->
MF);
805 return new ScheduleDAGLinearize(*IS->
MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
dxil DXContainer Global Emitter
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII)
getPhysicalRegisterVT - Returns the ValueType of the physical register definition of the specified no...
static RegisterScheduler fastDAGScheduler("fast", "Fast suboptimal list scheduling", createFastDAGScheduler)
static bool CheckForLiveRegDef(SUnit *SU, MCRegister Reg, std::vector< SUnit * > &LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI, const SDNode *Node=nullptr)
CheckForLiveRegDef - Return true and update live register vector if the specified register def of the...
static RegisterScheduler linearizeDAGScheduler("linearize", "Linearize DAG, no scheduling", createDAGLinearizer)
static SDNode * findGluedUser(SDNode *N)
findGluedUser - Find the representative use of a glue value by walking the use chain.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
bool isCommutable() const
Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z,...
MCRegAliasIterator enumerates all registers aliasing Reg.
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
Wrapper class representing virtual and physical registers.
Represents one node in the SelectionDAG.
int getNodeId() const
Return the unique node id.
SDNode * getGluedUser() const
If this node has a glue value with a user, return the user (there is at most one).
void setNodeId(int Id)
Set unique node id.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
LLVM_ABI bool isOperandOf(const SDNode *N) const
Return true if this node is an operand of N.
iterator_range< user_iterator > users()
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
@ Data
Regular data dependence (aka true-dependence).
@ Barrier
An unknown scheduling barrier.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Register getReg() const
Returns the register associated with this edge.
Scheduling unit. This is a node in the scheduling DAG.
LLVM_ABI void setHeightToAtLeast(unsigned NewHeight)
If NewHeight is greater than this node's height value, set it to be the new height value.
unsigned NodeNum
Entry # of node in the node vector.
const TargetRegisterClass * CopyDstRC
Is a special copy node if != nullptr.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
LLVM_ABI void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
unsigned short Latency
Node latency.
bool isPending
True once pending.
bool isScheduled
True once scheduled.
bool isAvailable
True once available.
SmallVector< SDep, 4 > Succs
All sunit successors.
const TargetRegisterClass * CopySrcRC
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
bool isTwoAddress
Is a two-address instruction.
bool isCommutable
Is a commutable instruction.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
LLVM_ABI bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
virtual void Schedule()=0
Schedule - Order nodes according to selected style, filling in the Sequence member.
virtual MachineBasicBlock * EmitSchedule(MachineBasicBlock::iterator &InsertPos)
EmitSchedule - Insert MachineInstrs into the MachineBasicBlock according to the order specified in Se...
virtual bool forceUnitLatencies() const
ForceUnitLatencies - Return true if all scheduling edges should be given a latency value of one.
std::vector< SUnit * > Sequence
The schedule. Null SUnit*'s represent noop instructions.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ INLINEASM
INLINEASM - Represents an inline asm block.
Reg
All possible values of the reg field in the ModR/M byte.
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
LLVM_ABI ScheduleDAGSDNodes * createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)
createFastDAGScheduler - This creates a "fast" scheduler.
LLVM_ABI ScheduleDAGSDNodes * createDAGLinearizer(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)
createDAGLinearizer - This creates a "no-scheduling" scheduler which linearize the DAG using topologi...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CodeGenOptLevel
Code generation optimization level.