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// ===----------------------------------------------------------------------===//
@@ -419,15 +438,18 @@ void CopyPropagation::run() {
419438 InstructionDeleter deleter (std::move (callbacks));
420439 bool changed = false ;
421440
422- GraphNodeWorklist<BeginBorrowInst *, 16 > beginBorrowsToShrink;
441+ StackList<BeginBorrowInst *> beginBorrowsToShrink (f);
442+ StackList<MoveValueInst *> moveValues (f);
423443
424444 // Driver: Find all copied or borrowed defs.
425445 for (auto &bb : *f) {
426446 for (auto &i : bb) {
427447 if (auto *copy = dyn_cast<CopyValueInst>(&i)) {
428448 defWorklist.updateForCopy (copy);
429449 } else if (auto *borrow = dyn_cast<BeginBorrowInst>(&i)) {
430- beginBorrowsToShrink.insert (borrow);
450+ 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 ());
@@ -446,7 +468,7 @@ void CopyPropagation::run() {
446468 // NOTE: We assume that the function is in reverse post order so visiting the
447469 // blocks and pushing begin_borrows as we see them and then popping them
448470 // off the end will result in shrinking inner borrow scopes first.
449- while (auto *bbi = beginBorrowsToShrink. pop () ) {
471+ for (auto *bbi : beginBorrowsToShrink) {
450472 bool firstRun = true ;
451473 // Run the sequence of utilities:
452474 // - ShrinkBorrowScope
@@ -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