18 #define DEBUG_TYPE "machine-scheduler" 22 class GCNILPScheduler {
34 unsigned CurQueueId = 0;
36 std::vector<unsigned> SUNumbers;
39 unsigned CurCycle = 0;
41 unsigned getNodePriority(
const SUnit *SU)
const;
44 Candidate* pickCandidate();
46 void releasePending();
47 void advanceToCycle(
unsigned NextCycle);
48 void releasePredecessors(
const SUnit* SU);
60 unsigned &SethiUllmanNumber = SUNumbers[SU->
NodeNum];
61 if (SethiUllmanNumber != 0)
62 return SethiUllmanNumber;
66 if (Pred.
isCtrl())
continue;
69 if (PredSethiUllman > SethiUllmanNumber) {
70 SethiUllmanNumber = PredSethiUllman;
73 else if (PredSethiUllman == SethiUllmanNumber)
77 SethiUllmanNumber += Extra;
79 if (SethiUllmanNumber == 0)
80 SethiUllmanNumber = 1;
82 return SethiUllmanNumber;
87 unsigned GCNILPScheduler::getNodePriority(
const SUnit *SU)
const {
108 unsigned MaxHeight = 0;
110 if (Succ.
isCtrl())
continue;
114 if (Height > MaxHeight)
123 unsigned Scratches = 0;
125 if (Pred.
isCtrl())
continue;
146 if (LHeight != RHeight)
147 return LHeight > RHeight ? 1 : -1;
151 if (LDepth != RDepth) {
153 <<
") depth " << LDepth <<
" vs SU (" << right->
NodeNum 154 <<
") depth " << RDepth <<
"\n");
155 return LDepth < RDepth ? 1 : -1;
163 const SUnit *GCNILPScheduler::pickBest(
const SUnit *left,
const SUnit *right)
169 if (!DisableSchedCriticalPath) {
171 if (
std::abs(spread) > MaxReorderWindow) {
174 <<
"): " << right->
getDepth() <<
"\n");
182 if (
std::abs(spread) > MaxReorderWindow)
187 unsigned LPriority = getNodePriority(left);
188 unsigned RPriority = getNodePriority(right);
190 if (LPriority != RPriority)
191 return LPriority > RPriority ? right : left;
213 return LDist < RDist ? right : left;
218 if (LScratch != RScratch)
219 return LScratch > RScratch ? right : left;
222 if (!DisableSchedCycles) {
225 return result > 0 ? right : left;
237 "NodeQueueId cannot be zero");
241 GCNILPScheduler::Candidate* GCNILPScheduler::pickCandidate() {
242 if (AvailQueue.empty())
244 auto Best = AvailQueue.begin();
245 for (
auto I = std::next(AvailQueue.begin()),
E = AvailQueue.end();
I !=
E; ++
I) {
246 auto NewBestSU = pickBest(Best->SU,
I->SU);
247 if (NewBestSU != Best->SU) {
255 void GCNILPScheduler::releasePending() {
258 for(
auto I = PendingQueue.begin(),
E = PendingQueue.end();
I !=
E;) {
260 if (
C.SU->getHeight() <= CurCycle) {
261 PendingQueue.remove(
C);
262 AvailQueue.push_back(
C);
263 C.SU->NodeQueueId = CurQueueId++;
269 void GCNILPScheduler::advanceToCycle(
unsigned NextCycle) {
270 if (NextCycle <= CurCycle)
272 CurCycle = NextCycle;
276 void GCNILPScheduler::releasePredecessors(
const SUnit* SU) {
277 for (
const auto &PredEdge : SU->
Preds) {
278 auto PredSU = PredEdge.getSUnit();
279 if (PredEdge.isWeak())
281 assert(PredSU->isBoundaryNode() || PredSU->NumSuccsLeft > 0);
283 PredSU->setHeightToAtLeast(SU->
getHeight() + PredEdge.getLatency());
285 if (!PredSU->isBoundaryNode() && --PredSU->NumSuccsLeft == 0)
286 PendingQueue.push_front(*new (Alloc.
Allocate()) Candidate(PredSU));
290 std::vector<const SUnit*>
293 auto &SUnits =
const_cast<ScheduleDAG&
>(DAG).SUnits;
295 std::vector<SUnit> SUSavedCopy;
296 SUSavedCopy.resize(SUnits.size());
300 for (
const SUnit &SU : SUnits)
303 SUNumbers.assign(SUnits.size(), 0);
304 for (
const SUnit &SU : SUnits)
307 for (
auto SU : BotRoots) {
308 AvailQueue.push_back(
309 *
new (Alloc.
Allocate()) Candidate(const_cast<SUnit*>(SU)));
311 releasePredecessors(&DAG.
ExitSU);
313 std::vector<const SUnit*> Schedule;
314 Schedule.reserve(SUnits.size());
316 if (AvailQueue.empty() && !PendingQueue.empty()) {
317 auto EarliestSU = std::min_element(
318 PendingQueue.begin(), PendingQueue.end(),
319 [=](
const Candidate& C1,
const Candidate& C2) {
320 return C1.SU->getHeight() < C2.SU->getHeight();
322 advanceToCycle(
std::max(CurCycle + 1, EarliestSU->getHeight()));
324 if (AvailQueue.empty())
331 <<
' ' <<
C.SU->NodeNum;
334 auto C = pickCandidate();
336 AvailQueue.remove(*C);
342 releasePredecessors(SU);
343 Schedule.push_back(SU);
346 assert(SUnits.size() == Schedule.size());
351 for (
auto &SU : SUnits)
361 return S.schedule(BotRoots, DAG);
static int BUCompareLatency(const SUnit *left, const SUnit *right)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
unsigned NumPreds
of SDep::Data preds.
This class represents lattice values for constants.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
virtual void dumpNode(const SUnit &SU) const =0
static unsigned closestSucc(const SUnit *SU)
closestSucc - Returns the scheduled cycle of the successor which is closest to the current cycle...
SmallVector< SDep, 4 > Preds
All sunit predecessors.
bool isScheduled
True once scheduled.
unsigned NumSuccs
of SDep::Data sucss.
A simple intrusive list implementation.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
unsigned short Latency
Node latency.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
static cl::opt< bool > DisableSchedCriticalPath("disable-sched-critical-path", cl::Hidden, cl::init(false), cl::desc("Disable critical path priority in sched=list-ilp"))
static cl::opt< bool > DisableSchedHeight("disable-sched-height", cl::Hidden, cl::init(false), cl::desc("Disable scheduled-height priority in sched=list-ilp"))
static unsigned CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector< unsigned > &SUNumbers)
CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned NodeQueueId
Queue id of node.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
SUnit ExitSU
Special node for the region exit.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
static cl::opt< bool > DisableSchedCycles("disable-sched-cycles", cl::Hidden, cl::init(false), cl::desc("Disable cycle-level precision during preRA scheduling"))
unsigned NodeNum
Entry # of node in the node vector.
std::vector< const SUnit * > makeGCNILPScheduler(ArrayRef< const SUnit *> BotRoots, const ScheduleDAG &DAG)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< int > MaxReorderWindow("max-sched-reorder", cl::Hidden, cl::init(6), cl::desc("Number of instructions to allow ahead of the critical path " "in sched=list-ilp"))
SmallVector< SDep, 4 > Succs
All sunit successors.
Scheduling unit. This is a node in the scheduling DAG.
static unsigned calcMaxScratches(const SUnit *SU)
calcMaxScratches - Returns an cost estimate of the worse case requirement for scratch registers...