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;
78 : ScheduleDAGSDNodes(mf) {}
80 void Schedule()
override;
83 void AddPred(SUnit *SU,
const SDep &
D) { SU->
addPred(
D); }
86 void RemovePred(SUnit *SU,
const SDep &
D) { SU->
removePred(
D); }
89 void ReleasePred(SUnit *SU, SDep *PredEdge);
90 void ReleasePredecessors(SUnit *SU,
unsigned CurCycle);
91 void ScheduleNodeBottomUp(SUnit*,
unsigned);
92 SUnit *CopyAndMoveSuccessors(SUnit*);
93 void InsertCopiesAndMoveSuccs(SUnit*,
unsigned,
96 SmallVectorImpl<SUnit*>&);
97 bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl<unsigned>&);
98 void ListScheduleBottomUp();
101 bool forceUnitLatencies()
const override {
return true; }
107void ScheduleDAGFast::Schedule() {
111 LiveRegDefs.resize(
TRI->getNumRegs(),
nullptr);
112 LiveRegCycles.resize(
TRI->getNumRegs(), 0);
120 ListScheduleBottomUp();
129void ScheduleDAGFast::ReleasePred(SUnit *SU, SDep *PredEdge) {
130 SUnit *PredSU = PredEdge->
getSUnit();
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) {
152 for (SDep &Pred : SU->
Preds) {
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);
182 for (SDep &Succ : SU->
Succs) {
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)
217 for (
const SDValue &
Op :
N->op_values()) {
218 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
225 if (!
TII->unfoldMemoryOperand(*DAG,
N, NewNodes))
228 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
231 SDNode *LoadNode = NewNodes[0];
232 unsigned NumVals =
N->getNumValues();
238 assert(
N->getNodeId() == -1 &&
"Node using a new load can't exist yet!");
242 for (
unsigned i = 0; i != NumVals; ++i)
243 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), i), SDValue(
N, i));
244 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), OldNumVals - 1),
245 SDValue(LoadNode, 1));
247 SUnit *NewSU = newSUnit(
N);
250 const MCInstrDesc &MCID =
TII->get(
N->getMachineOpcode());
260 SUnit *LoadSU = newSUnit(LoadNode);
268 for (SDep &Pred : SU->
Preds) {
277 for (SDep &Succ : SU->
Succs) {
285 RemovePred(SU, ChainPred);
286 AddPred(LoadSU, ChainPred);
288 for (
const SDep &Pred : LoadPreds) {
289 RemovePred(SU, Pred);
290 AddPred(LoadSU, Pred);
292 for (
const SDep &Pred : NodePreds) {
293 RemovePred(SU, Pred);
294 AddPred(NewSU, Pred);
296 for (SDep
D : NodeSuccs) {
297 SUnit *SuccDep =
D.getSUnit();
299 RemovePred(SuccDep,
D);
303 for (SDep
D : ChainSuccs) {
304 SUnit *SuccDep =
D.getSUnit();
306 RemovePred(SuccDep,
D);
327 for (SDep &Pred : SU->
Preds)
329 AddPred(NewSU, Pred);
334 for (SDep &Succ : SU->
Succs) {
346 for (
const auto &[Del, Dep] : DelDeps)
347 RemovePred(Del, Dep);
355void ScheduleDAGFast::InsertCopiesAndMoveSuccs(SUnit *SU,
unsigned Reg,
358 SmallVectorImpl<SUnit*> &
Copies) {
359 SUnit *CopyFromSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
363 SUnit *CopyToSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
370 for (SDep &Succ : SU->
Succs) {
378 DelDeps.
push_back(std::make_pair(SuccSU, Succ));
381 for (
const auto &[Del, Dep] : DelDeps)
382 RemovePred(Del, Dep);
384 FromDep.setLatency(SU->
Latency);
385 AddPred(CopyFromSU, FromDep);
387 ToDep.setLatency(CopyFromSU->
Latency);
388 AddPred(CopyToSU, ToDep);
390 Copies.push_back(CopyFromSU);
391 Copies.push_back(CopyToSU);
399 std::vector<SUnit *> &LiveRegDefs,
407 if (!LiveRegDefs[*AI])
411 if (LiveRegDefs[*AI] == SU)
419 if (RegAdded.
insert(*AI).second) {
431bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
432 SmallVectorImpl<unsigned> &LRegs){
433 if (NumLiveRegs == 0)
436 SmallSet<unsigned, 4> RegAdded;
438 for (SDep &Pred : SU->
Preds) {
441 RegAdded, LRegs,
TRI);
445 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode()) {
450 if (
Node->getOperand(
NumOps-1).getValueType() == MVT::Glue)
454 unsigned Flags =
Node->getConstantOperandVal(i);
455 const InlineAsm::Flag
F(Flags);
456 unsigned NumVals =
F.getNumOperandRegisters();
459 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
462 for (; NumVals; --NumVals, ++i) {
476 SDNode *SrcNode =
Node->getOperand(2).getNode();
481 if (!
Node->isMachineOpcode())
483 const MCInstrDesc &MCID =
TII->get(
Node->getMachineOpcode());
487 return !LRegs.
empty();
493void ScheduleDAGFast::ListScheduleBottomUp() {
494 unsigned CurCycle = 0;
497 ReleasePredecessors(&ExitSU, CurCycle);
500 if (!SUnits.empty()) {
501 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
502 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
504 AvailableQueue.push(RootSU);
510 DenseMap<SUnit*, SmallVector<unsigned, 4> > LRegsMap;
512 while (!AvailableQueue.empty()) {
513 bool Delayed =
false;
515 SUnit *CurSU = AvailableQueue.pop();
517 SmallVector<unsigned, 4> LRegs;
518 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
521 LRegsMap.
insert(std::make_pair(CurSU, LRegs));
525 CurSU = AvailableQueue.pop();
531 if (Delayed && !CurSU) {
536 SUnit *TrySU = NotReady[0];
537 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
538 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
539 unsigned Reg = LRegs[0];
540 SUnit *LRDef = LiveRegDefs[
Reg];
551 SUnit *NewDef =
nullptr;
553 NewDef = CopyAndMoveSuccessors(LRDef);
554 if (!DestRC && !NewDef)
556 "register dependency!");
561 InsertCopiesAndMoveSuccs(LRDef,
Reg, DestRC, RC,
Copies);
563 << *
Copies.front() <<
"\n");
570 LiveRegDefs[
Reg] = NewDef;
582 for (SUnit *SU : NotReady) {
586 AvailableQueue.push(SU);
591 ScheduleNodeBottomUp(CurSU, CurCycle);
599 VerifyScheduledSequence(
true);
610class ScheduleDAGLinearize :
public ScheduleDAGSDNodes {
614 void Schedule()
override;
620 std::vector<SDNode*> Sequence;
621 DenseMap<SDNode*, SDNode*> GluedMap;
623 void ScheduleNode(SDNode *
N);
627void ScheduleDAGLinearize::ScheduleNode(SDNode *
N) {
628 if (
N->getNodeId() != 0)
631 if (!
N->isMachineOpcode() &&
638 Sequence.push_back(
N);
640 unsigned NumOps =
N->getNumOperands();
641 if (
unsigned NumLeft =
NumOps) {
642 SDNode *GluedOpN =
nullptr;
644 const SDValue &
Op =
N->getOperand(NumLeft-1);
645 SDNode *OpN =
Op.getNode();
647 if (NumLeft ==
NumOps &&
Op.getValueType() == MVT::Glue) {
660 auto DI = GluedMap.find(OpN);
661 if (DI != GluedMap.end() && DI->second !=
N)
666 assert(Degree > 0 &&
"Predecessor over-released!");
677 while (
SDNode *Glued =
N->getGluedUser())
682void ScheduleDAGLinearize::Schedule() {
683 LLVM_DEBUG(
dbgs() <<
"********** DAG Linearization **********\n");
686 unsigned DAGSize = 0;
687 for (SDNode &Node : DAG->allnodes()) {
691 unsigned Degree =
N->use_size();
692 N->setNodeId(Degree);
693 unsigned NumVals =
N->getNumValues();
694 if (NumVals &&
N->getValueType(NumVals-1) == MVT::Glue &&
695 N->hasAnyUseOfValue(NumVals-1)) {
699 GluedMap.insert(std::make_pair(
N, User));
703 if (
N->isMachineOpcode() ||
708 for (SDNode *Glue : Glues) {
709 SDNode *GUser = GluedMap[Glue];
710 unsigned Degree = Glue->getNodeId();
715 SDNode *ImmGUser = Glue->getGluedUser();
716 for (
const SDNode *U : Glue->users())
723 Sequence.reserve(DAGSize);
724 ScheduleNode(DAG->getRoot().getNode());
729 InstrEmitter
Emitter(DAG->getTarget(), BB, InsertPos);
734 unsigned NumNodes = Sequence.size();
735 MachineBasicBlock *BB =
Emitter.getBlock();
736 for (
unsigned i = 0; i != NumNodes; ++i) {
737 SDNode *
N = Sequence[NumNodes-i-1];
739 Emitter.EmitNode(
N,
false,
false, VRBaseMap);
742 if (
N->getHasDebugValue()) {
744 for (
auto *DV : DAG->GetDbgValues(
N)) {
745 if (!DV->isEmitted())
746 if (
auto *DbgMI =
Emitter.EmitDbgValue(DV, VRBaseMap))
747 BB->
insert(InsertPos, DbgMI);
754 InsertPos =
Emitter.getInsertPos();
764 return new ScheduleDAGFast(*IS->MF);
769 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
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Register const TargetRegisterInfo * TRI
Promote Memory to Register
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)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
SmallDenseMap< SDValue, Register, 16 > VRBaseMapType
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
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.
MachineInstrBundleIterator< MachineInstr > iterator
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
int getNodeId() const
Return the unique node id.
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.
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
@ 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.
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.
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.
@ 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.
@ User
could "use" a pointer
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
MCRegisterClass TargetRegisterClass