2020#include " swift/SIL/SILInstruction.h"
2121#include " swift/SIL/SILValue.h"
2222#include " swift/SILOptimizer/Analysis/Reachability.h"
23+ #include " swift/SILOptimizer/Analysis/VisitBarrierAccessScopes.h"
2324#include " swift/SILOptimizer/Utils/CanonicalizeBorrowScope.h"
2425#include " swift/SILOptimizer/Utils/InstOptUtils.h"
2526#include " swift/SILOptimizer/Utils/InstructionDeleter.h"
@@ -112,11 +113,14 @@ struct DeinitBarriers final {
112113 DeinitBarriers &operator =(DeinitBarriers const &) = delete ;
113114};
114115
116+ class BarrierAccessScopeFinder ;
117+
115118// / Works backwards from the current location of destroy_values to the earliest
116119// / place they can be hoisted to.
117120// /
118121// / Implements IterativeBackwardReachability::Effects
119122// / Implements IterativeBackwardReachability::bindBarriers::Visitor
123+ // / Implements VisitBarrierAccessScopes::Effects
120124class Dataflow final {
121125 using Reachability = IterativeBackwardReachability<Dataflow>;
122126 using Effect = Reachability::Effect;
@@ -125,6 +129,7 @@ class Dataflow final {
125129 DeinitBarriers &barriers;
126130 Reachability::Result result;
127131 Reachability reachability;
132+ SmallPtrSet<BeginAccessInst *, 8 > barrierAccessScopes;
128133
129134 enum class Classification { Barrier, Other };
130135
@@ -140,18 +145,29 @@ class Dataflow final {
140145
141146private:
142147 friend Reachability;
148+ friend class BarrierAccessScopeFinder ;
149+ friend class VisitBarrierAccessScopes <Dataflow, BarrierAccessScopeFinder>;
143150
144151 Classification classifyInstruction (SILInstruction *);
145152
146153 bool classificationIsBarrier (Classification);
147154
148155 // / IterativeBackwardReachability::Effects
156+ // / VisitBarrierAccessScopes::Effects
149157
150158 ArrayRef<SILInstruction *> gens () { return uses.ends ; }
151159
152160 Effect effectForInstruction (SILInstruction *);
153161 Effect effectForPhi (SILBasicBlock *);
154162
163+ // / VisitBarrierAccessScopes::Effects
164+
165+ auto localGens () { return result.localGens ; }
166+
167+ bool isLocalGen (SILInstruction *instruction) {
168+ return result.localGens .contains (instruction);
169+ }
170+
155171 // / IterativeBackwardReachability::bindBarriers::Visitor
156172
157173 void visitBarrierInstruction (SILInstruction *instruction) {
@@ -173,6 +189,11 @@ Dataflow::classifyInstruction(SILInstruction *instruction) {
173189 if (uses.users .contains (instruction)) {
174190 return Classification::Barrier;
175191 }
192+ if (auto *eai = dyn_cast<EndAccessInst>(instruction)) {
193+ return barrierAccessScopes.contains (eai->getBeginAccess ())
194+ ? Classification::Barrier
195+ : Classification::Other;
196+ }
176197 if (isDeinitBarrier (instruction)) {
177198 return Classification::Barrier;
178199 }
@@ -209,8 +230,41 @@ Dataflow::Effect Dataflow::effectForPhi(SILBasicBlock *block) {
209230 return isBarrier ? Effect::Kill () : Effect::NoEffect ();
210231}
211232
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+
212264void Dataflow::run () {
213265 reachability.initialize ();
266+ BarrierAccessScopeFinder finder (context, *this );
267+ finder.find ();
214268 reachability.solve ();
215269 reachability.findBarriers (*this );
216270}
0 commit comments