Skip to content

Commit 9587d53

Browse files
committed
[region-isolation] Initialize TrackableValueState's regionInfo with a .none instead of a disconnected region.
The design change here is that instead of just initializing the regionInfo with disconnected, we set it as .none and if we see .none, just return a newly construct disconnected isolation region info when getIsolationRegionInfo() is called. This enables us to provide a setIsolationRegionInfo() helper for RegionAnalysisValueMap::getTrackableValue that does not perform a merge. This is important since for nonisolated(unsafe), we want to not have nonisolated(unsafe) propagate through merging. So if we use merging to initialize the internal regionInfo state of a SILIsolationInfo, we will never have a SILIsolationInfo with that bit set since it will be lost in the merge. So we need some sort of other assignment operator. Noting that we should only compute a value's SILIsolationInfo once in RegionAnalysisValueMap before we cache it in the map, it made sense to just represent it as an optional that way we can guarantee that the regionInfo is only ever set exactly once by that routine. (cherry picked from commit 89a2cfc)
1 parent 3648bf6 commit 9587d53

File tree

4 files changed

+111
-37
lines changed

4 files changed

+111
-37
lines changed

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
namespace swift {
2525

2626
class RegionAnalysisFunctionInfo;
27+
class RegionAnalysisValueMap;
2728

2829
namespace regionanalysisimpl {
2930

@@ -121,10 +122,11 @@ using TrackedValueFlagSet = OptionSet<TrackableValueFlag>;
121122
} // namespace regionanalysisimpl
122123

123124
class regionanalysisimpl::TrackableValueState {
125+
friend RegionAnalysisValueMap;
126+
124127
unsigned id;
125128
TrackedValueFlagSet flagSet = {TrackableValueFlag::isMayAlias};
126-
SILIsolationInfo regionInfo =
127-
SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
129+
std::optional<SILIsolationInfo> regionInfo = {};
128130

129131
public:
130132
TrackableValueState(unsigned newID) : id(newID) {}
@@ -141,20 +143,26 @@ class regionanalysisimpl::TrackableValueState {
141143

142144
bool isNonSendable() const { return !isSendable(); }
143145

146+
SILIsolationInfo getIsolationRegionInfo() const {
147+
if (!regionInfo) {
148+
return SILIsolationInfo::getDisconnected(false);
149+
}
150+
151+
return *regionInfo;
152+
}
153+
144154
SILIsolationInfo::Kind getIsolationRegionInfoKind() const {
145-
return regionInfo.getKind();
155+
return getIsolationRegionInfo().getKind();
146156
}
147157

148158
ActorIsolation getActorIsolation() const {
149-
return regionInfo.getActorIsolation();
159+
return getIsolationRegionInfo().getActorIsolation();
150160
}
151161

152162
void mergeIsolationRegionInfo(SILIsolationInfo newRegionInfo) {
153-
regionInfo = regionInfo.merge(newRegionInfo);
163+
regionInfo = getIsolationRegionInfo().merge(newRegionInfo);
154164
}
155165

156-
SILIsolationInfo getIsolationRegionInfo() const { return regionInfo; }
157-
158166
Element getID() const { return Element(id); }
159167

160168
void addFlag(TrackableValueFlag flag) { flagSet |= flag; }
@@ -166,11 +174,22 @@ class regionanalysisimpl::TrackableValueState {
166174
<< "][is_no_alias: " << (isNoAlias() ? "yes" : "no")
167175
<< "][is_sendable: " << (isSendable() ? "yes" : "no")
168176
<< "][region_value_kind: ";
169-
getIsolationRegionInfo().printForDiagnostics(os);
177+
getIsolationRegionInfo().printForOneLineLogging(os);
170178
os << "].";
171179
}
172180

173181
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
182+
183+
private:
184+
bool hasIsolationRegionInfo() const { return bool(regionInfo); }
185+
186+
/// Set the isolation region info for this TrackableValueState. Private so it
187+
/// can only be used by RegionAnalysisValueMap::getTrackableValue.
188+
void setIsolationRegionInfo(SILIsolationInfo newRegionInfo) {
189+
assert(!regionInfo.has_value() &&
190+
"Can only call setIsolationRegionInfo once!\n");
191+
regionInfo = newRegionInfo;
192+
}
174193
};
175194

176195
/// The representative value of the equivalence class that makes up a tracked

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ class SILIsolationInfo {
187187

188188
void print(llvm::raw_ostream &os) const;
189189

190+
/// Print a textual representation of the text info that is meant to be
191+
/// included in other logging output for types that compose with
192+
/// SILIsolationInfo. As a result, we only print state that can fit on
193+
/// one line.
194+
void printForOneLineLogging(llvm::raw_ostream &os) const;
195+
190196
SWIFT_DEBUG_DUMP {
191197
print(llvm::dbgs());
192198
llvm::dbgs() << '\n';

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,7 +3255,27 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
32553255

32563256
// Otherwise, we need to compute our flags.
32573257

3258-
// First for addresses.
3258+
// Treat function ref and class method as either actor isolated or
3259+
// sendable. Formally they are non-Sendable, so we do the check before we
3260+
// check the oracle.
3261+
if (isa<FunctionRefInst, ClassMethodInst>(value)) {
3262+
if (auto isolation = SILIsolationInfo::get(value)) {
3263+
iter.first->getSecond().setIsolationRegionInfo(isolation);
3264+
return {iter.first->first, iter.first->second};
3265+
}
3266+
3267+
iter.first->getSecond().addFlag(TrackableValueFlag::isSendable);
3268+
return {iter.first->first, iter.first->second};
3269+
}
3270+
3271+
// Then check our oracle to see if the value is actually sendable. If we have
3272+
// a Sendable value, just return early.
3273+
if (!SILIsolationInfo::isNonSendableType(value->getType(), fn)) {
3274+
iter.first->getSecond().addFlag(TrackableValueFlag::isSendable);
3275+
return {iter.first->first, iter.first->second};
3276+
}
3277+
3278+
// Ok, at this point we have a non-Sendable value. First process addresses.
32593279
if (value->getType().isAddress()) {
32603280
// If we were able to find this was actor isolated from finding our
32613281
// underlying object, use that. It is never wrong.
@@ -3270,7 +3290,7 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
32703290
}
32713291

32723292
if (isolation) {
3273-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3293+
iter.first->getSecond().setIsolationRegionInfo(isolation);
32743294
}
32753295
}
32763296

@@ -3284,32 +3304,14 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
32843304
}
32853305

32863306
if (auto isolation = SILIsolationInfo::get(storage.base)) {
3287-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3307+
iter.first->getSecond().setIsolationRegionInfo(isolation);
32883308
}
32893309
}
32903310
}
32913311

3292-
// Treat function ref and class method as either actor isolated or
3293-
// sendable. Formally they are non-Sendable, so we do the check before we
3294-
// check the oracle.
3295-
if (isa<FunctionRefInst, ClassMethodInst>(value)) {
3296-
if (auto isolation = SILIsolationInfo::get(value)) {
3297-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3298-
return {iter.first->first, iter.first->second};
3299-
}
3300-
3301-
iter.first->getSecond().addFlag(TrackableValueFlag::isSendable);
3302-
return {iter.first->first, iter.first->second};
3303-
}
3304-
3305-
// Otherwise refer to the oracle. If we have a Sendable value, just return.
3306-
if (!SILIsolationInfo::isNonSendableType(value->getType(), fn)) {
3307-
iter.first->getSecond().addFlag(TrackableValueFlag::isSendable);
3308-
return {iter.first->first, iter.first->second};
3309-
}
3310-
3311-
// Check if our base is a ref_element_addr from an actor. In such a case,
3312-
// mark this value as actor derived.
3312+
// Check if we have a load or load_borrow from an address. In that case, we
3313+
// want to look through the load and find a better root from the address we
3314+
// loaded from.
33133315
if (isa<LoadInst, LoadBorrowInst>(iter.first->first.getValue())) {
33143316
auto *svi = cast<SingleValueInstruction>(iter.first->first.getValue());
33153317

@@ -3320,7 +3322,7 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
33203322
// everywhere. Just haven't done it due to possible perturbations.
33213323
auto parentAddrInfo = getUnderlyingTrackedValue(svi);
33223324
if (parentAddrInfo.actorIsolation) {
3323-
iter.first->getSecond().mergeIsolationRegionInfo(
3325+
iter.first->getSecond().setIsolationRegionInfo(
33243326
SILIsolationInfo::getActorInstanceIsolated(
33253327
svi, parentAddrInfo.value,
33263328
parentAddrInfo.actorIsolation->getActor()));
@@ -3329,16 +3331,20 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
33293331
auto storage = AccessStorageWithBase::compute(svi->getOperand(0));
33303332
if (storage.storage) {
33313333
if (auto isolation = SILIsolationInfo::get(storage.base)) {
3332-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3334+
iter.first->getSecond().setIsolationRegionInfo(isolation);
33333335
}
33343336
}
33353337

33363338
return {iter.first->first, iter.first->second};
33373339
}
33383340

3339-
// Ok, we have a non-Sendable type, attempt to infer its isolation.
3340-
if (auto isolation = SILIsolationInfo::get(iter.first->first.getValue())) {
3341-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3341+
// Ok, we have a non-Sendable type, see if we do not have any isolation
3342+
// yet. If we don't, attempt to infer its isolation.
3343+
if (!iter.first->getSecond().hasIsolationRegionInfo()) {
3344+
if (auto isolation = SILIsolationInfo::get(iter.first->first.getValue())) {
3345+
iter.first->getSecond().setIsolationRegionInfo(isolation);
3346+
return {iter.first->first, iter.first->second};
3347+
}
33423348
}
33433349

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

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,49 @@ void SILIsolationInfo::printForDiagnostics(llvm::raw_ostream &os) const {
629629
}
630630
}
631631

632+
void SILIsolationInfo::printForOneLineLogging(llvm::raw_ostream &os) const {
633+
switch (Kind(*this)) {
634+
case Unknown:
635+
os << "unknown";
636+
return;
637+
case Disconnected:
638+
os << "disconnected";
639+
if (unsafeNonIsolated) {
640+
os << ": nonisolated(unsafe)";
641+
}
642+
return;
643+
case Actor:
644+
if (auto instance = getActorInstance()) {
645+
switch (instance.getKind()) {
646+
case ActorInstance::Kind::Value: {
647+
SILValue value = instance.getValue();
648+
if (auto name = VariableNameInferrer::inferName(value)) {
649+
os << "'" << *name << "'-isolated";
650+
return;
651+
}
652+
break;
653+
}
654+
case ActorInstance::Kind::ActorAccessorInit:
655+
os << "'self'-isolated";
656+
return;
657+
}
658+
}
659+
660+
if (getActorIsolation().getKind() == ActorIsolation::ActorInstance) {
661+
if (auto *vd = getActorIsolation().getActorInstance()) {
662+
os << "'" << vd->getBaseIdentifier() << "'-isolated";
663+
return;
664+
}
665+
}
666+
667+
getActorIsolation().printForDiagnostics(os);
668+
return;
669+
case Task:
670+
os << "task-isolated";
671+
return;
672+
}
673+
}
674+
632675
// Check if the passed in type is NonSendable.
633676
//
634677
// NOTE: We special case RawPointer and NativeObject to ensure they are

0 commit comments

Comments
 (0)