Skip to content

Commit 22ca6b9

Browse files
committed
[Region isolation] Factor SILIsolationInfo creation into static methods
Better match the style of SILIsolationInfo by moving the code for determining SILIsolationInfo from conformances or dynamic casts to existentials into static `getXYZ` methods on SILIsolationInfo. Other than adding an assertion regarding disconnected regions, no intended functionality change.
1 parent 6637960 commit 22ca6b9

File tree

3 files changed

+121
-121
lines changed

3 files changed

+121
-121
lines changed

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ class SILIsolationInfo {
225225
->lookThroughAllOptionalTypes()
226226
->getAnyActor())) &&
227227
"actorInstance must be an actor if it is non-empty");
228+
assert((getKind() != Disconnected || isolatedConformance == nullptr) &&
229+
"isolated conformance cannot be introduced with disconnected region");
228230
}
229231

230232
SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance,
@@ -501,6 +503,15 @@ class SILIsolationInfo {
501503
return {};
502504
}
503505

506+
/// Infer isolation region from the set of protocol conformances.
507+
static SILIsolationInfo getFromConformances(
508+
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
509+
510+
/// Determine the isolation of conformances that could be introduced by a
511+
/// cast from sourceType to destType.
512+
static SILIsolationInfo getForCastConformances(
513+
SILValue value, CanType sourceType, CanType destType);
514+
504515
/// A helper that is used to ensure that we treat certain builtin values as
505516
/// non-Sendable that the AST level otherwise thinks are non-Sendable.
506517
///

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 8 additions & 121 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"
@@ -265,59 +261,6 @@ struct AddressBaseComputingVisitor
265261

266262
} // namespace
267263

268-
/// Determine the isolation of conformances that could be introduced by a cast from sourceType to
269-
/// destType.
270-
///
271-
///
272-
static SILIsolationInfo getIsolationForCastConformances(
273-
SILValue value, CanType sourceType, CanType destType) {
274-
// If the enclosing function is @concurrent, then a cast cannot pick up
275-
// any isolated conformances because it's not on any actor.
276-
auto function = value->getFunction();
277-
auto functionIsolation = function->getActorIsolation();
278-
if (functionIsolation && functionIsolation->isNonisolated())
279-
return {};
280-
281-
auto sendableMetatype =
282-
sourceType->getASTContext().getProtocol(KnownProtocolKind::SendableMetatype);
283-
if (!sendableMetatype)
284-
return {};
285-
286-
if (!destType.isAnyExistentialType())
287-
return {};
288-
289-
const auto &destLayout = destType.getExistentialLayout();
290-
for (auto proto : destLayout.getProtocols()) {
291-
if (proto->isMarkerProtocol())
292-
continue;
293-
294-
// If the source type already conforms to the protocol, we won't be looking
295-
// it up dynamically.
296-
if (!lookupConformance(sourceType, proto, /*allowMissing=*/false).isInvalid())
297-
continue;
298-
299-
// If the protocol inherits SendableMetatype, it can't have isolated
300-
// conformances.
301-
if (proto->inheritsFrom(sendableMetatype))
302-
continue;
303-
304-
// The cast can produce a conformance with the same isolation as this
305-
// function is dynamically executing. If that's known (i.e., because we're
306-
// on a global actor), the value is isolated to that global actor.
307-
// Otherwise, it's task-isolated.
308-
if (functionIsolation && functionIsolation->isGlobalActor()) {
309-
return SILIsolationInfo::getGlobalActorIsolated(
310-
value, functionIsolation->getGlobalActor(), proto);
311-
}
312-
313-
// Consider the cast to be task-isolated, because the runtime could find
314-
// a conformance that is isolated to the current context.
315-
return SILIsolationInfo::getTaskIsolated(value, proto);
316-
}
317-
318-
return {};
319-
}
320-
321264
/// Classify an instructions as look through when we are looking through
322265
/// values. We assert that all instructions that are CONSTANT_TRANSLATION
323266
/// LookThrough to make sure they stay in sync.
@@ -381,7 +324,7 @@ static bool isStaticallyLookThroughInst(SILInstruction *inst) {
381324

382325
// If this cast introduces isolation due to conformances, we cannot look
383326
// through it to the source.
384-
if (!getIsolationForCastConformances(
327+
if (!SILIsolationInfo::getForCastConformances(
385328
llvm::cast<UnconditionalCheckedCastInst>(inst),
386329
cast.getSourceFormalType(), cast.getTargetFormalType())
387330
.isDisconnected())
@@ -2189,13 +2132,6 @@ class PartitionOpTranslator {
21892132
return valueMap.lookupValueID(value);
21902133
}
21912134

2192-
/// Determine the isolation of a set of conformances.
2193-
///
2194-
/// This function identifies potentially-isolated conformances that might affect the isolation of the given
2195-
/// value.
2196-
SILIsolationInfo getIsolationFromConformances(
2197-
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
2198-
21992135
public:
22002136
/// Return the partition consisting of all function arguments.
22012137
///
@@ -3970,7 +3906,7 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
39703906

39713907
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
39723908
UnconditionalCheckedCastInst *ucci) {
3973-
auto isolation = getIsolationForCastConformances(
3909+
auto isolation = SILIsolationInfo::getForCastConformances(
39743910
ucci, ucci->getSourceFormalType(), ucci->getTargetFormalType());
39753911

39763912
if (isolation.isDisconnected() &&
@@ -3988,7 +3924,7 @@ TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
39883924

39893925
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastAddrInst(
39903926
UnconditionalCheckedCastAddrInst *uccai) {
3991-
auto isolation = getIsolationForCastConformances(
3927+
auto isolation = SILIsolationInfo::getForCastConformances(
39923928
uccai->getAllOperands()[CopyLikeInstruction::Dest].get(),
39933929
uccai->getSourceFormalType(), uccai->getTargetFormalType());
39943930

@@ -4086,58 +4022,9 @@ PartitionOpTranslator::visitPartialApplyInst(PartialApplyInst *pai) {
40864022
return TranslationSemantics::Special;
40874023
}
40884024

4089-
SILIsolationInfo
4090-
PartitionOpTranslator::getIsolationFromConformances(
4091-
SILValue value, ArrayRef<ProtocolConformanceRef> conformances) {
4092-
for (auto conformance: conformances) {
4093-
if (conformance.getProtocol()->isMarkerProtocol())
4094-
continue;
4095-
4096-
// If the conformance is a pack, recurse.
4097-
if (conformance.isPack()) {
4098-
auto pack = conformance.getPack();
4099-
for (auto innerConformance : pack->getPatternConformances()) {
4100-
auto isolation = getIsolationFromConformances(value, innerConformance);
4101-
if (isolation)
4102-
return isolation;
4103-
}
4104-
4105-
continue;
4106-
}
4107-
4108-
// If a concrete conformance is global-actor-isolated, then the resulting
4109-
// value must be.
4110-
if (conformance.isConcrete()) {
4111-
auto isolation = conformance.getConcrete()->getIsolation();
4112-
if (isolation.isGlobalActor()) {
4113-
return SILIsolationInfo::getGlobalActorIsolated(
4114-
value, isolation.getGlobalActor(), conformance.getProtocol());
4115-
}
4116-
4117-
continue;
4118-
}
4119-
4120-
// If an abstract conformance is for a non-SendableMetatype-conforming
4121-
// type, the resulting value is task-isolated.
4122-
if (conformance.isAbstract()) {
4123-
auto sendableMetatype =
4124-
conformance.getType()->getASTContext()
4125-
.getProtocol(KnownProtocolKind::SendableMetatype);
4126-
if (sendableMetatype &&
4127-
lookupConformance(conformance.getType(), sendableMetatype,
4128-
/*allowMissing=*/false).isInvalid()) {
4129-
return SILIsolationInfo::getTaskIsolated(value,
4130-
conformance.getProtocol());
4131-
}
4132-
}
4133-
}
4134-
4135-
return {};
4136-
}
4137-
41384025
TranslationSemantics
41394026
PartitionOpTranslator::visitInitExistentialAddrInst(InitExistentialAddrInst *ieai) {
4140-
auto conformanceIsolationInfo = getIsolationFromConformances(
4027+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
41414028
ieai, ieai->getConformances());
41424029

41434030
translateSILMultiAssign(ieai->getResults(),
@@ -4149,7 +4036,7 @@ PartitionOpTranslator::visitInitExistentialAddrInst(InitExistentialAddrInst *iea
41494036

41504037
TranslationSemantics
41514038
PartitionOpTranslator::visitInitExistentialRefInst(InitExistentialRefInst *ieri) {
4152-
auto conformanceIsolationInfo = getIsolationFromConformances(
4039+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
41534040
ieri, ieri->getConformances());
41544041

41554042
translateSILMultiAssign(ieri->getResults(),
@@ -4161,7 +4048,7 @@ PartitionOpTranslator::visitInitExistentialRefInst(InitExistentialRefInst *ieri)
41614048

41624049
TranslationSemantics
41634050
PartitionOpTranslator::visitInitExistentialValueInst(InitExistentialValueInst *ievi) {
4164-
auto conformanceIsolationInfo = getIsolationFromConformances(
4051+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
41654052
ievi, ievi->getConformances());
41664053

41674054
translateSILMultiAssign(ievi->getResults(),
@@ -4175,7 +4062,7 @@ TranslationSemantics
41754062
PartitionOpTranslator::visitCheckedCastBranchInst(CheckedCastBranchInst *ccbi) {
41764063
// Consider whether the value produced by the cast might be task-isolated.
41774064
auto resultValue = ccbi->getSuccessBB()->getArgument(0);
4178-
auto conformanceIsolation = getIsolationForCastConformances(
4065+
auto conformanceIsolation = SILIsolationInfo::getForCastConformances(
41794066
resultValue,
41804067
ccbi->getSourceFormalType(),
41814068
ccbi->getTargetFormalType());
@@ -4192,7 +4079,7 @@ TranslationSemantics PartitionOpTranslator::visitCheckedCastAddrBranchInst(
41924079

41934080
// Consider whether the value written into by the cast might be task-isolated.
41944081
auto resultValue = ccabi->getAllOperands().back().get();
4195-
auto conformanceIsolation = getIsolationForCastConformances(
4082+
auto conformanceIsolation = SILIsolationInfo::getForCastConformances(
41964083
resultValue,
41974084
ccabi->getSourceFormalType(),
41984085
ccabi->getTargetFormalType());

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
#include "swift/SILOptimizer/Utils/SILIsolationInfo.h"
1414

1515
#include "swift/AST/ASTWalker.h"
16+
#include "swift/AST/ConformanceLookup.h"
1617
#include "swift/AST/DistributedDecl.h"
18+
#include "swift/AST/ExistentialLayout.h"
1719
#include "swift/AST/Expr.h"
20+
#include "swift/AST/PackConformance.h"
21+
#include "swift/AST/ProtocolConformance.h"
1822
#include "swift/SIL/AddressWalker.h"
1923
#include "swift/SIL/ApplySite.h"
2024
#include "swift/SIL/InstructionUtils.h"
@@ -960,6 +964,104 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
960964
return SILIsolationInfo::getTaskIsolated(fArg);
961965
}
962966

967+
/// Infer isolation region from the set of protocol conformances.
968+
SILIsolationInfo SILIsolationInfo::getFromConformances(
969+
SILValue value, ArrayRef<ProtocolConformanceRef> conformances) {
970+
for (auto conformance: conformances) {
971+
if (conformance.getProtocol()->isMarkerProtocol())
972+
continue;
973+
974+
// If the conformance is a pack, recurse.
975+
if (conformance.isPack()) {
976+
auto pack = conformance.getPack();
977+
for (auto innerConformance : pack->getPatternConformances()) {
978+
auto isolation = getFromConformances(value, innerConformance);
979+
if (isolation)
980+
return isolation;
981+
}
982+
983+
continue;
984+
}
985+
986+
// If a concrete conformance is global-actor-isolated, then the resulting
987+
// value must be.
988+
if (conformance.isConcrete()) {
989+
auto isolation = conformance.getConcrete()->getIsolation();
990+
if (isolation.isGlobalActor()) {
991+
return SILIsolationInfo::getGlobalActorIsolated(
992+
value, isolation.getGlobalActor(), conformance.getProtocol());
993+
}
994+
995+
continue;
996+
}
997+
998+
// If an abstract conformance is for a non-SendableMetatype-conforming
999+
// type, the resulting value is task-isolated.
1000+
if (conformance.isAbstract()) {
1001+
auto sendableMetatype =
1002+
conformance.getType()->getASTContext()
1003+
.getProtocol(KnownProtocolKind::SendableMetatype);
1004+
if (sendableMetatype &&
1005+
lookupConformance(conformance.getType(), sendableMetatype,
1006+
/*allowMissing=*/false).isInvalid()) {
1007+
return SILIsolationInfo::getTaskIsolated(value,
1008+
conformance.getProtocol());
1009+
}
1010+
}
1011+
}
1012+
1013+
return {};
1014+
}
1015+
1016+
SILIsolationInfo SILIsolationInfo::getForCastConformances(
1017+
SILValue value, CanType sourceType, CanType destType) {
1018+
// If the enclosing function is @concurrent, then a cast cannot pick up
1019+
// any isolated conformances because it's not on any actor.
1020+
auto function = value->getFunction();
1021+
auto functionIsolation = function->getActorIsolation();
1022+
if (functionIsolation && functionIsolation->isNonisolated())
1023+
return {};
1024+
1025+
auto sendableMetatype =
1026+
sourceType->getASTContext().getProtocol(KnownProtocolKind::SendableMetatype);
1027+
if (!sendableMetatype)
1028+
return {};
1029+
1030+
if (!destType.isAnyExistentialType())
1031+
return {};
1032+
1033+
const auto &destLayout = destType.getExistentialLayout();
1034+
for (auto proto : destLayout.getProtocols()) {
1035+
if (proto->isMarkerProtocol())
1036+
continue;
1037+
1038+
// If the source type already conforms to the protocol, we won't be looking
1039+
// it up dynamically.
1040+
if (!lookupConformance(sourceType, proto, /*allowMissing=*/false).isInvalid())
1041+
continue;
1042+
1043+
// If the protocol inherits SendableMetatype, it can't have isolated
1044+
// conformances.
1045+
if (proto->inheritsFrom(sendableMetatype))
1046+
continue;
1047+
1048+
// The cast can produce a conformance with the same isolation as this
1049+
// function is dynamically executing. If that's known (i.e., because we're
1050+
// on a global actor), the value is isolated to that global actor.
1051+
// Otherwise, it's task-isolated.
1052+
if (functionIsolation && functionIsolation->isGlobalActor()) {
1053+
return SILIsolationInfo::getGlobalActorIsolated(
1054+
value, functionIsolation->getGlobalActor(), proto);
1055+
}
1056+
1057+
// Consider the cast to be task-isolated, because the runtime could find
1058+
// a conformance that is isolated to the current context.
1059+
return SILIsolationInfo::getTaskIsolated(value, proto);
1060+
}
1061+
1062+
return {};
1063+
}
1064+
9631065
void SILIsolationInfo::printOptions(llvm::raw_ostream &os) const {
9641066
if (isolatedConformance) {
9651067
os << "isolated-conformance-to(" << isolatedConformance->getName() << ")";

0 commit comments

Comments
 (0)