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 for (
auto &[Hash, SNs] : CanonicalSNs) {
160 for (
size_t I = 0;
I != SNs.size(); ++
I) {
161 if (Remove(SNs[
I])) {
170 CanonicalSNs.erase(Hash);
179 SortedContainers.reserve(
M.size());
180 for (
auto &[Container, Elems] : M)
181 SortedContainers.push_back(Container);
184 for (
auto &Container : SortedContainers) {
185 auto &ContainerElems =
M.at(Container);
187 ContainerElems.end());
194 SuperNode *findCanonicalSuperNode(hash_code
H,
196 for (
auto *SN : CanonicalSNs[
H])
202 DenseMap<hash_code, SmallVector<SuperNode *>> CanonicalSNs;
216 for (
auto &[Container, Elems] : Defs) {
217 assert(!Elems.empty() &&
"Defs for container must not be empty");
218 auto I = Deps.
find(Container);
221 auto &DepsForContainer =
I->second;
222 for (
auto &Elem : Elems)
223 DepsForContainer.erase(Elem);
224 if (DepsForContainer.empty())
228 Deps.
erase(Container);
229 if (
auto SN = C.addOrCreateSuperNode(std::move(Defs), std::move(Deps)))
230 SNs.push_back(std::move(SN));
233 return std::move(SNs);
238 std::vector<std::unique_ptr<SuperNode>> SNs;
241 class SimplifyResult {
246 const std::vector<std::unique_ptr<SuperNode>> &
superNodes()
const {
252 ElemToSuperNodeMap ElemToSN)
254 std::vector<std::unique_ptr<SuperNode>> SNs;
255 ElemToSuperNodeMap ElemToSN;
259 static SimplifyResult
simplify(std::vector<std::unique_ptr<SuperNode>> SNs) {
261 ElemToSuperNodeMap ElemToSN;
262 for (
auto &SN : SNs) {
263 for (
auto &[Container, Elements] : SN->Defs) {
264 auto &ContainerElemToSN = ElemToSN[Container];
265 for (
auto &
E : Elements)
266 ContainerElemToSN[
E] = SN.get();
270 SuperNodeDepsMap SuperNodeDeps;
271 hoistDeps(SuperNodeDeps, SNs, ElemToSN);
272 propagateSuperNodeDeps(SuperNodeDeps);
273 sinkDeps(SNs, SuperNodeDeps);
278 return {std::move(SNs), std::move(ElemToSN)};
282 std::vector<std::unique_ptr<SuperNode>>
Ready;
283 std::vector<std::unique_ptr<SuperNode>>
Failed;
293 template <
typename GetExternalStateFn>
294 EmitResult
emit(SimplifyResult SR, GetExternalStateFn &&GetExternalState) {
295 auto NewSNs = std::move(SR.SNs);
296 auto ElemToNewSN = std::move(SR.ElemToSN);
299 auto FailedSNs = processExternalDeps(NewSNs, GetExternalState);
302 std::vector<std::unique_ptr<SuperNode>> ModifiedPendingSNs;
303 for (
size_t I = 0;
I != PendingSNs.size();) {
304 auto &SN = PendingSNs[
I];
306 for (
auto &[Container, Elems] : SN->Deps) {
307 auto I = ElemToNewSN.find(Container);
308 if (
I == ElemToNewSN.end())
310 for (
auto Elem : Elems) {
311 if (
I->second.contains(Elem)) {
320 ModifiedPendingSNs.push_back(std::move(SN));
322 PendingSNs.pop_back();
328 SuperNodeDepsMap SuperNodeDeps;
329 hoistDeps(SuperNodeDeps, ModifiedPendingSNs, ElemToNewSN);
331 CoalesceToPendingSNs.remove(
332 [&](SuperNode *SN) {
return SuperNodeDeps.count(SN); });
334 hoistDeps(SuperNodeDeps, NewSNs, ElemToPendingSN);
335 propagateSuperNodeDeps(SuperNodeDeps);
336 sinkDeps(NewSNs, SuperNodeDeps);
337 sinkDeps(ModifiedPendingSNs, SuperNodeDeps);
341 std::vector<std::unique_ptr<SuperNode>> ReadyNodes, FailedNodes;
342 processReadyOrFailed(ModifiedPendingSNs, ReadyNodes, FailedNodes,
343 SuperNodeDeps, ElemToPendingSN, FailedSNs);
344 processReadyOrFailed(NewSNs, ReadyNodes, FailedNodes, SuperNodeDeps,
345 ElemToNewSN, FailedSNs);
347 CoalesceToPendingSNs.coalesce(ModifiedPendingSNs, ElemToPendingSN);
348 CoalesceToPendingSNs.coalesce(NewSNs, ElemToPendingSN);
351 for (
auto &SN : ModifiedPendingSNs)
352 PendingSNs.push_back(std::move(SN));
355 for (
auto &SN : NewSNs) {
356 for (
auto &[Container, Elems] : SN->Defs) {
357 auto &Row = ElemToPendingSN[Container];
358 for (
auto &Elem : Elems)
359 Row[Elem] = SN.get();
361 PendingSNs.push_back(std::move(SN));
364 return {std::move(ReadyNodes), std::move(FailedNodes)};
371 std::vector<std::unique_ptr<SuperNode>>
373 std::vector<std::unique_ptr<SuperNode>> FailedSNs;
375 for (
size_t I = 0;
I != PendingSNs.size();) {
376 auto &PendingSN = PendingSNs[
I];
377 bool FailPendingSN =
false;
378 for (
auto &[Container, Elems] : PendingSN->Deps) {
381 auto I =
Failed.find(Container);
384 for (
auto &Elem : Elems) {
385 if (
I->second.count(Elem)) {
386 FailPendingSN =
true;
392 FailedSNs.push_back(std::move(PendingSN));
393 PendingSN = std::move(PendingSNs.back());
394 PendingSNs.pop_back();
399 for (
auto &SN : FailedSNs) {
400 CoalesceToPendingSNs.remove(
401 [&](SuperNode *SNC) {
return SNC == SN.get(); });
402 for (
auto &[Container, Elems] : SN->Defs) {
403 assert(ElemToPendingSN.count(Container));
404 auto &CElems = ElemToPendingSN[Container];
405 for (
auto &Elem : Elems)
408 ElemToPendingSN.erase(Container);
423 for (
auto &PendingSN : PendingSNs) {
424 if (PendingSN->Deps.empty())
425 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has empty dep set.\n";
427 bool BadElem =
false;
428 for (
auto &[Container, Elems] : PendingSN->Deps) {
429 auto I = ElemToPendingSN.find(Container);
430 if (
I == ElemToPendingSN.end())
433 ErrLog() <<
"Pending SN " << PendingSN.get()
434 <<
" has dependence map entry for " << Container
435 <<
" with empty element set.\n";
436 for (
auto &Elem : Elems) {
437 if (
I->second.count(Elem)) {
438 ErrLog() <<
"Pending SN " << PendingSN.get()
439 <<
" has dependence on emitted element ( " << Container
440 <<
", " << Elem <<
")\n";
450 for (
auto &[Container, Elems] : PendingSN->Defs) {
452 ErrLog() <<
"Pending SN " << PendingSN.get()
453 <<
" has def map entry for " << Container
454 <<
" with empty element set.\n";
455 DefCount += Elems.size();
456 auto I = ElemToPendingSN.find(Container);
457 if (
I == ElemToPendingSN.end())
458 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has "
459 << Elems.size() <<
" defs in container " << Container
460 <<
" not covered by ElemsToPendingSN.\n";
462 for (
auto &Elem : Elems) {
463 auto J =
I->second.find(Elem);
464 if (J ==
I->second.end())
465 ErrLog() <<
"Pending SN " << PendingSN.get() <<
" has element ("
466 << Container <<
", " << Elem
467 <<
") not covered by ElemsToPendingSN.\n";
468 else if (J->second != PendingSN.get())
469 ErrLog() <<
"ElemToPendingSN value invalid for (" << Container
470 <<
", " << Elem <<
")\n";
476 size_t DefCount2 = 0;
477 for (
auto &[Container, Elems] : ElemToPendingSN)
478 DefCount2 += Elems.size();
480 assert(DefCount2 >= DefCount);
481 if (DefCount2 != DefCount)
482 ErrLog() <<
"ElemToPendingSN contains extra elements.\n";
493 static void hoistDeps(SuperNodeDepsMap &SuperNodeDeps,
494 std::vector<std::unique_ptr<SuperNode>> &SNs,
495 ElemToSuperNodeMap &ElemToSN) {
496 for (
auto &SN : SNs) {
497 auto &SNDeps = SuperNodeDeps[SN.get()];
498 for (
auto &[DefContainer, DefElems] : ElemToSN) {
499 auto I = SN->Deps.find(DefContainer);
500 if (
I == SN->Deps.end())
502 for (
auto &[DefElem, DefSN] : DefElems)
503 if (
I->second.erase(DefElem))
504 SNDeps.insert(DefSN);
505 if (
I->second.empty())
512 static void propagateSuperNodeDeps(SuperNodeDepsMap &SuperNodeDeps) {
513 for (
auto &[SN, Deps] : SuperNodeDeps) {
514 DenseSet<SuperNode *> Reachable({SN});
517 while (!Worklist.empty()) {
518 auto *DepSN = Worklist.pop_back_val();
519 if (!Reachable.insert(DepSN).second)
521 auto I = SuperNodeDeps.find(DepSN);
522 if (
I == SuperNodeDeps.end())
524 for (
auto *DepSNDep :
I->second)
525 Worklist.push_back(DepSNDep);
528 Deps = std::move(Reachable);
533 static void sinkDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
534 SuperNodeDepsMap &SuperNodeDeps) {
535 for (
auto &SN : SNs) {
536 auto I = SuperNodeDeps.find(SN.get());
537 if (
I == SuperNodeDeps.end())
540 for (
auto *DepSN :
I->second)
541 for (
auto &[Container, Elems] : DepSN->Deps)
542 SN->Deps[Container].insert(Elems.begin(), Elems.end());
546 template <
typename GetExternalStateFn>
547 static std::vector<SuperNode *>
548 processExternalDeps(std::vector<std::unique_ptr<SuperNode>> &SNs,
549 GetExternalStateFn &GetExternalState) {
550 std::vector<SuperNode *> FailedSNs;
551 for (
auto &SN : SNs) {
552 bool SNHasError =
false;
554 for (
auto &[Container, Elems] : SN->Deps) {
556 for (
auto &Elem : Elems) {
557 switch (GetExternalState(Container, Elem)) {
561 ElemToRemove.push_back(Elem);
564 ElemToRemove.push_back(Elem);
569 for (
auto &Elem : ElemToRemove)
572 ContainersToRemove.push_back(Container);
574 for (
auto &Container : ContainersToRemove)
575 SN->Deps.erase(Container);
577 FailedSNs.push_back(SN.get());
583 void processReadyOrFailed(std::vector<std::unique_ptr<SuperNode>> &SNs,
584 std::vector<std::unique_ptr<SuperNode>> &
Ready,
585 std::vector<std::unique_ptr<SuperNode>> &
Failed,
586 SuperNodeDepsMap &SuperNodeDeps,
587 ElemToSuperNodeMap &ElemToSNs,
588 std::vector<SuperNode *> FailedSNs) {
589 for (
size_t I = 0;
I != SNs.size();) {
592 bool SNFailed =
false;
593 assert(SuperNodeDeps.count(SN.get()));
594 auto &SNSuperNodeDeps = SuperNodeDeps[SN.get()];
595 for (
auto *FailedSN : FailedSNs) {
596 if (FailedSN == SN.get() || SNSuperNodeDeps.count(FailedSN)) {
602 bool SNReady = SN->Deps.empty();
604 if (SNReady || SNFailed) {
614 std::vector<std::unique_ptr<SuperNode>> PendingSNs;
615 ElemToSuperNodeMap ElemToPendingSN;
616 Coalescer CoalesceToPendingSNs;