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;
77 ScheduleDAGFast(MachineFunction &mf)
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,
94 const TargetRegisterClass*,
95 const TargetRegisterClass*,
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)
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!");
244 const MCInstrDesc &MCID =
TII->get(
N->getMachineOpcode());
257 bool isNewLoad =
true;
263 LoadSU = newSUnit(LoadNode);
272 for (SDep &Pred : SU->
Preds) {
281 for (SDep &Succ : SU->
Succs) {
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);
338 for (SDep &Pred : SU->
Preds)
340 AddPred(NewSU, Pred);
345 for (SDep &Succ : SU->
Succs) {
357 for (
const auto &[Del, Dep] : DelDeps)
358 RemovePred(Del, Dep);
366void ScheduleDAGFast::InsertCopiesAndMoveSuccs(SUnit *SU,
unsigned Reg,
367 const TargetRegisterClass *DestRC,
368 const TargetRegisterClass *SrcRC,
369 SmallVectorImpl<SUnit*> &
Copies) {
370 SUnit *CopyFromSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
374 SUnit *CopyToSU = newSUnit(
static_cast<SDNode *
>(
nullptr));
381 for (SDep &Succ : SU->
Succs) {
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);
410 std::vector<SUnit *> &LiveRegDefs,
418 if (!LiveRegDefs[*AI])
422 if (LiveRegDefs[*AI] == SU)
430 if (RegAdded.
insert(*AI).second) {
442bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
443 SmallVectorImpl<unsigned> &LRegs){
444 if (NumLiveRegs == 0)
447 SmallSet<unsigned, 4> RegAdded;
449 for (SDep &Pred : SU->
Preds) {
452 RegAdded, LRegs,
TRI);
456 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode()) {
461 if (
Node->getOperand(
NumOps-1).getValueType() == MVT::Glue)
465 unsigned Flags =
Node->getConstantOperandVal(i);
466 const InlineAsm::Flag
F(Flags);
467 unsigned NumVals =
F.getNumOperandRegisters();
470 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
473 for (; NumVals; --NumVals, ++i) {
487 SDNode *SrcNode =
Node->getOperand(2).getNode();
492 if (!
Node->isMachineOpcode())
494 const MCInstrDesc &MCID =
TII->get(
Node->getMachineOpcode());
498 return !LRegs.
empty();
504void ScheduleDAGFast::ListScheduleBottomUp() {
505 unsigned CurCycle = 0;
508 ReleasePredecessors(&ExitSU, CurCycle);
511 if (!SUnits.empty()) {
512 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
513 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
515 AvailableQueue.push(RootSU);
521 DenseMap<SUnit*, SmallVector<unsigned, 4> > LRegsMap;
523 while (!AvailableQueue.empty()) {
524 bool Delayed =
false;
526 SUnit *CurSU = AvailableQueue.pop();
528 SmallVector<unsigned, 4> LRegs;
529 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
532 LRegsMap.
insert(std::make_pair(CurSU, LRegs));
536 CurSU = AvailableQueue.pop();
542 if (Delayed && !CurSU) {
547 SUnit *TrySU = NotReady[0];
548 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
549 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
550 unsigned Reg = LRegs[0];
551 SUnit *LRDef = LiveRegDefs[
Reg];
552 const TargetRegisterClass *RC =
TRI->getMinimalPhysRegClass(
Reg);
553 const TargetRegisterClass *DestRC =
TRI->getCrossCopyRegClass(RC);
562 SUnit *NewDef =
nullptr;
564 NewDef = CopyAndMoveSuccessors(LRDef);
565 if (!DestRC && !NewDef)
567 "register dependency!");
572 InsertCopiesAndMoveSuccs(LRDef,
Reg, DestRC, RC,
Copies);
574 <<
" to SU #" <<
Copies.front()->NodeNum <<
"\n");
580 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
581 LiveRegDefs[
Reg] = NewDef;
593 for (SUnit *SU : NotReady) {
597 AvailableQueue.push(SU);
602 ScheduleNodeBottomUp(CurSU, CurCycle);
610 VerifyScheduledSequence(
true);
621class ScheduleDAGLinearize :
public ScheduleDAGSDNodes {
623 ScheduleDAGLinearize(MachineFunction &mf) : ScheduleDAGSDNodes(mf) {}
625 void Schedule()
override;
631 std::vector<SDNode*> Sequence;
632 DenseMap<SDNode*, SDNode*> GluedMap;
634 void ScheduleNode(SDNode *
N);
638void ScheduleDAGLinearize::ScheduleNode(SDNode *
N) {
639 if (
N->getNodeId() != 0)
642 if (!
N->isMachineOpcode() &&
649 Sequence.push_back(
N);
651 unsigned NumOps =
N->getNumOperands();
652 if (
unsigned NumLeft =
NumOps) {
653 SDNode *GluedOpN =
nullptr;
656 SDNode *OpN =
Op.getNode();
658 if (NumLeft ==
NumOps &&
Op.getValueType() == MVT::Glue) {
671 auto DI = GluedMap.find(OpN);
672 if (DI != GluedMap.end() && DI->second !=
N)
677 assert(Degree > 0 &&
"Predecessor over-released!");
688 while (
SDNode *Glued =
N->getGluedUser())
693void ScheduleDAGLinearize::Schedule() {
694 LLVM_DEBUG(
dbgs() <<
"********** DAG Linearization **********\n");
697 unsigned DAGSize = 0;
698 for (SDNode &Node : DAG->allnodes()) {
702 unsigned Degree =
N->use_size();
703 N->setNodeId(Degree);
704 unsigned NumVals =
N->getNumValues();
705 if (NumVals &&
N->getValueType(NumVals-1) == MVT::Glue &&
706 N->hasAnyUseOfValue(NumVals-1)) {
710 GluedMap.insert(std::make_pair(
N, User));
714 if (
N->isMachineOpcode() ||
719 for (SDNode *Glue : Glues) {
720 SDNode *GUser = GluedMap[Glue];
721 unsigned Degree = Glue->getNodeId();
726 SDNode *ImmGUser = Glue->getGluedUser();
727 for (
const SDNode *U : Glue->users())
734 Sequence.reserve(DAGSize);
735 ScheduleNode(DAG->getRoot().getNode());
740 InstrEmitter
Emitter(DAG->getTarget(), BB, InsertPos);
745 unsigned NumNodes = Sequence.size();
746 MachineBasicBlock *BB =
Emitter.getBlock();
747 for (
unsigned i = 0; i != NumNodes; ++i) {
748 SDNode *
N = Sequence[NumNodes-i-1];
750 Emitter.EmitNode(
N,
false,
false, VRBaseMap);
753 if (
N->getHasDebugValue()) {
755 for (
auto *DV : DAG->GetDbgValues(
N)) {
756 if (!DV->isEmitted())
757 if (
auto *DbgMI =
Emitter.EmitDbgValue(DV, VRBaseMap))
758 BB->
insert(InsertPos, DbgMI);
765 InsertPos =
Emitter.getInsertPos();
775 return new ScheduleDAGFast(*IS->
MF);
780 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.