16 DGNode *TopN = Nodes.front();
25 DGNode *BotN = Nodes.front();
34 for (
auto *
N : Nodes) {
35 auto *
I =
N->getInstruction();
36 if (
I->getIterator() == Where)
38 I->moveBefore(*Where.getNodeParent(), Where);
57 while (!ListCopy.empty()) {
58 OS << *ListCopy.top() <<
"\n";
70 OS <<
"Before begin of BB " << BB->getName();
72 OS <<
"At end of BB " << BB->getName();
83void Scheduler::scheduleAndUpdateReadyList(
SchedBundle &Bndl) {
85 assert(ScheduleFrontierOpt &&
"Should have been set by now!");
87 ? ScheduleFrontierOpt->getIterator()
88 : ScheduleFrontierOpt->getNext().getIterator();
100 for (
auto *DepN :
N->preds(DAG)) {
101 DepN->decrUnscheduledDeps();
102 if (DepN->ready() && !DepN->scheduled())
108 for (
auto *DepN :
N->succs(DAG)) {
109 DepN->decrUnscheduledDeps();
110 if (DepN->ready() && !DepN->scheduled())
120void Scheduler::notifyCreateInstrBeforeDAGUpdates(
DGNode *
N) {
125 ScheduleFrontierOpt &&
126 ScheduleFrontierOpt->getIterator() !=
I->getParent()->end() &&
128 (*ScheduleFrontierOpt.value()).comesBefore(
I)) ||
130 I->comesBefore(&*ScheduleFrontierOpt.value())));
135void Scheduler::notifyCreateInstrAfterDAGUpdates(
DGNode *
N) {
139 if (!
N->scheduled()) {
141 for (
auto *PredN :
N->preds(DAG)) {
142 ReadyList.remove(PredN);
143 PredN->incrUnscheduledDeps();
146 for (
auto *SuccN :
N->succs(DAG)) {
147 ReadyList.remove(SuccN);
148 SuccN->incrUnscheduledDeps();
158 auto *
N = DAG.getNode(
I);
164 auto UpdateNodeAndTryAddToReadyList = [
this,
N](
DGNode *DepN) {
165 if (DepN->scheduled())
167 if (!
N->scheduled() && !DepN->ready())
168 DepN->decrUnscheduledDeps();
169 if (DepN->ready() && !ReadyList.contains(DepN))
170 ReadyList.insert(DepN);
173 for (
auto *DepN :
N->preds(DAG))
174 UpdateNodeAndTryAddToReadyList(DepN);
176 for (
auto *DepN :
N->succs(DAG))
177 UpdateNodeAndTryAddToReadyList(DepN);
181void Scheduler::notifyMoveInstr(
Instruction *
I,
const BBIterator &To) {
192void Scheduler::notifySetUse(
const Use &U,
Value *NewSrc) {
197 DGNode *DstN = DAG.getNode(DstI);
208 if (OldSrcN && OldSrcN->ready() && !OldSrcN->scheduled() &&
209 !ReadyList.contains(OldSrcN))
210 ReadyList.insert(OldSrcN);
212 if (NewSrcN && (!DstN || !DstN->scheduled()) && !NewSrcN->ready())
213 ReadyList.remove(NewSrcN);
218 if (DstN && DstN->ready() && !NewSrcN->scheduled() &&
219 !ReadyList.contains(NewSrcN))
220 ReadyList.insert(NewSrcN);
222 if (DstN && !DstN->ready())
223 ReadyList.remove(NewSrcN);
229SchedBundle *Scheduler::createBundle(ArrayRef<Instruction *> Instrs) {
232 for (
auto *
I : Instrs)
233 Nodes.push_back(DAG.getNode(
I));
234 auto BndlPtr = std::make_unique<SchedBundle>(std::move(Nodes));
235 auto *Bndl = BndlPtr.get();
236 Bndls[Bndl] = std::move(BndlPtr);
240void Scheduler::eraseBundle(
SchedBundle *SB) { Bndls.erase(SB); }
242bool Scheduler::tryScheduleUntil(ArrayRef<Instruction *> Instrs) {
245 auto *InstrsSB = createBundle(Instrs);
250 bool KeepScheduling =
true;
251 while (KeepScheduling) {
252 enum class TryScheduleRes {
261 auto TryScheduleBndl = [
this, InstrsSB](
DGNode *ReadyN) -> TryScheduleRes {
262 auto *SB = ReadyN->getSchedBundle();
266 auto *SingletonSB = createBundle({ReadyN->getInstruction()});
267 scheduleAndUpdateReadyList(*SingletonSB);
268 return TryScheduleRes::Success;
270 if (SB->ready(Dir)) {
274 for (
auto *
N : *SB) {
279 scheduleAndUpdateReadyList(*SB);
282 return TryScheduleRes::Finished;
283 return TryScheduleRes::Success;
285 return TryScheduleRes::Failure;
287 while (!ReadyList.empty()) {
288 auto *ReadyN = ReadyList.pop();
289 auto Res = TryScheduleBndl(ReadyN);
291 case TryScheduleRes::Success:
294 case TryScheduleRes::Failure:
297 Retry.push_back(ReadyN);
299 case TryScheduleRes::Finished:
306 KeepScheduling =
false;
308 auto Res = TryScheduleBndl(
N);
309 if (Res == TryScheduleRes::Success) {
310 Retry.erase(
find(Retry,
N));
311 KeepScheduling =
true;
319 for (
auto *RetryN : Retry)
320 ReadyList.insert(RetryN);
322 eraseBundle(InstrsSB);
326Scheduler::BndlSchedState
327Scheduler::getBndlSchedState(ArrayRef<Instruction *> Instrs)
const {
328 assert(!Instrs.empty() &&
"Expected non-empty bundle");
329 auto *N0 = DAG.getNode(Instrs[0]);
330 auto *SB0 = N0 !=
nullptr ? N0->getSchedBundle() :
nullptr;
331 bool AllUnscheduled = SB0 ==
nullptr;
332 bool FullyScheduled = SB0 !=
nullptr && !SB0->isSingleton();
334 auto *
N = DAG.getNode(
I);
335 auto *SB =
N !=
nullptr ?
N->getSchedBundle() :
nullptr;
338 AllUnscheduled =
false;
339 if (SB->isSingleton()) {
342 FullyScheduled =
false;
349 FullyScheduled =
false;
351 if ((SB !=
nullptr && !SB->isSingleton()) ||
352 (SB0 !=
nullptr && !SB0->isSingleton()))
353 return BndlSchedState::AlreadyScheduled;
356 return AllUnscheduled ? BndlSchedState::NoneScheduled
357 : FullyScheduled ? BndlSchedState::FullyScheduled
358 : BndlSchedState::TemporarilyScheduled;
361void Scheduler::trimSchedule(ArrayRef<Instruction *> Instrs) {
378 ? &*ScheduleFrontierOpt.value()
382 : &*ScheduleFrontierOpt.value();
388 for (
auto &
I : ResetIntvl) {
389 auto *
N = DAG.getNode(&
I);
392 auto *SB =
N->getSchedBundle();
393 if (SB->isSingleton())
395 N->resetScheduleState();
400 auto *
N = DAG.getNode(&
I);
404 for (
auto *PredN :
N->preds(DAG))
405 PredN->incrUnscheduledDeps();
410 for (
auto *SuccN :
N->succs(DAG))
411 SuccN->incrUnscheduledDeps();
424 auto *
N = DAG.getNode(&
I);
431void Scheduler::assertSameDirection(ArrayRef<Instruction *> Instrs)
const {
437 return ScheduleFrontierOpt->comesBefore(*
I);
439 "Wrong scheduling direction!");
444 return ScheduleFrontierOpt->comesBefore(*
I);
446 "Wrong scheduling direction!");
455 return I->getParent() == (*Instrs.
begin())->getParent();
457 "Instrs not in the same BB, should have been rejected by Legality!");
459 if (!DAG.getInterval().empty()) {
460 auto *BB = DAG.getInterval().top()->getParent();
461 if (
any_of(Instrs, [BB](
auto *
I) {
return I->getParent() != BB; }))
464 if (ScheduledBB ==
nullptr)
465 ScheduledBB = Instrs[0]->getParent();
468 [
this](
Instruction *
I) {
return I->getParent() != ScheduledBB; }))
483 auto SchedState = getBndlSchedState(Instrs);
484 switch (SchedState) {
485 case BndlSchedState::FullyScheduled:
488 case BndlSchedState::AlreadyScheduled:
493 case BndlSchedState::TemporarilyScheduled:
498 trimSchedule(Instrs);
499 ScheduleFrontierOpt = GetSchedPoint(Dir, Instrs);
500 return tryScheduleUntil(Instrs);
501 case BndlSchedState::NoneScheduled: {
503 if (!ScheduleFrontierOpt) {
505 ScheduleFrontierOpt = GetSchedPoint(Dir, Instrs);
508 assertSameDirection(Instrs);
514 for (
auto &
I : Extension) {
515 auto *
N = DAG.getNode(&
I);
518 if (
N->ready() && !ReadyList.contains(
N))
522 return tryScheduleUntil(Instrs);
530 OS <<
"ReadyList:\n";
535 if (ScheduleFrontierOpt)
536 OS << **ScheduleFrontierOpt;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
std::pair< uint64_t, uint64_t > Interval
InstListType::iterator iterator
Instruction iterators...
void reserve(size_type N)
This class implements an extremely fast bulk output stream that can only output to a stream.
An ArrayRef of Values or Instructions that we can print/dump for debugging.
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(BndlRef< Instruction * > Instrs)
Tries to build a schedule that includes all of Instrs scheduled at the same scheduling cycle.
The scheduling point in the context of the Scheduler points to the top-of-schedule (i....
SchedulingPoint getNext() const
Returns the SchedulingPoint pointing after this.
BasicBlock * atEndOrNull() const
If the SchedulingPoint points after the last instruction in the BB then this returns the correspondin...
Instruction * atInstrOrNull() const
Returns the instruction pointed to by this SchedulingPoint or null if we are before/after BB.
LLVM_DUMP_METHOD void dump() const
SchedulingPoint getPrev() const
Returns the SchedulingPoint pointing before this.
BasicBlock * atBeforeBeginOrNull() const
If the SchedulingPoint points to before the beginning of a BB, then this returns that BB,...
void print(raw_ostream &OS) const
Represents a Def-use/Use-def edge in SandboxIR.
A SandboxIR Value has users. This is the base class.
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)
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.