14 #define DEBUG_TYPE "pre-RA-sched"
31 STATISTIC(NumUnfolds,
"Number of nodes unfolded");
32 STATISTIC(NumDups,
"Number of duplicated nodes");
33 STATISTIC(NumPRCopies,
"Number of physical copies");
47 struct FastPriorityQueue {
50 bool empty()
const {
return Queue.
empty(); }
57 if (empty())
return NULL;
58 SUnit *V = Queue.back();
70 FastPriorityQueue AvailableQueue;
76 std::vector<SUnit*> LiveRegDefs;
77 std::vector<unsigned> LiveRegCycles;
93 void RemovePred(
SUnit *SU,
const SDep &D) {
98 void ReleasePred(
SUnit *SU,
SDep *PredEdge);
99 void ReleasePredecessors(
SUnit *SU,
unsigned CurCycle);
100 void ScheduleNodeBottomUp(
SUnit*,
unsigned);
102 void InsertCopiesAndMoveSuccs(
SUnit*,
unsigned,
107 void ListScheduleBottomUp();
110 bool forceUnitLatencies()
const {
return true; }
116 void ScheduleDAGFast::Schedule() {
117 DEBUG(
dbgs() <<
"********** List Scheduling **********\n");
120 LiveRegDefs.resize(TRI->getNumRegs(), NULL);
121 LiveRegCycles.resize(TRI->getNumRegs(), 0);
124 BuildSchedGraph(NULL);
126 DEBUG(
for (
unsigned su = 0, e = SUnits.size(); su != e; ++su)
127 SUnits[su].dumpAll(
this));
130 ListScheduleBottomUp();
139 void ScheduleDAGFast::ReleasePred(
SUnit *SU,
SDep *PredEdge) {
144 dbgs() <<
"*** Scheduling failed! ***\n";
146 dbgs() <<
" has been released too many times!\n";
156 AvailableQueue.push(PredSU);
160 void ScheduleDAGFast::ReleasePredecessors(
SUnit *SU,
unsigned CurCycle) {
164 ReleasePred(SU, &*
I);
165 if (
I->isAssignedRegDep()) {
170 if (!LiveRegDefs[
I->getReg()]) {
172 LiveRegDefs[
I->getReg()] =
I->getSUnit();
173 LiveRegCycles[
I->getReg()] = CurCycle;
182 void ScheduleDAGFast::ScheduleNodeBottomUp(
SUnit *SU,
unsigned CurCycle) {
183 DEBUG(
dbgs() <<
"*** Scheduling [" << CurCycle <<
"]: ");
186 assert(CurCycle >= SU->
getHeight() &&
"Node scheduled below its height!");
190 ReleasePredecessors(SU, CurCycle);
195 if (
I->isAssignedRegDep()) {
196 if (LiveRegCycles[
I->getReg()] ==
I->getSUnit()->getHeight()) {
197 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
198 assert(LiveRegDefs[
I->getReg()] == SU &&
199 "Physical register dependency violated?");
201 LiveRegDefs[
I->getReg()] = NULL;
202 LiveRegCycles[
I->getReg()] = 0;
212 SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(
SUnit *SU) {
221 bool TryUnfold =
false;
222 for (
unsigned i = 0, e = N->
getNumValues(); i != e; ++i) {
238 if (!
TII->unfoldMemoryOperand(*DAG, N, NewNodes))
242 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
245 SDNode *LoadNode = NewNodes[0];
246 unsigned NumVals = N->getNumValues();
248 for (
unsigned i = 0; i != NumVals; ++i)
250 DAG->ReplaceAllUsesOfValueWith(
SDValue(SU->
getNode(), OldNumVals-1),
253 SUnit *NewSU = newSUnit(N);
254 assert(N->getNodeId() == -1 &&
"Node already inserted!");
270 bool isNewLoad =
true;
276 LoadSU = newSUnit(LoadNode);
289 else if (
I->getSUnit()->getNode() &&
290 I->getSUnit()->getNode()->isOperandOf(LoadNode))
304 RemovePred(SU, ChainPred);
306 AddPred(LoadSU, ChainPred);
308 for (
unsigned i = 0, e = LoadPreds.
size(); i != e; ++i) {
309 const SDep &Pred = LoadPreds[i];
310 RemovePred(SU, Pred);
312 AddPred(LoadSU, Pred);
315 for (
unsigned i = 0, e = NodePreds.
size(); i != e; ++i) {
316 const SDep &Pred = NodePreds[i];
317 RemovePred(SU, Pred);
318 AddPred(NewSU, Pred);
320 for (
unsigned i = 0, e = NodeSuccs.
size(); i != e; ++i) {
321 SDep D = NodeSuccs[i];
324 RemovePred(SuccDep, D);
328 for (
unsigned i = 0, e = ChainSuccs.
size(); i != e; ++i) {
329 SDep D = ChainSuccs[i];
332 RemovePred(SuccDep, D);
359 if (!
I->isArtificial())
367 if (
I->isArtificial())
369 SUnit *SuccSU =
I->getSUnit();
375 DelDeps.
push_back(std::make_pair(SuccSU, D));
378 for (
unsigned i = 0, e = DelDeps.
size(); i != e; ++i)
379 RemovePred(DelDeps[i].first, DelDeps[i].second);
387 void ScheduleDAGFast::InsertCopiesAndMoveSuccs(
SUnit *SU,
unsigned Reg,
391 SUnit *CopyFromSU = newSUnit(static_cast<SDNode *>(NULL));
395 SUnit *CopyToSU = newSUnit(static_cast<SDNode *>(NULL));
404 if (
I->isArtificial())
406 SUnit *SuccSU =
I->getSUnit();
411 DelDeps.
push_back(std::make_pair(SuccSU, *
I));
414 for (
unsigned i = 0, e = DelDeps.
size(); i != e; ++i) {
415 RemovePred(DelDeps[i].first, DelDeps[i].second);
418 FromDep.setLatency(SU->
Latency);
419 AddPred(CopyFromSU, FromDep);
421 ToDep.setLatency(CopyFromSU->
Latency);
422 AddPred(CopyToSU, ToDep);
436 assert(MCID.
ImplicitDefs &&
"Physical reg def must be in implicit def list!");
438 for (
const uint16_t *ImpDef = MCID.
getImplicitDefs(); *ImpDef; ++ImpDef) {
449 std::vector<SUnit*> &LiveRegDefs,
455 if (LiveRegDefs[*AI] && LiveRegDefs[*AI] != SU) {
456 if (RegAdded.
insert(*AI)) {
469 bool ScheduleDAGFast::DelayForLiveRegsBottomUp(
SUnit *SU,
471 if (NumLiveRegs == 0)
478 if (
I->isAssignedRegDep()) {
480 RegAdded, LRegs, TRI);
487 unsigned NumOps = Node->getNumOperands();
488 if (Node->getOperand(NumOps-1).getValueType() ==
MVT::Glue)
491 for (
unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
493 cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
501 for (; NumVals; --NumVals, ++i) {
502 unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->
getReg();
511 if (!Node->isMachineOpcode())
520 return !LRegs.
empty();
526 void ScheduleDAGFast::ListScheduleBottomUp() {
527 unsigned CurCycle = 0;
530 ReleasePredecessors(&ExitSU, CurCycle);
533 if (!SUnits.empty()) {
534 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
535 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
537 AvailableQueue.push(RootSU);
545 while (!AvailableQueue.empty()) {
546 bool Delayed =
false;
548 SUnit *CurSU = AvailableQueue.pop();
551 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
554 LRegsMap.
insert(std::make_pair(CurSU, LRegs));
558 CurSU = AvailableQueue.pop();
564 if (Delayed && !CurSU) {
569 SUnit *TrySU = NotReady[0];
571 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
572 unsigned Reg = LRegs[0];
576 TRI->getMinimalPhysRegClass(Reg, VT);
588 NewDef = CopyAndMoveSuccessors(LRDef);
589 if (!DestRC && !NewDef)
591 "register dependency!");
596 InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies);
600 NewDef = Copies.
back();
604 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
605 LiveRegDefs[
Reg] = NewDef;
617 for (
unsigned i = 0, e = NotReady.
size(); i != e; ++i) {
618 NotReady[i]->isPending =
false;
621 AvailableQueue.push(NotReady[i]);
626 ScheduleNodeBottomUp(CurSU, CurCycle);
634 VerifyScheduledSequence(
true);
657 void ScheduleNode(
SDNode *N);
661 void ScheduleDAGLinearize::ScheduleNode(
SDNode *N) {
675 if (
unsigned NumLeft = NumOps) {
684 assert(OpN->
getNodeId() != 0 &&
"Glue operand not ready?");
695 if (DI != GluedMap.
end() && DI->second !=
N)
700 assert(Degree > 0 &&
"Predecessor over-released!");
716 void ScheduleDAGLinearize::Schedule() {
717 DEBUG(
dbgs() <<
"********** DAG Linearization **********\n");
720 unsigned DAGSize = 0;
722 E = DAG->allnodes_end();
I != E; ++
I) {
734 GluedMap.insert(std::make_pair(N, User));
743 for (
unsigned i = 0, e = Glues.
size(); i != e; ++i) {
745 SDNode *GUser = GluedMap[Glue];
761 ScheduleNode(DAG->getRoot().getNode());
770 dbgs() <<
"\n*** Final schedule ***\n";
774 unsigned NumNodes =
Sequence.size();
775 for (
unsigned i = 0; i != NumNodes; ++i) {
778 Emitter.EmitNode(N,
false,
false, VRBaseMap);
783 InsertPos = Emitter.getInsertPos();
784 return Emitter.getBlock();
793 return new ScheduleDAGFast(*IS->
MF);
798 return new ScheduleDAGLinearize(*IS->
MF);
void push_back(const T &Elt)
const uint16_t * getImplicitDefs() const
void dump() const
dump - Dump this node, for debugging.
bool isCommutable() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions. Register definitions always occur...
SDNode * getGluedNode() const
unsigned getOpcode() const
static bool isClobberKind(unsigned Flag)
unsigned getNumOperands() const
const SDValue & getOperand(unsigned Num) const
void removePred(const SDep &D)
void setNodeId(int Id)
setNodeId - Set unique node id.
const TargetRegisterClass * CopyDstRC
EntryToken - This is the marker used to indicate the start of a region.
unsigned getResNo() const
get the index which selects a specific result in the SDNode
SmallVector< SDep, 4 > Preds
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
unsigned getHeight() const
const HexagonInstrInfo * TII
#define llvm_unreachable(msg)
EVT getValueType(unsigned ResNo) const
Regular data dependence (aka true-dependence).
static bool isRegDefEarlyClobberKind(unsigned Flag)
unsigned getNumValues() const
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
ScheduleDAGSDNodes * createDAGLinearizer(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
static bool isRegDefKind(unsigned Flag)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
SDNode * getNode() const
get the SDNode which holds the desired result
bundle_iterator< MachineInstr, instr_iterator > iterator
void setHeightToAtLeast(unsigned NewHeight)
* if(!EatIfPresent(lltok::kw_thread_local)) return false
STATISTIC(NumUnfolds,"Number of nodes unfolded")
static unsigned getNumOperandRegisters(unsigned Flag)
use_iterator use_begin() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set. Returns -1 if it is not set...
const MCInstrDesc & get(unsigned Opcode) const
An unknown scheduling barrier.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
SDNode * getGluedUser() const
const TargetRegisterClass * CopySrcRC
static SDNode * findGluedUser(SDNode *N)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
static RegisterScheduler fastDAGScheduler("fast","Fast suboptimal list scheduling", createFastDAGScheduler)
static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII)
static use_iterator use_end()
void setLatency(unsigned Lat)
setLatency - Set the latency for this edge.
static bool isPhysicalRegister(unsigned Reg)
bool hasAnyUseOfValue(unsigned Value) const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
static bool CheckForLiveRegDef(SUnit *SU, unsigned Reg, std::vector< SUnit * > &LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI)
static RegisterScheduler linearizeDAGScheduler("linearize","Linearize DAG, no scheduling", createDAGLinearizer)
const uint16_t * ImplicitDefs
bool addPred(const SDep &D, bool Required=true)
SmallVector< SDep, 4 > Succs
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction. Note that variadic (isVari...
Arbitrary strong DAG edge (no real dependence).
ScheduleDAGSDNodes * createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
iterator find(const KeyT &Val)
void dump(const ScheduleDAG *G) const
SUnit - Scheduling unit. This is a node in the scheduling DAG.
bool isMachineOpcode() const
unsigned getMachineOpcode() const