Skip to content

Commit 0d96a16

Browse files
committed
[region-isolation] Move IsolationRegionInfo higher up in PartitionUtils.h
This is in preparation for beginning to track an IsolationRegionInfo in TransferringOperand. Just splitting this into a separate commit to make it easier to read.
1 parent e6a1d83 commit 0d96a16

File tree

1 file changed

+181
-177
lines changed

1 file changed

+181
-177
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 181 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,187 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
9090

9191
namespace swift {
9292

93+
class IsolationRegionInfo {
94+
public:
95+
/// The lattice is:
96+
///
97+
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
98+
///
99+
/// Unknown means no information. We error when merging on it.
100+
enum Kind {
101+
Unknown,
102+
Disconnected,
103+
Task,
104+
Actor,
105+
};
106+
107+
private:
108+
Kind kind;
109+
// clang-format off
110+
std::variant<
111+
// Used for actor isolated when we have ActorIsolation info from the AST.
112+
std::optional<ActorIsolation>,
113+
// Used for actor isolation when we infer the actor at the SIL level.
114+
NominalTypeDecl *,
115+
// The task isolated parameter when we find a task isolated value.
116+
SILValue
117+
> data;
118+
// clang-format on
119+
120+
IsolationRegionInfo(Kind kind, std::optional<ActorIsolation> actorIsolation)
121+
: kind(kind), data(actorIsolation) {}
122+
IsolationRegionInfo(Kind kind, NominalTypeDecl *decl)
123+
: kind(kind), data(decl) {}
124+
125+
IsolationRegionInfo(Kind kind, SILValue value) : kind(kind), data(value) {}
126+
127+
public:
128+
IsolationRegionInfo() : kind(Kind::Unknown), data() {}
129+
130+
operator bool() const { return kind != Kind::Unknown; }
131+
132+
operator Kind() const { return kind; }
133+
134+
Kind getKind() const { return kind; }
135+
136+
bool isDisconnected() const { return kind == Kind::Disconnected; }
137+
bool isActorIsolated() const { return kind == Kind::Actor; }
138+
bool isTaskIsolated() const { return kind == Kind::Task; }
139+
140+
void print(llvm::raw_ostream &os) const {
141+
switch (Kind(*this)) {
142+
case Unknown:
143+
os << "unknown";
144+
return;
145+
case Disconnected:
146+
os << "disconnected";
147+
return;
148+
case Actor:
149+
os << "actor";
150+
return;
151+
case Task:
152+
os << "task";
153+
return;
154+
}
155+
}
156+
157+
void printForDiagnostics(llvm::raw_ostream &os) const;
158+
159+
SWIFT_DEBUG_DUMP {
160+
print(llvm::dbgs());
161+
llvm::dbgs() << '\n';
162+
}
163+
164+
std::optional<ActorIsolation> getActorIsolation() const {
165+
assert(kind == Actor);
166+
assert(std::holds_alternative<std::optional<ActorIsolation>>(data) &&
167+
"Doesn't have an actor isolation?!");
168+
return std::get<std::optional<ActorIsolation>>(data);
169+
}
170+
171+
NominalTypeDecl *getActorInstance() const {
172+
assert(kind == Actor);
173+
assert(std::holds_alternative<NominalTypeDecl *>(data) &&
174+
"Doesn't have an actor instance?!");
175+
return std::get<NominalTypeDecl *>(data);
176+
}
177+
178+
SILValue getTaskIsolatedValue() const {
179+
assert(kind == Task);
180+
assert(std::holds_alternative<SILValue>(data) &&
181+
"Doesn't have a task isolated value");
182+
return std::get<SILValue>(data);
183+
}
184+
185+
bool hasActorIsolation() const {
186+
return kind == Actor &&
187+
std::holds_alternative<std::optional<ActorIsolation>>(data);
188+
}
189+
190+
bool hasActorInstance() const {
191+
return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
192+
}
193+
194+
bool hasTaskIsolatedValue() const {
195+
return kind == Task && std::holds_alternative<SILValue>(data);
196+
}
197+
198+
/// If we actually have an actor decl, return that. Otherwise, see if we have
199+
/// an actor isolation if we can find one in there. Returns nullptr if we
200+
/// fail.
201+
NominalTypeDecl *tryInferActorDecl() const {
202+
if (hasActorIsolation()) {
203+
auto actorIsolation = getActorIsolation();
204+
if (auto *actor = actorIsolation->getActorOrNullPtr()) {
205+
return actor;
206+
}
207+
return nullptr;
208+
}
209+
210+
if (hasActorInstance()) {
211+
auto actorDecl = getActorInstance();
212+
return actorDecl;
213+
}
214+
215+
return nullptr;
216+
}
217+
218+
[[nodiscard]] IsolationRegionInfo merge(IsolationRegionInfo other) const {
219+
// If we are greater than the other kind, then we are further along the
220+
// lattice. We ignore the change.
221+
if (unsigned(other.kind) < unsigned(kind))
222+
return *this;
223+
224+
// TODO: Make this failing mean that we emit an unknown SIL error instead of
225+
// asserting.
226+
if (other.isActorIsolated() && isActorIsolated()) {
227+
if (other.hasActorInstance() && hasActorInstance()) {
228+
assert(other.getActorInstance() == getActorInstance() &&
229+
"Actor should never be merged with another actor unless with "
230+
"the same actor?!");
231+
} else if (other.hasActorIsolation() && hasActorIsolation()) {
232+
assert(other.getActorIsolation() == getActorIsolation() &&
233+
"Actor should never be merged with another actor unless with "
234+
"the same actor?!");
235+
}
236+
}
237+
238+
// Otherwise, take the other value.
239+
return other;
240+
}
241+
242+
IsolationRegionInfo withActorIsolated(ActorIsolation isolation) {
243+
return IsolationRegionInfo::getActorIsolated(isolation);
244+
}
245+
246+
static IsolationRegionInfo getDisconnected() {
247+
return {Kind::Disconnected, {}};
248+
}
249+
250+
static IsolationRegionInfo getActorIsolated(ActorIsolation actorIsolation) {
251+
return {Kind::Actor, actorIsolation};
252+
}
253+
254+
/// Sometimes we may have something that is actor isolated or that comes from
255+
/// a type. First try getActorIsolation and otherwise, just use the type.
256+
static IsolationRegionInfo getActorIsolated(NominalTypeDecl *nomDecl) {
257+
auto actorIsolation = swift::getActorIsolation(nomDecl);
258+
if (actorIsolation.isActorIsolated())
259+
return getActorIsolated(actorIsolation);
260+
if (nomDecl->isActor())
261+
return {Kind::Actor, nomDecl};
262+
return {};
263+
}
264+
265+
static IsolationRegionInfo getTaskIsolated(SILValue value) {
266+
return {Kind::Task, value};
267+
}
268+
};
269+
270+
} // namespace swift
271+
272+
namespace swift {
273+
93274
struct TransferringOperand {
94275
using ValueType = llvm::PointerIntPair<Operand *, 1>;
95276
ValueType value;
@@ -965,183 +1146,6 @@ class Partition {
9651146
}
9661147
};
9671148

968-
class IsolationRegionInfo {
969-
public:
970-
/// The lattice is:
971-
///
972-
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
973-
///
974-
/// Unknown means no information. We error when merging on it.
975-
enum Kind {
976-
Unknown,
977-
Disconnected,
978-
Task,
979-
Actor,
980-
};
981-
982-
private:
983-
Kind kind;
984-
// clang-format off
985-
std::variant<
986-
// Used for actor isolated when we have ActorIsolation info from the AST.
987-
std::optional<ActorIsolation>,
988-
// Used for actor isolation when we infer the actor at the SIL level.
989-
NominalTypeDecl *,
990-
// The task isolated parameter when we find a task isolated value.
991-
SILValue
992-
> data;
993-
// clang-format on
994-
995-
IsolationRegionInfo(Kind kind, std::optional<ActorIsolation> actorIsolation)
996-
: kind(kind), data(actorIsolation) {}
997-
IsolationRegionInfo(Kind kind, NominalTypeDecl *decl)
998-
: kind(kind), data(decl) {}
999-
1000-
IsolationRegionInfo(Kind kind, SILValue value) : kind(kind), data(value) {}
1001-
1002-
public:
1003-
IsolationRegionInfo() : kind(Kind::Unknown), data() {}
1004-
1005-
operator bool() const { return kind != Kind::Unknown; }
1006-
1007-
operator Kind() const { return kind; }
1008-
1009-
Kind getKind() const { return kind; }
1010-
1011-
bool isDisconnected() const { return kind == Kind::Disconnected; }
1012-
bool isActorIsolated() const { return kind == Kind::Actor; }
1013-
bool isTaskIsolated() const { return kind == Kind::Task; }
1014-
1015-
void print(llvm::raw_ostream &os) const {
1016-
switch (Kind(*this)) {
1017-
case Unknown:
1018-
os << "unknown";
1019-
return;
1020-
case Disconnected:
1021-
os << "disconnected";
1022-
return;
1023-
case Actor:
1024-
os << "actor";
1025-
return;
1026-
case Task:
1027-
os << "task";
1028-
return;
1029-
}
1030-
}
1031-
1032-
void printForDiagnostics(llvm::raw_ostream &os) const;
1033-
1034-
SWIFT_DEBUG_DUMP {
1035-
print(llvm::dbgs());
1036-
llvm::dbgs() << '\n';
1037-
}
1038-
1039-
std::optional<ActorIsolation> getActorIsolation() const {
1040-
assert(kind == Actor);
1041-
assert(std::holds_alternative<std::optional<ActorIsolation>>(data) &&
1042-
"Doesn't have an actor isolation?!");
1043-
return std::get<std::optional<ActorIsolation>>(data);
1044-
}
1045-
1046-
NominalTypeDecl *getActorInstance() const {
1047-
assert(kind == Actor);
1048-
assert(std::holds_alternative<NominalTypeDecl *>(data) &&
1049-
"Doesn't have an actor instance?!");
1050-
return std::get<NominalTypeDecl *>(data);
1051-
}
1052-
1053-
SILValue getTaskIsolatedValue() const {
1054-
assert(kind == Task);
1055-
assert(std::holds_alternative<SILValue>(data) &&
1056-
"Doesn't have a task isolated value");
1057-
return std::get<SILValue>(data);
1058-
}
1059-
1060-
bool hasActorIsolation() const {
1061-
return kind == Actor &&
1062-
std::holds_alternative<std::optional<ActorIsolation>>(data);
1063-
}
1064-
1065-
bool hasActorInstance() const {
1066-
return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
1067-
}
1068-
1069-
bool hasTaskIsolatedValue() const {
1070-
return kind == Task && std::holds_alternative<SILValue>(data);
1071-
}
1072-
1073-
/// If we actually have an actor decl, return that. Otherwise, see if we have
1074-
/// an actor isolation if we can find one in there. Returns nullptr if we
1075-
/// fail.
1076-
NominalTypeDecl *tryInferActorDecl() const {
1077-
if (hasActorIsolation()) {
1078-
auto actorIsolation = getActorIsolation();
1079-
if (auto *actor = actorIsolation->getActorOrNullPtr()) {
1080-
return actor;
1081-
}
1082-
return nullptr;
1083-
}
1084-
1085-
if (hasActorInstance()) {
1086-
auto actorDecl = getActorInstance();
1087-
return actorDecl;
1088-
}
1089-
1090-
return nullptr;
1091-
}
1092-
1093-
[[nodiscard]] IsolationRegionInfo merge(IsolationRegionInfo other) const {
1094-
// If we are greater than the other kind, then we are further along the
1095-
// lattice. We ignore the change.
1096-
if (unsigned(other.kind) < unsigned(kind))
1097-
return *this;
1098-
1099-
// TODO: Make this failing mean that we emit an unknown SIL error instead of
1100-
// asserting.
1101-
if (other.isActorIsolated() && isActorIsolated()) {
1102-
if (other.hasActorInstance() && hasActorInstance()) {
1103-
assert(other.getActorInstance() == getActorInstance() &&
1104-
"Actor should never be merged with another actor unless with "
1105-
"the same actor?!");
1106-
} else if (other.hasActorIsolation() && hasActorIsolation()) {
1107-
assert(other.getActorIsolation() == getActorIsolation() &&
1108-
"Actor should never be merged with another actor unless with "
1109-
"the same actor?!");
1110-
}
1111-
}
1112-
1113-
// Otherwise, take the other value.
1114-
return other;
1115-
}
1116-
1117-
IsolationRegionInfo withActorIsolated(ActorIsolation isolation) {
1118-
return IsolationRegionInfo::getActorIsolated(isolation);
1119-
}
1120-
1121-
static IsolationRegionInfo getDisconnected() {
1122-
return {Kind::Disconnected, {}};
1123-
}
1124-
1125-
static IsolationRegionInfo getActorIsolated(ActorIsolation actorIsolation) {
1126-
return {Kind::Actor, actorIsolation};
1127-
}
1128-
1129-
/// Sometimes we may have something that is actor isolated or that comes from
1130-
/// a type. First try getActorIsolation and otherwise, just use the type.
1131-
static IsolationRegionInfo getActorIsolated(NominalTypeDecl *nomDecl) {
1132-
auto actorIsolation = swift::getActorIsolation(nomDecl);
1133-
if (actorIsolation.isActorIsolated())
1134-
return getActorIsolated(actorIsolation);
1135-
if (nomDecl->isActor())
1136-
return {Kind::Actor, nomDecl};
1137-
return {};
1138-
}
1139-
1140-
static IsolationRegionInfo getTaskIsolated(SILValue value) {
1141-
return {Kind::Task, value};
1142-
}
1143-
};
1144-
11451149
/// A data structure that applies a series of PartitionOps to a single Partition
11461150
/// that it modifies.
11471151
///

0 commit comments

Comments
 (0)