LLVM: lib/Transforms/Vectorize/SandboxVectorizer/Scheduler.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
11
13
14
16 DGNode *TopN = Nodes.front();
18 if (N->getInstruction()->comesBefore(TopN->getInstruction()))
19 TopN = N;
20 }
21 return TopN;
22}
23
25 DGNode *BotN = Nodes.front();
28 BotN = N;
29 }
30 return BotN;
31}
32
34 for (auto *N : Nodes) {
35 auto *I = N->getInstruction();
36 if (I->getIterator() == Where)
37 ++Where;
38 I->moveBefore(*Where.getNodeParent(), Where);
39 }
40}
41
42#ifndef NDEBUG
44 for (auto *N : Nodes)
45 OS << *N;
46}
47
52#endif
53
54#ifndef NDEBUG
56 auto ListCopy = List;
57 while (!ListCopy.empty()) {
58 OS << *ListCopy.top() << "\n";
59 ListCopy.pop();
60 }
61}
62
67#endif
68
69void Scheduler::scheduleAndUpdateReadyList(SchedBundle &Bndl) {
70
71 assert(ScheduleTopItOpt && "Should have been set by now!");
72 auto Where = *ScheduleTopItOpt;
73
75
77
78
80 for (auto *DepN : N->preds(DAG)) {
81 DepN->decrUnscheduledSuccs();
82 if (DepN->ready() && !DepN->scheduled())
83 ReadyList.insert(DepN);
84 }
85 N->setScheduled(true);
86 }
87}
88
89void Scheduler::notifyCreateInstr(Instruction *I) {
90
92
93
94 if (N == nullptr)
95 return;
96
97
98 bool IsScheduled = ScheduleTopItOpt &&
99 *ScheduleTopItOpt != I->getParent()->end() &&
100 (*ScheduleTopItOpt.value()).comesBefore(I);
101 if (IsScheduled)
102 N->setScheduled(true);
103
104
105
106 if (!IsScheduled) {
107 for (auto *PredN : N->preds(DAG)) {
108 ReadyList.remove(PredN);
109 PredN->incrUnscheduledSuccs();
110 }
111 }
112}
113
116 Nodes.reserve(Instrs.size());
117 for (auto *I : Instrs)
118 Nodes.push_back(DAG.getNode(I));
119 auto BndlPtr = std::make_unique(std::move(Nodes));
120 auto *Bndl = BndlPtr.get();
121 Bndls[Bndl] = std::move(BndlPtr);
122 return Bndl;
123}
124
125void Scheduler::eraseBundle(SchedBundle *SB) { Bndls.erase(SB); }
126
128
129
130 auto *InstrsSB = createBundle(Instrs);
131
132
133
135 bool KeepScheduling = true;
136 while (KeepScheduling) {
137 enum class TryScheduleRes {
138 Success,
139 Failure,
140 Finished,
141
142 };
143
144
145
146 auto TryScheduleBndl = [this, InstrsSB](DGNode *ReadyN) -> TryScheduleRes {
147 auto *SB = ReadyN->getSchedBundle();
148 if (SB == nullptr) {
149
150
151 auto *SingletonSB = createBundle({ReadyN->getInstruction()});
152 scheduleAndUpdateReadyList(*SingletonSB);
153 return TryScheduleRes::Success;
154 }
155 if (SB->ready()) {
156
157
158
159 for (auto *N : *SB) {
160 if (N != ReadyN)
161 ReadyList.remove(N);
162 }
163
164 scheduleAndUpdateReadyList(*SB);
165 if (SB == InstrsSB)
166
167 return TryScheduleRes::Finished;
168 return TryScheduleRes::Success;
169 }
170 return TryScheduleRes::Failure;
171 };
172 while (!ReadyList.empty()) {
173 auto *ReadyN = ReadyList.pop();
174 auto Res = TryScheduleBndl(ReadyN);
175 switch (Res) {
176 case TryScheduleRes::Success:
177
178 continue;
179 case TryScheduleRes::Failure:
180
181
182 Retry.push_back(ReadyN);
183 continue;
184 case TryScheduleRes::Finished:
185
186 return true;
187 }
189 }
190
191 KeepScheduling = false;
193 auto Res = TryScheduleBndl(N);
194 if (Res == TryScheduleRes::Success) {
195 Retry.erase(find(Retry, N));
196 KeepScheduling = true;
197 }
198 }
199 }
200
201 eraseBundle(InstrsSB);
202 return false;
203}
204
205Scheduler::BndlSchedState
207 assert(!Instrs.empty() && "Expected non-empty bundle");
208 auto *N0 = DAG.getNode(Instrs[0]);
209 auto *SB0 = N0 != nullptr ? N0->getSchedBundle() : nullptr;
210 bool AllUnscheduled = SB0 == nullptr;
211 bool FullyScheduled = SB0 != nullptr && !SB0->isSingleton();
214 auto *SB = N != nullptr ? N->getSchedBundle() : nullptr;
215 if (SB != nullptr) {
216
217 AllUnscheduled = false;
218 if (SB->isSingleton()) {
219
220
221 FullyScheduled = false;
222 }
223 }
224
225 if (SB != SB0) {
226
227
228 FullyScheduled = false;
229
230 if ((SB != nullptr && !SB->isSingleton()) ||
231 (SB0 != nullptr && !SB0->isSingleton()))
232 return BndlSchedState::AlreadyScheduled;
233 }
234 }
235 return AllUnscheduled ? BndlSchedState::NoneScheduled
236 : FullyScheduled ? BndlSchedState::FullyScheduled
237 : BndlSchedState::TemporarilyScheduled;
238}
239
241
242
243
244
245
246
247
248
249
250
251
252
253
254 Instruction *TopI = &*ScheduleTopItOpt.value();
256
257 for (auto *I = LowestI, *E = TopI->getPrevNode(); I != E;
260 if (N == nullptr)
261 continue;
262 auto *SB = N->getSchedBundle();
263 if (SB->isSingleton())
264 eraseBundle(SB);
265 }
266
267
268
269
270
273 auto *N = DAG.getNode(&I);
274 N->resetScheduleState();
275
276
277 for (auto *PredN : N->preds(DAG))
278 PredN->incrUnscheduledSuccs();
279 }
280
281 ReadyList.clear();
284 auto *N = DAG.getNode(&I);
285 if (N->ready())
286 ReadyList.insert(N);
287 }
288}
289
293 return I->getParent() == (*Instrs.begin())->getParent();
294 }) &&
295 "Instrs not in the same BB, should have been rejected by Legality!");
296
297 if (!DAG.getInterval().empty()) {
298 auto *BB = DAG.getInterval().top()->getParent();
299 if (any_of(Instrs, [BB](auto *I) { return I->getParent() != BB; }))
300 return false;
301 }
302 if (ScheduledBB == nullptr)
303 ScheduledBB = Instrs[0]->getParent();
304
306 [this](Instruction *I) { return I->getParent() != ScheduledBB; }))
307 return false;
308 auto SchedState = getBndlSchedState(Instrs);
309 switch (SchedState) {
310 case BndlSchedState::FullyScheduled:
311
312 return true;
313 case BndlSchedState::AlreadyScheduled:
314
315
316
317 return false;
318 case BndlSchedState::TemporarilyScheduled:
319
320
321
322 DAG.extend(Instrs);
323 trimSchedule(Instrs);
324 ScheduleTopItOpt = std::next(VecUtils::getLowest(Instrs)->getIterator());
325 return tryScheduleUntil(Instrs);
326 case BndlSchedState::NoneScheduled: {
327
328 if (!ScheduleTopItOpt)
329
330 ScheduleTopItOpt = std::next(VecUtils::getLowest(Instrs)->getIterator());
331
333
335 auto *N = DAG.getNode(&I);
336 if (N->ready())
337 ReadyList.insert(N);
338 }
339
340 return tryScheduleUntil(Instrs);
341 }
342 }
344}
345
346#ifndef NDEBUG
348 OS << "ReadyList:\n";
349 ReadyList.dump(OS);
350 OS << "Top of schedule: ";
351 if (ScheduleTopItOpt)
352 OS << **ScheduleTopItOpt;
353 else
354 OS << "Empty";
355 OS << "\n";
356}
358#endif
359
360}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
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
Definition Scheduler.cpp:63
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.
Definition Scheduler.cpp:24
LLVM_ABI DGNode * getTop() const
\Returns the bundle node that comes before the others in program order.
Definition Scheduler.cpp:15
SmallVector< DGNode *, 4 > ContainerTy
LLVM_DUMP_METHOD void dump() const
Definition Scheduler.cpp:48
LLVM_ABI void cluster(BasicBlock::iterator Where)
Move all bundle instructions to Where back-to-back.
Definition Scheduler.cpp:33
LLVM_DUMP_METHOD void dump() const
Definition Scheduler.cpp:357
LLVM_ABI bool trySchedule(ArrayRef< Instruction * > Instrs)
Tries to build a schedule that includes all of Instrs scheduled at the same scheduling cycle.
Definition Scheduler.cpp:290
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.
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 >