109 using ElemToSuperNodeMap =
118 auto H = getHash(Deps);
119 if (
auto *ExistingSN = findCanonicalSuperNode(
H, Deps)) {
120 for (
auto &[Container, Elems] : Defs) {
121 auto &DstCElems = ExistingSN->Defs[Container];
122 [[maybe_unused]]
size_t ExpectedSize =
123 DstCElems.size() + Elems.size();
124 DstCElems.insert(Elems.begin(), Elems.end());
125 assert(DstCElems.size() == ExpectedSize);
131 std::make_unique<SuperNode>(std::move(Defs), std::move(Deps));
132 CanonicalSNs[
H].push_back(NewSN.get());
133 assert(!SNHashes.count(NewSN.get()));
134 SNHashes[NewSN.get()] =
H;
138 void coalesce(std::vector<std::unique_ptr<SuperNode>> &SNs,
139 ElemToSuperNodeMap &ElemToSN) {
140 for (
size_t I = 0;
I != SNs.size();) {
142 assert(!SNHashes.count(SN.get()) &&
143 "Elements of SNs should be new to the coalescer");
144 auto H = getHash(SN->Deps);
145 if (
auto *CanonicalSN = findCanonicalSuperNode(
H, SN->Deps)) {
146 for (
auto &[Container, Elems] : SN->Defs) {
147 CanonicalSN->Defs[Container].insert(Elems.begin(), Elems.end());
148 auto &ContainerElemToSN = ElemToSN[Container];
149 for (
auto &Elem : Elems)
150 ContainerElemToSN[Elem] = CanonicalSN;
155 CanonicalSNs[
H].push_back(SN.get());
156 SNHashes[SN.get()] =
H;
167 CanonicalSNs.clear();
172 void erase(SuperNode *SN) {
177 auto I = SNHashes.find(SN);
178 assert(
I != SNHashes.end() &&
"SN not tracked by coalescer");
184 auto I = CanonicalSNs.find(
H);
185 assert(
I != CanonicalSNs.end() &&
"Hash not in CanonicalSNs");
186 auto &SNs =
I->second;
189 for (; J != SNs.size(); ++J)
193 assert(J < SNs.size() &&
"SN not in CanonicalSNs map");
198 CanonicalSNs.erase(
I);
204 SortedContainers.reserve(
M.size());
205 for (
auto &[Container, Elems] : M)
206 SortedContainers.push_back(Container);
209 for (
auto &Container : SortedContainers) {
210 auto &ContainerElems =
M.at(Container);
212 ContainerElems.end());
219 SuperNode *findCanonicalSuperNode(hash_code
H,
221 for (
auto *SN : CanonicalSNs[
H])
227 DenseMap<hash_code, SmallVector<SuperNode *>> CanonicalSNs;
228 DenseMap<SuperNode *, hash_code> SNHashes;
242 for (
auto &[Container, Elems] : Defs) {
243 assert(!Elems.empty() &&
"Defs for container must not be empty");
244 auto I = Deps.
find(Container);
247 auto &DepsForContainer =
I->second;
248 for (
auto &Elem : Elems)
249 DepsForContainer.erase(Elem);
250 if (DepsForContainer.empty())
254 Deps.
erase(Container);
255 if (
auto SN = C.addOrCreateSuperNode(std::move(Defs), std::move(Deps)))
256 SNs.push_back(std::move(SN));
260 return std::move(SNs);
265 std::vector<std::unique_ptr<SuperNode>> SNs;
268 class SimplifyResult {
273 const std::vector<std::unique_ptr<SuperNode>> &
superNodes()
const {
279 ElemToSuperNodeMap ElemToSN)
281 std::vector<std::unique_ptr<SuperNode>> SNs;
282 ElemToSuperNodeMap ElemToSN;
286 static SimplifyResult
simplify(std::vector<std::unique_ptr<SuperNode>> SNs) {
288 ElemToSuperNodeMap ElemToSN;
289 for (
auto &SN : SNs) {
290 for (
auto &[Container, Elements] : SN->Defs) {
291 auto &ContainerElemToSN = ElemToSN[Container];
292 for (
auto &
E : Elements)
293 ContainerElemToSN[
E] = SN.get();
297 SuperNodeDepsMap SuperNodeDeps;
298 hoistDeps(SuperNodeDeps, SNs, ElemToSN);
299 propagateDeps(SuperNodeDeps);
304 return {std::move(SNs), std::move(ElemToSN)};
308 std::vector<std::unique_ptr<SuperNode>>
Ready;
309 std::vector<std::unique_ptr<SuperNode>>
Failed;
319 template <
typename GetExternalStateFn>
320 EmitResult
emit(SimplifyResult SR, GetExternalStateFn &&GetExternalState) {
321 auto NewSNs = std::move(SR.SNs);
322 auto ElemToNewSN = std::move(SR.ElemToSN);
325 auto FailedSNs = processExternalDeps(NewSNs, GetExternalState);
328 std::vector<std::unique_ptr<SuperNode>> ModifiedPendingSNs;
329 for (
size_t I = 0;
I != PendingSNs.size();) {
330 auto &SN = PendingSNs[
I];
332 for (
auto &[Container, Elems] : SN->Deps) {
333 auto I = ElemToNewSN.find(Container);
334 if (
I == ElemToNewSN.end())
336 for (
auto Elem : Elems) {
337 if (
I->second.contains(Elem)) {
346 ModifiedPendingSNs.push_back(std::move(SN));
348 PendingSNs.pop_back();
354 SuperNodeDepsMap SuperNodeDeps;
355 hoistDeps(SuperNodeDeps, ModifiedPendingSNs, ElemToNewSN);
358 for (
auto &SN : ModifiedPendingSNs)
359 CoalesceToPendingSNs.erase(SN.get());
361 hoistDeps(SuperNodeDeps, NewSNs, ElemToPendingSN);
362 propagateDeps(SuperNodeDeps);
364 propagateFailures(FailedSNs, SuperNodeDeps);
368 std::vector<std::unique_ptr<SuperNode>> ReadyNodes, FailedNodes;
369 processReadyOrFailed(ModifiedPendingSNs, ReadyNodes, FailedNodes,
370 SuperNodeDeps, FailedSNs, &ElemToPendingSN);
371 processReadyOrFailed(NewSNs, ReadyNodes, FailedNodes, SuperNodeDeps,
374 CoalesceToPendingSNs.coalesce(ModifiedPendingSNs, ElemToPendingSN);
375 CoalesceToPendingSNs.coalesce(NewSNs, ElemToPendingSN);
378 for (
auto &SN : ModifiedPendingSNs)
379 PendingSNs.push_back(std::move(SN));
382 for (
auto &SN : NewSNs) {
383 for (
auto &[Container, Elems] : SN->Defs) {
384 auto &Row = ElemToPendingSN[Container];
385 for (
auto &Elem : Elems)
386 Row[Elem] = SN.get();
388 PendingSNs.push_back(std::move(SN));
391 return {std::move(ReadyNodes), std::move(FailedNodes)};
398 std::vector<std::unique_ptr<SuperNode>>
400 std::vector<std::unique_ptr<SuperNode>> FailedSNs;
402 for (
size_t I = 0;
I != PendingSNs.size();) {
403 auto &PendingSN = PendingSNs[
I];
404 bool FailPendingSN =
false;
405 for (
auto &[Container, Elems] : PendingSN->Deps) {
408 auto I =
Failed.find(Container);
411 for (
auto &Elem : Elems) {
412 if (
I->second.count(Elem)) {
413 FailPendingSN =
true;
419 FailedSNs.push_back(std::move(PendingSN));
420 PendingSN = std::move(PendingSNs.back());
421 PendingSNs.pop_back();
426 for (
auto &FailedSN : FailedSNs)
427 CoalesceToPendingSNs.erase(FailedSN.get());
429 for (
auto &SN : FailedSNs) {
430 for (
auto &[Container, Elems] : SN->Defs) {
431 assert(ElemToPendingSN.count(Container));
432 auto &CElems = ElemToPendingSN[Container];
433 for (
auto &Elem : Elems)
436 ElemToPendingSN.erase(Container);
451 for (
auto &PendingSN : PendingSNs) {
452 if (PendingSN->Deps.empty())
453 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has empty dep set.\n";
455 bool BadElem =
false;
456 for (
auto &[Container, Elems] : PendingSN->Deps) {
457 auto I = ElemToPendingSN.find(Container);
458 if (
I == ElemToPendingSN.end())
461 ErrLog() <<
"Pending SN " << PendingSN.get()
462 <<
" has dependence map entry for " << Container
463 <<
" with empty element set.\n";
464 for (
auto &Elem : Elems) {
465 if (
I->second.count(Elem)) {
466 ErrLog() <<
"Pending SN " << PendingSN.get()
467 <<
" has dependence on emitted element ( " << Container
468 <<
", " << Elem <<
")\n";
478 for (
auto &[Container, Elems] : PendingSN->Defs) {
480 ErrLog() <<
"Pending SN " << PendingSN.get()
481 <<
" has def map entry for " << Container
482 <<
" with empty element set.\n";
483 DefCount += Elems.size();
484 auto I = ElemToPendingSN.find(Container);
485 if (
I == ElemToPendingSN.end())
486 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has "
487 << Elems.size() <<
" defs in container " << Container
488 <<
" not covered by ElemsToPendingSN.\n";
490 for (
auto &Elem : Elems) {
491 auto J =
I->second.find(Elem);
492 if (J ==
I->second.end())
493 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has element ("
494 << Container <<
", " << Elem
495 <<
") not covered by ElemsToPendingSN.\n";
496 else if (J->second != PendingSN.get())
497 ErrLog() <<
"ElemToPendingSN value invalid for (" << Container
498 <<
", " << Elem <<
")\n";
504 size_t DefCount2 = 0;
505 for (
auto &[Container, Elems] : ElemToPendingSN)
506 DefCount2 += Elems.size();
508 assert(DefCount2 >= DefCount);
509 if (DefCount2 != DefCount)
510 ErrLog() <<
"ElemToPendingSN contains extra elements.\n";
517 static void hoistDeps(SuperNodeDepsMap &SuperNodeDeps,
518 std::vector<std::unique_ptr<SuperNode>> &SNs,
519 ElemToSuperNodeMap &ElemToSN) {
521 for (
auto &SN : SNs) {
523 for (
auto &[DepContainer, DepElems] : SN->Deps) {
527 auto I = ElemToSN.find(DepContainer);
528 if (
I == ElemToSN.end())
530 auto &ContainerElemToSN =
I->second;
535 if (ContainerElemToSN.size() < DepElems.size()) {
536 for (
auto &[DefElem, DefSN] : ContainerElemToSN)
537 if (DepElems.erase(DefElem) && DefSN != SN.get())
538 SuperNodeDeps[DefSN].insert(SN.get());
541 for (
auto &DepElem : DepElems) {
542 auto J = ContainerElemToSN.find(DepElem);
543 if (J == ContainerElemToSN.end())
546 SuperNode *DefSN = J->second;
547 if (DefSN != SN.get())
548 SuperNodeDeps[DefSN].insert(SN.get());
551 for (
auto &DepElem : ElemsToRemove)
552 DepElems.
erase(DepElem);
557 if (DepElems.empty())
558 ContainersToRemove.
push_back(DepContainer);
562 for (
auto &DepContainer : ContainersToRemove) {
563 assert(SN->Deps.count(DepContainer) &&
"DepContainer already removed?");
564 assert(SN->Deps[DepContainer].empty() &&
"DepContainer deps not empty");
565 SN->Deps.erase(DepContainer);
571 static void propagateDeps(SuperNodeDepsMap &SuperNodeDeps) {
574 if (SuperNodeDeps.empty())
578 Worklist.reserve(SuperNodeDeps.size());
579 for (
auto &[SN, SNDependants] : SuperNodeDeps)
580 Worklist.push_back(SN);
583 DenseSet<SuperNode *> ToVisitNext;
587 while (!Worklist.empty()) {
588 auto *SN = Worklist.pop_back_val();
589 auto I = SuperNodeDeps.find(SN);
590 if (
I == SuperNodeDeps.end())
593 for (
auto *DependantSN :
I->second) {
595 for (
auto &[DepContainer, DepElems] : SN->Deps) {
596 auto &DepSNContainerElems = DependantSN->Deps[DepContainer];
597 for (
auto &DepElem : DepElems)
598 Changed |= DepSNContainerElems.insert(DepElem).second;
601 ToVisitNext.insert(DependantSN);
605 if (ToVisitNext.empty())
608 Worklist.append(ToVisitNext.begin(), ToVisitNext.end());
612 static void propagateFailures(DenseSet<SuperNode *> &FailedNodes,
613 SuperNodeDepsMap &SuperNodeDeps) {
614 if (FailedNodes.empty())
619 while (!Worklist.empty()) {
620 auto *SN = Worklist.pop_back_val();
621 auto I = SuperNodeDeps.find(SN);
622 if (
I == SuperNodeDeps.end())
625 for (
auto *DependantSN :
I->second)
626 if (FailedNodes.insert(DependantSN).second)
627 Worklist.push_back(DependantSN);
631 template <
typename GetExternalStateFn>
632 static DenseSet<SuperNode *>
633 processExternalDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
634 GetExternalStateFn &GetExternalState) {
635 DenseSet<SuperNode *> FailedSNs;
636 for (
auto &SN : SNs) {
637 bool SNHasError =
false;
639 for (
auto &[Container, Elems] : SN->Deps) {
641 for (
auto &Elem : Elems) {
642 switch (GetExternalState(Container, Elem)) {
646 ElemToRemove.push_back(Elem);
649 ElemToRemove.push_back(Elem);
654 for (
auto &Elem : ElemToRemove)
657 ContainersToRemove.push_back(Container);
659 for (
auto &Container : ContainersToRemove)
660 SN->Deps.
erase(Container);
662 FailedSNs.insert(SN.get());
668 void processReadyOrFailed(std::vector<std::unique_ptr<SuperNode>> &SNs,
669 std::vector<std::unique_ptr<SuperNode>> &
Ready,
670 std::vector<std::unique_ptr<SuperNode>> &
Failed,
671 SuperNodeDepsMap &SuperNodeDeps,
672 const DenseSet<SuperNode *> &FailedSNs,
673 ElemToSuperNodeMap *ElemToSNs) {
677 for (
size_t I = 0;
I != SNs.size();) {
680 bool SNFailed = FailedSNs.count(SN.get());
681 bool SNReady = SN->Deps.empty();
683 if (SNReady || SNFailed) {
685 ToRemoveFromElemToSNs.push_back(SN.get());
695 for (
auto *SN : ToRemoveFromElemToSNs) {
696 for (
auto &[Container, Elems] : SN->defs()) {
697 auto &Row = (*ElemToSNs)[Container];
698 for (
auto &Elem : Elems)
704 std::vector<std::unique_ptr<SuperNode>> PendingSNs;
705 ElemToSuperNodeMap ElemToPendingSN;
706 Coalescer CoalesceToPendingSNs;