@@ -1090,15 +1090,16 @@ class ValueIsolationRegionInfo {
1090
1090
}
1091
1091
1092
1092
bool hasActorIsolation () const {
1093
- return std::holds_alternative<std::optional<ActorIsolation>>(data);
1093
+ return kind == Actor &&
1094
+ std::holds_alternative<std::optional<ActorIsolation>>(data);
1094
1095
}
1095
1096
1096
1097
bool hasActorInstance () const {
1097
- return std::holds_alternative<NominalTypeDecl *>(data);
1098
+ return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
1098
1099
}
1099
1100
1100
1101
bool hasTaskIsolatedValue () const {
1101
- return std::holds_alternative<SILValue>(data);
1102
+ return kind == Task && std::holds_alternative<SILValue>(data);
1102
1103
}
1103
1104
1104
1105
// / If we actually have an actor decl, return that. Otherwise, see if we have
@@ -1128,8 +1129,19 @@ class ValueIsolationRegionInfo {
1128
1129
if (unsigned (other.kind ) < unsigned (kind))
1129
1130
return *this ;
1130
1131
1131
- assert (kind != ValueIsolationRegionInfo::Actor &&
1132
- " Actor should never be merged with another actor?!" );
1132
+ // TODO: Make this failing mean that we emit an unknown SIL error instead of
1133
+ // asserting.
1134
+ if (other.isActorIsolated () && isActorIsolated ()) {
1135
+ if (other.hasActorInstance () && hasActorInstance ()) {
1136
+ assert (other.getActorInstance () == getActorInstance () &&
1137
+ " Actor should never be merged with another actor unless with "
1138
+ " the same actor?!" );
1139
+ } else if (other.hasActorIsolation () && hasActorIsolation ()) {
1140
+ assert (other.getActorIsolation () == getActorIsolation () &&
1141
+ " Actor should never be merged with another actor unless with "
1142
+ " the same actor?!" );
1143
+ }
1144
+ }
1133
1145
1134
1146
// Otherwise, take the other value.
1135
1147
return other;
@@ -1204,15 +1216,18 @@ struct PartitionOpEvaluator {
1204
1216
}
1205
1217
1206
1218
// / Call handleTransferNonTransferrable on our CRTP subclass.
1207
- void handleTransferNonTransferrable (const PartitionOp &op,
1208
- Element elt) const {
1209
- return asImpl ().handleTransferNonTransferrable (op, elt);
1219
+ void handleTransferNonTransferrable (
1220
+ const PartitionOp &op, Element elt,
1221
+ ValueIsolationRegionInfo isolationRegionInfo) const {
1222
+ return asImpl ().handleTransferNonTransferrable (op, elt,
1223
+ isolationRegionInfo);
1210
1224
}
1211
-
1212
1225
// / Just call our CRTP subclass.
1213
- void handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1214
- Element otherElement) const {
1215
- return asImpl ().handleTransferNonTransferrable (op, elt, otherElement);
1226
+ void handleTransferNonTransferrable (
1227
+ const PartitionOp &op, Element elt, Element otherElement,
1228
+ ValueIsolationRegionInfo isolationRegionInfo) const {
1229
+ return asImpl ().handleTransferNonTransferrable (op, elt, otherElement,
1230
+ isolationRegionInfo);
1216
1231
}
1217
1232
1218
1233
// / Call isActorDerived on our CRTP subclass.
@@ -1282,39 +1297,35 @@ struct PartitionOpEvaluator {
1282
1297
assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
1283
1298
" Transfer PartitionOp's argument should already be tracked" );
1284
1299
1300
+ ValueIsolationRegionInfo isolationRegionInfo =
1301
+ getIsolationRegionInfo (op.getOpArgs ()[0 ]);
1302
+
1285
1303
// If we know our direct value is actor derived... immediately emit an
1286
1304
// error.
1287
- if (isActorDerived (op.getOpArgs ()[0 ]))
1288
- return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ]);
1305
+ if (isolationRegionInfo.hasActorIsolation ()) {
1306
+ return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ],
1307
+ isolationRegionInfo);
1308
+ }
1289
1309
1290
- // Otherwise, we may have a value that is actor derived or task isolated
1291
- // from another value. We need to prefer actor derived.
1292
- //
1293
- // While we are checking for actor derived, also check if our value or any
1294
- // value in our region is closure captured and propagate that bit in our
1295
- // transferred inst.
1310
+ // Otherwise, we need to merge our isolation region info with the
1311
+ // isolation region info of everything else in our region. This is the
1312
+ // dynamic isolation region info found by the dataflow.
1296
1313
bool isClosureCapturedElt =
1297
1314
isClosureCaptured (op.getOpArgs ()[0 ], op.getSourceOp ());
1298
1315
Region elementRegion = p.getRegion (op.getOpArgs ()[0 ]);
1299
- std::optional<Element> actorDerivedElt;
1300
- std::optional<Element> taskDerivedElt;
1301
1316
for (const auto &pair : p.range ()) {
1302
1317
if (pair.second == elementRegion) {
1303
- if (isActorDerived (pair.first ))
1304
- actorDerivedElt = pair.first ;
1305
- if (isTaskIsolatedDerived (pair.first ))
1306
- taskDerivedElt = pair.first ;
1318
+ isolationRegionInfo =
1319
+ isolationRegionInfo.merge (getIsolationRegionInfo (pair.first ));
1307
1320
isClosureCapturedElt |=
1308
1321
isClosureCaptured (pair.first , op.getSourceOp ());
1309
1322
}
1310
1323
}
1311
1324
1312
- // Now try to add the actor derived elt first and then the task derived
1313
- // elt, preferring actor derived.
1314
- if (actorDerivedElt.has_value () || taskDerivedElt.has_value ()) {
1315
- return handleTransferNonTransferrable (
1316
- op, op.getOpArgs ()[0 ],
1317
- actorDerivedElt.has_value () ? *actorDerivedElt : *taskDerivedElt);
1325
+ // If we merged anything, we need to handle a transfer non-transferrable.
1326
+ if (bool (isolationRegionInfo) && !isolationRegionInfo.isDisconnected ()) {
1327
+ return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ],
1328
+ isolationRegionInfo);
1318
1329
}
1319
1330
1320
1331
// Mark op.getOpArgs()[0] as transferred.
@@ -1415,14 +1426,13 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
1415
1426
1416
1427
// / This is called if we detect a never transferred element that was passed to
1417
1428
// / a transfer instruction.
1418
- void handleTransferNonTransferrable (const PartitionOp &op,
1419
- Element elt) const {}
1429
+ void
1430
+ handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1431
+ ValueIsolationRegionInfo regionInfo) const {}
1420
1432
1421
- // / This is called if we detect a never transferred element that was passed to
1422
- // / a transfer instruction but the actual element that could not be
1423
- // / transferred is a different element in its region.
1424
- void handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1425
- Element otherEltInRegion) const {}
1433
+ void handleTransferNonTransferrable (
1434
+ const PartitionOp &op, Element elt, Element otherElement,
1435
+ ValueIsolationRegionInfo isolationRegionInfo) const {}
1426
1436
1427
1437
// / This is used to determine if an element is actor derived. If we determine
1428
1438
// / that a region containing such an element is transferred, we emit an error
0 commit comments