Skip to content

Commit 9384493

Browse files
committed
[region-isolation] Begin tracking region information instead of just whether a value is actor derived.
To keep this as an NFC commit, I only modeled initially actor isolated using this. I am going to make it so that we properly treat global actor isolated values as actor isolated/etc in a subsequent commit.
1 parent 7f5194b commit 9384493

File tree

4 files changed

+274
-106
lines changed

4 files changed

+274
-106
lines changed

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 142 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,24 +125,133 @@ enum class TrackableValueFlag {
125125

126126
/// Set to true if this TrackableValue's representative is Sendable.
127127
isSendable = 0x2,
128-
129-
/// Set to true if this TrackableValue is a non-sendable object derived from
130-
/// an actor. Example: a value loaded from a ref_element_addr from an actor.
131-
///
132-
/// NOTE: We track values with an actor representative even though actors are
133-
/// sendable to be able to properly identify values that escape an actor since
134-
/// if we escape an actor into a closure, we want to mark the closure as actor
135-
/// derived.
136-
isActorDerived = 0x4,
137128
};
138129

139130
using TrackedValueFlagSet = OptionSet<TrackableValueFlag>;
140131

132+
class ValueIsolationRegionInfo {
133+
public:
134+
/// The lattice is:
135+
///
136+
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
137+
///
138+
/// Unknown means no information. We error when merging on it.
139+
enum Kind {
140+
Unknown,
141+
Disconnected,
142+
Actor,
143+
};
144+
145+
private:
146+
Kind kind;
147+
148+
/// When this is set it corresponds to a specific ActorIsolation from the AST
149+
/// that we found.
150+
///
151+
/// NOTE: actorInstanceType and actorIsolation should never be both set!
152+
std::optional<ActorIsolation> actorIsolation;
153+
154+
/// When this is set it corresponds to a specific Actor type that we
155+
/// identified as being actor isolated from a SIL level type. We do not have
156+
/// the ActorIsolation information, so this is artificial.
157+
///
158+
/// NOTE: actorInstanceType and actorIsolation should never be both set!
159+
NominalTypeDecl *actorInstanceType = nullptr;
160+
161+
ValueIsolationRegionInfo(Kind kind,
162+
std::optional<ActorIsolation> actorIsolation,
163+
NominalTypeDecl *actorInstanceType = nullptr)
164+
: kind(kind), actorIsolation(actorIsolation),
165+
actorInstanceType(actorInstanceType) {}
166+
167+
public:
168+
ValueIsolationRegionInfo() : kind(Kind::Unknown), actorIsolation() {}
169+
170+
operator bool() const { return kind != Kind::Unknown; }
171+
172+
operator Kind() const { return kind; }
173+
174+
Kind getKind() const { return kind; }
175+
176+
bool isDisconnected() const { return kind == Kind::Disconnected; }
177+
bool isActorIsolated() const { return kind == Kind::Actor; }
178+
179+
void print(llvm::raw_ostream &os) const {
180+
switch (Kind(*this)) {
181+
case Unknown:
182+
os << "unknown";
183+
return;
184+
case Disconnected:
185+
os << "disconnected";
186+
return;
187+
case Actor:
188+
os << "actor";
189+
return;
190+
}
191+
}
192+
193+
SWIFT_DEBUG_DUMP {
194+
print(llvm::dbgs());
195+
llvm::dbgs() << '\n';
196+
}
197+
198+
std::optional<ActorIsolation> getActorIsolation() const {
199+
assert(!actorInstanceType &&
200+
"Should never be set if getActorIsolation is called");
201+
return actorIsolation;
202+
}
203+
204+
NominalTypeDecl *getActorInstance() const {
205+
assert(!actorIsolation.has_value());
206+
return actorInstanceType;
207+
}
208+
209+
[[nodiscard]] ValueIsolationRegionInfo
210+
merge(ValueIsolationRegionInfo other) const {
211+
// If we are greater than the other kind, then we are further along the
212+
// lattice. We ignore the change.
213+
if (unsigned(other.kind) < unsigned(kind))
214+
return *this;
215+
216+
assert(kind != ValueIsolationRegionInfo::Actor &&
217+
"Actor should never be merged with another actor?!");
218+
219+
// Otherwise, take the other value.
220+
return other;
221+
}
222+
223+
ValueIsolationRegionInfo withActorIsolated(ActorIsolation isolation) {
224+
return ValueIsolationRegionInfo::getActorIsolated(isolation);
225+
}
226+
227+
static ValueIsolationRegionInfo getDisconnected() {
228+
return {Kind::Disconnected, {}};
229+
}
230+
231+
static ValueIsolationRegionInfo
232+
getActorIsolated(ActorIsolation actorIsolation) {
233+
return {Kind::Actor, actorIsolation};
234+
}
235+
236+
/// Sometimes we may have something that is actor isolated or that comes from
237+
/// a type. First try getActorIsolation and otherwise, just use the type.
238+
static ValueIsolationRegionInfo getActorIsolated(NominalTypeDecl *nomDecl) {
239+
auto actorIsolation = swift::getActorIsolation(nomDecl);
240+
if (actorIsolation.isActorIsolated())
241+
return getActorIsolated(actorIsolation);
242+
if (nomDecl->isActor())
243+
return {Kind::Actor, {}, nomDecl};
244+
return {};
245+
}
246+
};
247+
141248
} // namespace regionanalysisimpl
142249

143250
class regionanalysisimpl::TrackableValueState {
144251
unsigned id;
145252
TrackedValueFlagSet flagSet = {TrackableValueFlag::isMayAlias};
253+
ValueIsolationRegionInfo regionInfo =
254+
ValueIsolationRegionInfo::getDisconnected();
146255

147256
public:
148257
TrackableValueState(unsigned newID) : id(newID) {}
@@ -159,10 +268,20 @@ class regionanalysisimpl::TrackableValueState {
159268

160269
bool isNonSendable() const { return !isSendable(); }
161270

162-
bool isActorDerived() const {
163-
return flagSet.contains(TrackableValueFlag::isActorDerived);
271+
ValueIsolationRegionInfo::Kind getRegionInfoKind() {
272+
return regionInfo.getKind();
164273
}
165274

275+
ActorIsolation getActorIsolation() const {
276+
return regionInfo.getActorIsolation().value();
277+
}
278+
279+
void mergeIsolationRegionInfo(ValueIsolationRegionInfo newRegionInfo) {
280+
regionInfo = regionInfo.merge(newRegionInfo);
281+
}
282+
283+
ValueIsolationRegionInfo getIsolationRegionInfo() const { return regionInfo; }
284+
166285
TrackableValueID getID() const { return TrackableValueID(id); }
167286

168287
void addFlag(TrackableValueFlag flag) { flagSet |= flag; }
@@ -173,7 +292,9 @@ class regionanalysisimpl::TrackableValueState {
173292
os << "TrackableValueState[id: " << id
174293
<< "][is_no_alias: " << (isNoAlias() ? "yes" : "no")
175294
<< "][is_sendable: " << (isSendable() ? "yes" : "no")
176-
<< "][is_actor_derived: " << (isActorDerived() ? "yes" : "no") << "].";
295+
<< "][region_value_kind: ";
296+
getIsolationRegionInfo().print(os);
297+
os << "].";
177298
}
178299

179300
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
@@ -257,7 +378,9 @@ class regionanalysisimpl::TrackableValue {
257378

258379
bool isNonSendable() const { return !isSendable(); }
259380

260-
bool isActorDerived() const { return valueState.isActorDerived(); }
381+
ValueIsolationRegionInfo getIsolationRegionInfo() const {
382+
return valueState.getIsolationRegionInfo();
383+
}
261384

262385
TrackableValueID getID() const {
263386
return TrackableValueID(valueState.getID());
@@ -293,6 +416,7 @@ class RegionAnalysisValueMap {
293416
using TrackableValueState = regionanalysisimpl::TrackableValueState;
294417
using TrackableValueID = Element;
295418
using RepresentativeValue = regionanalysisimpl::RepresentativeValue;
419+
using ValueIsolationRegionInfo = regionanalysisimpl::ValueIsolationRegionInfo;
296420

297421
private:
298422
/// A map from the representative of an equivalence class of values to their
@@ -326,7 +450,7 @@ class RegionAnalysisValueMap {
326450
/// value" returns an empty SILValue.
327451
SILValue maybeGetRepresentative(Element trackableValueID) const;
328452

329-
bool isActorDerived(Element trackableValueID) const;
453+
ValueIsolationRegionInfo getIsolationRegion(Element trackableValueID) const;
330454

331455
ArrayRef<Element> getNonTransferrableElements() const {
332456
return neverTransferredValueIDs;
@@ -345,8 +469,10 @@ class RegionAnalysisValueMap {
345469
std::optional<TrackableValue> getValueForId(TrackableValueID id) const;
346470
std::optional<TrackableValue> tryToTrackValue(SILValue value) const;
347471
TrackableValue
348-
getActorIntroducingRepresentative(SILInstruction *introducingInst) const;
349-
bool markValueAsActorDerived(SILValue value);
472+
getActorIntroducingRepresentative(SILInstruction *introducingInst,
473+
ValueIsolationRegionInfo isolation) const;
474+
bool mergeIsolationRegionInfo(SILValue value,
475+
ValueIsolationRegionInfo isolation);
350476
void addNeverTransferredValueID(TrackableValueID valueID) {
351477
neverTransferredValueIDs.push_back(valueID);
352478
}

0 commit comments

Comments
 (0)