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 VisitBarrierAccessScopes::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,18 +145,29 @@ 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
146
153
bool classificationIsBarrier (Classification);
147
154
148
155
// / IterativeBackwardReachability::Effects
156
+ // / VisitBarrierAccessScopes::Effects
149
157
150
158
ArrayRef<SILInstruction *> gens () { return uses.ends ; }
151
159
152
160
Effect effectForInstruction (SILInstruction *);
153
161
Effect effectForPhi (SILBasicBlock *);
154
162
163
+ // / VisitBarrierAccessScopes::Effects
164
+
165
+ auto localGens () { return result.localGens ; }
166
+
167
+ bool isLocalGen (SILInstruction *instruction) {
168
+ return result.localGens .contains (instruction);
169
+ }
170
+
155
171
// / IterativeBackwardReachability::bindBarriers::Visitor
156
172
157
173
void visitBarrierInstruction (SILInstruction *instruction) {
@@ -173,6 +189,11 @@ Dataflow::classifyInstruction(SILInstruction *instruction) {
173
189
if (uses.users .contains (instruction)) {
174
190
return Classification::Barrier;
175
191
}
192
+ if (auto *eai = dyn_cast<EndAccessInst>(instruction)) {
193
+ return barrierAccessScopes.contains (eai->getBeginAccess ())
194
+ ? Classification::Barrier
195
+ : Classification::Other;
196
+ }
176
197
if (isDeinitBarrier (instruction)) {
177
198
return Classification::Barrier;
178
199
}
@@ -209,8 +230,41 @@ Dataflow::Effect Dataflow::effectForPhi(SILBasicBlock *block) {
209
230
return isBarrier ? Effect::Kill () : Effect::NoEffect ();
210
231
}
211
232
233
+ // / Finds end_access instructions which are barriers to hoisting because the
234
+ // / access scopes they contain barriers to hoisting. Hoisting destroy_values
235
+ // / into such access scopes could introduce exclusivity violations.
236
+ // /
237
+ // / Implements BarrierAccessScopeFinder::Visitor
238
+ class BarrierAccessScopeFinder final {
239
+ using Impl = VisitBarrierAccessScopes<Dataflow, BarrierAccessScopeFinder>;
240
+ Impl impl;
241
+ Dataflow &dataflow;
242
+
243
+ public:
244
+ BarrierAccessScopeFinder (Context const &context, Dataflow &dataflow)
245
+ : impl(&context.function, dataflow, *this ), dataflow(dataflow) {}
246
+
247
+ void find () { impl.visit (); }
248
+
249
+ private:
250
+ friend Impl;
251
+
252
+ bool isInRegion (SILBasicBlock *block) {
253
+ return dataflow.result .discoveredBlocks .contains (block);
254
+ }
255
+
256
+ void visitBarrierAccessScope (BeginAccessInst *bai) {
257
+ dataflow.barrierAccessScopes .insert (bai);
258
+ for (auto *eai : bai->getEndAccesses ()) {
259
+ dataflow.reachability .addKill (eai);
260
+ }
261
+ }
262
+ };
263
+
212
264
void Dataflow::run () {
213
265
reachability.initialize ();
266
+ BarrierAccessScopeFinder finder (context, *this );
267
+ finder.find ();
214
268
reachability.solve ();
215
269
reachability.findBarriers (*this );
216
270
}
0 commit comments