|
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