Skip to content

Commit f1539f1

Browse files
authored
Merge pull request #73304 from gottesmm/pr-0f53738606af56510a700d55dbd3a83360da595e
[region-isolation] Look through actor isolated, non-Sendable struct_element_addr geps.
2 parents bbd7863 + 077f62c commit f1539f1

File tree

4 files changed

+321
-34
lines changed

4 files changed

+321
-34
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -156,59 +156,38 @@ struct UseDefChainVisitor
156156
isMerge = true;
157157
break;
158158
case ProjectionKind::Enum: {
159-
// Enum is never a merge since it always has a single tuple field... but
160-
// it can be actor isolated.
161-
if (!bool(actorIsolation)) {
162-
auto *uedi = cast<UncheckedTakeEnumDataAddrInst>(inst);
163-
auto i = getActorIsolation(uedi->getEnumDecl());
164-
// If our operand decl is actor isolated, then we want to stop looking
165-
// through since it is Sendable.
166-
if (i.isActorIsolated()) {
167-
actorIsolation = i;
168-
return SILValue();
169-
}
170-
}
159+
auto op = cast<UncheckedTakeEnumDataAddrInst>(inst)->getOperand();
160+
161+
// See if our operand type is a sendable type. In such a case, we do not
162+
// want to look through our operand.
163+
if (!isNonSendableType(op->getType(), op->getFunction()))
164+
return SILValue();
165+
171166
break;
172167
}
173168
case ProjectionKind::Tuple: {
174169
// These are merges if we have multiple fields.
175-
auto *tti = cast<TupleElementAddrInst>(inst);
170+
auto op = cast<TupleElementAddrInst>(inst)->getOperand();
176171

177-
// See if our result type is a sendable type. In such a case, we do not
178-
// want to look through the tuple_element_addr since we do not want to
179-
// identify the sendable type with the non-sendable operand. These we
180-
// are always going to ignore anyways since a sendable let/var field of
181-
// a struct can always be used.
182-
if (!isNonSendableType(tti->getType(), tti->getFunction()))
172+
if (!isNonSendableType(op->getType(), op->getFunction()))
183173
return SILValue();
184174

185-
isMerge |= tti->getOperand()->getType().getNumTupleElements() > 1;
175+
isMerge |= op->getType().getNumTupleElements() > 1;
186176
break;
187177
}
188178
case ProjectionKind::Struct:
189-
auto *sea = cast<StructElementAddrInst>(inst);
190-
191-
// See if our type is actor isolated.
192-
if (!bool(actorIsolation)) {
193-
auto i = getActorIsolation(sea->getStructDecl());
194-
// If our parent type is actor isolated then we do not want to keep on
195-
// walking up from use->def since the value is considered Sendable.
196-
if (i.isActorIsolated()) {
197-
actorIsolation = i;
198-
return SILValue();
199-
}
200-
}
179+
auto op = cast<StructElementAddrInst>(inst)->getOperand();
201180

202181
// See if our result type is a sendable type. In such a case, we do not
203182
// want to look through the struct_element_addr since we do not want to
204183
// identify the sendable type with the non-sendable operand. These we
205184
// are always going to ignore anyways since a sendable let/var field of
206185
// a struct can always be used.
207-
if (!isNonSendableType(sea->getType(), sea->getFunction()))
186+
if (!isNonSendableType(op->getType(), op->getFunction()))
208187
return SILValue();
209188

210189
// These are merges if we have multiple fields.
211-
isMerge |= sea->getOperand()->getType().getNumNominalFields() > 1;
190+
isMerge |= op->getType().getNumNominalFields() > 1;
212191
break;
213192
}
214193
}
@@ -1457,6 +1436,8 @@ class PartitionOpTranslator {
14571436
LLVM_DEBUG(llvm::dbgs() << " %%" << state->getID() << ": ";
14581437
state->print(llvm::dbgs()); llvm::dbgs() << *arg);
14591438
nonSendableJoinedIndices.push_back(state->getID());
1439+
} else {
1440+
LLVM_DEBUG(llvm::dbgs() << " Sendable: " << *arg);
14601441
}
14611442
}
14621443

lib/SILOptimizer/Utils/PartitionUtils.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,23 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
243243
sei->getStructDecl());
244244
}
245245

246+
if (auto *seai = dyn_cast<StructElementAddrInst>(inst)) {
247+
return SILIsolationInfo::getActorIsolated(seai, SILValue(),
248+
seai->getStructDecl());
249+
}
250+
246251
// See if we have an unchecked_enum_data from a global actor isolated type.
247252
if (auto *uedi = dyn_cast<UncheckedEnumDataInst>(inst)) {
248253
return SILIsolationInfo::getActorIsolated(uedi, SILValue(),
249254
uedi->getEnumDecl());
250255
}
251256

257+
// See if we have an unchecked_enum_data from a global actor isolated type.
258+
if (auto *utedi = dyn_cast<UncheckedTakeEnumDataAddrInst>(inst)) {
259+
return SILIsolationInfo::getActorIsolated(utedi, SILValue(),
260+
utedi->getEnumDecl());
261+
}
262+
252263
// Check if we have an unsafeMutableAddressor from a global actor, mark the
253264
// returned value as being actor derived.
254265
if (auto applySite = dyn_cast<ApplyInst>(inst)) {

test/Concurrency/transfernonsendable_global_actor.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ var booleanFlag: Bool { false }
3030
@MainActor var mainActorIsolatedGlobal = NonSendableKlass()
3131
@CustomActor var customActorIsolatedGlobal = NonSendableKlass()
3232

33+
@MainActor
34+
class NonSendableGlobalActorIsolatedKlass {}
35+
36+
@available(*, unavailable)
37+
extension NonSendableGlobalActorIsolatedKlass: Sendable {}
38+
39+
@MainActor
40+
struct NonSendableGlobalActorIsolatedStruct {
41+
var k = NonSendableKlass()
42+
}
43+
44+
@available(*, unavailable)
45+
extension NonSendableGlobalActorIsolatedStruct: Sendable {}
46+
47+
@MainActor
48+
enum NonSendableGlobalActorIsolatedEnum {
49+
case first
50+
case second(NonSendableKlass)
51+
case third(SendableKlass)
52+
}
53+
54+
@available(*, unavailable)
55+
extension NonSendableGlobalActorIsolatedEnum: Sendable {}
56+
57+
3358
/////////////////
3459
// MARK: Tests //
3560
/////////////////

0 commit comments

Comments
 (0)