Skip to content

Commit 2f3ef58

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 64157d6 commit 2f3ef58

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
@@ -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,
@@ -532,6 +534,15 @@ class SILIsolationInfo {
532534
return {};
533535
}
534536

537+
/// Infer isolation region from the set of protocol conformances.
538+
static SILIsolationInfo getFromConformances(
539+
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
540+
541+
/// Determine the isolation of conformances that could be introduced by a
542+
/// cast from sourceType to destType.
543+
static SILIsolationInfo getForCastConformances(
544+
SILValue value, CanType sourceType, CanType destType);
545+
535546
/// A helper that is used to ensure that we treat certain builtin values as
536547
/// non-Sendable that the AST level otherwise thinks are non-Sendable.
537548
///

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"
@@ -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.
@@ -391,7 +334,7 @@ static bool isStaticallyLookThroughInst(SILInstruction *inst) {
391334

392335
// If this cast introduces isolation due to conformances, we cannot look
393336
// through it to the source.
394-
if (!getIsolationForCastConformances(
337+
if (!SILIsolationInfo::getForCastConformances(
395338
llvm::cast<UnconditionalCheckedCastInst>(inst),
396339
cast.getSourceFormalType(), cast.getTargetFormalType())
397340
.isDisconnected())
@@ -2231,13 +2174,6 @@ class PartitionOpTranslator {
22312174
return valueMap.lookupValueID(value);
22322175
}
22332176

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-
22412177
public:
22422178
/// Return the partition consisting of all function arguments.
22432179
///
@@ -4014,7 +3950,7 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
40143950

40153951
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
40163952
UnconditionalCheckedCastInst *ucci) {
4017-
auto isolation = getIsolationForCastConformances(
3953+
auto isolation = SILIsolationInfo::getForCastConformances(
40183954
ucci, ucci->getSourceFormalType(), ucci->getTargetFormalType());
40193955

40203956
if (isolation.isDisconnected() &&
@@ -4032,7 +3968,7 @@ TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
40323968

40333969
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastAddrInst(
40343970
UnconditionalCheckedCastAddrInst *uccai) {
4035-
auto isolation = getIsolationForCastConformances(
3971+
auto isolation = SILIsolationInfo::getForCastConformances(
40363972
uccai->getAllOperands()[CopyLikeInstruction::Dest].get(),
40373973
uccai->getSourceFormalType(), uccai->getTargetFormalType());
40383974

@@ -4130,58 +4066,9 @@ PartitionOpTranslator::visitPartialApplyInst(PartialApplyInst *pai) {
41304066
return TranslationSemantics::Special;
41314067
}
41324068

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-
41824069
TranslationSemantics
41834070
PartitionOpTranslator::visitInitExistentialAddrInst(InitExistentialAddrInst *ieai) {
4184-
auto conformanceIsolationInfo = getIsolationFromConformances(
4071+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
41854072
ieai, ieai->getConformances());
41864073

41874074
translateSILMultiAssign(ieai->getResults(),
@@ -4193,7 +4080,7 @@ PartitionOpTranslator::visitInitExistentialAddrInst(InitExistentialAddrInst *iea
41934080

41944081
TranslationSemantics
41954082
PartitionOpTranslator::visitInitExistentialRefInst(InitExistentialRefInst *ieri) {
4196-
auto conformanceIsolationInfo = getIsolationFromConformances(
4083+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
41974084
ieri, ieri->getConformances());
41984085

41994086
translateSILMultiAssign(ieri->getResults(),
@@ -4205,7 +4092,7 @@ PartitionOpTranslator::visitInitExistentialRefInst(InitExistentialRefInst *ieri)
42054092

42064093
TranslationSemantics
42074094
PartitionOpTranslator::visitInitExistentialValueInst(InitExistentialValueInst *ievi) {
4208-
auto conformanceIsolationInfo = getIsolationFromConformances(
4095+
auto conformanceIsolationInfo = SILIsolationInfo::getFromConformances(
42094096
ievi, ievi->getConformances());
42104097

42114098
translateSILMultiAssign(ievi->getResults(),
@@ -4219,7 +4106,7 @@ TranslationSemantics
42194106
PartitionOpTranslator::visitCheckedCastBranchInst(CheckedCastBranchInst *ccbi) {
42204107
// Consider whether the value produced by the cast might be task-isolated.
42214108
auto resultValue = ccbi->getSuccessBB()->getArgument(0);
4222-
auto conformanceIsolation = getIsolationForCastConformances(
4109+
auto conformanceIsolation = SILIsolationInfo::getForCastConformances(
42234110
resultValue,
42244111
ccbi->getSourceFormalType(),
42254112
ccbi->getTargetFormalType());
@@ -4236,7 +4123,7 @@ TranslationSemantics PartitionOpTranslator::visitCheckedCastAddrBranchInst(
42364123

42374124
// Consider whether the value written into by the cast might be task-isolated.
42384125
auto resultValue = ccabi->getAllOperands().back().get();
4239-
auto conformanceIsolation = getIsolationForCastConformances(
4126+
auto conformanceIsolation = SILIsolationInfo::getForCastConformances(
42404127
resultValue,
42414128
ccabi->getSourceFormalType(),
42424129
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"
@@ -1069,6 +1073,104 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
10691073
return SILIsolationInfo::getTaskIsolated(fArg);
10701074
}
10711075

1076+
/// Infer isolation region from the set of protocol conformances.
1077+
SILIsolationInfo SILIsolationInfo::getFromConformances(
1078+
SILValue value, ArrayRef<ProtocolConformanceRef> conformances) {
1079+
for (auto conformance: conformances) {
1080+
if (conformance.getProtocol()->isMarkerProtocol())
1081+
continue;
1082+
1083+
// If the conformance is a pack, recurse.
1084+
if (conformance.isPack()) {
1085+
auto pack = conformance.getPack();
1086+
for (auto innerConformance : pack->getPatternConformances()) {
1087+
auto isolation = getFromConformances(value, innerConformance);
1088+
if (isolation)
1089+
return isolation;
1090+
}
1091+
1092+
continue;
1093+
}
1094+
1095+
// If a concrete conformance is global-actor-isolated, then the resulting
1096+
// value must be.
1097+
if (conformance.isConcrete()) {
1098+
auto isolation = conformance.getConcrete()->getIsolation();
1099+
if (isolation.isGlobalActor()) {
1100+
return SILIsolationInfo::getGlobalActorIsolated(
1101+
value, isolation.getGlobalActor(), conformance.getProtocol());
1102+
}
1103+
1104+
continue;
1105+
}
1106+
1107+
// If an abstract conformance is for a non-SendableMetatype-conforming
1108+
// type, the resulting value is task-isolated.
1109+
if (conformance.isAbstract()) {
1110+
auto sendableMetatype =
1111+
conformance.getType()->getASTContext()
1112+
.getProtocol(KnownProtocolKind::SendableMetatype);
1113+
if (sendableMetatype &&
1114+
lookupConformance(conformance.getType(), sendableMetatype,
1115+
/*allowMissing=*/false).isInvalid()) {
1116+
return SILIsolationInfo::getTaskIsolated(value,
1117+
conformance.getProtocol());
1118+
}
1119+
}
1120+
}
1121+
1122+
return {};
1123+
}
1124+
1125+
SILIsolationInfo SILIsolationInfo::getForCastConformances(
1126+
SILValue value, CanType sourceType, CanType destType) {
1127+
// If the enclosing function is @concurrent, then a cast cannot pick up
1128+
// any isolated conformances because it's not on any actor.
1129+
auto function = value->getFunction();
1130+
auto functionIsolation = function->getActorIsolation();
1131+
if (functionIsolation && functionIsolation->isNonisolated())
1132+
return {};
1133+
1134+
auto sendableMetatype =
1135+
sourceType->getASTContext().getProtocol(KnownProtocolKind::SendableMetatype);
1136+
if (!sendableMetatype)
1137+
return {};
1138+
1139+
if (!destType.isAnyExistentialType())
1140+
return {};
1141+
1142+
const auto &destLayout = destType.getExistentialLayout();
1143+
for (auto proto : destLayout.getProtocols()) {
1144+
if (proto->isMarkerProtocol())
1145+
continue;
1146+
1147+
// If the source type already conforms to the protocol, we won't be looking
1148+
// it up dynamically.
1149+
if (!lookupConformance(sourceType, proto, /*allowMissing=*/false).isInvalid())
1150+
continue;
1151+
1152+
// If the protocol inherits SendableMetatype, it can't have isolated
1153+
// conformances.
1154+
if (proto->inheritsFrom(sendableMetatype))
1155+
continue;
1156+
1157+
// The cast can produce a conformance with the same isolation as this
1158+
// function is dynamically executing. If that's known (i.e., because we're
1159+
// on a global actor), the value is isolated to that global actor.
1160+
// Otherwise, it's task-isolated.
1161+
if (functionIsolation && functionIsolation->isGlobalActor()) {
1162+
return SILIsolationInfo::getGlobalActorIsolated(
1163+
value, functionIsolation->getGlobalActor(), proto);
1164+
}
1165+
1166+
// Consider the cast to be task-isolated, because the runtime could find
1167+
// a conformance that is isolated to the current context.
1168+
return SILIsolationInfo::getTaskIsolated(value, proto);
1169+
}
1170+
1171+
return {};
1172+
}
1173+
10721174
void SILIsolationInfo::printOptions(llvm::raw_ostream &os) const {
10731175
if (isolatedConformance) {
10741176
os << "isolated-conformance-to(" << isolatedConformance->getName() << ")";

0 commit comments

Comments
 (0)