|
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 VisitBarrierAccessScopes::Effects |
142 | 146 | class Dataflow final {
|
143 | 147 | public:
|
144 | 148 | using Reachability = IterativeBackwardReachability<Dataflow>;
|
@@ -167,19 +171,30 @@ 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 |
|
173 | 179 | bool classificationIsBarrier(Classification);
|
174 | 180 |
|
175 |
| - /// Implements IterativeBackwardReachability::Effects. |
| 181 | + /// IterativeBackwardReachability::Effects |
| 182 | + /// VisitBarrierAccessScopes::Effects |
176 | 183 |
|
177 | 184 | ArrayRef<SILInstruction *> gens() { return uses.ends; }
|
178 | 185 |
|
179 | 186 | Effect effectForInstruction(SILInstruction *);
|
180 | 187 |
|
181 | 188 | Effect effectForPhi(SILBasicBlock *);
|
182 | 189 |
|
| 190 | + /// VisitBarrierAccessScopes::Effects |
| 191 | + |
| 192 | + auto localGens() { return result.localGens; } |
| 193 | + |
| 194 | + bool isLocalGen(SILInstruction *instruction) { |
| 195 | + return result.localGens.contains(instruction); |
| 196 | + } |
| 197 | + |
183 | 198 | /// IterativeBackwardReachability::findBarrier::Visitor.
|
184 | 199 |
|
185 | 200 | void visitBarrierInstruction(SILInstruction *instruction) {
|
@@ -224,6 +239,11 @@ Dataflow::classifyInstruction(SILInstruction *instruction) {
|
224 | 239 | if (uses.users.contains(instruction)) {
|
225 | 240 | return Classification::Barrier;
|
226 | 241 | }
|
| 242 | + if (auto *eai = dyn_cast<EndAccessInst>(instruction)) { |
| 243 | + return barrierAccessScopes.contains(eai->getBeginAccess()) |
| 244 | + ? Classification::Barrier |
| 245 | + : Classification::Other; |
| 246 | + } |
227 | 247 | if (isDeinitBarrier(instruction)) {
|
228 | 248 | return Classification::Barrier;
|
229 | 249 | }
|
@@ -263,8 +283,43 @@ Dataflow::Effect Dataflow::effectForPhi(SILBasicBlock *block) {
|
263 | 283 | return isBarrier ? Effect::Kill() : Effect::NoEffect();
|
264 | 284 | }
|
265 | 285 |
|
| 286 | +/// Finds end_access instructions which are barriers to hoisting because the |
| 287 | +/// access scopes they contain barriers to hoisting. Hoisting end_borrows into |
| 288 | +/// such access scopes could introduce exclusivity violations. |
| 289 | +/// |
| 290 | +/// Implements BarrierAccessScopeFinder::Visitor |
| 291 | +class BarrierAccessScopeFinder final { |
| 292 | + using Impl = VisitBarrierAccessScopes<Dataflow, BarrierAccessScopeFinder>; |
| 293 | + Context const &context; |
| 294 | + Impl impl; |
| 295 | + Dataflow &dataflow; |
| 296 | + |
| 297 | +public: |
| 298 | + BarrierAccessScopeFinder(Context const &context, Dataflow &dataflow) |
| 299 | + : context(context), impl(&context.function, dataflow, *this), |
| 300 | + dataflow(dataflow) {} |
| 301 | + |
| 302 | + void find() { impl.visit(); } |
| 303 | + |
| 304 | +private: |
| 305 | + friend Impl; |
| 306 | + |
| 307 | + bool isInRegion(SILBasicBlock *block) { |
| 308 | + return dataflow.result.discoveredBlocks.contains(block); |
| 309 | + } |
| 310 | + |
| 311 | + void visitBarrierAccessScope(BeginAccessInst *bai) { |
| 312 | + dataflow.barrierAccessScopes.insert(bai); |
| 313 | + for (auto *eai : bai->getEndAccesses()) { |
| 314 | + dataflow.reachability.addKill(eai); |
| 315 | + } |
| 316 | + } |
| 317 | +}; |
| 318 | + |
266 | 319 | void Dataflow::run() {
|
267 | 320 | reachability.initialize();
|
| 321 | + BarrierAccessScopeFinder finder(context, *this); |
| 322 | + finder.find(); |
268 | 323 | reachability.solve();
|
269 | 324 | recordCopies = true;
|
270 | 325 | reachability.findBarriers(*this);
|
|
0 commit comments