Skip to content

CopyPropagation: Avoid regenerating destroys. #39672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/swift/SILOptimizer/Utils/CanonicalOSSALifetime.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,8 @@ class CanonicalizeOSSALifetime {

void findOrInsertDestroys();

void insertDestroyOnCFGEdge(SILBasicBlock *predBB, SILBasicBlock *succBB,
bool needsPoison);
void findOrInsertDestroyOnCFGEdge(SILBasicBlock *predBB,
SILBasicBlock *succBB, bool needsPoison);

void rewriteCopies();

Expand Down
49 changes: 36 additions & 13 deletions lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,25 +343,48 @@ void CanonicalizeOSSALifetime::extendLivenessThroughOverlappingAccess() {
// liveness computed in Step 1.
//===----------------------------------------------------------------------===//

// Look past destroys and incidental uses to find a destroy on \p edgeBB that
// destroys \p def.
static DestroyValueInst *findDestroyOnCFGEdge(SILBasicBlock *edgeBB,
SILValue def) {
for (auto &inst : *edgeBB) {
if (isIncidentalUse(&inst))
continue;
if (auto *destroy = dyn_cast<DestroyValueInst>(&inst)) {
if (destroy->getOperand() == def)
return destroy;
continue;
}
break;
}
return nullptr;
}

/// The liveness boundary is at a CFG edge `predBB` -> `succBB`, meaning that
/// `currentDef` is live out of at least one other `predBB` successor.
///
/// Create and record a final destroy_value at the beginning of `succBB`
/// (assuming no critical edges).
void CanonicalizeOSSALifetime::insertDestroyOnCFGEdge(
SILBasicBlock *predBB, SILBasicBlock *succBB, bool needsPoison) {
///
/// Avoid deleting and recreating a destroy that was already placed on this
/// edge. Ignore any intervening destroys that may have been placed while
/// canonicalizing other values. This is especially important when
/// canonicalization is called within an iterative worklist such as SILCombine.
void CanonicalizeOSSALifetime::findOrInsertDestroyOnCFGEdge(
SILBasicBlock *predBB, SILBasicBlock *succBB, bool needsPoison) {

assert(succBB->getSinglePredecessorBlock() == predBB
&& "value is live-out on another predBB successor: critical edge?");

auto pos = succBB->begin();
// TODO: to improve debugability, consider advancing the poison position ahead
// of operations that are known not to access weak references.
SILBuilderWithScope builder(pos);
auto loc = RegularLocation::getAutoGeneratedLocation(pos->getLoc());
auto *di = builder.createDestroyValue(loc, currentDef, needsPoison);
getCallbacks().createdNewInst(di);

auto *di = findDestroyOnCFGEdge(succBB, currentDef);
if (!di) {
auto pos = succBB->begin();
// TODO: to improve debugability, consider advancing the poison position
// ahead of operations that are known not to access weak references.
SILBuilderWithScope builder(pos);
auto loc = RegularLocation::getAutoGeneratedLocation(pos->getLoc());
di = builder.createDestroyValue(loc, currentDef, needsPoison);
getCallbacks().createdNewInst(di);
}
consumes.recordFinalConsume(di);

++NumDestroysGenerated;
Expand Down Expand Up @@ -431,7 +454,7 @@ void CanonicalizeOSSALifetime::findOrInsertDestroyInBlock(SILBasicBlock *bb) {
// Insert a destroy after this non-consuming use.
if (isa<TermInst>(inst)) {
for (auto &succ : bb->getSuccessors()) {
insertDestroyOnCFGEdge(bb, succ, poisonRefsMode);
findOrInsertDestroyOnCFGEdge(bb, succ, poisonRefsMode);
}
} else {
if (existingDestroy) {
Expand Down Expand Up @@ -540,7 +563,7 @@ void CanonicalizeOSSALifetime::findOrInsertDestroys() {
// Continue searching upward to find the pruned liveness boundary.
for (auto *predBB : bb->getPredecessorBlocks()) {
if (liveness.getBlockLiveness(predBB) == PrunedLiveBlocks::LiveOut) {
insertDestroyOnCFGEdge(predBB, bb, poisonRefsMode);
findOrInsertDestroyOnCFGEdge(predBB, bb, poisonRefsMode);
} else {
if (poisonRefsMode) {
remnantLiveOutBlocks.insert(predBB);
Expand Down