@@ -499,16 +499,73 @@ class Partition {
499
499
}
500
500
501
501
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
+ }
504
535
505
536
// Increment the fresh label so it remains fresh.
506
537
fresh_label = Region (fresh_label + 1 );
507
538
canonical = false ;
508
539
}
509
540
541
+ // / Assigns \p oldElt to the region associated with \p newElt.
510
542
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
+
512
569
canonical = false ;
513
570
}
514
571
@@ -766,6 +823,22 @@ class Partition {
766
823
return set;
767
824
}
768
825
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
+
769
842
// / Used only in assertions, check that Partitions promised to be canonical
770
843
// / are actually canonical
771
844
bool is_canonical_correct () {
@@ -781,12 +854,7 @@ class Partition {
781
854
return false ;
782
855
};
783
856
784
- llvm::SmallDenseSet<Region, 8 > seenRegion;
785
857
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
-
790
858
// Labels should not exceed fresh_label.
791
859
if (regionNo >= fresh_label)
792
860
return fail (eltNo, 0 );
@@ -804,10 +872,8 @@ class Partition {
804
872
return fail (eltNo, 3 );
805
873
}
806
874
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 ();
811
877
812
878
return true ;
813
879
#endif
@@ -868,6 +934,7 @@ class Partition {
868
934
return ;
869
935
canonical = true ;
870
936
937
+ validateRegionToTransferredOpMapRegions ();
871
938
std::map<Region, Region> oldRegionToRelabeledMap;
872
939
873
940
// We rely on in-order traversal of labels to ensure that we always take the
0 commit comments