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"
@@ -111,10 +112,13 @@ struct DeinitBarriers final {
111
112
DeinitBarriers &operator =(DeinitBarriers const &) = delete ;
112
113
};
113
114
115
+ class BarrierAccessScopeFinder ;
116
+
114
117
// / Works backwards from the current location of destroy_values to the earliest
115
118
// / place they can be hoisted to.
116
119
// /
117
120
// / Implements IterativeBackwardReachability::Effects
121
+ // / Implements BarrierAccessScopeFinder::Effects
118
122
class DataFlow final {
119
123
using Reachability = IterativeBackwardReachability<DataFlow>;
120
124
using Effect = Reachability::Effect;
@@ -123,6 +127,7 @@ class DataFlow final {
123
127
DeinitBarriers &barriers;
124
128
Reachability::Result result;
125
129
Reachability reachability;
130
+ SmallPtrSet<BeginAccessInst *, 8 > barrierAccessScopes;
126
131
127
132
enum class Classification { Barrier, Other };
128
133
@@ -138,6 +143,8 @@ class DataFlow final {
138
143
139
144
private:
140
145
friend Reachability;
146
+ friend class BarrierAccessScopeFinder ;
147
+ friend class VisitBarrierAccessScopes <DataFlow, BarrierAccessScopeFinder>;
141
148
142
149
Classification classifyInstruction (SILInstruction *);
143
150
@@ -150,8 +157,37 @@ class DataFlow final {
150
157
Optional<Effect> effectForPhi (SILBasicBlock *);
151
158
};
152
159
160
+ // / Finds end_access instructions which are barriers to hoisting because the
161
+ // / access scopes they contain barriers to hoisting. Hoisting destroy_values
162
+ // / into such access scopes could introduce exclusivity violations.
163
+ // /
164
+ // / Implements BarrierAccessScopeFinder::Visitor
165
+ class BarrierAccessScopeFinder final {
166
+ using Impl = VisitBarrierAccessScopes<DataFlow, BarrierAccessScopeFinder>;
167
+ Context const &context;
168
+ Impl impl;
169
+ DataFlow &dataflow;
170
+ Optional<SmallVector<SILBasicBlock *, 16 >> cachedRoots;
171
+
172
+ public:
173
+ BarrierAccessScopeFinder (Context const &context, DataFlow &dataflow)
174
+ : context(context), impl(&context.function, dataflow, *this ),
175
+ dataflow (dataflow) {}
176
+
177
+ void find ();
178
+
179
+ private:
180
+ friend Impl;
181
+
182
+ ArrayRef<SILBasicBlock *> roots ();
183
+ bool isInRegion (SILBasicBlock *);
184
+ void visitBarrierAccessScope (BeginAccessInst *);
185
+ };
186
+
153
187
void DataFlow::run () {
154
188
reachability.initialize ();
189
+ BarrierAccessScopeFinder finder (context, *this );
190
+ finder.find ();
155
191
reachability.solve ();
156
192
reachability.findBarriers (barriers.instructions , barriers.phis ,
157
193
barriers.blocks );
@@ -165,6 +201,11 @@ DataFlow::classifyInstruction(SILInstruction *instruction) {
165
201
if (uses.users .contains (instruction)) {
166
202
return Classification::Barrier;
167
203
}
204
+ if (auto *eai = dyn_cast<EndAccessInst>(instruction)) {
205
+ return barrierAccessScopes.contains (eai->getBeginAccess ())
206
+ ? Classification::Barrier
207
+ : Classification::Other;
208
+ }
168
209
if (isDeinitBarrier (instruction)) {
169
210
return Classification::Barrier;
170
211
}
@@ -204,6 +245,33 @@ Optional<DataFlow::Effect> DataFlow::effectForPhi(SILBasicBlock *block) {
204
245
return isBarrier ? Optional<Effect>{Effect::Kill} : llvm::None;
205
246
}
206
247
248
+ void BarrierAccessScopeFinder::find () { impl.visit (); }
249
+
250
+ ArrayRef<SILBasicBlock *> BarrierAccessScopeFinder::roots () {
251
+ if (cachedRoots)
252
+ return *cachedRoots;
253
+
254
+ cachedRoots = SmallVector<SILBasicBlock *, 16 >{};
255
+ BasicBlockSet seenRoots (&context.function );
256
+ for (auto *gen : dataflow.gens ()) {
257
+ seenRoots.insert (gen->getParent ());
258
+ cachedRoots->push_back (gen->getParent ());
259
+ }
260
+
261
+ return *cachedRoots;
262
+ }
263
+
264
+ bool BarrierAccessScopeFinder::isInRegion (SILBasicBlock *block) {
265
+ return dataflow.result .discoveredBlocks .contains (block);
266
+ }
267
+
268
+ void BarrierAccessScopeFinder::visitBarrierAccessScope (BeginAccessInst *bai) {
269
+ dataflow.barrierAccessScopes .insert (bai);
270
+ for (auto *eai : bai->getEndAccesses ()) {
271
+ dataflow.reachability .addKill (eai);
272
+ }
273
+ }
274
+
207
275
// / Hoist the destroy_values of %value.
208
276
class Rewriter final {
209
277
Context &context;
0 commit comments