108 using ElemToSuperNodeMap =
117 auto H = getHash(Deps);
118 if (
auto *ExistingSN = findCanonicalSuperNode(
H, Deps)) {
119 for (
auto &[Container, Elems] : Defs) {
120 auto &DstCElems = ExistingSN->Defs[Container];
121 [[maybe_unused]]
size_t ExpectedSize =
122 DstCElems.size() + Elems.size();
123 DstCElems.insert(Elems.begin(), Elems.end());
124 assert(DstCElems.size() == ExpectedSize);
130 std::make_unique<SuperNode>(std::move(Defs), std::move(Deps));
131 CanonicalSNs[
H].push_back(NewSN.get());
135 void coalesce(std::vector<std::unique_ptr<SuperNode>> &SNs,
136 ElemToSuperNodeMap &ElemToSN) {
137 for (
size_t I = 0;
I != SNs.size();) {
139 auto H = getHash(SN->Deps);
140 if (
auto *CanonicalSN = findCanonicalSuperNode(
H, SN->Deps)) {
141 for (
auto &[Container, Elems] : SN->Defs) {
142 CanonicalSN->Defs[Container].insert(Elems.begin(), Elems.end());
143 auto &ContainerElemToSN = ElemToSN[Container];
144 for (
auto &Elem : Elems)
145 ContainerElemToSN[Elem] = CanonicalSN;
150 CanonicalSNs[
H].push_back(SN.get());
156 template <
typename Pred>
void remove(Pred &&Remove) {
157 for (
auto &[Hash, SNs] : CanonicalSNs) {
159 for (
size_t I = 0;
I != SNs.size(); ++
I) {
160 if (Remove(SNs[
I])) {
169 CanonicalSNs.erase(Hash);
178 SortedContainers.reserve(
M.size());
179 for (
auto &[Container, Elems] : M)
180 SortedContainers.push_back(Container);
183 for (
auto &Container : SortedContainers) {
184 auto &ContainerElems =
M.at(Container);
186 ContainerElems.end());
195 SuperNode *findCanonicalSuperNode(hash_code
H,
197 for (
auto *SN : CanonicalSNs[
H])
203 DenseMap<hash_code, SmallVector<SuperNode *>> CanonicalSNs;
217 for (
auto &[Container, Elems] : Defs) {
218 assert(!Elems.empty() &&
"Defs for container must not be empty");
219 auto I = Deps.
find(Container);
222 auto &DepsForContainer =
I->second;
223 for (
auto &Elem : Elems)
224 DepsForContainer.erase(Elem);
225 if (DepsForContainer.empty())
229 Deps.
erase(Container);
230 if (
auto SN = C.addOrCreateSuperNode(std::move(Defs), std::move(Deps)))
231 SNs.push_back(std::move(SN));
234 return std::move(SNs);
239 std::vector<std::unique_ptr<SuperNode>> SNs;
242 class SimplifyResult {
247 const std::vector<std::unique_ptr<SuperNode>> &
superNodes()
const {
253 ElemToSuperNodeMap ElemToSN)
255 std::vector<std::unique_ptr<SuperNode>> SNs;
256 ElemToSuperNodeMap ElemToSN;
260 static SimplifyResult
simplify(std::vector<std::unique_ptr<SuperNode>> SNs) {
262 ElemToSuperNodeMap ElemToSN;
263 for (
auto &SN : SNs) {
264 for (
auto &[Container, Elements] : SN->Defs) {
265 auto &ContainerElemToSN = ElemToSN[Container];
266 for (
auto &
E : Elements)
267 ContainerElemToSN[
E] = SN.get();
271 SuperNodeDepsMap SuperNodeDeps;
272 hoistDeps(SuperNodeDeps, SNs, ElemToSN);
273 propagateSuperNodeDeps(SuperNodeDeps);
274 sinkDeps(SNs, SuperNodeDeps);
279 return {std::move(SNs), std::move(ElemToSN)};
283 std::vector<std::unique_ptr<SuperNode>>
Ready;
284 std::vector<std::unique_ptr<SuperNode>>
Failed;
294 template <
typename GetExternalStateFn>
295 EmitResult
emit(SimplifyResult SR, GetExternalStateFn &&GetExternalState) {
296 auto NewSNs = std::move(SR.SNs);
297 auto ElemToNewSN = std::move(SR.ElemToSN);
300 auto FailedSNs = processExternalDeps(NewSNs, GetExternalState);
303 std::vector<std::unique_ptr<SuperNode>> ModifiedPendingSNs;
304 for (
size_t I = 0;
I != PendingSNs.size();) {
305 auto &SN = PendingSNs[
I];
307 for (
auto &[Container, Elems] : SN->Deps) {
308 auto I = ElemToNewSN.find(Container);
309 if (
I == ElemToNewSN.end())
311 for (
auto Elem : Elems) {
312 if (
I->second.contains(Elem)) {
321 ModifiedPendingSNs.push_back(std::move(SN));
323 PendingSNs.pop_back();
329 SuperNodeDepsMap SuperNodeDeps;
330 hoistDeps(SuperNodeDeps, ModifiedPendingSNs, ElemToNewSN);
332 CoalesceToPendingSNs.remove(
333 [&](SuperNode *SN) {
return SuperNodeDeps.count(SN); });
335 hoistDeps(SuperNodeDeps, NewSNs, ElemToPendingSN);
336 propagateSuperNodeDeps(SuperNodeDeps);
337 sinkDeps(NewSNs, SuperNodeDeps);
338 sinkDeps(ModifiedPendingSNs, SuperNodeDeps);
342 std::vector<std::unique_ptr<SuperNode>> ReadyNodes, FailedNodes;
343 processReadyOrFailed(ModifiedPendingSNs, ReadyNodes, FailedNodes,
344 SuperNodeDeps, ElemToPendingSN, FailedSNs);
345 processReadyOrFailed(NewSNs, ReadyNodes, FailedNodes, SuperNodeDeps,
346 ElemToNewSN, FailedSNs);
348 CoalesceToPendingSNs.coalesce(ModifiedPendingSNs, ElemToPendingSN);
349 CoalesceToPendingSNs.coalesce(NewSNs, ElemToPendingSN);
352 for (
auto &SN : ModifiedPendingSNs)
353 PendingSNs.push_back(std::move(SN));
356 for (
auto &SN : NewSNs) {
357 for (
auto &[Container, Elems] : SN->Defs) {
358 auto &Row = ElemToPendingSN[Container];
359 for (
auto &Elem : Elems)
360 Row[Elem] = SN.get();
362 PendingSNs.push_back(std::move(SN));
365 return {std::move(ReadyNodes), std::move(FailedNodes)};
372 std::vector<std::unique_ptr<SuperNode>>
374 std::vector<std::unique_ptr<SuperNode>> FailedSNs;
376 for (
size_t I = 0;
I != PendingSNs.size();) {
377 auto &PendingSN = PendingSNs[
I];
378 bool FailPendingSN =
false;
379 for (
auto &[Container, Elems] : PendingSN->Deps) {
382 auto I =
Failed.find(Container);
385 for (
auto &Elem : Elems) {
386 if (
I->second.count(Elem)) {
387 FailPendingSN =
true;
393 FailedSNs.push_back(std::move(PendingSN));
394 PendingSN = std::move(PendingSNs.back());
395 PendingSNs.pop_back();
400 for (
auto &SN : FailedSNs) {
401 CoalesceToPendingSNs.remove(
402 [&](SuperNode *SNC) {
return SNC == SN.get(); });
403 for (
auto &[Container, Elems] : SN->Defs) {
404 assert(ElemToPendingSN.count(Container));
405 auto &CElems = ElemToPendingSN[Container];
406 for (
auto &Elem : Elems)
409 ElemToPendingSN.erase(Container);
424 for (
auto &PendingSN : PendingSNs) {
425 if (PendingSN->Deps.empty())
426 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has empty dep set.\n";
428 bool BadElem =
false;
429 for (
auto &[Container, Elems] : PendingSN->Deps) {
430 auto I = ElemToPendingSN.find(Container);
431 if (
I == ElemToPendingSN.end())
434 ErrLog() <<
"Pending SN " << PendingSN.get()
435 <<
" has dependence map entry for " << Container
436 <<
" with empty element set.\n";
437 for (
auto &Elem : Elems) {
438 if (
I->second.count(Elem)) {
439 ErrLog() <<
"Pending SN " << PendingSN.get()
440 <<
" has dependence on emitted element ( " << Container
441 <<
", " << Elem <<
")\n";
451 for (
auto &[Container, Elems] : PendingSN->Defs) {
453 ErrLog() <<
"Pending SN " << PendingSN.get()
454 <<
" has def map entry for " << Container
455 <<
" with empty element set.\n";
456 DefCount += Elems.size();
457 auto I = ElemToPendingSN.find(Container);
458 if (
I == ElemToPendingSN.end())
459 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has "
460 << Elems.size() <<
" defs in container " << Container
461 <<
" not covered by ElemsToPendingSN.\n";
463 for (
auto &Elem : Elems) {
464 auto J =
I->second.find(Elem);
465 if (J ==
I->second.end())
466 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has element ("
467 << Container <<
", " << Elem
468 <<
") not covered by ElemsToPendingSN.\n";
469 else if (J->second != PendingSN.get())
470 ErrLog() <<
"ElemToPendingSN value invalid for (" << Container
471 <<
", " << Elem <<
")\n";
477 size_t DefCount2 = 0;
478 for (
auto &[Container, Elems] : ElemToPendingSN)
479 DefCount2 += Elems.size();
481 assert(DefCount2 >= DefCount);
482 if (DefCount2 != DefCount)
483 ErrLog() <<
"ElemToPendingSN contains extra elements.\n";
494 static void hoistDeps(SuperNodeDepsMap &SuperNodeDeps,
495 std::vector<std::unique_ptr<SuperNode>> &SNs,
496 ElemToSuperNodeMap &ElemToSN) {
497 for (
auto &SN : SNs) {
498 auto &SNDeps = SuperNodeDeps[SN.get()];
499 for (
auto &[DefContainer, DefElems] : ElemToSN) {
500 auto I = SN->Deps.find(DefContainer);
501 if (
I == SN->Deps.end())
503 for (
auto &[DefElem, DefSN] : DefElems)
504 if (
I->second.erase(DefElem))
505 SNDeps.insert(DefSN);
506 if (
I->second.empty())
513 static void propagateSuperNodeDeps(SuperNodeDepsMap &SuperNodeDeps) {
514 for (
auto &[SN, Deps] : SuperNodeDeps) {
515 DenseSet<SuperNode *> Reachable({SN});
518 while (!Worklist.empty()) {
519 auto *DepSN = Worklist.pop_back_val();
520 if (!Reachable.insert(DepSN).second)
522 auto I = SuperNodeDeps.find(DepSN);
523 if (
I == SuperNodeDeps.end())
525 for (
auto *DepSNDep :
I->second)
526 Worklist.push_back(DepSNDep);
529 Deps = std::move(Reachable);
534 static void sinkDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
535 SuperNodeDepsMap &SuperNodeDeps) {
536 for (
auto &SN : SNs) {
537 auto I = SuperNodeDeps.find(SN.get());
538 if (
I == SuperNodeDeps.end())
541 for (
auto *DepSN :
I->second)
542 for (
auto &[Container, Elems] : DepSN->Deps)
543 SN->Deps[Container].insert(Elems.begin(), Elems.end());
547 template <
typename GetExternalStateFn>
548 static std::vector<SuperNode *>
549 processExternalDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
550 GetExternalStateFn &GetExternalState) {
551 std::vector<SuperNode *> FailedSNs;
552 for (
auto &SN : SNs) {
553 bool SNHasError =
false;
555 for (
auto &[Container, Elems] : SN->Deps) {
557 for (
auto &Elem : Elems) {
558 switch (GetExternalState(Container, Elem)) {
562 ElemToRemove.push_back(Elem);
565 ElemToRemove.push_back(Elem);
570 for (
auto &Elem : ElemToRemove)
573 ContainersToRemove.push_back(Container);
575 for (
auto &Container : ContainersToRemove)
576 SN->Deps.erase(Container);
578 FailedSNs.push_back(SN.get());
584 void processReadyOrFailed(std::vector<std::unique_ptr<SuperNode>> &SNs,
585 std::vector<std::unique_ptr<SuperNode>> &
Ready,
586 std::vector<std::unique_ptr<SuperNode>> &
Failed,
587 SuperNodeDepsMap &SuperNodeDeps,
588 ElemToSuperNodeMap &ElemToSNs,
589 std::vector<SuperNode *> FailedSNs) {
590 for (
size_t I = 0;
I != SNs.size();) {
593 bool SNFailed =
false;
594 assert(SuperNodeDeps.count(SN.get()));
595 auto &SNSuperNodeDeps = SuperNodeDeps[SN.get()];
596 for (
auto *FailedSN : FailedSNs) {
597 if (FailedSN == SN.get() || SNSuperNodeDeps.count(FailedSN)) {
603 bool SNReady = SN->Deps.empty();
605 if (SNReady || SNFailed) {
615 std::vector<std::unique_ptr<SuperNode>> PendingSNs;
616 ElemToSuperNodeMap ElemToPendingSN;
617 Coalescer CoalesceToPendingSNs;