@@ -499,16 +499,73 @@ class Partition {
499499 }
500500
501501 void trackNewElement (Element newElt) {
502- // Map index newElt to a fresh label.
503- elementToRegionMap.insert_or_assign (newElt, fresh_label);
502+ SWIFT_DEFER { validateRegionToTransferredOpMapRegions (); };
503+
504+ // First try to emplace newElt with fresh_label.
505+ auto iter = elementToRegionMap.try_emplace (newElt, fresh_label);
506+
507+ // If we did insert, then we know that the value is completely new. We can
508+ // just update the fresh_label, set canonical to false, and return.
509+ if (iter.second ) {
510+ // Increment the fresh label so it remains fresh.
511+ fresh_label = Region (fresh_label + 1 );
512+ canonical = false ;
513+ return ;
514+ }
515+
516+ // Otherwise, we have a bit more work that we need to perform:
517+ //
518+ // 1. We of course need to update iter to point at fresh_label.
519+ //
520+ // 2. We need to see if this value was the last element in its current
521+ // region. If so, then we need to remove the region from the transferred op
522+ // map.
523+ //
524+ // This is important to ensure that every region in the transferredOpMap is
525+ // also in elementToRegionMap.
526+ auto oldRegion = iter.first ->second ;
527+ iter.first ->second = fresh_label;
528+
529+ if (llvm::none_of (elementToRegionMap,
530+ [&](std::pair<Element, Region> value) {
531+ return value.second == oldRegion;
532+ })) {
533+ regionToTransferredOpMap.erase (oldRegion);
534+ }
504535
505536 // Increment the fresh label so it remains fresh.
506537 fresh_label = Region (fresh_label + 1 );
507538 canonical = false ;
508539 }
509540
541+ // / Assigns \p oldElt to the region associated with \p newElt.
510542 void assignElement (Element oldElt, Element newElt) {
511- elementToRegionMap.insert_or_assign (oldElt, elementToRegionMap.at (newElt));
543+ SWIFT_DEFER { validateRegionToTransferredOpMapRegions (); };
544+
545+ // First try to emplace oldElt with the newRegion.
546+ auto newRegion = elementToRegionMap.at (newElt);
547+ auto iter = elementToRegionMap.try_emplace (oldElt, newRegion);
548+
549+ // If we did an insert, then we know that the value is new and we can just
550+ // set canonical to false and return.
551+ if (iter.second ) {
552+ canonical = false ;
553+ return ;
554+ }
555+
556+ // Otherwise, we did an assign. In such a case, we need to see if oldElt was
557+ // the last element in oldRegion. If so, we need to erase the oldRegion from
558+ // regionToTransferredOpMap.
559+ auto oldRegion = iter.first ->second ;
560+ iter.first ->second = newRegion;
561+
562+ if (llvm::none_of (elementToRegionMap,
563+ [&](std::pair<Element, Region> value) {
564+ return value.second == oldRegion;
565+ })) {
566+ regionToTransferredOpMap.erase (oldRegion);
567+ }
568+
512569 canonical = false ;
513570 }
514571
@@ -766,6 +823,22 @@ class Partition {
766823 return set;
767824 }
768825
826+ // / Validate that all regions in the regionToTransferredOpMap exist in the
827+ // / elementToRegionMap.
828+ // /
829+ // / Asserts when NDEBUG is set. Does nothing otherwise.
830+ void validateRegionToTransferredOpMapRegions () const {
831+ #ifndef NDEBUG
832+ llvm::SmallSet<Region, 8 > regions;
833+ for (auto [eltNo, regionNo] : elementToRegionMap) {
834+ regions.insert (regionNo);
835+ }
836+ for (auto [regionNo, opSet] : regionToTransferredOpMap) {
837+ assert (regions.contains (regionNo) && " Region doesn't exist?!" );
838+ }
839+ #endif
840+ }
841+
769842 // / Used only in assertions, check that Partitions promised to be canonical
770843 // / are actually canonical
771844 bool is_canonical_correct () {
@@ -781,12 +854,7 @@ class Partition {
781854 return false ;
782855 };
783856
784- llvm::SmallDenseSet<Region, 8 > seenRegion;
785857 for (auto &[eltNo, regionNo] : elementToRegionMap) {
786- // See if all of our regionToTransferMap keys are regions in labels.
787- if (regionToTransferredOpMap.count (regionNo))
788- seenRegion.insert (regionNo);
789-
790858 // Labels should not exceed fresh_label.
791859 if (regionNo >= fresh_label)
792860 return fail (eltNo, 0 );
@@ -804,10 +872,8 @@ class Partition {
804872 return fail (eltNo, 3 );
805873 }
806874
807- if (seenRegion.size () != regionToTransferredOpMap.size ()) {
808- llvm::report_fatal_error (
809- " FAIL! regionToTransferMap has a region that isn't being tracked?!" );
810- }
875+ // Before we do anything, validate region to transferred op map.
876+ validateRegionToTransferredOpMapRegions ();
811877
812878 return true ;
813879#endif
@@ -868,6 +934,7 @@ class Partition {
868934 return ;
869935 canonical = true ;
870936
937+ validateRegionToTransferredOpMapRegions ();
871938 std::map<Region, Region> oldRegionToRelabeledMap;
872939
873940 // We rely on in-order traversal of labels to ensure that we always take the
0 commit comments