Skip to content

Commit 26853f4

Browse files
committed
[SSADestroyHoisting] Avoid second per-var dataflow.
In order to determine which end_access instructions are barriers to hoisting, a data flow which looks for access scopes containing barriers is run. Those scopes that do contain barriers are added to a set. When the second pass runs, the end_access instructions corresponding to scopes in that set (i.e. the ends of scopes which contain barriers) are treated as barriers. In the common case where there are no barrier access scopes, though, running two dataflows per variable is wasteful. Avoid that by just checking whether we found any scopes that are barriers. If we didn't, then we already visited all the barrier instructions and were told by BackwardReachability which blocks had reachable ends and begins. Tweaked the first data flow to record the barriers and the blocks in DeinitBarriers. In DeinitBarriers::compute, if no access scopes that are barriers were found, stop working. If any were found, clear what had been recorded so far and run the second data flow. In order to be able to clear everything, switched from using BasicBlockSet and BasicBlockSetVector to SmallPtrSet<SILBasicBlock *> and SmallPtrSetVector<SILBasicBlock *>.
1 parent e35261f commit 26853f4

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
#define DEBUG_TYPE "ssa-destroy-hoisting"
9191

9292
#include "swift/Basic/GraphNodeWorklist.h"
93+
#include "swift/Basic/SmallPtrSetVector.h"
9394
#include "swift/SIL/BasicBlockDatastructures.h"
9495
#include "swift/SIL/MemAccessUtils.h"
9596
#include "swift/SIL/SILBasicBlock.h"
@@ -192,11 +193,11 @@ class DeinitBarriers {
192193
public:
193194
// Data flow state: blocks whose beginning is backward reachable from a
194195
// destroy without first reaching a barrier or storage use.
195-
BasicBlockSetVector destroyReachesBeginBlocks;
196+
SmallPtrSetVector<SILBasicBlock *, 4> destroyReachesBeginBlocks;
196197

197198
// Data flow state: blocks whose end is backward reachable from a destroy
198199
// without first reaching a barrier or storage use.
199-
BasicBlockSet destroyReachesEndBlocks;
200+
SmallPtrSet<SILBasicBlock *, 4> destroyReachesEndBlocks;
200201

201202
// Deinit barriers or storage uses within a block, reachable from a destroy.
202203
SmallVector<SILInstruction *, 4> barriers;
@@ -215,8 +216,7 @@ class DeinitBarriers {
215216
explicit DeinitBarriers(bool ignoreDeinitBarriers,
216217
const KnownStorageUses &knownUses,
217218
SILFunction *function)
218-
: destroyReachesBeginBlocks(function), destroyReachesEndBlocks(function),
219-
ignoreDeinitBarriers(ignoreDeinitBarriers), knownUses(knownUses) {
219+
: ignoreDeinitBarriers(ignoreDeinitBarriers), knownUses(knownUses) {
220220
auto rootValue = knownUses.getStorage().getRoot();
221221
assert(rootValue && "HoistDestroys requires a single storage root");
222222
// null for function args
@@ -225,6 +225,12 @@ class DeinitBarriers {
225225

226226
void compute() {
227227
FindBarrierAccessScopes(*this).solveBackward();
228+
if (barrierAccessScopes.size() == 0)
229+
return;
230+
destroyReachesBeginBlocks.clear();
231+
destroyReachesEndBlocks.clear();
232+
barriers.clear();
233+
deadUsers.clear();
228234
DestroyReachability(*this).solveBackward();
229235
}
230236

@@ -289,7 +295,6 @@ class DeinitBarriers {
289295
// open access scopes in the block's predecessors.
290296
class FindBarrierAccessScopes {
291297
DeinitBarriers &result;
292-
BasicBlockSetVector destroyReachesBeginBlocks;
293298
llvm::DenseMap<SILBasicBlock *, llvm::SmallPtrSet<BeginAccessInst *, 2>>
294299
liveInAccessScopes;
295300
llvm::SmallPtrSet<BeginAccessInst *, 2> runningLiveAccessScopes;
@@ -298,9 +303,7 @@ class DeinitBarriers {
298303

299304
public:
300305
FindBarrierAccessScopes(DeinitBarriers &result)
301-
: result(result),
302-
destroyReachesBeginBlocks(result.knownUses.getFunction()),
303-
reachability(result.knownUses.getFunction(), *this) {
306+
: result(result), reachability(result.knownUses.getFunction(), *this) {
304307
// Seed backward reachability with destroy points.
305308
for (SILInstruction *destroy : result.knownUses.originalDestroys) {
306309
reachability.initLastUse(destroy);
@@ -314,17 +317,18 @@ class DeinitBarriers {
314317
}
315318

316319
bool hasReachableBegin(SILBasicBlock *block) {
317-
return destroyReachesBeginBlocks.contains(block);
320+
return result.destroyReachesBeginBlocks.contains(block);
318321
}
319322

320323
void markReachableBegin(SILBasicBlock *block) {
321-
destroyReachesBeginBlocks.insert(block);
324+
result.destroyReachesBeginBlocks.insert(block);
322325
if (!runningLiveAccessScopes.empty()) {
323326
liveInAccessScopes[block] = runningLiveAccessScopes;
324327
}
325328
}
326329

327330
void markReachableEnd(SILBasicBlock *block) {
331+
result.destroyReachesEndBlocks.insert(block);
328332
runningLiveAccessScopes.clear();
329333
for (auto *predecessor : block->getPredecessorBlocks()) {
330334
auto iterator = liveInAccessScopes.find(predecessor);
@@ -347,7 +351,9 @@ class DeinitBarriers {
347351
} else if (auto *bai = dyn_cast<BeginAccessInst>(inst)) {
348352
runningLiveAccessScopes.erase(bai);
349353
}
350-
bool isBarrier = result.isBarrier(inst);
354+
auto classification = result.classifyInstruction(inst);
355+
result.visitedInstruction(inst, classification);
356+
auto isBarrier = result.classificationIsBarrier(classification);
351357
if (isBarrier) {
352358
markLiveAccessScopesAsBarriers();
353359
}

0 commit comments

Comments
 (0)