Skip to content

Commit 777dac5

Browse files
authored
Merge pull request #75596 from gottesmm/release/6.0-rdar132767643
[6.0][region-isolation] Fix handling of coroutine apply results.
2 parents 0382996 + 1cdec42 commit 777dac5

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
@@ -120,15 +120,26 @@ class ActorInstance {
120120
/// matching.
121121
class SILIsolationInfo {
122122
public:
123-
/// The lattice is:
123+
/// This forms a lattice of semantics. The lattice progresses from left ->
124+
/// right below:
124125
///
125126
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
126127
///
127-
/// Unknown means no information. We error when merging on it.
128128
enum Kind : uint8_t {
129+
/// Unknown means no information. We error when merging on it.
129130
Unknown,
131+
132+
/// An entity with disconnected isolation can be freely transferred into
133+
/// another isolation domain. These are associated with "use after transfer"
134+
/// diagnostics.
130135
Disconnected,
136+
137+
/// An entity that is in the same region as a task-isolated value. Cannot be
138+
/// sent into another isolation domain.
131139
Task,
140+
141+
/// An entity that is in the same region as an actor-isolated value. Cannot
142+
/// be sent into another isolation domain.
132143
Actor,
133144
};
134145

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

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

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

11651173
void addAssign(SILValue destValue, Operand *srcOperand) {
@@ -1732,23 +1740,18 @@ class PartitionOpTranslator {
17321740
return;
17331741
}
17341742

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

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

test/Concurrency/transfernonsendable.sil

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

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

0 commit comments

Comments
 (0)