Skip to content

Commit 89a2cfc

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.
1 parent b66cfcc commit 89a2cfc

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
@@ -3256,7 +3256,27 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
32563256

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

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

32733293
if (isolation) {
3274-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3294+
iter.first->getSecond().setIsolationRegionInfo(isolation);
32753295
}
32763296
}
32773297

@@ -3285,32 +3305,14 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
32853305
}
32863306

32873307
if (auto isolation = SILIsolationInfo::get(storage.base)) {
3288-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3308+
iter.first->getSecond().setIsolationRegionInfo(isolation);
32893309
}
32903310
}
32913311
}
32923312

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

@@ -3321,7 +3323,7 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
33213323
// everywhere. Just haven't done it due to possible perturbations.
33223324
auto parentAddrInfo = getUnderlyingTrackedValue(svi);
33233325
if (parentAddrInfo.actorIsolation) {
3324-
iter.first->getSecond().mergeIsolationRegionInfo(
3326+
iter.first->getSecond().setIsolationRegionInfo(
33253327
SILIsolationInfo::getActorInstanceIsolated(
33263328
svi, parentAddrInfo.value,
33273329
parentAddrInfo.actorIsolation->getActor()));
@@ -3330,16 +3332,20 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
33303332
auto storage = AccessStorageWithBase::compute(svi->getOperand(0));
33313333
if (storage.storage) {
33323334
if (auto isolation = SILIsolationInfo::get(storage.base)) {
3333-
iter.first->getSecond().mergeIsolationRegionInfo(isolation);
3335+
iter.first->getSecond().setIsolationRegionInfo(isolation);
33343336
}
33353337
}
33363338

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

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

33453351
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)