Skip to content

Commit 9dfc9b6

Browse files
committed
[region-isolation] Track if a non-Sendable value was derived from an actor and treat its region as being within an actor's isolation domain.
Importantly, we determine at the error stage if a specific value that is transferred is within the same region of a value that is Actor derived. This means that we can in a flow insensitive manner determine the values that are actor derived and then via propagating those values into various regions determine the issue... using our region analysis to handle the flow sensitivity. One important case to reason about here is that since we are relying on the region propagation for flow sensitivity is that this solves the var case for us. A var when declared is never marked as actor derived. Var uses only become actor derived if the var was merged into a region that contain is actor derived. That means that re-assigning to a non-actor derived value, eliminates the actor derived bit. As part of this, I also discovered I could just get rid of the captured uniquely identified array in favor of just passing in an actor derived flag. rdar://115656589
1 parent bf64711 commit 9dfc9b6

File tree

4 files changed

+529
-91
lines changed

4 files changed

+529
-91
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,9 @@ class Partition {
408408
[](const PartitionOp &, Element) {},
409409
ArrayRef<Element> nonconsumables = {},
410410
llvm::function_ref<void(const PartitionOp &, Element)>
411-
handleConsumeNonConsumable = [](const PartitionOp &, Element) {}) {
411+
handleConsumeNonConsumable = [](const PartitionOp &, Element) {},
412+
llvm::function_ref<bool(Element)> isActorDerived = nullptr) {
413+
412414
REGIONBASEDISOLATION_VERBOSE_LOG(llvm::dbgs() << "Applying: ";
413415
op.print(llvm::dbgs()));
414416
REGIONBASEDISOLATION_VERBOSE_LOG(llvm::dbgs() << " Before: ";
@@ -444,7 +446,7 @@ class Partition {
444446
fresh_label = Region(fresh_label + 1);
445447
canonical = false;
446448
break;
447-
case PartitionOpKind::Transfer:
449+
case PartitionOpKind::Transfer: {
448450
assert(op.OpArgs.size() == 1 &&
449451
"Consume PartitionOp should be passed 1 argument");
450452
assert(labels.count(op.OpArgs[0]) &&
@@ -464,12 +466,26 @@ class Partition {
464466
}
465467
}
466468

467-
// ensure region is transferred
469+
// If this value is actor derived or if any elements in its region are
470+
// actor derived, we need to treat as non-consumable.
471+
if (isActorDerived && isActorDerived(op.OpArgs[0]))
472+
return handleConsumeNonConsumable(op, op.OpArgs[0]);
473+
Region elementRegion = labels.at(op.OpArgs[0]);
474+
if (llvm::any_of(labels,
475+
[&](const std::pair<Element, Region> &pair) -> bool {
476+
if (pair.second != elementRegion)
477+
return false;
478+
return isActorDerived && isActorDerived(pair.first);
479+
}))
480+
return handleConsumeNonConsumable(op, op.OpArgs[0]);
481+
482+
// Ensure if the region is transferred...
468483
if (!isTransferred(op.OpArgs[0]))
469-
// mark region as transferred
484+
// that all elements associated with the region are marked as
485+
// transferred.
470486
horizontalUpdate(labels, op.OpArgs[0], Region::transferred());
471-
472487
break;
488+
}
473489
case PartitionOpKind::Merge:
474490
assert(op.OpArgs.size() == 2 &&
475491
"Merge PartitionOp should be passed 2 arguments");

0 commit comments

Comments
 (0)