34 for (
auto *
N : Nodes) {
35 auto *
I =
N->getInstruction();
36 if (
I->getIterator() == Where)
57 while (!ListCopy.empty()) {
58 OS << *ListCopy.top() <<
"\n";
69void Scheduler::scheduleAndUpdateReadyList(
SchedBundle &Bndl) {
71 assert(ScheduleTopItOpt &&
"Should have been set by now!");
72 auto Where = *ScheduleTopItOpt;
80 for (
auto *DepN :
N->preds(DAG)) {
81 DepN->decrUnscheduledSuccs();
82 if (DepN->ready() && !DepN->scheduled())
85 N->setScheduled(
true);
89void Scheduler::notifyCreateInstr(Instruction *
I) {
98 bool IsScheduled = ScheduleTopItOpt &&
99 *ScheduleTopItOpt !=
I->getParent()->end() &&
100 (*ScheduleTopItOpt.value()).comesBefore(
I);
102 N->setScheduled(
true);
107 for (
auto *PredN :
N->preds(DAG)) {
109 PredN->incrUnscheduledSuccs();
114SchedBundle *Scheduler::createBundle(ArrayRef<Instruction *> Instrs) {
117 for (
auto *
I : Instrs)
119 auto BndlPtr = std::make_unique<SchedBundle>(std::move(Nodes));
120 auto *Bndl = BndlPtr.get();
121 Bndls[Bndl] = std::move(BndlPtr);
125void Scheduler::eraseBundle(SchedBundle *SB) { Bndls.erase(SB); }
127bool Scheduler::tryScheduleUntil(ArrayRef<Instruction *> Instrs) {
130 auto *InstrsSB = createBundle(Instrs);
134 SmallVector<DGNode *> Retry;
135 bool KeepScheduling =
true;
136 while (KeepScheduling) {
137 enum class TryScheduleRes {
146 auto TryScheduleBndl = [
this, InstrsSB](
DGNode *ReadyN) -> TryScheduleRes {
147 auto *SB = ReadyN->getSchedBundle();
151 auto *SingletonSB = createBundle({ReadyN->getInstruction()});
152 scheduleAndUpdateReadyList(*SingletonSB);
153 return TryScheduleRes::Success;
159 for (
auto *
N : *SB) {
164 scheduleAndUpdateReadyList(*SB);
167 return TryScheduleRes::Finished;
168 return TryScheduleRes::Success;
170 return TryScheduleRes::Failure;
172 while (!ReadyList.
empty()) {
173 auto *ReadyN = ReadyList.
pop();
174 auto Res = TryScheduleBndl(ReadyN);
176 case TryScheduleRes::Success:
179 case TryScheduleRes::Failure:
182 Retry.push_back(ReadyN);
184 case TryScheduleRes::Finished:
191 KeepScheduling =
false;
193 auto Res = TryScheduleBndl(
N);
194 if (Res == TryScheduleRes::Success) {
195 Retry.erase(
find(Retry,
N));
196 KeepScheduling =
true;
201 eraseBundle(InstrsSB);
205Scheduler::BndlSchedState
206Scheduler::getBndlSchedState(ArrayRef<Instruction *> Instrs)
const {
207 assert(!Instrs.empty() &&
"Expected non-empty bundle");
208 auto *N0 = DAG.
getNode(Instrs[0]);
210 bool AllUnscheduled = SB0 ==
nullptr;
211 bool FullyScheduled = SB0 !=
nullptr && !SB0->
isSingleton();
214 auto *SB =
N !=
nullptr ?
N->getSchedBundle() :
nullptr;
217 AllUnscheduled =
false;
218 if (SB->isSingleton()) {
221 FullyScheduled =
false;
228 FullyScheduled =
false;
230 if ((SB !=
nullptr && !SB->isSingleton()) ||
231 (SB0 !=
nullptr && !SB0->isSingleton()))
232 return BndlSchedState::AlreadyScheduled;
235 return AllUnscheduled ? BndlSchedState::NoneScheduled
236 : FullyScheduled ? BndlSchedState::FullyScheduled
237 : BndlSchedState::TemporarilyScheduled;
240void Scheduler::trimSchedule(ArrayRef<Instruction *> Instrs) {
254 Instruction *TopI = &*ScheduleTopItOpt.value();
257 for (
auto *
I = LowestI, *
E = TopI->getPrevNode();
I !=
E;
258 I =
I->getPrevNode()) {
262 auto *SB =
N->getSchedBundle();
263 if (SB->isSingleton())
272 for (Instruction &
I : ResetIntvl) {
274 N->resetScheduleState();
277 for (
auto *PredN :
N->preds(DAG))
278 PredN->incrUnscheduledSuccs();
283 for (Instruction &
I : RefillIntvl) {
293 return I->getParent() == (*Instrs.
begin())->getParent();
295 "Instrs not in the same BB, should have been rejected by Legality!");
299 if (
any_of(Instrs, [BB](
auto *
I) {
return I->getParent() != BB; }))
302 if (ScheduledBB ==
nullptr)
303 ScheduledBB = Instrs[0]->getParent();
306 [
this](
Instruction *
I) {
return I->getParent() != ScheduledBB; }))
308 auto SchedState = getBndlSchedState(Instrs);
309 switch (SchedState) {
310 case BndlSchedState::FullyScheduled:
313 case BndlSchedState::AlreadyScheduled:
318 case BndlSchedState::TemporarilyScheduled:
323 trimSchedule(Instrs);
325 return tryScheduleUntil(Instrs);
326 case BndlSchedState::NoneScheduled: {
328 if (!ScheduleTopItOpt)
340 return tryScheduleUntil(Instrs);
348 OS <<
"ReadyList:\n";
350 OS <<
"Top of schedule: ";
351 if (ScheduleTopItOpt)
352 OS << **ScheduleTopItOpt;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::pair< uint64_t, uint64_t > Interval
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
void reserve(size_type N)
This class implements an extremely fast bulk output stream that can only output to a stream.
Iterator for Instructions in a `BasicBlock.
LLVM_ABI BasicBlock * getNodeParent() const
\Returns the parent BB.
A DependencyGraph Node that points to an Instruction and contains memory dependency edges.
SchedBundle * getSchedBundle() const
\Returns the scheduling bundle that this node belongs to, or nullptr.
Instruction * getInstruction() const
Interval< Instruction > getInterval() const
\Returns the range of instructions included in the DAG.
DGNode * getNode(Instruction *I) const
LLVM_ABI Interval< Instruction > extend(ArrayRef< Instruction * > Instrs)
Build/extend the dependency graph such that it includes Instrs.
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
void remove(DGNode *N)
\Removes N if found in the ready list.
void dump(raw_ostream &OS) 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.
bool isSingleton() const
Singleton bundles are created when scheduling instructions temporarily to fill in the schedule until ...
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ Success
The lock was released successfully.