Skip to content

Commit 0a0ae14

Browse files
committed
[region-isolation] Finish moving isolation computation into SILIsolationInfo::get.
(cherry picked from commit b407b21)
1 parent 6c33b4d commit 0a0ae14

File tree

3 files changed

+126
-148
lines changed

3 files changed

+126
-148
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,11 @@ class SILIsolationInfo {
207207
static SILIsolationInfo get(SILInstruction *inst);
208208

209209
/// Attempt to infer the isolation region info for \p arg.
210-
static SILIsolationInfo get(SILFunctionArgument *arg);
210+
static SILIsolationInfo get(SILArgument *arg);
211211

212212
static SILIsolationInfo get(SILValue value) {
213-
if (auto *fArg = dyn_cast<SILFunctionArgument>(value))
214-
return get(fArg);
213+
if (auto *arg = dyn_cast<SILArgument>(value))
214+
return get(arg);
215215
if (auto *inst = dyn_cast<SingleValueInstruction>(value))
216216
return get(inst);
217217
return {};

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 4 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -557,28 +557,6 @@ static bool isAsyncLetBeginPartialApply(PartialApplyInst *pai) {
557557
return *kind == BuiltinValueKind::StartAsyncLetWithLocalBuffer;
558558
}
559559

560-
static std::optional<ActorIsolation>
561-
getGlobalActorInitIsolation(SILFunction *fn) {
562-
auto block = fn->begin();
563-
564-
// Make sure our function has a single block. We should always have a single
565-
// block today. Return nullptr otherwise.
566-
if (block == fn->end() || std::next(block) != fn->end())
567-
return {};
568-
569-
GlobalAddrInst *gai = nullptr;
570-
if (!match(cast<SILInstruction>(block->getTerminator()),
571-
m_ReturnInst(m_AddressToPointerInst(m_GlobalAddrInst(gai)))))
572-
return {};
573-
574-
auto *globalDecl = gai->getReferencedGlobal()->getDecl();
575-
if (!globalDecl)
576-
return {};
577-
578-
// See if our globalDecl is specifically guarded.
579-
return getActorIsolation(globalDecl);
580-
}
581-
582560
/// Returns true if this is a function argument that is able to be transferred
583561
/// in the body of our function.
584562
static bool isTransferrableFunctionArgument(SILFunctionArgument *arg) {
@@ -3340,123 +3318,13 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
33403318
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
33413319
}
33423320
}
3343-
}
3344-
3345-
// See if we have a struct_extract from a global actor isolated type.
3346-
if (auto *sei = dyn_cast<StructExtractInst>(iter.first->first.getValue())) {
3347-
iter.first->getSecond().mergeIsolationRegionInfo(
3348-
SILIsolationInfo::getActorIsolated(sei, sei->getStructDecl()));
3349-
}
3350-
3351-
// See if we have an unchecked_enum_data from a global actor isolated type.
3352-
if (auto *uedi =
3353-
dyn_cast<UncheckedEnumDataInst>(iter.first->first.getValue())) {
3354-
iter.first->getSecond().mergeIsolationRegionInfo(
3355-
SILIsolationInfo::getActorIsolated(uedi, uedi->getEnumDecl()));
3356-
}
3357-
3358-
// Handle a switch_enum from a global actor isolated type.
3359-
if (auto *arg = dyn_cast<SILPhiArgument>(iter.first->first.getValue())) {
3360-
if (auto *singleTerm = arg->getSingleTerminator()) {
3361-
if (auto *swi = dyn_cast<SwitchEnumInst>(singleTerm)) {
3362-
auto enumDecl =
3363-
swi->getOperand()->getType().getEnumOrBoundGenericEnum();
3364-
iter.first->getSecond().mergeIsolationRegionInfo(
3365-
SILIsolationInfo::getActorIsolated(arg, enumDecl));
3366-
}
3367-
}
3368-
}
3369-
3370-
// Check if we have an unsafeMutableAddressor from a global actor, mark the
3371-
// returned value as being actor derived.
3372-
if (auto applySite = FullApplySite::isa(iter.first->first.getValue())) {
3373-
if (auto *calleeFunction = applySite.getCalleeFunction()) {
3374-
if (calleeFunction->isGlobalInit()) {
3375-
auto isolation = getGlobalActorInitIsolation(calleeFunction);
3376-
if (isolation && isolation->isGlobalActor()) {
3377-
iter.first->getSecond().mergeIsolationRegionInfo(
3378-
// TODO: What to do about this.
3379-
SILIsolationInfo::getActorIsolated(SILValue(), *isolation));
3380-
}
3381-
}
3382-
}
3383-
}
33843321

3385-
// See if we have a non-transferring argument from a function. In such a case,
3386-
// mark the value as actor isolated if self is actor isolated and task
3387-
// isolated otherwise.
3388-
if (auto *fArg =
3389-
dyn_cast<SILFunctionArgument>(iter.first->first.getValue())) {
3390-
if (!isTransferrableFunctionArgument(fArg)) {
3391-
iter.first->getSecond().mergeIsolationRegionInfo(
3392-
SILIsolationInfo::get(fArg));
3393-
return {iter.first->first, iter.first->second};
3394-
}
3322+
return {iter.first->first, iter.first->second};
33953323
}
33963324

3397-
// See if we have a convert function from a Sendable actor isolated function,
3398-
// we want to treat the result of the convert function as being actor isolated
3399-
// so that we cannot escape the value.
3400-
//
3401-
// NOTE: At this point, we already know that cfi's result is not sendable,
3402-
// since we would have exited above already.
3403-
if (auto *cfi = dyn_cast<ConvertFunctionInst>(iter.first->first.getValue())) {
3404-
SILValue operand = cfi->getOperand();
3405-
if (operand->getType().getAs<SILFunctionType>()->isSendable()) {
3406-
SILValue newValue = operand;
3407-
do {
3408-
operand = newValue;
3409-
3410-
newValue = lookThroughOwnershipInsts(operand);
3411-
if (auto *ttfi = dyn_cast<ThinToThickFunctionInst>(newValue)) {
3412-
newValue = ttfi->getOperand();
3413-
}
3414-
3415-
if (auto *cfi = dyn_cast<ConvertFunctionInst>(newValue)) {
3416-
newValue = cfi->getOperand();
3417-
}
3418-
3419-
if (auto *pai = dyn_cast<PartialApplyInst>(newValue)) {
3420-
newValue = pai->getCallee();
3421-
}
3422-
} while (newValue != operand);
3423-
3424-
if (auto *ai = dyn_cast<ApplyInst>(operand)) {
3425-
if (auto *callExpr = ai->getLoc().getAsASTNode<ApplyExpr>()) {
3426-
if (auto *callType = callExpr->getType()->getAs<AnyFunctionType>()) {
3427-
if (callType->hasGlobalActor()) {
3428-
iter.first->getSecond().mergeIsolationRegionInfo(
3429-
SILIsolationInfo::getGlobalActorIsolated(
3430-
ai, callType->getGlobalActor()));
3431-
return {iter.first->first, iter.first->second};
3432-
}
3433-
}
3434-
}
3435-
}
3436-
3437-
if (auto *fri = dyn_cast<FunctionRefInst>(operand)) {
3438-
if (auto actorIsolation =
3439-
fri->getReferencedFunction()->getActorIsolation()) {
3440-
if (actorIsolation.isActorIsolated()) {
3441-
iter.first->getSecond().mergeIsolationRegionInfo(
3442-
SILIsolationInfo::getActorIsolated(fri, actorIsolation));
3443-
return {iter.first->first, iter.first->second};
3444-
}
3445-
}
3446-
3447-
// See if the function ref statically is known to have actor isolation.
3448-
//
3449-
// TODO: We should make it so that the closure constructed has actor
3450-
// isolation.
3451-
if (auto value = tryToTrackValue(fri)) {
3452-
auto isolation = value->getIsolationRegionInfo();
3453-
if (isolation.isActorIsolated()) {
3454-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3455-
return {iter.first->first, iter.first->second};
3456-
}
3457-
}
3458-
}
3459-
}
3325+
// Ok, we have a non-Sendable type, attempt to infer its isolation.
3326+
if (auto isolation = SILIsolationInfo::get(iter.first->first.getValue())) {
3327+
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
34603328
}
34613329

34623330
return {iter.first->first, iter.first->second};

lib/SILOptimizer/Utils/PartitionUtils.cpp

Lines changed: 119 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
#include "swift/SILOptimizer/Utils/PartitionUtils.h"
1414
#include "swift/AST/Expr.h"
1515
#include "swift/SIL/ApplySite.h"
16+
#include "swift/SIL/InstructionUtils.h"
17+
#include "swift/SIL/PatternMatch.h"
1618
#include "swift/SIL/SILGlobalVariable.h"
1719
#include "llvm/Support/CommandLine.h"
1820

1921
using namespace swift;
22+
using namespace swift::PatternMatch;
2023
using namespace swift::PartitionPrimitives;
2124

2225
//===----------------------------------------------------------------------===//
@@ -42,6 +45,28 @@ static llvm::cl::opt<bool, true> // The parser
4245
// MARK: SILIsolationInfo
4346
//===----------------------------------------------------------------------===//
4447

48+
static std::optional<ActorIsolation>
49+
getGlobalActorInitIsolation(SILFunction *fn) {
50+
auto block = fn->begin();
51+
52+
// Make sure our function has a single block. We should always have a single
53+
// block today. Return nullptr otherwise.
54+
if (block == fn->end() || std::next(block) != fn->end())
55+
return {};
56+
57+
GlobalAddrInst *gai = nullptr;
58+
if (!match(cast<SILInstruction>(block->getTerminator()),
59+
m_ReturnInst(m_AddressToPointerInst(m_GlobalAddrInst(gai)))))
60+
return {};
61+
62+
auto *globalDecl = gai->getReferencedGlobal()->getDecl();
63+
if (!globalDecl)
64+
return {};
65+
66+
// See if our globalDecl is specifically guarded.
67+
return getActorIsolation(globalDecl);
68+
}
69+
4570
SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
4671
if (ApplyExpr *apply = inst->getLoc().getAsASTNode<ApplyExpr>()) {
4772
if (auto crossing = apply->getIsolationCrossing()) {
@@ -148,28 +173,113 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
148173
}
149174
}
150175

176+
// See if we have a struct_extract from a global actor isolated type.
177+
if (auto *sei = dyn_cast<StructExtractInst>(inst)) {
178+
return SILIsolationInfo::getActorIsolated(sei, sei->getStructDecl());
179+
}
180+
181+
// See if we have an unchecked_enum_data from a global actor isolated type.
182+
if (auto *uedi = dyn_cast<UncheckedEnumDataInst>(inst)) {
183+
return SILIsolationInfo::getActorIsolated(uedi, uedi->getEnumDecl());
184+
}
185+
186+
// Check if we have an unsafeMutableAddressor from a global actor, mark the
187+
// returned value as being actor derived.
188+
if (auto applySite = FullApplySite::isa(inst)) {
189+
if (auto *calleeFunction = applySite.getCalleeFunction()) {
190+
if (calleeFunction->isGlobalInit()) {
191+
auto isolation = getGlobalActorInitIsolation(calleeFunction);
192+
if (isolation && isolation->isGlobalActor()) {
193+
return SILIsolationInfo::getActorIsolated(SILValue(), *isolation);
194+
}
195+
}
196+
}
197+
}
198+
199+
// See if we have a convert function from a Sendable actor isolated function,
200+
// we want to treat the result of the convert function as being actor isolated
201+
// so that we cannot escape the value.
202+
//
203+
// NOTE: At this point, we already know that cfi's result is not sendable,
204+
// since we would have exited above already.
205+
if (auto *cfi = dyn_cast<ConvertFunctionInst>(inst)) {
206+
SILValue operand = cfi->getOperand();
207+
if (operand->getType().getAs<SILFunctionType>()->isSendable()) {
208+
SILValue newValue = operand;
209+
do {
210+
operand = newValue;
211+
212+
newValue = lookThroughOwnershipInsts(operand);
213+
if (auto *ttfi = dyn_cast<ThinToThickFunctionInst>(newValue)) {
214+
newValue = ttfi->getOperand();
215+
}
216+
217+
if (auto *cfi = dyn_cast<ConvertFunctionInst>(newValue)) {
218+
newValue = cfi->getOperand();
219+
}
220+
221+
if (auto *pai = dyn_cast<PartialApplyInst>(newValue)) {
222+
newValue = pai->getCallee();
223+
}
224+
} while (newValue != operand);
225+
226+
if (auto *ai = dyn_cast<ApplyInst>(operand)) {
227+
if (auto *callExpr = ai->getLoc().getAsASTNode<ApplyExpr>()) {
228+
if (auto *callType = callExpr->getType()->getAs<AnyFunctionType>()) {
229+
if (callType->hasGlobalActor()) {
230+
return SILIsolationInfo::getGlobalActorIsolated(
231+
ai, callType->getGlobalActor());
232+
}
233+
}
234+
}
235+
}
236+
237+
if (auto *fri = dyn_cast<FunctionRefInst>(operand)) {
238+
if (auto isolation = SILIsolationInfo::get(fri)) {
239+
return isolation;
240+
}
241+
}
242+
}
243+
}
244+
151245
return SILIsolationInfo();
152246
}
153247

154-
SILIsolationInfo SILIsolationInfo::get(SILFunctionArgument *arg) {
248+
SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
249+
// Handle a switch_enum from a global actor isolated type.
250+
if (auto *phiArg = dyn_cast<SILPhiArgument>(arg)) {
251+
if (auto *singleTerm = phiArg->getSingleTerminator()) {
252+
if (auto *swi = dyn_cast<SwitchEnumInst>(singleTerm)) {
253+
auto enumDecl =
254+
swi->getOperand()->getType().getEnumOrBoundGenericEnum();
255+
return SILIsolationInfo::getActorIsolated(arg, enumDecl);
256+
}
257+
}
258+
return SILIsolationInfo();
259+
}
260+
261+
auto *fArg = cast<SILFunctionArgument>(arg);
262+
155263
// Transferring is always disconnected.
156-
if (!arg->isIndirectResult() && !arg->isIndirectErrorResult() &&
157-
arg->isTransferring())
264+
if (!fArg->isIndirectResult() && !fArg->isIndirectErrorResult() &&
265+
((fArg->isClosureCapture() &&
266+
fArg->getFunction()->getLoweredFunctionType()->isSendable()) ||
267+
fArg->isTransferring()))
158268
return SILIsolationInfo::getDisconnected();
159269

160270
// If we have self and our function is actor isolated, all of our arguments
161271
// should be marked as actor isolated.
162-
if (auto *self = arg->getFunction()->maybeGetSelfArgument()) {
163-
if (auto functionIsolation = arg->getFunction()->getActorIsolation()) {
272+
if (auto *self = fArg->getFunction()->maybeGetSelfArgument()) {
273+
if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) {
164274
if (functionIsolation.isActorIsolated()) {
165275
if (auto *nomDecl = self->getType().getNominalOrBoundGenericNominal()) {
166-
return SILIsolationInfo::getActorIsolated(arg, nomDecl);
276+
return SILIsolationInfo::getActorIsolated(fArg, nomDecl);
167277
}
168278
}
169279
}
170280
}
171281

172-
if (auto *decl = arg->getDecl()) {
282+
if (auto *decl = fArg->getDecl()) {
173283
auto isolation = swift::getActorIsolation(const_cast<ValueDecl *>(decl));
174284
if (!bool(isolation)) {
175285
if (auto *dc = decl->getDeclContext()) {
@@ -178,11 +288,11 @@ SILIsolationInfo SILIsolationInfo::get(SILFunctionArgument *arg) {
178288
}
179289

180290
if (isolation.isActorIsolated()) {
181-
return SILIsolationInfo::getActorIsolated(arg, isolation);
291+
return SILIsolationInfo::getActorIsolated(fArg, isolation);
182292
}
183293
}
184294

185-
return SILIsolationInfo::getTaskIsolated(arg);
295+
return SILIsolationInfo::getTaskIsolated(fArg);
186296
}
187297

188298
void SILIsolationInfo::print(llvm::raw_ostream &os) const {

0 commit comments

Comments
 (0)