Skip to content

Commit 505ac43

Browse files
committed
[feedback]: move logic to caller & add utilities
1 parent 6d5515b commit 505ac43

File tree

4 files changed

+47
-28
lines changed

4 files changed

+47
-28
lines changed

include/swift/SIL/BasicBlockUtils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ class DeadEndBlocks {
8585
return reachableBlocks.count(block) == 0;
8686
}
8787

88+
/// Returns true iff none of the function's blocks is a dead-end.
89+
/// Note: This value is not cached, and may visit all the function's blocks
90+
/// to produce its return value.
91+
bool isEmpty() {
92+
return llvm::none_of(
93+
*f, [this](const SILBasicBlock &BB) { return isDeadEnd(&BB); });
94+
}
95+
8896
/// Return true if this dead end blocks has computed its internal cache yet.
8997
///
9098
/// Used to determine if we need to verify a DeadEndBlocks.

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ class CanonicalizeOSSALifetime final {
237237
/// copies.
238238
const MaximizeLifetime_t maximizeLifetime;
239239

240+
/// When non-null, indicates whether dead-end blocks are assumed to be present
241+
/// in the current function.
242+
/// Set in `::canonicalizeValueLifetime`, and reset in `::clear`.
243+
std::optional<bool> hasDeadEnd = std::nullopt;
244+
240245
SILFunction *function;
241246

242247
// If present, will be used to ensure that the lifetime is not shortened to
@@ -375,6 +380,8 @@ class CanonicalizeOSSALifetime final {
375380
}
376381

377382
void clear() {
383+
hasDeadEnd.reset();
384+
378385
// Clear the access blocks analysis pointer in case the client invalidates
379386
// the analysis. If the client did, the analysis will be recomputed in
380387
// extendLivenessThroughOverlappingAccess; if it didn't, the analysis
@@ -411,8 +418,10 @@ class CanonicalizeOSSALifetime final {
411418
/// This only deletes instructions within \p def's extended lifetime. Use
412419
/// InstructionDeleter::cleanUpDeadInstructions() to recursively delete dead
413420
/// operands.
414-
bool canonicalizeValueLifetime(
415-
SILValue def, ArrayRef<SILInstruction *> lexicalLifetimeEnds = {});
421+
bool
422+
canonicalizeValueLifetime(SILValue def,
423+
ArrayRef<SILInstruction *> lexicalLifetimeEnds = {},
424+
bool assumeDeadEnds = true);
416425

417426
/// Compute the liveness information for \p def. But do not do any rewriting
418427
/// or computation of boundaries.
@@ -475,6 +484,13 @@ class CanonicalizeOSSALifetime final {
475484
return !endingLifetimeAtExplicitEnds();
476485
}
477486

487+
bool hasAnyDeadEnds() const {
488+
if (hasDeadEnd)
489+
return *hasDeadEnd;
490+
491+
return !deadEndBlocksAnalysis->get(function)->isEmpty();
492+
}
493+
478494
bool respectsDeinitBarriers() const {
479495
if (!currentDef->isLexical())
480496
return false;

lib/SILOptimizer/Transforms/CopyPropagation.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,18 @@ void CopyPropagation::propagateCopies(
489489
pruneDebug, MaximizeLifetime_t(!getFunction()->shouldOptimize()),
490490
getFunction(), accessBlockAnalysis, deadEndBlocksAnalysis, domTree,
491491
calleeAnalysis, deleter);
492+
493+
// Utility to canonicalize a value lifetime that lazily checks if dead
494+
// end blocks are present
495+
std::optional<bool> hasDeadEndBlocks = std::nullopt;
496+
auto canonicalizeValueLifetime = [&](SILValue def) -> bool {
497+
if (!hasDeadEndBlocks.has_value())
498+
hasDeadEndBlocks = !deadEndBlocksAnalysis->get(getFunction())->isEmpty();
499+
500+
return canonicalizer.canonicalizeValueLifetime(
501+
def, /*lexicalLifetimeEnd*/ {}, hasDeadEndBlocks.value());
502+
};
503+
492504
// NOTE: We assume that the function is in reverse post order so visiting the
493505
// blocks and pushing begin_borrows as we see them and then popping them
494506
// off the end will result in shrinking inner borrow scopes first.
@@ -520,7 +532,7 @@ void CopyPropagation::propagateCopies(
520532

521533
if (!continueWithNextSubpassRun(borrowee))
522534
return;
523-
auto canonicalized = canonicalizer.canonicalizeValueLifetime(borrowee);
535+
auto canonicalized = canonicalizeValueLifetime(borrowee);
524536
if (!canonicalized && !firstRun)
525537
break;
526538

@@ -529,7 +541,7 @@ void CopyPropagation::propagateCopies(
529541
auto folded = foldDestroysOfCopiedLexicalBorrow(bbi, *domTree, deleter);
530542
if (!folded)
531543
break;
532-
auto hoisted = canonicalizer.canonicalizeValueLifetime(folded);
544+
auto hoisted = canonicalizeValueLifetime(folded);
533545
// Keep running even if the new move's destroys can't be hoisted.
534546
(void)hoisted;
535547
if (!continueWithNextSubpassRun(folded))
@@ -547,7 +559,7 @@ void CopyPropagation::propagateCopies(
547559
if (argument->getOwnershipKind() == OwnershipKind::Owned) {
548560
if (!continueWithNextSubpassRun(argument))
549561
return;
550-
canonicalizer.canonicalizeValueLifetime(argument);
562+
canonicalizeValueLifetime(argument);
551563
}
552564
}
553565
deleter.cleanupDeadInstructions();
@@ -586,7 +598,7 @@ void CopyPropagation::propagateCopies(
586598
for (auto result : ownedForward->getResults()) {
587599
if (!continueWithNextSubpassRun(result))
588600
return;
589-
canonicalizer.canonicalizeValueLifetime(result);
601+
canonicalizeValueLifetime(result);
590602
}
591603
if (!continueWithNextSubpassRun(ownedForward))
592604
return;
@@ -631,7 +643,7 @@ void CopyPropagation::propagateCopies(
631643
SILValue def = defWorklist.ownedValues.pop_back_val();
632644
if (!continueWithNextSubpassRun(def))
633645
return;
634-
auto canonicalized = canonicalizer.canonicalizeValueLifetime(def);
646+
auto canonicalized = canonicalizeValueLifetime(def);
635647
if (!canonicalized)
636648
continue;
637649
// Copies of borrowed values may be dead.

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,6 @@ static bool isDestroyOfCopyOf(SILInstruction *instruction, SILValue def) {
125125
return false;
126126
}
127127

128-
static bool
129-
functionHasAnyDeadEnds(SILFunction *function,
130-
DeadEndBlocksAnalysis *deadEndBlocksAnalysis) {
131-
bool hasAnyDeadEnds = false;
132-
auto *deadEnds = deadEndBlocksAnalysis->get(function);
133-
for (auto &bb : *function) {
134-
hasAnyDeadEnds = deadEnds->isDeadEnd(&bb);
135-
if (hasAnyDeadEnds)
136-
break;
137-
}
138-
return hasAnyDeadEnds;
139-
}
140-
141128
//===----------------------------------------------------------------------===//
142129
// MARK: Step 1. Compute pruned liveness
143130
//===----------------------------------------------------------------------===//
@@ -314,9 +301,6 @@ void CanonicalizeOSSALifetime::extendLexicalLivenessToDeadEnds() {
314301
directLiveness.initializeDef(getCurrentDef());
315302
directLiveness.computeSimple();
316303

317-
if (!functionHasAnyDeadEnds(function, deadEndBlocksAnalysis))
318-
return;
319-
320304
OSSALifetimeCompletion::visitAvailabilityBoundary(
321305
getCurrentDef(), directLiveness, [&](auto *unreachable, auto end) {
322306
if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
@@ -390,9 +374,6 @@ void CanonicalizeOSSALifetime::extendLivenessToDeadEnds() {
390374
completeLiveness.updateForUse(pair.first, /*lifetimeEnding=*/false);
391375
}
392376

393-
if (!functionHasAnyDeadEnds(function, deadEndBlocksAnalysis))
394-
return;
395-
396377
OSSALifetimeCompletion::visitAvailabilityBoundary(
397378
getCurrentDef(), completeLiveness, [&](auto *unreachable, auto end) {
398379
if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
@@ -1426,7 +1407,7 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
14261407
clear();
14271408
return false;
14281409
}
1429-
if (respectsDeadEnds()) {
1410+
if (respectsDeadEnds() && hasAnyDeadEnds()) {
14301411
if (respectsDeinitBarriers()) {
14311412
extendLexicalLivenessToDeadEnds();
14321413
}
@@ -1472,8 +1453,10 @@ void CanonicalizeOSSALifetime::rewriteLifetimes() {
14721453

14731454
/// Canonicalize a single extended owned lifetime.
14741455
bool CanonicalizeOSSALifetime::canonicalizeValueLifetime(
1475-
SILValue def, ArrayRef<SILInstruction *> lexicalLifetimeEnds) {
1456+
SILValue def, ArrayRef<SILInstruction *> lexicalLifetimeEnds,
1457+
bool assumeDeadEnds) {
14761458
LivenessState livenessState(*this, def, lexicalLifetimeEnds);
1459+
hasDeadEnd = assumeDeadEnds;
14771460

14781461
// Don't canonicalize the lifetimes of values of move-only type. According to
14791462
// language rules, they are fixed.

0 commit comments

Comments
 (0)