@@ -359,8 +359,6 @@ class PartitionOp {
359
359
}
360
360
};
361
361
362
- struct PartitionOpEvaluator ;
363
-
364
362
// / A map from Element -> Region that represents the current partition set.
365
363
// /
366
364
// /
@@ -369,7 +367,6 @@ class Partition {
369
367
// / A class defined in PartitionUtils unittest used to grab state from
370
368
// / Partition without exposing it to other users.
371
369
struct PartitionTester ;
372
- friend PartitionOpEvaluator;
373
370
374
371
using Element = PartitionPrimitives::Element;
375
372
using Region = PartitionPrimitives::Region;
@@ -451,14 +448,16 @@ class Partition {
451
448
return fst.elementToRegionMap == snd.elementToRegionMap ;
452
449
}
453
450
454
- bool isTracked (Element val) const { return elementToRegionMap.count (val); }
451
+ bool isTrackingElement (Element val) const {
452
+ return elementToRegionMap.count (val);
453
+ }
455
454
456
455
// / Mark val as transferred.
457
456
void markTransferred (Element val,
458
457
TransferringOperandSet *transferredOperandSet) {
459
458
// First see if our val is tracked. If it is not tracked, insert it and mark
460
459
// its new region as transferred.
461
- if (!isTracked (val)) {
460
+ if (!isTrackingElement (val)) {
462
461
elementToRegionMap.insert_or_assign (val, fresh_label);
463
462
regionToTransferredOpMap.insert ({fresh_label, transferredOperandSet});
464
463
fresh_label = Region (fresh_label + 1 );
@@ -485,7 +484,7 @@ class Partition {
485
484
// / we found that \p val was transferred. We return false otherwise.
486
485
bool undoTransfer (Element val) {
487
486
// First see if our val is tracked. If it is not tracked, insert it.
488
- if (!isTracked (val)) {
487
+ if (!isTrackingElement (val)) {
489
488
elementToRegionMap.insert_or_assign (val, fresh_label);
490
489
fresh_label = Region (fresh_label + 1 );
491
490
canonical = false ;
@@ -499,7 +498,7 @@ class Partition {
499
498
return regionToTransferredOpMap.erase (iter1->second );
500
499
}
501
500
502
- void addElement (Element newElt) {
501
+ void trackNewElement (Element newElt) {
503
502
// Map index newElt to a fresh label.
504
503
elementToRegionMap.insert_or_assign (newElt, fresh_label);
505
504
@@ -508,6 +507,22 @@ class Partition {
508
507
canonical = false ;
509
508
}
510
509
510
+ void assignElement (Element oldElt, Element newElt) {
511
+ elementToRegionMap.insert_or_assign (oldElt, elementToRegionMap.at (newElt));
512
+ canonical = false ;
513
+ }
514
+
515
+ bool areElementsInSameRegion (Element firstElt, Element secondElt) const {
516
+ return elementToRegionMap.at (firstElt) == elementToRegionMap.at (secondElt);
517
+ }
518
+
519
+ Region getRegion (Element elt) const { return elementToRegionMap.at (elt); }
520
+
521
+ using iterator = std::map<Element, Region>::iterator;
522
+ iterator begin () { return elementToRegionMap.begin (); }
523
+ iterator end () { return elementToRegionMap.end (); }
524
+ llvm::iterator_range<iterator> range () { return {begin (), end ()}; }
525
+
511
526
// / Construct the partition corresponding to the union of the two passed
512
527
// / partitions.
513
528
// /
@@ -754,10 +769,12 @@ class Partition {
754
769
return set;
755
770
}
756
771
757
- private:
758
772
// / Used only in assertions, check that Partitions promised to be canonical
759
773
// / are actually canonical
760
774
bool is_canonical_correct () {
775
+ #ifdef NDEBUG
776
+ return true ;
777
+ #else
761
778
if (!canonical)
762
779
return true ; // vacuously correct
763
780
@@ -796,8 +813,54 @@ class Partition {
796
813
}
797
814
798
815
return true ;
816
+ #endif
799
817
}
800
818
819
+ // / Merge the regions of two indices while maintaining canonicality. Returns
820
+ // / the final region used.
821
+ // /
822
+ // / This runs in linear time.
823
+ Region merge (Element fst, Element snd) {
824
+ assert (elementToRegionMap.count (fst) && elementToRegionMap.count (snd));
825
+
826
+ auto fstRegion = elementToRegionMap.at (fst);
827
+ auto sndRegion = elementToRegionMap.at (snd);
828
+
829
+ if (fstRegion == sndRegion)
830
+ return fstRegion;
831
+
832
+ // Maintain canonicality by renaming the greater-numbered region to the
833
+ // smaller region.
834
+ std::optional<Region> result;
835
+ if (fstRegion < sndRegion) {
836
+ result = fstRegion;
837
+
838
+ // Rename snd to use first region.
839
+ horizontalUpdate (elementToRegionMap, snd, fstRegion);
840
+ auto iter = regionToTransferredOpMap.find (sndRegion);
841
+ if (iter != regionToTransferredOpMap.end ()) {
842
+ auto operand = iter->second ;
843
+ regionToTransferredOpMap.erase (iter);
844
+ regionToTransferredOpMap.try_emplace (fstRegion, operand);
845
+ }
846
+ } else {
847
+ result = sndRegion;
848
+
849
+ horizontalUpdate (elementToRegionMap, fst, sndRegion);
850
+ auto iter = regionToTransferredOpMap.find (fstRegion);
851
+ if (iter != regionToTransferredOpMap.end ()) {
852
+ auto operand = iter->second ;
853
+ regionToTransferredOpMap.erase (iter);
854
+ regionToTransferredOpMap.try_emplace (sndRegion, operand);
855
+ }
856
+ }
857
+
858
+ assert (is_canonical_correct ());
859
+ assert (elementToRegionMap.at (fst) == elementToRegionMap.at (snd));
860
+ return *result;
861
+ }
862
+
863
+ private:
801
864
// / For each region label that occurs, find the first index at which it occurs
802
865
// / and relabel all instances of it to that index. This excludes the -1 label
803
866
// / for transferred regions.
@@ -845,51 +908,6 @@ class Partition {
845
908
assert (is_canonical_correct ());
846
909
}
847
910
848
- // / Merge the regions of two indices while maintaining canonicality. Returns
849
- // / the final region used.
850
- // /
851
- // / This runs in linear time.
852
- Region merge (Element fst, Element snd) {
853
- assert (elementToRegionMap.count (fst) && elementToRegionMap.count (snd));
854
-
855
- auto fstRegion = elementToRegionMap.at (fst);
856
- auto sndRegion = elementToRegionMap.at (snd);
857
-
858
- if (fstRegion == sndRegion)
859
- return fstRegion;
860
-
861
- // Maintain canonicality by renaming the greater-numbered region to the
862
- // smaller region.
863
- std::optional<Region> result;
864
- if (fstRegion < sndRegion) {
865
- result = fstRegion;
866
-
867
- // Rename snd to use first region.
868
- horizontalUpdate (elementToRegionMap, snd, fstRegion);
869
- auto iter = regionToTransferredOpMap.find (sndRegion);
870
- if (iter != regionToTransferredOpMap.end ()) {
871
- auto operand = iter->second ;
872
- regionToTransferredOpMap.erase (iter);
873
- regionToTransferredOpMap.try_emplace (fstRegion, operand);
874
- }
875
- } else {
876
- result = sndRegion;
877
-
878
- horizontalUpdate (elementToRegionMap, fst, sndRegion);
879
- auto iter = regionToTransferredOpMap.find (fstRegion);
880
- if (iter != regionToTransferredOpMap.end ()) {
881
- auto operand = iter->second ;
882
- regionToTransferredOpMap.erase (iter);
883
- regionToTransferredOpMap.try_emplace (sndRegion, operand);
884
- }
885
- }
886
-
887
- assert (is_canonical_correct ());
888
- assert (elementToRegionMap.at (fst) == elementToRegionMap.at (snd));
889
- return *result;
890
- }
891
-
892
- private:
893
911
// / For the passed `map`, ensure that `key` maps to `val`. If `key` already
894
912
// / mapped to a different value, ensure that all other keys mapped to that
895
913
// / value also now map to `val`. This is a relatively expensive (linear time)
@@ -1035,7 +1053,7 @@ struct PartitionOpEvaluator {
1035
1053
case PartitionOpKind::Assign:
1036
1054
assert (op.getOpArgs ().size () == 2 &&
1037
1055
" Assign PartitionOp should be passed 2 arguments" );
1038
- assert (p.elementToRegionMap . count (op.getOpArgs ()[1 ]) &&
1056
+ assert (p.isTrackingElement (op.getOpArgs ()[1 ]) &&
1039
1057
" Assign PartitionOp's source argument should be already tracked" );
1040
1058
// If we are using a region that was transferred as our assignment source
1041
1059
// value... emit an error.
@@ -1044,37 +1062,30 @@ struct PartitionOpEvaluator {
1044
1062
handleFailure (op, op.getOpArgs ()[1 ], transferredOperand);
1045
1063
}
1046
1064
}
1047
-
1048
- p.elementToRegionMap .insert_or_assign (
1049
- op.getOpArgs ()[0 ], p.elementToRegionMap .at (op.getOpArgs ()[1 ]));
1050
-
1051
- // assignment could have invalidated canonicality of either the old region
1052
- // of op.getOpArgs()[0] or the region of op.getOpArgs()[1], or both
1053
- p.canonical = false ;
1065
+ p.assignElement (op.getOpArgs ()[0 ], op.getOpArgs ()[1 ]);
1054
1066
return ;
1055
1067
case PartitionOpKind::AssignFresh:
1056
1068
assert (op.getOpArgs ().size () == 1 &&
1057
1069
" AssignFresh PartitionOp should be passed 1 argument" );
1058
1070
1059
- p.addElement (op.getOpArgs ()[0 ]);
1071
+ p.trackNewElement (op.getOpArgs ()[0 ]);
1060
1072
return ;
1061
1073
case PartitionOpKind::Transfer: {
1062
1074
assert (op.getOpArgs ().size () == 1 &&
1063
1075
" Transfer PartitionOp should be passed 1 argument" );
1064
- assert (p.elementToRegionMap . count (op.getOpArgs ()[0 ]) &&
1076
+ assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
1065
1077
" Transfer PartitionOp's argument should already be tracked" );
1066
1078
1067
1079
// check if any nontransferrables are transferred here, and handle the
1068
1080
// failure if so
1069
1081
for (Element nonTransferrable : nonTransferrableElements) {
1070
1082
assert (
1071
- p.elementToRegionMap . count (nonTransferrable) &&
1083
+ p.isTrackingElement (nonTransferrable) &&
1072
1084
" nontransferrables should be function args and self, and therefore"
1073
1085
" always present in the label map because of initialization at "
1074
1086
" entry" );
1075
1087
if (!p.isTransferred (nonTransferrable) &&
1076
- p.elementToRegionMap .at (nonTransferrable) ==
1077
- p.elementToRegionMap .at (op.getOpArgs ()[0 ])) {
1088
+ p.areElementsInSameRegion (nonTransferrable, op.getOpArgs ()[0 ])) {
1078
1089
return handleTransferNonTransferrable (op, nonTransferrable);
1079
1090
}
1080
1091
}
@@ -1090,8 +1101,8 @@ struct PartitionOpEvaluator {
1090
1101
bool isClosureCapturedElt =
1091
1102
isClosureCaptured (op.getOpArgs ()[0 ], op.getSourceOp ());
1092
1103
1093
- Region elementRegion = p.elementToRegionMap . at (op.getOpArgs ()[0 ]);
1094
- for (const auto &pair : p.elementToRegionMap ) {
1104
+ Region elementRegion = p.getRegion (op.getOpArgs ()[0 ]);
1105
+ for (const auto &pair : p.range () ) {
1095
1106
if (pair.second == elementRegion && isActorDerived (pair.first ))
1096
1107
return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ]);
1097
1108
isClosureCapturedElt |= isClosureCaptured (pair.first , op.getSourceOp ());
@@ -1106,7 +1117,7 @@ struct PartitionOpEvaluator {
1106
1117
case PartitionOpKind::UndoTransfer: {
1107
1118
assert (op.getOpArgs ().size () == 1 &&
1108
1119
" UndoTransfer PartitionOp should be passed 1 argument" );
1109
- assert (p.elementToRegionMap . count (op.getOpArgs ()[0 ]) &&
1120
+ assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
1110
1121
" UndoTransfer PartitionOp's argument should already be tracked" );
1111
1122
1112
1123
// Mark op.getOpArgs()[0] as not transferred.
@@ -1116,8 +1127,8 @@ struct PartitionOpEvaluator {
1116
1127
case PartitionOpKind::Merge:
1117
1128
assert (op.getOpArgs ().size () == 2 &&
1118
1129
" Merge PartitionOp should be passed 2 arguments" );
1119
- assert (p.elementToRegionMap . count (op.getOpArgs ()[0 ]) &&
1120
- p.elementToRegionMap . count (op.getOpArgs ()[1 ]) &&
1130
+ assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
1131
+ p.isTrackingElement (op.getOpArgs ()[1 ]) &&
1121
1132
" Merge PartitionOp's arguments should already be tracked" );
1122
1133
1123
1134
// if attempting to merge a transferred region, handle the failure
@@ -1137,7 +1148,7 @@ struct PartitionOpEvaluator {
1137
1148
case PartitionOpKind::Require:
1138
1149
assert (op.getOpArgs ().size () == 1 &&
1139
1150
" Require PartitionOp should be passed 1 argument" );
1140
- assert (p.elementToRegionMap . count (op.getOpArgs ()[0 ]) &&
1151
+ assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
1141
1152
" Require PartitionOp's argument should already be tracked" );
1142
1153
if (auto *transferredOperandSet = p.getTransferred (op.getOpArgs ()[0 ])) {
1143
1154
for (auto transferredOperand : transferredOperandSet->data ()) {
0 commit comments