Skip to content

Commit 72edcad

Browse files
authored
Merge pull request #82900 from DougGregor/region-analysis-conformances-cleanup
[Region isolation] Factor SILIsolationInfo creation into static methods
2 parents 2edec10 + 1e87656 commit 72edcad

File tree

4 files changed

+180
-197
lines changed

4 files changed

+180
-197
lines changed

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ class SILIsolationInfo {
229229
->lookThroughAllOptionalTypes()
230230
->getAnyActor())) &&
231231
"actorInstance must be an actor if it is non-empty");
232+
assert((getKind() != Disconnected || isolatedConformance == nullptr) &&
233+
"isolated conformance cannot be introduced with disconnected region");
232234
}
233235

234236
SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance,
@@ -251,6 +253,15 @@ class SILIsolationInfo {
251253
SILIsolationInfo(Kind kind, Options options = Options())
252254
: actorIsolation(), kind(kind), options(options.toRaw()) {}
253255

256+
/// Infer isolation region from the set of protocol conformances.
257+
static SILIsolationInfo getFromConformances(
258+
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
259+
260+
/// Determine the isolation of conformances that could be introduced by a
261+
/// cast from sourceType to destType.
262+
static SILIsolationInfo getForCastConformances(
263+
SILValue value, CanType sourceType, CanType destType);
264+
254265
public:
255266
SILIsolationInfo() : actorIsolation(), kind(Kind::Unknown), options(0) {}
256267

@@ -532,6 +543,9 @@ class SILIsolationInfo {
532543
return {};
533544
}
534545

546+
/// Infer isolation of conformances for the given instruction.
547+
static SILIsolationInfo getConformanceIsolation(SILInstruction *inst);
548+
535549
/// A helper that is used to ensure that we treat certain builtin values as
536550
/// non-Sendable that the AST level otherwise thinks are non-Sendable.
537551
///

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 20 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@
1515
#include "swift/SILOptimizer/Analysis/RegionAnalysis.h"
1616

1717
#include "swift/AST/ASTWalker.h"
18-
#include "swift/AST/ConformanceLookup.h"
1918
#include "swift/AST/DiagnosticsSIL.h"
2019
#include "swift/AST/Expr.h"
21-
#include "swift/AST/ExistentialLayout.h"
22-
#include "swift/AST/PackConformance.h"
23-
#include "swift/AST/ProtocolConformance.h"
2420
#include "swift/AST/Type.h"
2521
#include "swift/Basic/Assertions.h"
2622
#include "swift/Basic/FrozenMultiMap.h"
@@ -274,59 +270,6 @@ struct AddressBaseComputingVisitor
274270

275271
} // namespace
276272

277-
/// Determine the isolation of conformances that could be introduced by a cast from sourceType to
278-
/// destType.
279-
///
280-
///
281-
static SILIsolationInfo getIsolationForCastConformances(
282-
SILValue value, CanType sourceType, CanType destType) {
283-
// If the enclosing function is @concurrent, then a cast cannot pick up
284-
// any isolated conformances because it's not on any actor.
285-
auto function = value->getFunction();
286-
auto functionIsolation = function->getActorIsolation();
287-
if (functionIsolation && functionIsolation->isNonisolated())
288-
return {};
289-
290-
auto sendableMetatype =
291-
sourceType->getASTContext().getProtocol(KnownProtocolKind::SendableMetatype);
292-
if (!sendableMetatype)
293-
return {};
294-
295-
if (!destType.isAnyExistentialType())
296-
return {};
297-
298-
const auto &destLayout = destType.getExistentialLayout();
299-
for (auto proto : destLayout.getProtocols()) {
300-
if (proto->isMarkerProtocol())
301-
continue;
302-
303-
// If the source type already conforms to the protocol, we won't be looking
304-
// it up dynamically.
305-
if (!lookupConformance(sourceType, proto, /*allowMissing=*/false).isInvalid())
306-
continue;
307-
308-
// If the protocol inherits SendableMetatype, it can't have isolated
309-
// conformances.
310-
if (proto->inheritsFrom(sendableMetatype))
311-
continue;
312-
313-
// The cast can produce a conformance with the same isolation as this
314-
// function is dynamically executing. If that's known (i.e., because we're
315-
// on a global actor), the value is isolated to that global actor.
316-
// Otherwise, it's task-isolated.
317-
if (functionIsolation && functionIsolation->isGlobalActor()) {
318-
return SILIsolationInfo::getGlobalActorIsolated(
319-
value, functionIsolation->getGlobalActor(), proto);
320-
}
321-
322-
// Consider the cast to be task-isolated, because the runtime could find
323-
// a conformance that is isolated to the current context.
324-
return SILIsolationInfo::getTaskIsolated(value, proto);
325-
}
326-
327-
return {};
328-
}
329-
330273
/// Classify an instructions as look through when we are looking through
331274
/// values. We assert that all instructions that are CONSTANT_TRANSLATION
332275
/// LookThrough to make sure they stay in sync.
@@ -385,16 +328,15 @@ static bool isStaticallyLookThroughInst(SILInstruction *inst) {
385328
case SILInstructionKind::BeginBorrowInst:
386329
// Look through if it isn't from a var decl.
387330
return !cast<BeginBorrowInst>(inst)->isFromVarDecl();
331+
case SILInstructionKind::InitExistentialValueInst:
332+
return !SILIsolationInfo::getConformanceIsolation(inst);
388333
case SILInstructionKind::UnconditionalCheckedCastInst: {
389334
auto cast = SILDynamicCastInst::getAs(inst);
390335
assert(cast);
391336

392337
// If this cast introduces isolation due to conformances, we cannot look
393338
// through it to the source.
394-
if (!getIsolationForCastConformances(
395-
llvm::cast<UnconditionalCheckedCastInst>(inst),
396-
cast.getSourceFormalType(), cast.getTargetFormalType())
397-
.isDisconnected())
339+
if (SILIsolationInfo::getConformanceIsolation(inst))
398340
return false;
399341

400342
if (cast.isRCIdentityPreserving())
@@ -2231,13 +2173,6 @@ class PartitionOpTranslator {
22312173
return valueMap.lookupValueID(value);
22322174
}
22332175

2234-
/// Determine the isolation of a set of conformances.
2235-
///
2236-
/// This function identifies potentially-isolated conformances that might affect the isolation of the given
2237-
/// value.
2238-
SILIsolationInfo getIsolationFromConformances(
2239-
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
2240-
22412176
public:
22422177
/// Return the partition consisting of all function arguments.
22432178
///
@@ -3210,7 +3145,8 @@ class PartitionOpTranslator {
32103145

32113146
case TranslationSemantics::Assign:
32123147
return translateSILMultiAssign(
3213-
inst->getResults(), makeOperandRefRange(inst->getAllOperands()));
3148+
inst->getResults(), makeOperandRefRange(inst->getAllOperands()),
3149+
SILIsolationInfo::getConformanceIsolation(inst));
32143150

32153151
case TranslationSemantics::Require:
32163152
for (auto op : inst->getOperandValues())
@@ -3227,7 +3163,8 @@ class PartitionOpTranslator {
32273163
case TranslationSemantics::Store:
32283164
return translateSILStore(
32293165
&inst->getAllOperands()[CopyLikeInstruction::Dest],
3230-
&inst->getAllOperands()[CopyLikeInstruction::Src]);
3166+
&inst->getAllOperands()[CopyLikeInstruction::Src],
3167+
SILIsolationInfo::getConformanceIsolation(inst));
32313168

32323169
case TranslationSemantics::Special:
32333170
return;
@@ -3238,7 +3175,8 @@ class PartitionOpTranslator {
32383175
case TranslationSemantics::TerminatorPhi: {
32393176
TermArgSources sources;
32403177
sources.init(inst);
3241-
return translateSILPhi(sources);
3178+
return translateSILPhi(
3179+
sources, SILIsolationInfo::getConformanceIsolation(inst));
32423180
}
32433181

32443182
case TranslationSemantics::Asserting:
@@ -3451,6 +3389,8 @@ CONSTANT_TRANSLATION(CopyBlockInst, Assign)
34513389
CONSTANT_TRANSLATION(CopyBlockWithoutEscapingInst, Assign)
34523390
CONSTANT_TRANSLATION(IndexAddrInst, Assign)
34533391
CONSTANT_TRANSLATION(InitBlockStorageHeaderInst, Assign)
3392+
CONSTANT_TRANSLATION(InitExistentialAddrInst, Assign)
3393+
CONSTANT_TRANSLATION(InitExistentialRefInst, Assign)
34543394
CONSTANT_TRANSLATION(OpenExistentialBoxInst, Assign)
34553395
CONSTANT_TRANSLATION(OpenExistentialRefInst, Assign)
34563396
CONSTANT_TRANSLATION(TailAddrInst, Assign)
@@ -3539,6 +3479,7 @@ CONSTANT_TRANSLATION(StoreInst, Store)
35393479
CONSTANT_TRANSLATION(StoreWeakInst, Store)
35403480
CONSTANT_TRANSLATION(MarkUnresolvedMoveAddrInst, Store)
35413481
CONSTANT_TRANSLATION(UncheckedRefCastAddrInst, Store)
3482+
CONSTANT_TRANSLATION(UnconditionalCheckedCastAddrInst, Store)
35423483
CONSTANT_TRANSLATION(StoreUnownedInst, Store)
35433484

35443485
//===---
@@ -3613,6 +3554,7 @@ CONSTANT_TRANSLATION(YieldInst, Require)
36133554
// Terminators that act as phis.
36143555
CONSTANT_TRANSLATION(BranchInst, TerminatorPhi)
36153556
CONSTANT_TRANSLATION(CondBranchInst, TerminatorPhi)
3557+
CONSTANT_TRANSLATION(CheckedCastBranchInst, TerminatorPhi)
36163558
CONSTANT_TRANSLATION(DynamicMethodBranchInst, TerminatorPhi)
36173559

36183560
// Function exiting terminators.
@@ -4014,34 +3956,16 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
40143956

40153957
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
40163958
UnconditionalCheckedCastInst *ucci) {
4017-
auto isolation = getIsolationForCastConformances(
4018-
ucci, ucci->getSourceFormalType(), ucci->getTargetFormalType());
3959+
auto isolation = SILIsolationInfo::getConformanceIsolation(ucci);
40193960

4020-
if (isolation.isDisconnected() &&
3961+
if (!isolation &&
40213962
SILDynamicCastInst(ucci).isRCIdentityPreserving()) {
40223963
assert(isStaticallyLookThroughInst(ucci) && "Out of sync");
40233964
return TranslationSemantics::LookThrough;
40243965
}
40253966

40263967
assert(!isStaticallyLookThroughInst(ucci) && "Out of sync");
4027-
translateSILMultiAssign(
4028-
ucci->getResults(), makeOperandRefRange(ucci->getAllOperands()),
4029-
isolation);
4030-
return TranslationSemantics::Special;
4031-
}
4032-
4033-
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastAddrInst(
4034-
UnconditionalCheckedCastAddrInst *uccai) {
4035-
auto isolation = getIsolationForCastConformances(
4036-
uccai->getAllOperands()[CopyLikeInstruction::Dest].get(),
4037-
uccai->getSourceFormalType(), uccai->getTargetFormalType());
4038-
4039-
translateSILStore(
4040-
&uccai->getAllOperands()[CopyLikeInstruction::Dest],
4041-
&uccai->getAllOperands()[CopyLikeInstruction::Src],
4042-
isolation);
4043-
4044-
return TranslationSemantics::Special;
3968+
return TranslationSemantics::Assign;
40453969
}
40463970

40473971
// RefElementAddrInst is not considered to be a lookThrough since we want to
@@ -4130,117 +4054,18 @@ PartitionOpTranslator::visitPartialApplyInst(PartialApplyInst *pai) {
41304054
return TranslationSemantics::Special;
41314055
}
41324056

4133-
SILIsolationInfo
4134-
PartitionOpTranslator::getIsolationFromConformances(
4135-
SILValue value, ArrayRef<ProtocolConformanceRef> conformances) {
4136-
for (auto conformance: conformances) {
4137-
if (conformance.getProtocol()->isMarkerProtocol())
4138-
continue;
4139-
4140-
// If the conformance is a pack, recurse.
4141-
if (conformance.isPack()) {
4142-
auto pack = conformance.getPack();
4143-
for (auto innerConformance : pack->getPatternConformances()) {
4144-
auto isolation = getIsolationFromConformances(value, innerConformance);
4145-
if (isolation)
4146-
return isolation;
4147-
}
4148-
4149-
continue;
4150-
}
4151-
4152-
// If a concrete conformance is global-actor-isolated, then the resulting
4153-
// value must be.
4154-
if (conformance.isConcrete()) {
4155-
auto isolation = conformance.getConcrete()->getIsolation();
4156-
if (isolation.isGlobalActor()) {
4157-
return SILIsolationInfo::getGlobalActorIsolated(
4158-
value, isolation.getGlobalActor(), conformance.getProtocol());
4159-
}
4160-
4161-
continue;
4162-
}
4163-
4164-
// If an abstract conformance is for a non-SendableMetatype-conforming
4165-
// type, the resulting value is task-isolated.
4166-
if (conformance.isAbstract()) {
4167-
auto sendableMetatype =
4168-
conformance.getType()->getASTContext()
4169-
.getProtocol(KnownProtocolKind::SendableMetatype);
4170-
if (sendableMetatype &&
4171-
lookupConformance(conformance.getType(), sendableMetatype,
4172-
/*allowMissing=*/false).isInvalid()) {
4173-
return SILIsolationInfo::getTaskIsolated(value,
4174-
conformance.getProtocol());
4175-
}
4176-
}
4177-
}
4178-
4179-
return {};
4180-
}
4181-
4182-
TranslationSemantics
4183-
PartitionOpTranslator::visitInitExistentialAddrInst(InitExistentialAddrInst *ieai) {
4184-
auto conformanceIsolationInfo = getIsolationFromConformances(
4185-
ieai, ieai->getConformances());
4186-
4187-
translateSILMultiAssign(ieai->getResults(),
4188-
makeOperandRefRange(ieai->getAllOperands()),
4189-
conformanceIsolationInfo);
4190-
4191-
return TranslationSemantics::Special;
4192-
}
4193-
4194-
TranslationSemantics
4195-
PartitionOpTranslator::visitInitExistentialRefInst(InitExistentialRefInst *ieri) {
4196-
auto conformanceIsolationInfo = getIsolationFromConformances(
4197-
ieri, ieri->getConformances());
4198-
4199-
translateSILMultiAssign(ieri->getResults(),
4200-
makeOperandRefRange(ieri->getAllOperands()),
4201-
conformanceIsolationInfo);
4202-
4203-
return TranslationSemantics::Special;
4204-
}
4205-
42064057
TranslationSemantics
42074058
PartitionOpTranslator::visitInitExistentialValueInst(InitExistentialValueInst *ievi) {
4208-
auto conformanceIsolationInfo = getIsolationFromConformances(
4209-
ievi, ievi->getConformances());
4210-
4211-
translateSILMultiAssign(ievi->getResults(),
4212-
makeOperandRefRange(ievi->getAllOperands()),
4213-
conformanceIsolationInfo);
4214-
4215-
return TranslationSemantics::Special;
4216-
}
4217-
4218-
TranslationSemantics
4219-
PartitionOpTranslator::visitCheckedCastBranchInst(CheckedCastBranchInst *ccbi) {
4220-
// Consider whether the value produced by the cast might be task-isolated.
4221-
auto resultValue = ccbi->getSuccessBB()->getArgument(0);
4222-
auto conformanceIsolation = getIsolationForCastConformances(
4223-
resultValue,
4224-
ccbi->getSourceFormalType(),
4225-
ccbi->getTargetFormalType());
4226-
TermArgSources sources;
4227-
sources.init(static_cast<SILInstruction *>(ccbi));
4228-
translateSILPhi(sources, conformanceIsolation);
4059+
if (isStaticallyLookThroughInst(ievi))
4060+
return TranslationSemantics::LookThrough;
42294061

4230-
return TranslationSemantics::Special;
4062+
return TranslationSemantics::Assign;
42314063
}
42324064

42334065
TranslationSemantics PartitionOpTranslator::visitCheckedCastAddrBranchInst(
42344066
CheckedCastAddrBranchInst *ccabi) {
42354067
assert(ccabi->getSuccessBB()->getNumArguments() <= 1);
42364068

4237-
// Consider whether the value written into by the cast might be task-isolated.
4238-
auto resultValue = ccabi->getAllOperands().back().get();
4239-
auto conformanceIsolation = getIsolationForCastConformances(
4240-
resultValue,
4241-
ccabi->getSourceFormalType(),
4242-
ccabi->getTargetFormalType());
4243-
42444069
// checked_cast_addr_br does not have any arguments in its resulting
42454070
// block. We should just use a multi-assign on its operands.
42464071
//
@@ -4250,7 +4075,7 @@ TranslationSemantics PartitionOpTranslator::visitCheckedCastAddrBranchInst(
42504075
// but still correct.
42514076
translateSILMultiAssign(ArrayRef<SILValue>(),
42524077
makeOperandRefRange(ccabi->getAllOperands()),
4253-
conformanceIsolation);
4078+
SILIsolationInfo::getConformanceIsolation(ccabi));
42544079
return TranslationSemantics::Special;
42554080
}
42564081

0 commit comments

Comments
 (0)