Skip to content

Commit 1901aa7

Browse files
Merge pull request #75422 from nate-chandler/opt/20240722/1
[NFC] PrunedLiveness: Clarified boundary API.
2 parents 1527139 + 042241a commit 1901aa7

14 files changed

+49
-34
lines changed

include/swift/SIL/PrunedLiveness.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,10 +617,13 @@ class PrunedLiveRange : public PrunedLiveness {
617617
bool isAvailableOut(SILBasicBlock *block, DeadEndBlocks &deadEndBlocks) const;
618618
bool isInstructionAvailable(SILInstruction *user,
619619
DeadEndBlocks &deadEndBlocks) const;
620+
/// Whether \p user is within the liveness boundary (never extended into
621+
/// dead-end regions).
622+
bool isWithinLivenessBoundary(SILInstruction *inst) const;
620623
/// Whether \p user is within the boundary extended from live regions into
621624
/// dead-end regions up to the availability boundary.
622625
bool isWithinExtendedBoundary(SILInstruction *user,
623-
DeadEndBlocks *deadEndBlocks) const;
626+
DeadEndBlocks &deadEndBlocks) const;
624627

625628
public:
626629
/// Add \p inst to liveness which uses the def as indicated by \p usage.
@@ -660,7 +663,12 @@ class PrunedLiveRange : public PrunedLiveness {
660663

661664
/// Check if \p inst occurs in between the definition this def and the
662665
/// liveness boundary.
663-
bool isWithinBoundary(SILInstruction *inst) const;
666+
///
667+
/// Pass \p deadEndBlocks when the defs' lifetime isn't known to be complete.
668+
/// When passed, the liveness boundary is understood to extend into dead-end
669+
/// regions.
670+
bool isWithinBoundary(SILInstruction *inst,
671+
DeadEndBlocks *deadEndBlocks) const;
664672

665673
/// Returns true when all \p uses are between this def and the liveness
666674
/// boundary \p deadEndBlocks is optional.

lib/SIL/Utils/OSSALifetimeCompletion.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ static void visitUsersOutsideLinearLivenessBoundary(
131131
continue;
132132
}
133133
auto *user = pair.first;
134-
if (linearLiveness.getLiveness().isWithinBoundary(user)) {
134+
if (linearLiveness.getLiveness().isWithinBoundary(
135+
user, /*deadEndBlocks=*/nullptr)) {
135136
continue;
136137
}
137138
visitor(user);

lib/SIL/Utils/PrunedLiveness.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ static FunctionTest SSAUseLivenessTest("ssa_use_liveness", [](auto &function,
501501
} // end namespace swift::test
502502

503503
template <typename LivenessWithDefs>
504-
bool PrunedLiveRange<LivenessWithDefs>::isWithinBoundary(
504+
bool PrunedLiveRange<LivenessWithDefs>::isWithinLivenessBoundary(
505505
SILInstruction *inst) const {
506506
assert(asImpl().isInitialized());
507507

@@ -574,8 +574,18 @@ bool PrunedLiveRange<LivenessWithDefs>::isInstructionAvailable(
574574
}
575575

576576
template <typename LivenessWithDefs>
577-
bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
577+
bool PrunedLiveRange<LivenessWithDefs>::isWithinBoundary(
578578
SILInstruction *inst, DeadEndBlocks *deadEndBlocks) const {
579+
if (deadEndBlocks) {
580+
return asImpl().isWithinExtendedBoundary(inst, *deadEndBlocks);
581+
} else {
582+
return asImpl().isWithinLivenessBoundary(inst);
583+
}
584+
}
585+
586+
template <typename LivenessWithDefs>
587+
bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
588+
SILInstruction *inst, DeadEndBlocks &deadEndBlocks) const {
579589
// A value has a pruned live region, a live region and an available region.
580590
// (Note: PrunedLiveness does not distinguish between the pruned live region
581591
// and the live region; the pruned live region coincides with the live region
@@ -628,21 +638,13 @@ bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
628638
// That this region is of interest is another result of lacking complete
629639
// OSSA lifetimes.
630640

631-
if (asImpl().isWithinBoundary(inst)) {
641+
if (asImpl().isWithinLivenessBoundary(inst)) {
632642
// The extended region is a superset of the pruned live region.
633643
return true;
634644
}
635645

636-
if (!deadEndBlocks) {
637-
// Without knowledge of the dead-end region, the extended region can't be
638-
// determined. It could, of course, be rediscovered here, but that would
639-
// be silly; instead, allowing a nullable pointer provides a mechanism for
640-
// the client to indicate what invariants hold. Specifically, omitting
641-
// dead-end blocks is equivalent to asserting that lifetimes are complete.
642-
return false;
643-
}
644646
SILBasicBlock *parent = inst->getParent();
645-
if (!deadEndBlocks->isDeadEnd(parent)) {
647+
if (!deadEndBlocks.isDeadEnd(parent)) {
646648
// The extended region intersected with the non-dead-end region is equal to
647649
// the pruned live region.
648650
return false;
@@ -652,7 +654,7 @@ bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
652654
break;
653655
case PrunedLiveBlocks::LiveWithin:
654656
// Dead defs may result in LiveWithin but AvailableOut blocks.
655-
return isInstructionAvailable(inst, *deadEndBlocks);
657+
return isInstructionAvailable(inst, deadEndBlocks);
656658
case PrunedLiveBlocks::LiveOut:
657659
// The instruction is not within the boundary, but its parent is LiveOut;
658660
// therefore it must be a def block.
@@ -687,7 +689,7 @@ bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
687689
worklist.push(parent);
688690
while (auto *block = worklist.pop()) {
689691
auto isLive = liveBlocks.getBlockLiveness(block);
690-
if (!deadEndBlocks->isDeadEnd(block)) {
692+
if (!deadEndBlocks.isDeadEnd(block)) {
691693
// The first block beyond the dead-end region has been reached.
692694
if (isLive != PrunedLiveBlocks::LiveOut) {
693695
// Cases (2) above.
@@ -706,7 +708,7 @@ bool PrunedLiveRange<LivenessWithDefs>::isWithinExtendedBoundary(
706708
case PrunedLiveBlocks::LiveWithin:
707709
// Availability may have ended in this block. Check whether the block is
708710
// "AvailableOut".
709-
if (!isAvailableOut(block, *deadEndBlocks)) {
711+
if (!isAvailableOut(block, deadEndBlocks)) {
710712
// Case (1) above.
711713
return false;
712714
}
@@ -799,7 +801,7 @@ bool PrunedLiveRange<LivenessWithDefs>::areUsesWithinBoundary(
799801

800802
for (auto *use : uses) {
801803
auto *user = use->getUser();
802-
if (!isWithinExtendedBoundary(user, deadEndBlocks))
804+
if (!isWithinBoundary(user, deadEndBlocks))
803805
return false;
804806
}
805807
return true;
@@ -812,7 +814,7 @@ bool PrunedLiveRange<LivenessWithDefs>::areUsesOutsideBoundary(
812814

813815
for (auto *use : uses) {
814816
auto *user = use->getUser();
815-
if (isWithinExtendedBoundary(user, deadEndBlocks))
817+
if (isWithinBoundary(user, deadEndBlocks))
816818
return false;
817819
}
818820
return true;

lib/SIL/Utils/ScopedAddressUtils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ bool swift::hasOtherStoreBorrowsInLifetime(StoreBorrowInst *storeBorrow,
202202

203203
for (auto *otherStoreBorrow : otherStoreBorrows) {
204204
// Return true, if otherStoreBorrow was in \p storeBorrow's scope
205-
if (liveness->isWithinBoundary(otherStoreBorrow)) {
205+
if (liveness->isWithinBoundary(otherStoreBorrow,
206+
/*deadEndBlocks=*/nullptr)) {
206207
return true;
207208
}
208209
}

lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ bool LoadBorrowImmutabilityAnalysis::isImmutableInScope(
337337
continue;
338338
}
339339

340-
if (borrowLiveness.isWithinBoundary(write)) {
340+
if (borrowLiveness.isWithinBoundary(write, /*deadEndBlocks=*/nullptr)) {
341341
llvm::errs() << "Write: " << *write;
342342
return false;
343343
}

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ bool SILValueOwnershipChecker::checkDeadEnds(
516516
}
517517
auto allWithinBoundary = true;
518518
for (auto *use : regularUses) {
519-
if (!liveness.isWithinBoundary(use->getUser())) {
519+
if (!liveness.isWithinBoundary(use->getUser(), /*deadEndBlocks=*/nullptr)) {
520520
allWithinBoundary |= errorBuilder.handleMalformedSIL([&] {
521521
llvm::errs()
522522
<< "Owned value without lifetime ending uses whose regular use "

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2714,7 +2714,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27142714
LinearLiveness::DoNotIncludeExtensions);
27152715
linearLiveness.compute();
27162716
auto &liveness = linearLiveness.getLiveness();
2717-
require(!liveness.isWithinBoundary(I),
2717+
require(!liveness.isWithinBoundary(I, /*deadEndBlocks=*/nullptr),
27182718
"extend_lifetime use within unextended linear liveness boundary!?");
27192719
PrunedLivenessBoundary boundary;
27202720
liveness.computeBoundary(boundary);
@@ -2789,7 +2789,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27892789
if (scopedAddress.isScopeEndingUse(use)) {
27902790
continue;
27912791
}
2792-
if (!scopedAddressLiveness->isWithinBoundary(user)) {
2792+
if (!scopedAddressLiveness->isWithinBoundary(user,
2793+
/*deadEndBlocks=*/nullptr)) {
27932794
llvm::errs() << "User found outside scope: " << *user;
27942795
return false;
27952796
}

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ static bool isStoreCopy(SILValue value) {
364364
if (summary.innerBorrowKind != InnerBorrowKind::Contained) {
365365
return true;
366366
}
367-
if (!liveness.isWithinBoundary(storeInst)) {
367+
if (!liveness.isWithinBoundary(storeInst, /*deadEndBlocks=*/nullptr)) {
368368
return true;
369369
}
370370
return false;

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,8 @@ static SILValue tryRewriteToPartialApplyStack(
892892
if (!origUse->getUser()->mayWriteToMemory()) {
893893
return true;
894894
}
895-
if (closureLiveness.isWithinBoundary(origUse->getUser())) {
895+
if (closureLiveness.isWithinBoundary(origUse->getUser(),
896+
/*deadEndBlocks=*/nullptr)) {
896897
origIsUnmodifiedDuringClosureLifetime = false;
897898
LLVM_DEBUG(llvm::dbgs() << "-- original has other possibly writing "
898899
"use during closure lifetime\n";

lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableValuesChecker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ bool ConsumeOperatorCopyableValuesChecker::check() {
499499
mvi->setAllowsDiagnostics(false);
500500

501501
LLVM_DEBUG(llvm::dbgs() << "Move Value: " << *mvi);
502-
if (livenessInfo.liveness->isWithinBoundary(mvi)) {
502+
if (livenessInfo.liveness->isWithinBoundary(
503+
mvi, /*deadEndBlocks=*/nullptr)) {
503504
LLVM_DEBUG(llvm::dbgs() << " WithinBoundary: Yes!\n");
504505
emitDiagnosticForMove(lexicalValue, varName, mvi);
505506
} else {

lib/SILOptimizer/Mandatory/DiagnoseLifetimeIssues.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static bool isOutOfLifetime(SILInstruction *inst, SSAPrunedLiveness &liveness) {
322322
// impossible that a use of the object is not a potential load. So we would
323323
// always see a potential load if the lifetime of the object goes beyond the
324324
// store_weak.
325-
return !liveness.isWithinBoundary(inst);
325+
return !liveness.isWithinBoundary(inst, /*deadEndBlocks=*/nullptr);
326326
}
327327

328328
/// Reports a warning if the stored object \p storedObj is never loaded within

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,8 +2052,8 @@ struct GatherUsesVisitor : public TransitiveAddressWalker<GatherUsesVisitor> {
20522052
liveness->initializeDef(bai);
20532053
liveness->computeSimple();
20542054
for (auto *consumingUse : li->getConsumingUses()) {
2055-
if (!liveness->areUsesWithinBoundary(
2056-
{consumingUse},
2055+
if (!liveness->isWithinBoundary(
2056+
consumingUse->getUser(),
20572057
moveChecker.deba->get(consumingUse->getFunction()))) {
20582058
diagnosticEmitter.emitAddressExclusivityHazardDiagnostic(
20592059
markedValue, consumingUse->getUser());

lib/SILOptimizer/Mandatory/ReferenceBindingTransform.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ struct ValidateAllUsesWithinLiveness : public AccessUseVisitor {
111111
if (isa<EndAccessInst>(user))
112112
return true;
113113

114-
if (liveness.isWithinBoundary(user)) {
114+
if (liveness.isWithinBoundary(user, /*deadEndBlocks=*/nullptr)) {
115115
LLVM_DEBUG(llvm::dbgs() << "User in boundary: " << *user);
116116
diagnose(op->getUser(),
117117
diag::sil_referencebinding_src_used_within_inout_scope);

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ void CanonicalizeOSSALifetime::extendLivenessToDeadEnds() {
259259
SSAPrunedLiveness completeLiveness(*liveness, &discoveredBlocks);
260260

261261
for (auto destroy : destroys) {
262-
if (liveness->isWithinBoundary(destroy))
262+
if (liveness->isWithinBoundary(destroy, /*deadEndBlocks=*/nullptr))
263263
continue;
264264
completeLiveness.updateForUse(destroy, /*lifetimeEnding*/ true);
265265
}
@@ -592,7 +592,7 @@ void CanonicalizeOSSALifetime::visitExtendedUnconsumedBoundary(
592592

593593
#ifndef NDEBUG
594594
for (auto *consume : consumes) {
595-
assert(!liveness->isWithinBoundary(consume));
595+
assert(!liveness->isWithinBoundary(consume, /*deadEndBlocks=*/nullptr));
596596
}
597597
#endif
598598

0 commit comments

Comments
 (0)