Skip to content

Commit 304d2bb

Browse files
committed
[SSADestroyHoisting] Modifying ignores deinit barriers.
Restructured its DeinitBarrier's type a bit to avoid having to pass KnownStorageUses and ignoreDeinitBarriers around too much.
1 parent 092b6f2 commit 304d2bb

File tree

1 file changed

+41
-34
lines changed

1 file changed

+41
-34
lines changed

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -204,41 +204,40 @@ class DeinitBarriers {
204204
// Debug instructions that are no longer within this lifetime after shrinking.
205205
SmallVector<SILInstruction *, 4> deadUsers;
206206

207-
explicit DeinitBarriers(SILFunction *function)
208-
: destroyReachesBeginBlocks(function),
209-
destroyReachesEndBlocks(function)
210-
{}
211-
212-
void compute(const KnownStorageUses &knownUses) {
213-
DestroyReachability(knownUses, *this).solveBackward();
207+
explicit DeinitBarriers(bool ignoreDeinitBarriers,
208+
const KnownStorageUses &knownUses,
209+
SILFunction *function)
210+
: destroyReachesBeginBlocks(function), destroyReachesEndBlocks(function),
211+
ignoreDeinitBarriers(ignoreDeinitBarriers), knownUses(knownUses) {
212+
auto rootValue = knownUses.getStorage().getRoot();
213+
assert(rootValue && "HoistDestroys requires a single storage root");
214+
// null for function args
215+
storageDefInst = rootValue->getDefiningInstruction();
214216
}
215217

218+
void compute() { DestroyReachability(*this).solveBackward(); }
219+
216220
private:
217221
DeinitBarriers(DeinitBarriers const &) = delete;
218222
DeinitBarriers &operator=(DeinitBarriers const &) = delete;
219223

220-
// Conforms to BackwardReachability::BlockReachability
224+
bool ignoreDeinitBarriers;
225+
const KnownStorageUses &knownUses;
226+
SILInstruction *storageDefInst = nullptr;
227+
228+
// Implements BackwardReachability::BlockReachability
221229
class DestroyReachability {
222-
const KnownStorageUses &knownUses;
223230
DeinitBarriers &result;
224-
SILInstruction *storageDefInst = nullptr; // null for function args
225231

226232
enum class Classification { DeadUser, Barrier, Other };
227233

228234
BackwardReachability<DestroyReachability> reachability;
229235

230236
public:
231-
DestroyReachability(const KnownStorageUses &knownUses,
232-
DeinitBarriers &result)
233-
: knownUses(knownUses), result(result),
234-
reachability(knownUses.getFunction(), *this) {
235-
236-
auto rootValue = knownUses.getStorage().getRoot();
237-
assert(rootValue && "HoistDestroys requires a single storage root");
238-
storageDefInst = rootValue->getDefiningInstruction();
239-
237+
DestroyReachability(DeinitBarriers &result)
238+
: result(result), reachability(result.knownUses.getFunction(), *this) {
240239
// Seed backward reachability with destroy points.
241-
for (SILInstruction *destroy : knownUses.originalDestroys) {
240+
for (SILInstruction *destroy : result.knownUses.originalDestroys) {
242241
reachability.initLastUse(destroy);
243242
}
244243
}
@@ -272,16 +271,16 @@ class DeinitBarriers {
272271

273272
DeinitBarriers::DestroyReachability::Classification
274273
DeinitBarriers::DestroyReachability::classifyInstruction(SILInstruction *inst) {
275-
if (knownUses.debugInsts.contains(inst)) {
274+
if (result.knownUses.debugInsts.contains(inst)) {
276275
return Classification::DeadUser;
277276
}
278-
if (inst == storageDefInst) {
277+
if (inst == result.storageDefInst) {
279278
return Classification::Barrier;
280279
}
281-
if (knownUses.storageUsers.contains(inst)) {
280+
if (result.knownUses.storageUsers.contains(inst)) {
282281
return Classification::Barrier;
283282
}
284-
if (isDeinitBarrier(inst)) {
283+
if (!result.ignoreDeinitBarriers && isDeinitBarrier(inst)) {
285284
return Classification::Barrier;
286285
}
287286
return Classification::Other;
@@ -341,6 +340,7 @@ bool DeinitBarriers::DestroyReachability::checkReachablePhiBarrier(
341340
/// object.
342341
class HoistDestroys {
343342
SILValue storageRoot;
343+
bool ignoreDeinitBarriers;
344344
InstructionDeleter &deleter;
345345

346346
// Book-keeping for the rewriting stage.
@@ -349,9 +349,10 @@ class HoistDestroys {
349349
BasicBlockSetVector destroyMergeBlocks;
350350

351351
public:
352-
HoistDestroys(SILValue storageRoot, InstructionDeleter &deleter)
353-
: storageRoot(storageRoot), deleter(deleter),
354-
destroyMergeBlocks(getFunction()) {}
352+
HoistDestroys(SILValue storageRoot, bool ignoreDeinitBarriers,
353+
InstructionDeleter &deleter)
354+
: storageRoot(storageRoot), ignoreDeinitBarriers(ignoreDeinitBarriers),
355+
deleter(deleter), destroyMergeBlocks(getFunction()) {}
355356

356357
bool perform();
357358

@@ -386,8 +387,8 @@ bool HoistDestroys::perform() {
386387
if (!knownUses.findUses())
387388
return false;
388389

389-
DeinitBarriers deinitBarriers(getFunction());
390-
deinitBarriers.compute(knownUses);
390+
DeinitBarriers deinitBarriers(ignoreDeinitBarriers, knownUses, getFunction());
391+
deinitBarriers.compute();
391392

392393
// No SIL changes happen before rewriting.
393394
return rewriteDestroys(knownUses, deinitBarriers);
@@ -530,7 +531,8 @@ void HoistDestroys::mergeDestroys(SILBasicBlock *mergeBlock) {
530531
// Top-Level API
531532
// =============================================================================
532533

533-
bool hoistDestroys(SILValue root, InstructionDeleter &deleter) {
534+
bool hoistDestroys(SILValue root, bool ignoreDeinitBarriers,
535+
InstructionDeleter &deleter) {
534536
LLVM_DEBUG(llvm::dbgs() << "Performing destroy hoisting on " << root);
535537

536538
SILFunction *function = root->getFunction();
@@ -540,7 +542,7 @@ bool hoistDestroys(SILValue root, InstructionDeleter &deleter) {
540542
// The algorithm assumes no critical edges.
541543
assert(function->hasOwnership() && "requires OSSA");
542544

543-
return HoistDestroys(root, deleter).perform();
545+
return HoistDestroys(root, ignoreDeinitBarriers, deleter).perform();
544546
}
545547

546548
// =============================================================================
@@ -607,18 +609,23 @@ void SSADestroyHoisting::run() {
607609
// the end will result in hoisting inner begin_access' destroy_addrs first.
608610
while (!bais.empty()) {
609611
auto *bai = bais.pop_back_val();
610-
changed |= hoistDestroys(bai, deleter);
612+
changed |= hoistDestroys(bai, /*ignoreDeinitBarriers=*/true, deleter);
611613
}
612614
// Alloc stacks always enclose their accesses.
613615
for (auto *asi : asis) {
614-
changed |= hoistDestroys(asi, deleter);
616+
changed |= hoistDestroys(asi, /*ignoreDeinitBarriers=*/false, deleter);
615617
}
616618
// Arguments enclose everything.
617619
for (auto *arg : getFunction()->getArguments()) {
618620
if (arg->getType().isAddress()) {
619-
changed |= hoistDestroys(arg, deleter);
621+
bool isInout = cast<SILFunctionArgument>(arg)
622+
->getArgumentConvention()
623+
.isInoutConvention();
624+
changed |= hoistDestroys(arg, /*ignoreDeinitBarriers=*/
625+
isInout, deleter);
620626
}
621627
}
628+
622629
if (changed) {
623630
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
624631
}

0 commit comments

Comments
 (0)