28 DGNode *TopN = Nodes.front();
37 DGNode *BotN = Nodes.front();
46 for (
auto *
N : Nodes) {
47 auto *
I =
N->getInstruction();
48 if (
I->getIterator() == Where)
50 I->moveBefore(*Where.getNodeParent(), Where);
69 while (!ListCopy.empty()) {
70 OS << *ListCopy.top() <<
"\n";
81void Scheduler::scheduleAndUpdateReadyList(
SchedBundle &Bndl) {
83 assert(ScheduleTopItOpt &&
"Should have been set by now!");
85 : std::next(*ScheduleTopItOpt);
97 for (
auto *DepN :
N->preds(DAG)) {
98 DepN->decrUnscheduledSuccs();
99 if (DepN->readyBottomUp() && !DepN->scheduled())
105 for (
auto *DepN :
N->succs(DAG)) {
106 DepN->decrUnscheduledPreds();
107 if (DepN->readyTopDown() && !DepN->scheduled())
119 auto *
N = DAG.getNode(
I);
126 bool IsScheduled = ScheduleTopItOpt &&
127 *ScheduleTopItOpt !=
I->getParent()->end() &&
129 (*ScheduleTopItOpt.value()).comesBefore(
I)) ||
131 I->comesBefore(&*ScheduleTopItOpt.value())));
139 for (
auto *PredN :
N->preds(DAG)) {
140 ReadyList.remove(PredN);
141 PredN->incrUnscheduledSuccs();
144 for (
auto *SuccN :
N->succs(DAG)) {
145 ReadyList.remove(SuccN);
146 SuccN->incrUnscheduledPreds();
155 for (
auto *
I : Instrs)
156 Nodes.push_back(DAG.getNode(
I));
157 auto BndlPtr = std::make_unique<SchedBundle>(std::move(Nodes));
158 auto *Bndl = BndlPtr.get();
159 Bndls[Bndl] = std::move(BndlPtr);
163void Scheduler::eraseBundle(
SchedBundle *SB) { Bndls.erase(SB); }
168 auto *InstrsSB = createBundle(Instrs);
173 bool KeepScheduling =
true;
174 while (KeepScheduling) {
175 enum class TryScheduleRes {
184 auto TryScheduleBndl = [
this, InstrsSB](
DGNode *ReadyN) -> TryScheduleRes {
185 auto *SB = ReadyN->getSchedBundle();
189 auto *SingletonSB = createBundle({ReadyN->getInstruction()});
190 scheduleAndUpdateReadyList(*SingletonSB);
191 return TryScheduleRes::Success;
193 if (SB->ready(Dir)) {
197 for (
auto *
N : *SB) {
202 scheduleAndUpdateReadyList(*SB);
205 return TryScheduleRes::Finished;
206 return TryScheduleRes::Success;
208 return TryScheduleRes::Failure;
210 while (!ReadyList.empty()) {
211 auto *ReadyN = ReadyList.pop();
212 auto Res = TryScheduleBndl(ReadyN);
214 case TryScheduleRes::Success:
217 case TryScheduleRes::Failure:
220 Retry.push_back(ReadyN);
222 case TryScheduleRes::Finished:
229 KeepScheduling =
false;
231 auto Res = TryScheduleBndl(
N);
232 if (Res == TryScheduleRes::Success) {
233 Retry.erase(
find(Retry,
N));
234 KeepScheduling =
true;
239 eraseBundle(InstrsSB);
243Scheduler::BndlSchedState
245 assert(!Instrs.empty() &&
"Expected non-empty bundle");
246 auto *N0 = DAG.getNode(Instrs[0]);
247 auto *SB0 = N0 !=
nullptr ? N0->getSchedBundle() :
nullptr;
248 bool AllUnscheduled = SB0 ==
nullptr;
249 bool FullyScheduled = SB0 !=
nullptr && !SB0->isSingleton();
251 auto *
N = DAG.getNode(
I);
252 auto *SB =
N !=
nullptr ?
N->getSchedBundle() :
nullptr;
255 AllUnscheduled =
false;
256 if (SB->isSingleton()) {
259 FullyScheduled =
false;
266 FullyScheduled =
false;
268 if ((SB !=
nullptr && !SB->isSingleton()) ||
269 (SB0 !=
nullptr && !SB0->isSingleton()))
270 return BndlSchedState::AlreadyScheduled;
273 return AllUnscheduled ? BndlSchedState::NoneScheduled
274 : FullyScheduled ? BndlSchedState::FullyScheduled
275 : BndlSchedState::TemporarilyScheduled;
295 ? &*ScheduleTopItOpt.value()
299 : &*ScheduleTopItOpt.value();
302 for (
auto *
I = LowestI, *
E = TopI->getPrevNode();
I !=
E;
303 I =
I->getPrevNode()) {
304 auto *N = DAG.getNode(I);
307 auto *SB = N->getSchedBundle();
308 if (SB->isSingleton())
318 auto *
N = DAG.getNode(&
I);
319 N->resetScheduleState();
323 for (
auto *PredN :
N->preds(DAG))
324 PredN->incrUnscheduledSuccs();
329 for (
auto *SuccN :
N->succs(DAG))
330 SuccN->incrUnscheduledPreds();
338 auto *
N = DAG.getNode(&
I);
339 if (
N->readyBottomUp())
347 return I->getParent() == (*Instrs.
begin())->getParent();
349 "Instrs not in the same BB, should have been rejected by Legality!");
351 if (!DAG.getInterval().empty()) {
352 auto *BB = DAG.getInterval().top()->getParent();
353 if (
any_of(Instrs, [BB](
auto *
I) {
return I->getParent() != BB; }))
356 if (ScheduledBB ==
nullptr)
357 ScheduledBB = Instrs[0]->getParent();
360 [
this](
Instruction *
I) {
return I->getParent() != ScheduledBB; }))
372 auto SchedState = getBndlSchedState(Instrs);
373 switch (SchedState) {
374 case BndlSchedState::FullyScheduled:
377 case BndlSchedState::AlreadyScheduled:
382 case BndlSchedState::TemporarilyScheduled:
387 trimSchedule(Instrs);
388 ScheduleTopItOpt = GetSchedPoint(Dir, Instrs);
389 return tryScheduleUntil(Instrs);
390 case BndlSchedState::NoneScheduled: {
392 if (!ScheduleTopItOpt)
394 ScheduleTopItOpt = GetSchedPoint(Dir, Instrs);
398 for (
auto &
I : Extension) {
399 auto *
N = DAG.getNode(&
I);
405 return tryScheduleUntil(Instrs);
413 OS <<
"ReadyList:\n";
418 if (ScheduleTopItOpt)
419 OS << **ScheduleTopItOpt;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent a constant reference to an array (0 or more elements consecutively in memory),...
InstListType::iterator iterator
Instruction iterators...
void reserve(size_type N)
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
This class implements an extremely fast bulk output stream that can only output to a stream.
A DependencyGraph Node that points to an Instruction and contains memory dependency edges.
Instruction * getInstruction() const
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
LLVM_ABI BBIterator getIterator() const
\Returns a BasicBlock::iterator for this Instruction.
bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
LLVM_DUMP_METHOD void dump() const
The nodes that need to be scheduled back-to-back in a single scheduling cycle form a SchedBundle.
LLVM_ABI DGNode * getBot() const
\Returns the bundle node that comes after the others in program order.
LLVM_ABI DGNode * getTop() const
\Returns the bundle node that comes before the others in program order.
SmallVector< DGNode *, 4 > ContainerTy
LLVM_DUMP_METHOD void dump() const
LLVM_ABI void cluster(BasicBlock::iterator Where)
Move all bundle instructions to Where back-to-back.
LLVM_DUMP_METHOD void dump() const
LLVM_ABI bool trySchedule(ArrayRef< Instruction * > Instrs)
Tries to build a schedule that includes all of Instrs scheduled at the same scheduling cycle.
static Instruction * getLowest(ArrayRef< Instruction * > Instrs)
\Returns the instruction in Instrs that is lowest in the BB.
static Instruction * getHighest(ArrayRef< Instruction * > Instrs)
\Returns the instruction in Instrs that is highest in the BB.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringLiteral schedDirectionToStr(SchedDirection Dir)
template class LLVM_TEMPLATE_ABI Interval< Instruction >
friend class Instruction
Iterator for Instructions in a `BasicBlock.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Success
The lock was released successfully.
ArrayRef(const T &OneElt) -> ArrayRef< T >