20
20
#include " swift/SIL/SILInstruction.h"
21
21
#include " swift/SIL/SILValue.h"
22
22
#include " swift/SILOptimizer/Analysis/Reachability.h"
23
+ #include " swift/SILOptimizer/Analysis/VisitBarrierAccessScopes.h"
23
24
#include " swift/SILOptimizer/Utils/CanonicalizeBorrowScope.h"
24
25
#include " swift/SILOptimizer/Utils/InstOptUtils.h"
25
26
#include " swift/SILOptimizer/Utils/InstructionDeleter.h"
@@ -112,11 +113,14 @@ struct DeinitBarriers final {
112
113
DeinitBarriers &operator =(DeinitBarriers const &) = delete ;
113
114
};
114
115
116
+ class BarrierAccessScopeFinder ;
117
+
115
118
// / Works backwards from the current location of destroy_values to the earliest
116
119
// / place they can be hoisted to.
117
120
// /
118
121
// / Implements IterativeBackwardReachability::Effects
119
122
// / Implements IterativeBackwardReachability::bindBarriers::Visitor
123
+ // / Implements BarrierAccessScopeFinder::Effects
120
124
class Dataflow final {
121
125
using Reachability = IterativeBackwardReachability<Dataflow>;
122
126
using Effect = Reachability::Effect;
@@ -125,6 +129,7 @@ class Dataflow final {
125
129
DeinitBarriers &barriers;
126
130
Reachability::Result result;
127
131
Reachability reachability;
132
+ SmallPtrSet<BeginAccessInst *, 8 > barrierAccessScopes;
128
133
129
134
enum class Classification { Barrier, Other };
130
135
@@ -140,6 +145,8 @@ class Dataflow final {
140
145
141
146
private:
142
147
friend Reachability;
148
+ friend class BarrierAccessScopeFinder ;
149
+ friend class VisitBarrierAccessScopes <Dataflow, BarrierAccessScopeFinder>;
143
150
144
151
Classification classifyInstruction (SILInstruction *);
145
152
@@ -154,8 +161,37 @@ class Dataflow final {
154
161
void visitBarrierBlock (SILBasicBlock *);
155
162
};
156
163
164
+ // / Finds end_access instructions which are barriers to hoisting because the
165
+ // / access scopes they contain barriers to hoisting. Hoisting destroy_values
166
+ // / into such access scopes could introduce exclusivity violations.
167
+ // /
168
+ // / Implements BarrierAccessScopeFinder::Visitor
169
+ class BarrierAccessScopeFinder final {
170
+ using Impl = VisitBarrierAccessScopes<Dataflow, BarrierAccessScopeFinder>;
171
+ Context const &context;
172
+ Impl impl;
173
+ Dataflow &dataflow;
174
+ Optional<SmallVector<SILBasicBlock *, 16 >> cachedRoots;
175
+
176
+ public:
177
+ BarrierAccessScopeFinder (Context const &context, Dataflow &dataflow)
178
+ : context(context), impl(&context.function, dataflow, *this ),
179
+ dataflow (dataflow) {}
180
+
181
+ void find ();
182
+
183
+ private:
184
+ friend Impl;
185
+
186
+ ArrayRef<SILBasicBlock *> roots ();
187
+ bool isInRegion (SILBasicBlock *);
188
+ void visitBarrierAccessScope (BeginAccessInst *);
189
+ };
190
+
157
191
void Dataflow::run () {
158
192
reachability.initialize ();
193
+ BarrierAccessScopeFinder finder (context, *this );
194
+ finder.find ();
159
195
reachability.solve ();
160
196
reachability.findBarriers (*this );
161
197
}
@@ -168,6 +204,11 @@ Dataflow::classifyInstruction(SILInstruction *instruction) {
168
204
if (uses.users .contains (instruction)) {
169
205
return Classification::Barrier;
170
206
}
207
+ if (auto *eai = dyn_cast<EndAccessInst>(instruction)) {
208
+ return barrierAccessScopes.contains (eai->getBeginAccess ())
209
+ ? Classification::Barrier
210
+ : Classification::Other;
211
+ }
171
212
if (isDeinitBarrier (instruction)) {
172
213
return Classification::Barrier;
173
214
}
@@ -218,6 +259,33 @@ void Dataflow::visitBarrierBlock(SILBasicBlock *block) {
218
259
barriers.blocks .push_back (block);
219
260
}
220
261
262
+ void BarrierAccessScopeFinder::find () { impl.visit (); }
263
+
264
+ ArrayRef<SILBasicBlock *> BarrierAccessScopeFinder::roots () {
265
+ if (cachedRoots)
266
+ return *cachedRoots;
267
+
268
+ cachedRoots = SmallVector<SILBasicBlock *, 16 >{};
269
+ BasicBlockSet seenRoots (&context.function );
270
+ for (auto *gen : dataflow.gens ()) {
271
+ seenRoots.insert (gen->getParent ());
272
+ cachedRoots->push_back (gen->getParent ());
273
+ }
274
+
275
+ return *cachedRoots;
276
+ }
277
+
278
+ bool BarrierAccessScopeFinder::isInRegion (SILBasicBlock *block) {
279
+ return dataflow.result .discoveredBlocks .contains (block);
280
+ }
281
+
282
+ void BarrierAccessScopeFinder::visitBarrierAccessScope (BeginAccessInst *bai) {
283
+ dataflow.barrierAccessScopes .insert (bai);
284
+ for (auto *eai : bai->getEndAccesses ()) {
285
+ dataflow.reachability .addKill (eai);
286
+ }
287
+ }
288
+
221
289
// / Hoist the destroy_values of %value.
222
290
class Rewriter final {
223
291
Context &context;
0 commit comments