Skip to content

Commit d8a2f77

Browse files
committed
Fix MoveOnlyObjectCheckerPImpl::check() changed flag
Extract the special pattern matching logic that is otherwise unrelated to the check() function. This makes it obvious that the implementation was failing to set the 'changed' flag whenever needed. (cherry picked from commit c41715c)
1 parent ae735f3 commit d8a2f77

File tree

1 file changed

+89
-71
lines changed

1 file changed

+89
-71
lines changed

lib/SILOptimizer/Mandatory/MoveOnlyObjectCheckerUtils.cpp

Lines changed: 89 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)