@@ -185,6 +185,9 @@ struct MoveOnlyObjectCheckerPImpl {
185185
186186 bool
187187 checkForSameInstMultipleUseErrors (MarkUnresolvedNonCopyableValueInst *base);
188+
189+ bool eraseMarkWithCopiedOperand (
190+ MarkUnresolvedNonCopyableValueInst *markedInst);
188191};
189192
190193} // namespace
@@ -463,9 +466,6 @@ void MoveOnlyObjectCheckerPImpl::check(
463466 // MarkUnresolvedNonCopyableValueInst in Raw SIL. This ensures we do not
464467 // miss any.
465468 //
466- // NOTE: destroys is a separate array that we use to avoid iterator
467- // invalidation when cleaning up destroy_value of guaranteed checked values.
468- SmallVector<DestroyValueInst *, 8 > destroys;
469469 while (!moveIntroducersToProcess.empty ()) {
470470 auto *markedInst = moveIntroducersToProcess.pop_back_val ();
471471
@@ -475,80 +475,98 @@ void MoveOnlyObjectCheckerPImpl::check(
475475 if (!diagnosticEmitter.emittedDiagnosticForValue (markedInst)) {
476476 if (markedInst->getCheckKind () ==
477477 MarkUnresolvedNonCopyableValueInst::CheckKind::NoConsumeOrAssign) {
478- if (auto *cvi = dyn_cast<CopyValueInst>(markedInst->getOperand ())) {
479- auto replacement = cvi->getOperand ();
480- auto orig = replacement;
481- if (auto *copyToMoveOnly =
482- dyn_cast<CopyableToMoveOnlyWrapperValueInst>(orig)) {
483- orig = copyToMoveOnly->getOperand ();
484- }
485-
486- // TODO: Instead of pattern matching specific code generation patterns,
487- // we should be able to eliminate any `copy_value` whose canonical
488- // lifetime fits within the borrow scope of the borrowed value being
489- // copied from.
490-
491- // Handle:
492- //
493- // bb(%arg : @guaranteed $Type):
494- // %copy = copy_value %arg
495- // %mark = mark_unresolved_non_copyable_value [no_consume_or_assign] %copy
496- if (auto *arg = dyn_cast<SILArgument>(orig)) {
497- if (arg->getOwnershipKind () == OwnershipKind::Guaranteed) {
498- for (auto *use : markedInst->getConsumingUses ()) {
499- destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
500- }
501- while (!destroys.empty ())
502- destroys.pop_back_val ()->eraseFromParent ();
503- markedInst->replaceAllUsesWith (replacement);
504- markedInst->eraseFromParent ();
505- cvi->eraseFromParent ();
506- continue ;
507- }
508- }
509-
510- // Handle:
511- //
512- // %1 = load_borrow %0
513- // %2 = copy_value %1
514- // %3 = mark_unresolved_non_copyable_value [no_consume_or_assign] %2
515- if (isa<LoadBorrowInst>(orig)) {
516- for (auto *use : markedInst->getConsumingUses ()) {
517- destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
518- }
519- while (!destroys.empty ())
520- destroys.pop_back_val ()->eraseFromParent ();
521- markedInst->replaceAllUsesWith (replacement);
522- markedInst->eraseFromParent ();
523- cvi->eraseFromParent ();
524- continue ;
525- }
526-
527- // Handle:
528- // (%yield, ..., %handle) = begin_apply
529- // %copy = copy_value %yield
530- // %mark = mark_unresolved_noncopyable_value [no_consume_or_assign] %copy
531- if (isa_and_nonnull<BeginApplyInst>(orig->getDefiningInstruction ())) {
532- if (orig->getOwnershipKind () == OwnershipKind::Guaranteed) {
533- for (auto *use : markedInst->getConsumingUses ()) {
534- destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
535- }
536- while (!destroys.empty ())
537- destroys.pop_back_val ()->eraseFromParent ();
538- markedInst->replaceAllUsesWith (replacement);
539- markedInst->eraseFromParent ();
540- cvi->eraseFromParent ();
541- continue ;
542- }
543- }
478+ if (eraseMarkWithCopiedOperand (markedInst)) {
479+ changed = true ;
480+ continue ;
544481 }
545482 }
483+ markedInst->replaceAllUsesWith (markedInst->getOperand ());
484+ markedInst->eraseFromParent ();
485+ changed = true ;
486+ }
487+ }
488+ }
489+
490+ // / Erase a copy_value operand of MarkUnresolvedNonCopyableValueInst.
491+ bool MoveOnlyObjectCheckerPImpl::eraseMarkWithCopiedOperand (
492+ MarkUnresolvedNonCopyableValueInst *markedInst)
493+ {
494+ auto *cvi = dyn_cast<CopyValueInst>(markedInst->getOperand ());
495+ if (!cvi)
496+ return false ;
497+
498+ auto replacement = cvi->getOperand ();
499+ auto orig = replacement;
500+ if (auto *copyToMoveOnly =
501+ dyn_cast<CopyableToMoveOnlyWrapperValueInst>(orig)) {
502+ orig = copyToMoveOnly->getOperand ();
503+ }
504+
505+ // TODO: Instead of pattern matching specific code generation patterns,
506+ // we should be able to eliminate any `copy_value` whose canonical
507+ // lifetime fits within the borrow scope of the borrowed value being
508+ // copied from.
509+
510+ // NOTE: destroys is a separate array that we use to avoid iterator
511+ // invalidation when cleaning up destroy_value of guaranteed checked values.
512+ SmallVector<DestroyValueInst *, 8 > destroys;
513+
514+ // Handle:
515+ //
516+ // bb(%arg : @guaranteed $Type):
517+ // %copy = copy_value %arg
518+ // %mark = mark_unresolved_non_copyable_value [no_consume_or_assign]
519+ // %copy
520+ if (auto *arg = dyn_cast<SILArgument>(orig)) {
521+ if (arg->getOwnershipKind () == OwnershipKind::Guaranteed) {
522+ for (auto *use : markedInst->getConsumingUses ()) {
523+ destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
524+ }
525+ while (!destroys.empty ())
526+ destroys.pop_back_val ()->eraseFromParent ();
527+ markedInst->replaceAllUsesWith (replacement);
528+ markedInst->eraseFromParent ();
529+ cvi->eraseFromParent ();
530+ return true ;
546531 }
532+ }
547533
548- markedInst->replaceAllUsesWith (markedInst->getOperand ());
534+ // Handle:
535+ //
536+ // %1 = load_borrow %0
537+ // %2 = copy_value %1
538+ // %3 = mark_unresolved_non_copyable_value [no_consume_or_assign] %2
539+ if (isa<LoadBorrowInst>(orig)) {
540+ for (auto *use : markedInst->getConsumingUses ()) {
541+ destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
542+ }
543+ while (!destroys.empty ())
544+ destroys.pop_back_val ()->eraseFromParent ();
545+ markedInst->replaceAllUsesWith (replacement);
549546 markedInst->eraseFromParent ();
550- changed = true ;
547+ cvi->eraseFromParent ();
548+ return true ;
549+ }
550+
551+ // Handle:
552+ // (%yield, ..., %handle) = begin_apply
553+ // %copy = copy_value %yield
554+ // %mark = mark_unresolved_noncopyable_value [no_consume_or_assign]
555+ // %copy
556+ if (isa_and_nonnull<BeginApplyInst>(orig->getDefiningInstruction ())) {
557+ if (orig->getOwnershipKind () == OwnershipKind::Guaranteed) {
558+ for (auto *use : markedInst->getConsumingUses ()) {
559+ destroys.push_back (cast<DestroyValueInst>(use->getUser ()));
560+ }
561+ while (!destroys.empty ())
562+ destroys.pop_back_val ()->eraseFromParent ();
563+ markedInst->replaceAllUsesWith (replacement);
564+ markedInst->eraseFromParent ();
565+ cvi->eraseFromParent ();
566+ return true ;
567+ }
551568 }
569+ return false ;
552570}
553571
554572// ===----------------------------------------------------------------------===//
0 commit comments