Skip to content

Commit 45f1881

Browse files
committed
[CopyPropagation] Eliminate redundant moves.
SemanticARCOpts already eliminates move values that are redundant that block its optimizations. But it's always run after CopyPropagation. Because move_values divide copy-extended lifetimes, move_values obstruct lifetime canonicalization. If a move_value isn't separating lifetimes with different characteristics (specifically: lexicallity, escaping), then it is only obstructing lifetime canonicalization. Remove it before canonicalizing the lifetime of the moved-from value.
1 parent b33a14b commit 45f1881

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

lib/SILOptimizer/Transforms/CopyPropagation.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "swift/SIL/BasicBlockDatastructures.h"
4343
#include "swift/SIL/BasicBlockUtils.h"
4444
#include "swift/SIL/DebugUtils.h"
45+
#include "swift/SIL/OwnershipUtils.h"
4546
#include "swift/SIL/SILUndef.h"
4647
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
4748
#include "swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
@@ -263,6 +264,24 @@ static bool convertExtractsToDestructures(CanonicalDefWorklist &copiedDefs,
263264
return changed;
264265
}
265266

267+
//===----------------------------------------------------------------------===//
268+
// MARK: Eliminate redundant moves
269+
//===----------------------------------------------------------------------===//
270+
271+
/// If the specified move_value is redundant (there's no benefit to separating
272+
/// the lifetime at it), replace its uses with uses of the moved-from value and
273+
/// delete it.
274+
static bool eliminateRedundantMove(MoveValueInst *mvi,
275+
InstructionDeleter &deleter) {
276+
if (!isRedundantMoveValue(mvi))
277+
return false;
278+
mvi->replaceAllUsesWith(mvi->getOperand());
279+
// Call InstructionDeleter::forceDeleteWithUsers to avoid "fixing up"
280+
// ownership of the moved-from value, i.e. inserting a destroy_value.
281+
deleter.forceDeleteWithUsers(mvi);
282+
return true;
283+
}
284+
266285
//===----------------------------------------------------------------------===//
267286
// MARK: Sink owned forwarding operations
268287
//===----------------------------------------------------------------------===//
@@ -420,6 +439,7 @@ void CopyPropagation::run() {
420439
bool changed = false;
421440

422441
StackList<BeginBorrowInst *> beginBorrowsToShrink(f);
442+
StackList<MoveValueInst *> moveValues(f);
423443

424444
// Driver: Find all copied or borrowed defs.
425445
for (auto &bb : *f) {
@@ -428,6 +448,8 @@ void CopyPropagation::run() {
428448
defWorklist.updateForCopy(copy);
429449
} else if (auto *borrow = dyn_cast<BeginBorrowInst>(&i)) {
430450
beginBorrowsToShrink.push_back(borrow);
451+
} else if (auto *move = dyn_cast<MoveValueInst>(&i)) {
452+
moveValues.push_back(move);
431453
} else if (canonicalizeAll) {
432454
if (auto *destroy = dyn_cast<DestroyValueInst>(&i)) {
433455
defWorklist.updateForCopy(destroy->getOperand());
@@ -480,9 +502,13 @@ void CopyPropagation::run() {
480502
hoistDestroysOfOwnedLexicalValue(folded, *f, deleter, calleeAnalysis);
481503
// Keep running even if the new move's destroys can't be hoisted.
482504
(void)hoisted;
505+
eliminateRedundantMove(folded, deleter);
483506
firstRun = false;
484507
}
485508
}
509+
for (auto *mvi : moveValues) {
510+
eliminateRedundantMove(mvi, deleter);
511+
}
486512
for (auto *argument : f->getArguments()) {
487513
if (argument->getOwnershipKind() == OwnershipKind::Owned) {
488514
hoistDestroysOfOwnedLexicalValue(argument, *f, deleter, calleeAnalysis);

0 commit comments

Comments
 (0)