Skip to content

Commit af8b19d

Browse files
authored
Merge pull request #75590 from gottesmm/pr-66aa73e45aa508bc763af6ccc128f36e93a9e144
[region-isolation] Fix handling of coroutine apply results.
2 parents 68721a4 + 541863d commit af8b19d

File tree

4 files changed

+76
-24
lines changed

4 files changed

+76
-24
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,19 @@ class PartitionOp {
493493
"Transfer needs a sourceInst");
494494
}
495495

496+
template <typename T>
497+
PartitionOp(PartitionOpKind opKind, T collectionOfIndices,
498+
SILInstruction *sourceInst = nullptr)
499+
: opKind(opKind), opArgs(), source(sourceInst) {
500+
assert(((opKind != PartitionOpKind::Transfer &&
501+
opKind != PartitionOpKind::UndoTransfer) ||
502+
sourceInst) &&
503+
"Transfer needs a sourceInst");
504+
for (Element elt : collectionOfIndices) {
505+
opArgs.push_back(elt);
506+
}
507+
}
508+
496509
PartitionOp(PartitionOpKind opKind, Element arg1, Operand *sourceOperand)
497510
: opKind(opKind), opArgs({arg1}), source(sourceOperand) {
498511
assert(((opKind != PartitionOpKind::Transfer &&
@@ -529,9 +542,10 @@ class PartitionOp {
529542
return PartitionOp(PartitionOpKind::Assign, destElt, srcElt, srcOperand);
530543
}
531544

532-
static PartitionOp AssignFresh(Element tgt,
545+
template <typename T>
546+
static PartitionOp AssignFresh(T collection,
533547
SILInstruction *sourceInst = nullptr) {
534-
return PartitionOp(PartitionOpKind::AssignFresh, tgt, sourceInst);
548+
return PartitionOp(PartitionOpKind::AssignFresh, collection, sourceInst);
535549
}
536550

537551
static PartitionOp Transfer(Element tgt, Operand *transferringOp) {
@@ -1162,12 +1176,18 @@ struct PartitionOpEvaluator {
11621176
p.assignElement(op.getOpArgs()[0], op.getOpArgs()[1]);
11631177
return;
11641178
}
1165-
case PartitionOpKind::AssignFresh:
1166-
assert(op.getOpArgs().size() == 1 &&
1167-
"AssignFresh PartitionOp should be passed 1 argument");
1168-
1169-
p.trackNewElement(op.getOpArgs()[0]);
1179+
case PartitionOpKind::AssignFresh: {
1180+
auto arrayRef = op.getOpArgs();
1181+
1182+
Element front = arrayRef.front();
1183+
p.trackNewElement(front);
1184+
arrayRef = arrayRef.drop_front();
1185+
for (auto x : arrayRef) {
1186+
p.trackNewElement(x);
1187+
p.assignElement(x, front);
1188+
}
11701189
return;
1190+
}
11711191
case PartitionOpKind::Transfer: {
11721192
// NOTE: We purposely do not check here if a transferred value is already
11731193
// transferred. Callers are expected to put a require for that

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,26 @@ class ActorInstance {
140140
/// matching.
141141
class SILIsolationInfo {
142142
public:
143-
/// The lattice is:
143+
/// This forms a lattice of semantics. The lattice progresses from left ->
144+
/// right below:
144145
///
145146
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
146147
///
147-
/// Unknown means no information. We error when merging on it.
148148
enum Kind : uint8_t {
149+
/// Unknown means no information. We error when merging on it.
149150
Unknown,
151+
152+
/// An entity with disconnected isolation can be freely transferred into
153+
/// another isolation domain. These are associated with "use after transfer"
154+
/// diagnostics.
150155
Disconnected,
156+
157+
/// An entity that is in the same region as a task-isolated value. Cannot be
158+
/// sent into another isolation domain.
151159
Task,
160+
161+
/// An entity that is in the same region as an actor-isolated value. Cannot
162+
/// be sent into another isolation domain.
152163
Actor,
153164
};
154165

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,8 +1159,16 @@ struct PartitionOpBuilder {
11591159
Element getActorIntroducingRepresentative(SILIsolationInfo actorIsolation);
11601160

11611161
void addAssignFresh(SILValue value) {
1162+
std::array<Element, 1> values = {lookupValueID(value)};
11621163
currentInstPartitionOps.emplace_back(
1163-
PartitionOp::AssignFresh(lookupValueID(value), currentInst));
1164+
PartitionOp::AssignFresh(values, currentInst));
1165+
}
1166+
1167+
void addAssignFresh(ArrayRef<SILValue> values) {
1168+
auto transformedCollection = makeTransformRange(
1169+
values, [&](SILValue value) { return lookupValueID(value); });
1170+
currentInstPartitionOps.emplace_back(
1171+
PartitionOp::AssignFresh(transformedCollection, currentInst));
11641172
}
11651173

11661174
void addAssign(SILValue destValue, Operand *srcOperand) {
@@ -1733,23 +1741,18 @@ class PartitionOpTranslator {
17331741
return;
17341742
}
17351743

1736-
auto assignResultsRef = llvm::ArrayRef(assignResults);
1737-
SILValue front = assignResultsRef.front();
1738-
assignResultsRef = assignResultsRef.drop_front();
1739-
1744+
// If we do not have any non-Sendable srcs, then all of our results get one
1745+
// large fresh region.
17401746
if (assignOperands.empty()) {
1741-
// If no non-sendable srcs, non-sendable tgts get a fresh region.
1742-
builder.addAssignFresh(front);
1743-
} else {
1744-
builder.addAssign(front, assignOperands.front().first);
1747+
builder.addAssignFresh(assignResults);
1748+
return;
17451749
}
17461750

1747-
// Assign all targets to the target region.
1748-
while (assignResultsRef.size()) {
1749-
SILValue next = assignResultsRef.front();
1750-
assignResultsRef = assignResultsRef.drop_front();
1751-
1752-
builder.addAssign(next, assignOperands.front().first);
1751+
// Otherwise, we need to assign all of the results to be in the same region
1752+
// as the operands. Without losing generality, we just use the first
1753+
// non-Sendable one.
1754+
for (auto result : assignResults) {
1755+
builder.addAssign(result, assignOperands.front().first);
17531756
}
17541757
}
17551758

test/Concurrency/transfernonsendable.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ actor MyActor {
9898
var klass: NonSendableKlass { get set }
9999
}
100100

101+
sil @beginApplyMultipleResultCallee : $@yield_once @convention(thin) () -> (@yields @guaranteed NonSendableKlass, @yields @guaranteed NonSendableKlass)
102+
101103
/////////////////
102104
// MARK: Tests //
103105
/////////////////
@@ -395,3 +397,19 @@ bb0:
395397
%9999 = tuple ()
396398
return %9999 : $()
397399
}
400+
401+
// Make sure that we do not crash on this.
402+
//
403+
// We used to crash on this since we would want to assign the region of an
404+
// operand to the results... but we do not have one and have multiple
405+
// results. This doesn't normally happen with most applies since applies do not
406+
// have multiple results, so in such a case, we would just assign fresh and not
407+
// try to do the assignment for the rest of the values.
408+
sil [ossa] @handleNoOperandToAssignToResults : $@convention(thin) () -> () {
409+
bb0:
410+
%0 = function_ref @beginApplyMultipleResultCallee : $@yield_once @convention(thin) () -> (@yields @guaranteed NonSendableKlass, @yields @guaranteed NonSendableKlass)
411+
(%1, %2, %3) = begin_apply %0() : $@yield_once @convention(thin) () -> (@yields @guaranteed NonSendableKlass, @yields @guaranteed NonSendableKlass)
412+
end_apply %3 as $()
413+
%9999 = tuple ()
414+
return %9999 : $()
415+
}

0 commit comments

Comments
 (0)