21
21
#include " swift/SIL/SILBasicBlock.h"
22
22
#include " swift/SIL/SILInstruction.h"
23
23
#include " swift/SILOptimizer/Analysis/Reachability.h"
24
+ #include " swift/SILOptimizer/Analysis/VisitBarrierAccessScopes.h"
24
25
#include " swift/SILOptimizer/Utils/CanonicalizeBorrowScope.h"
25
26
#include " swift/SILOptimizer/Utils/InstOptUtils.h"
26
27
#include " swift/SILOptimizer/Utils/InstructionDeleter.h"
@@ -134,11 +135,14 @@ struct DeinitBarriers final {
134
135
DeinitBarriers &operator =(DeinitBarriers const &) = delete ;
135
136
};
136
137
138
+ class BarrierAccessScopeFinder ;
139
+
137
140
// / Works backwards from the current location of end_borrows to the earliest
138
141
// / place they can be hoisted to.
139
142
// /
140
143
// / Implements IterativeBackwardReachability::Effects.
141
144
// / Implements IterativeBackwardReachability::findBarrier::Visitor.
145
+ // / Implements BarrierAccessScopeFinder::Effects
142
146
class Dataflow final {
143
147
public:
144
148
using Reachability = IterativeBackwardReachability<Dataflow>;
@@ -167,6 +171,8 @@ class Dataflow final {
167
171
168
172
private:
169
173
friend Reachability;
174
+ friend class BarrierAccessScopeFinder ;
175
+ friend class VisitBarrierAccessScopes <Dataflow, BarrierAccessScopeFinder>;
170
176
171
177
Classification classifyInstruction (SILInstruction *);
172
178
@@ -181,6 +187,33 @@ class Dataflow final {
181
187
void visitBarrierBlock (SILBasicBlock *);
182
188
};
183
189
190
+ // / Finds end_access instructions which are barriers to hoisting because the
191
+ // / access scopes they contain barriers to hoisting. Hoisting end_borrows into
192
+ // / such access scopes could introduce exclusivity violations.
193
+ // /
194
+ // / Implements BarrierAccessScopeFinder::Visitor
195
+ class BarrierAccessScopeFinder final {
196
+ using Impl = VisitBarrierAccessScopes<Dataflow, BarrierAccessScopeFinder>;
197
+ Context const &context;
198
+ Impl impl;
199
+ Dataflow &dataflow;
200
+ Optional<SmallVector<SILBasicBlock *, 16 >> cachedRoots;
201
+
202
+ public:
203
+ BarrierAccessScopeFinder (Context const &context, Dataflow &dataflow)
204
+ : context(context), impl(&context.function, dataflow, *this ),
205
+ dataflow (dataflow) {}
206
+
207
+ void find ();
208
+
209
+ private:
210
+ friend Impl;
211
+
212
+ ArrayRef<SILBasicBlock *> roots ();
213
+ bool isInRegion (SILBasicBlock *);
214
+ void visitBarrierAccessScope (BeginAccessInst *);
215
+ };
216
+
184
217
// / Whether the specified value is %lifetime or its iterated copy_value.
185
218
// /
186
219
// / In other words, it has to be a simple extended def of %lifetime.
@@ -201,6 +234,8 @@ bool isSimpleExtendedIntroducerDef(Context const &context, SILValue value) {
201
234
202
235
void Dataflow::run () {
203
236
reachability.initialize ();
237
+ BarrierAccessScopeFinder finder (context, *this );
238
+ finder.find ();
204
239
reachability.solve ();
205
240
recordCopies = true ;
206
241
reachability.findBarriers (*this );
@@ -219,6 +254,11 @@ Dataflow::classifyInstruction(SILInstruction *instruction) {
219
254
if (uses.users .contains (instruction)) {
220
255
return Classification::Barrier;
221
256
}
257
+ if (auto *eai = dyn_cast<EndAccessInst>(instruction)) {
258
+ return barrierAccessScopes.contains (eai->getBeginAccess ())
259
+ ? Classification::Barrier
260
+ : Classification::Other;
261
+ }
222
262
if (isDeinitBarrier (instruction)) {
223
263
return Classification::Barrier;
224
264
}
@@ -272,6 +312,33 @@ void Dataflow::visitBarrierBlock(SILBasicBlock *block) {
272
312
barriers.blocks .push_back (block);
273
313
}
274
314
315
+ void BarrierAccessScopeFinder::find () { impl.visit (); }
316
+
317
+ ArrayRef<SILBasicBlock *> BarrierAccessScopeFinder::roots () {
318
+ if (cachedRoots)
319
+ return *cachedRoots;
320
+
321
+ cachedRoots = SmallVector<SILBasicBlock *, 16 >{};
322
+ BasicBlockSet seenRoots (&context.function );
323
+ for (auto *gen : dataflow.gens ()) {
324
+ seenRoots.insert (gen->getParent ());
325
+ cachedRoots->push_back (gen->getParent ());
326
+ }
327
+
328
+ return *cachedRoots;
329
+ }
330
+
331
+ bool BarrierAccessScopeFinder::isInRegion (SILBasicBlock *block) {
332
+ return dataflow.result .discoveredBlocks .contains (block);
333
+ }
334
+
335
+ void BarrierAccessScopeFinder::visitBarrierAccessScope (BeginAccessInst *bai) {
336
+ dataflow.barrierAccessScopes .insert (bai);
337
+ for (auto *eai : bai->getEndAccesses ()) {
338
+ dataflow.reachability .addKill (eai);
339
+ }
340
+ }
341
+
275
342
// / Hoist the scope ends of %lifetime, rewriting copies and borrows along the
276
343
// / way.
277
344
class Rewriter final {
0 commit comments