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());
136 void coalesce(std::vector<std::unique_ptr<SuperNode>> &SNs,
137 ElemToSuperNodeMap &ElemToSN) {
138 for (
size_t I = 0;
I != SNs.size();) {
140 auto H = getHash(SN->Deps);
141 if (
auto *CanonicalSN = findCanonicalSuperNode(
H, SN->Deps)) {
142 for (
auto &[Container, Elems] : SN->Defs) {
143 CanonicalSN->Defs[Container].insert(Elems.begin(), Elems.end());
144 auto &ContainerElemToSN = ElemToSN[Container];
145 for (
auto &Elem : Elems)
146 ContainerElemToSN[Elem] = CanonicalSN;
151 CanonicalSNs[
H].push_back(SN.get());
157 template <
typename Pred>
void remove(Pred &&Remove) {
158 std::vector<hash_code> HashesToErase;
159 for (
auto &[Hash, SNs] : CanonicalSNs) {
160 for (
size_t I = 0;
I != SNs.size();) {
161 if (Remove(SNs[
I])) {
168 HashesToErase.push_back(Hash);
170 for (
auto Hash : HashesToErase)
171 CanonicalSNs.erase(Hash);
177 SortedContainers.reserve(
M.size());
178 for (
auto &[Container, Elems] : M)
179 SortedContainers.push_back(Container);
182 for (
auto &Container : SortedContainers) {
183 auto &ContainerElems =
M.at(Container);
185 ContainerElems.end());
192 SuperNode *findCanonicalSuperNode(hash_code
H,
194 for (
auto *SN : CanonicalSNs[
H])
200 DenseMap<hash_code, SmallVector<SuperNode *>> CanonicalSNs;
214 for (
auto &[Container, Elems] : Defs) {
215 assert(!Elems.empty() &&
"Defs for container must not be empty");
216 auto I = Deps.
find(Container);
219 auto &DepsForContainer =
I->second;
220 for (
auto &Elem : Elems)
221 DepsForContainer.erase(Elem);
222 if (DepsForContainer.empty())
226 Deps.
erase(Container);
227 if (
auto SN = C.addOrCreateSuperNode(std::move(Defs), std::move(Deps)))
228 SNs.push_back(std::move(SN));
231 return std::move(SNs);
236 std::vector<std::unique_ptr<SuperNode>> SNs;
239 class SimplifyResult {
244 const std::vector<std::unique_ptr<SuperNode>> &
superNodes()
const {
250 ElemToSuperNodeMap ElemToSN)
252 std::vector<std::unique_ptr<SuperNode>> SNs;
253 ElemToSuperNodeMap ElemToSN;
257 static SimplifyResult
simplify(std::vector<std::unique_ptr<SuperNode>> SNs) {
259 ElemToSuperNodeMap ElemToSN;
260 for (
auto &SN : SNs) {
261 for (
auto &[Container, Elements] : SN->Defs) {
262 auto &ContainerElemToSN = ElemToSN[Container];
263 for (
auto &
E : Elements)
264 ContainerElemToSN[
E] = SN.get();
268 SuperNodeDepsMap SuperNodeDeps;
269 hoistDeps(SuperNodeDeps, SNs, ElemToSN);
270 propagateSuperNodeDeps(SuperNodeDeps);
271 sinkDeps(SNs, SuperNodeDeps);
276 return {std::move(SNs), std::move(ElemToSN)};
280 std::vector<std::unique_ptr<SuperNode>>
Ready;
281 std::vector<std::unique_ptr<SuperNode>>
Failed;
291 template <
typename GetExternalStateFn>
292 EmitResult
emit(SimplifyResult SR, GetExternalStateFn &&GetExternalState) {
293 auto NewSNs = std::move(SR.SNs);
294 auto ElemToNewSN = std::move(SR.ElemToSN);
297 auto FailedSNs = processExternalDeps(NewSNs, GetExternalState);
300 std::vector<std::unique_ptr<SuperNode>> ModifiedPendingSNs;
301 for (
size_t I = 0;
I != PendingSNs.size();) {
302 auto &SN = PendingSNs[
I];
304 for (
auto &[Container, Elems] : SN->Deps) {
305 auto I = ElemToNewSN.find(Container);
306 if (
I == ElemToNewSN.end())
308 for (
auto Elem : Elems) {
309 if (
I->second.contains(Elem)) {
318 ModifiedPendingSNs.push_back(std::move(SN));
320 PendingSNs.pop_back();
326 SuperNodeDepsMap SuperNodeDeps;
327 hoistDeps(SuperNodeDeps, ModifiedPendingSNs, ElemToNewSN);
329 CoalesceToPendingSNs.remove(
330 [&](SuperNode *SN) {
return SuperNodeDeps.count(SN); });
332 hoistDeps(SuperNodeDeps, NewSNs, ElemToPendingSN);
333 propagateSuperNodeDeps(SuperNodeDeps);
334 sinkDeps(NewSNs, SuperNodeDeps);
335 sinkDeps(ModifiedPendingSNs, SuperNodeDeps);
339 std::vector<std::unique_ptr<SuperNode>> ReadyNodes, FailedNodes;
340 processReadyOrFailed(ModifiedPendingSNs, ReadyNodes, FailedNodes,
341 SuperNodeDeps, FailedSNs, &ElemToPendingSN);
342 processReadyOrFailed(NewSNs, ReadyNodes, FailedNodes, SuperNodeDeps,
345 CoalesceToPendingSNs.coalesce(ModifiedPendingSNs, ElemToPendingSN);
346 CoalesceToPendingSNs.coalesce(NewSNs, ElemToPendingSN);
349 for (
auto &SN : ModifiedPendingSNs)
350 PendingSNs.push_back(std::move(SN));
353 for (
auto &SN : NewSNs) {
354 for (
auto &[Container, Elems] : SN->Defs) {
355 auto &Row = ElemToPendingSN[Container];
356 for (
auto &Elem : Elems)
357 Row[Elem] = SN.get();
359 PendingSNs.push_back(std::move(SN));
362 return {std::move(ReadyNodes), std::move(FailedNodes)};
369 std::vector<std::unique_ptr<SuperNode>>
371 std::vector<std::unique_ptr<SuperNode>> FailedSNs;
373 for (
size_t I = 0;
I != PendingSNs.size();) {
374 auto &PendingSN = PendingSNs[
I];
375 bool FailPendingSN =
false;
376 for (
auto &[Container, Elems] : PendingSN->Deps) {
379 auto I =
Failed.find(Container);
382 for (
auto &Elem : Elems) {
383 if (
I->second.count(Elem)) {
384 FailPendingSN =
true;
390 FailedSNs.push_back(std::move(PendingSN));
391 PendingSN = std::move(PendingSNs.back());
392 PendingSNs.pop_back();
397 CoalesceToPendingSNs.remove([&](SuperNode *SN) {
398 for (
auto &
E : FailedSNs)
404 for (
auto &SN : FailedSNs) {
405 for (
auto &[Container, Elems] : SN->Defs) {
406 assert(ElemToPendingSN.count(Container));
407 auto &CElems = ElemToPendingSN[Container];
408 for (
auto &Elem : Elems)
411 ElemToPendingSN.erase(Container);
426 for (
auto &PendingSN : PendingSNs) {
427 if (PendingSN->Deps.empty())
428 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has empty dep set.\n";
430 bool BadElem =
false;
431 for (
auto &[Container, Elems] : PendingSN->Deps) {
432 auto I = ElemToPendingSN.find(Container);
433 if (
I == ElemToPendingSN.end())
436 ErrLog() <<
"Pending SN " << PendingSN.get()
437 <<
" has dependence map entry for " << Container
438 <<
" with empty element set.\n";
439 for (
auto &Elem : Elems) {
440 if (
I->second.count(Elem)) {
441 ErrLog() <<
"Pending SN " << PendingSN.get()
442 <<
" has dependence on emitted element ( " << Container
443 <<
", " << Elem <<
")\n";
453 for (
auto &[Container, Elems] : PendingSN->Defs) {
455 ErrLog() <<
"Pending SN " << PendingSN.get()
456 <<
" has def map entry for " << Container
457 <<
" with empty element set.\n";
458 DefCount += Elems.size();
459 auto I = ElemToPendingSN.find(Container);
460 if (
I == ElemToPendingSN.end())
461 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has "
462 << Elems.size() <<
" defs in container " << Container
463 <<
" not covered by ElemsToPendingSN.\n";
465 for (
auto &Elem : Elems) {
466 auto J =
I->second.find(Elem);
467 if (J ==
I->second.end())
468 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has element ("
469 << Container <<
", " << Elem
470 <<
") not covered by ElemsToPendingSN.\n";
471 else if (J->second != PendingSN.get())
472 ErrLog() <<
"ElemToPendingSN value invalid for (" << Container
473 <<
", " << Elem <<
")\n";
479 size_t DefCount2 = 0;
480 for (
auto &[Container, Elems] : ElemToPendingSN)
481 DefCount2 += Elems.size();
483 assert(DefCount2 >= DefCount);
484 if (DefCount2 != DefCount)
485 ErrLog() <<
"ElemToPendingSN contains extra elements.\n";
496 static void hoistDeps(SuperNodeDepsMap &SuperNodeDeps,
497 std::vector<std::unique_ptr<SuperNode>> &SNs,
498 ElemToSuperNodeMap &ElemToSN) {
499 for (
auto &SN : SNs) {
500 auto &SNDeps = SuperNodeDeps[SN.get()];
501 for (
auto &[DefContainer, DefElems] : ElemToSN) {
502 auto I = SN->Deps.find(DefContainer);
503 if (
I == SN->Deps.end())
505 for (
auto &[DefElem, DefSN] : DefElems)
506 if (
I->second.erase(DefElem) && DefSN != SN.get())
507 SNDeps.insert(DefSN);
508 if (
I->second.empty())
515 static void propagateSuperNodeDeps(SuperNodeDepsMap &SuperNodeDeps) {
516 for (
auto &[SN, Deps] : SuperNodeDeps) {
517 DenseSet<SuperNode *> Reachable;
520 while (!Worklist.empty()) {
521 auto *DepSN = Worklist.pop_back_val();
524 if (!Reachable.insert(DepSN).second)
526 auto I = SuperNodeDeps.find(DepSN);
527 if (
I == SuperNodeDeps.end())
529 for (
auto *DepSNDep :
I->second)
530 Worklist.push_back(DepSNDep);
533 Deps = std::move(Reachable);
538 static void sinkDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
539 SuperNodeDepsMap &SuperNodeDeps) {
540 for (
auto &SN : SNs) {
541 auto I = SuperNodeDeps.find(SN.get());
542 if (
I == SuperNodeDeps.end())
545 for (
auto *DepSN :
I->second) {
546 assert(DepSN != SN.get() &&
"Unexpected self-dependence for SN");
547 for (
auto &[Container, Elems] : DepSN->Deps)
548 SN->Deps[Container].insert(Elems.begin(), Elems.end());
553 template <
typename GetExternalStateFn>
554 static std::vector<SuperNode *>
555 processExternalDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
556 GetExternalStateFn &GetExternalState) {
557 std::vector<SuperNode *> FailedSNs;
558 for (
auto &SN : SNs) {
559 bool SNHasError =
false;
561 for (
auto &[Container, Elems] : SN->Deps) {
563 for (
auto &Elem : Elems) {
564 switch (GetExternalState(Container, Elem)) {
568 ElemToRemove.push_back(Elem);
571 ElemToRemove.push_back(Elem);
576 for (
auto &Elem : ElemToRemove)
579 ContainersToRemove.push_back(Container);
581 for (
auto &Container : ContainersToRemove)
582 SN->Deps.erase(Container);
584 FailedSNs.push_back(SN.get());
590 void processReadyOrFailed(std::vector<std::unique_ptr<SuperNode>> &SNs,
591 std::vector<std::unique_ptr<SuperNode>> &
Ready,
592 std::vector<std::unique_ptr<SuperNode>> &
Failed,
593 SuperNodeDepsMap &SuperNodeDeps,
594 const std::vector<SuperNode *> &FailedSNs,
595 ElemToSuperNodeMap *ElemToSNs) {
599 for (
size_t I = 0;
I != SNs.size();) {
602 bool SNFailed =
false;
603 assert(SuperNodeDeps.count(SN.get()));
604 auto &SNSuperNodeDeps = SuperNodeDeps[SN.get()];
605 for (
auto *FailedSN : FailedSNs) {
606 if (FailedSN == SN.get() || SNSuperNodeDeps.count(FailedSN)) {
612 bool SNReady = SN->Deps.empty();
614 if (SNReady || SNFailed) {
616 ToRemoveFromElemToSNs.push_back(SN.get());
626 for (
auto *SN : ToRemoveFromElemToSNs) {
627 for (
auto &[Container, Elems] : SN->defs()) {
628 auto &Row = (*ElemToSNs)[Container];
629 for (
auto &Elem : Elems)
635 std::vector<std::unique_ptr<SuperNode>> PendingSNs;
636 ElemToSuperNodeMap ElemToPendingSN;
637 Coalescer CoalesceToPendingSNs;