@@ -56,6 +56,36 @@ static bool isApplyInst(SILInstruction &inst) {
56
56
return ApplySite::isa (&inst) || isa<BuiltinInst>(inst);
57
57
}
58
58
59
+ static AccessStorage getAccessStorageFromAddr (SILValue value) {
60
+ assert (isAddress (value));
61
+ auto accessStorage = AccessStorage::compute (value);
62
+ if (accessStorage && accessStorage.getRoot ()) {
63
+ if (auto definingInst = accessStorage.getRoot ().getDefiningInstruction ()) {
64
+ if (isa<InitExistentialAddrInst, CopyValueInst>(definingInst))
65
+ // look through these because AccessStorage does not
66
+ return getAccessStorageFromAddr (definingInst->getOperand (0 ));
67
+ }
68
+ }
69
+
70
+ return accessStorage;
71
+ }
72
+
73
+ static SILValue getUnderlyingTrackedValue (SILValue value) {
74
+ if (!isAddress (value)) {
75
+ return getUnderlyingObject (value);
76
+ }
77
+
78
+ if (auto accessStorage = getAccessStorageFromAddr (value)) {
79
+ if (accessStorage.getKind () == AccessRepresentation::Kind::Global)
80
+ // globals don't reduce
81
+ return value;
82
+ assert (accessStorage.getRoot ());
83
+ return accessStorage.getRoot ();
84
+ }
85
+
86
+ return value;
87
+ }
88
+
59
89
// ===----------------------------------------------------------------------===//
60
90
// MARK: Main Computation
61
91
// ===----------------------------------------------------------------------===//
@@ -67,6 +97,41 @@ static const char *SEP_STR = "╾───────────────
67
97
using TrackableValueID = PartitionPrimitives::Element;
68
98
using Region = PartitionPrimitives::Region;
69
99
100
+ class TrackableSILValue {
101
+ SILValue value;
102
+ bool aliased;
103
+ bool sendable;
104
+
105
+ public:
106
+ TrackableSILValue (SILValue inputValue, bool aliased, bool sendable)
107
+ : value(inputValue), aliased(aliased), sendable(sendable) {}
108
+
109
+ bool isAliased () const { return aliased; }
110
+
111
+ bool isUnaliased () const { return !aliased; }
112
+
113
+ bool isSendable () const { return sendable; }
114
+
115
+ bool isNonSendable () const { return !sendable; }
116
+
117
+ SILValue getValue () const { return value; }
118
+
119
+ // comparison operates lookthrough to the underlying SILValue
120
+ bool operator ==(const TrackableSILValue &other) const {
121
+ return value == other.value ;
122
+ }
123
+
124
+ bool operator <(const TrackableSILValue &other) const {
125
+ return value < other.value ;
126
+ }
127
+
128
+ void dump () const {
129
+ llvm::dbgs () << " TrackableSILValue[aliased=" << aliased
130
+ << " ][sendable=" << sendable << " ]: " ;
131
+ value->dump ();
132
+ }
133
+ };
134
+
70
135
// PartitionOpTranslator is responsible for performing the translation from
71
136
// SILInstructions to PartitionOps. Not all SILInstructions have an effect on
72
137
// the region partition, and some have multiple effects - such as an application
@@ -87,100 +152,8 @@ class PartitionOpTranslator {
87
152
SILFunction *function;
88
153
ProtocolDecl *sendableProtocol;
89
154
90
- class TrackableSILValue {
91
- bool aliased = true ;
92
- bool sendable = false ;
93
- SILValue value;
94
-
95
- AccessStorage getAccessStorageFromAddr (SILValue val) {
96
- assert (isAddress (val));
97
- auto accessStorage = AccessStorage::compute (val);
98
- if (accessStorage && accessStorage.getRoot ()) {
99
- auto definingInst = accessStorage.getRoot ().getDefiningInstruction ();
100
- if (definingInst &&
101
- isa<InitExistentialAddrInst, CopyValueInst>(definingInst))
102
- // look through these because AccessStorage does not
103
- return getAccessStorageFromAddr (definingInst->getOperand (0 ));
104
- }
105
- return accessStorage;
106
- }
107
-
108
- // simplifyVal reduces an address-typed SILValue to the root SILValue
109
- // that it was derived from, reducing the set of values that must be
110
- // reasoned about by rendering two values that are projections/aliases the
111
- // same.
112
- SILValue simplifyVal (SILValue val) {
113
- if (!isAddress (val))
114
- // TODO: consider adding more reduction for non-address values
115
- return getUnderlyingObject (val);
116
- if (auto accessStorage = getAccessStorageFromAddr (val)) {
117
- if (accessStorage.getKind () == AccessRepresentation::Kind::Global)
118
- // globals don't reduce
119
- return val;
120
- assert (accessStorage.getRoot ());
121
- return accessStorage.getRoot ();
122
- }
123
- return val;
124
- }
125
-
126
- public:
127
- TrackableSILValue (const PartitionOpTranslator *translator,
128
- SILValue value_in) :
129
- value (simplifyVal(value_in)) {
130
-
131
- // set `aliased` appropriately
132
- if (isAddress (value))
133
- if (auto accessStorage = AccessStorage::compute (value))
134
- aliased = !accessStorage.isUniquelyIdentified () ||
135
- translator->capturedUIValues .count (*this );
136
-
137
- // set `sendable` appropriately
138
- SILInstruction *defInst = value.getDefiningInstruction ();
139
- if (defInst && isa<ClassMethodInst, FunctionRefInst>(defInst)) {
140
- // though these values are technically non-Sendable, we can safely
141
- // and consistently treat them as Sendable
142
- sendable = true ;
143
- } else {
144
- sendable = !translator->isNonSendableType (value->getType ());
145
- }
146
- }
147
- inline bool isAliased () const {
148
- return aliased;
149
- }
150
-
151
- inline bool isUnaliased () const {
152
- return !aliased;
153
- }
154
-
155
- inline bool isSendable () const {
156
- return sendable;
157
- }
158
-
159
- inline bool isNonSendable () const {
160
- return !sendable;
161
- }
162
-
163
- SILValue getValue () const {
164
- return value;
165
- }
166
-
167
- // comparison operates lookthrough to the underlying SILValue
168
- bool operator ==(const TrackableSILValue &other) const {
169
- return value == other.value ;
170
- }
171
- bool operator <(const TrackableSILValue &other) const {
172
- return value < other.value ;
173
- }
174
-
175
- void dump () const {
176
- llvm::dbgs () << " TrackableSILValue[aliased="
177
- << aliased << " ][sendable=" << sendable << " ]: " ;
178
- value->dump ();
179
- }
180
- };
181
-
182
155
llvm::Optional<TrackableSILValue> trackIfNonSendable (SILValue value) const {
183
- auto trackedVal = TrackableSILValue ( this , value);
156
+ auto trackedVal = getTrackableSILValue ( value);
184
157
if (trackedVal.isNonSendable ()) {
185
158
return trackedVal;
186
159
}
@@ -202,7 +175,32 @@ class PartitionOpTranslator {
202
175
// but at what points in function flow they do, this would be more
203
176
// permissive, but I'm avoiding implementing it in case existing
204
177
// utilities would make it easier than handrolling
205
- std::set<TrackableSILValue> capturedUIValues;
178
+ std::set<SILValue> capturedUIValues;
179
+
180
+ TrackableSILValue getTrackableSILValue (SILValue value) const {
181
+ value = getUnderlyingTrackedValue (value);
182
+
183
+ bool isAliased = true ;
184
+
185
+ if (isAddress (value)) {
186
+ if (auto accessStorage = AccessStorage::compute (value))
187
+ isAliased = !accessStorage.isUniquelyIdentified () ||
188
+ capturedUIValues.count (value);
189
+ }
190
+
191
+ // set `sendable` appropriately
192
+ if (auto *defInst = value.getDefiningInstruction ()) {
193
+ // Though these values are technically non-Sendable, we can safely and
194
+ // consistently treat them as Sendable.
195
+ if (isa<ClassMethodInst, FunctionRefInst>(defInst)) {
196
+ return TrackableSILValue (value, isAliased, true /* is sendable*/ );
197
+ }
198
+ }
199
+
200
+ // Otherwise refer to the oracle.
201
+ return TrackableSILValue (value, isAliased,
202
+ !isNonSendableType (value->getType ()));
203
+ }
206
204
207
205
void initCapturedUIValues () {
208
206
for (auto &block : *function) {
@@ -211,9 +209,9 @@ class PartitionOpTranslator {
211
209
// add all nonsendable, uniquely identified arguments to applications
212
210
// to capturedUIValues, because applications capture them
213
211
for (SILValue val : inst.getOperandValues ()) {
214
- auto trackVal = TrackableSILValue ( this , val);
212
+ auto trackVal = getTrackableSILValue ( val);
215
213
if (trackVal.isNonSendable () && trackVal.isUnaliased ())
216
- capturedUIValues.insert (trackVal );
214
+ capturedUIValues.insert (val );
217
215
}
218
216
}
219
217
}
@@ -231,12 +229,10 @@ class PartitionOpTranslator {
231
229
" in contexts in which the availability of the "
232
230
" Sendable protocol has already been checked." );
233
231
initCapturedUIValues ();
234
- LLVM_DEBUG (
235
- llvm::dbgs () << " Captured Uniquely Identified addresses for "
236
- << function->getName () << " :\n " ;
237
- for (TrackableSILValue val : capturedUIValues)
238
- val.getValue ()->dump ();
239
- );
232
+ LLVM_DEBUG (llvm::dbgs () << " Captured Uniquely Identified addresses for "
233
+ << function->getName () << " :\n " ;
234
+ for (SILValue val
235
+ : capturedUIValues) val->dump (););
240
236
}
241
237
242
238
private:
0 commit comments