Skip to content

Commit d8e23cb

Browse files
authored
Merge pull request #84523 from kavon/manual-ownership/usability-fixes-4
Usability improvements for ManualOwnership, part 4
2 parents aa1f000 + a96e494 commit d8e23cb

File tree

4 files changed

+151
-104
lines changed

4 files changed

+151
-104
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RedundantLoadElimination.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ func eliminateRedundantLoads(in function: Function,
8989
variant: RedundantLoadEliminationVariant,
9090
_ context: FunctionPassContext) -> Bool
9191
{
92+
// FIXME: this skip is a hack for ManualOwnership prototyping, to workaround rdar://161359163
93+
if function.performanceConstraints == .manualOwnership && variant == .mandatory {
94+
return false
95+
}
96+
9297
// Avoid quadratic complexity by limiting the number of visited instructions.
9398
// This limit is sufficient for most "real-world" functions, by far.
9499
var complexityBudget = 50_000

include/swift/AST/DiagnosticsSIL.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -434,13 +434,13 @@ ERROR(wrong_linkage_for_serialized_function,none,
434434
NOTE(performance_called_from,none,
435435
"called from here", ())
436436
ERROR(manualownership_copy,none,
437-
"explicit 'copy' required here", ())
437+
"explicit 'copy' required here; please report this vague diagnostic as a bug", ())
438438
ERROR(manualownership_copy_happened,none,
439-
"accessing %0 produces a copy of it; write 'copy' to acknowledge", (Identifier))
439+
"accessing %0 may produce a copy; write 'copy' to acknowledge or 'consume' to elide", (Identifier))
440440
ERROR(manualownership_copy_demanded,none,
441-
"ownership of %0 is demanded and cannot not be consumed; write 'copy' to satisfy", (Identifier))
441+
"independent copy of %0 is required here; write 'copy' to acknowledge or 'consume' to elide", (Identifier))
442442
ERROR(manualownership_copy_captured,none,
443-
"ownership of %0 is demanded by a closure; write 'copy' in its capture list to satisfy", (Identifier))
443+
"closure capture of '%0' requires independent copy of it; write [%0 = copy %0] in the closure's capture list to acknowledge", (StringRef))
444444

445445
// 'transparent' diagnostics
446446
ERROR(circular_transparent,none,

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,11 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
388388
case SILInstructionKind::ExplicitCopyAddrInst:
389389
case SILInstructionKind::ExplicitCopyValueInst:
390390
break; // Explicitly acknowledged copies are OK.
391+
case SILInstructionKind::CopyAddrInst: {
392+
if (!cast<CopyAddrInst>(inst)->isTakeOfSrc())
393+
shouldDiagnose = true; // If it isn't a [take], it's a copy.
394+
break;
395+
}
391396
case SILInstructionKind::LoadInst: {
392397
// FIXME: we don't have an `explicit_load` and transparent functions can
393398
// end up bringing in a `load [copy]`. A better approach is needed to
@@ -429,38 +434,53 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
429434
<< "\n has unexpected copying instruction: " << *inst);
430435

431436
// Try to come up with a useful diagnostic.
437+
438+
// First, identify what is being copied.
439+
SILValue copied;
432440
if (auto svi = dyn_cast<SingleValueInstruction>(inst)) {
433-
if (auto name = VariableNameInferrer::inferName(svi)) {
434-
// Simplistic check for whether this is a closure capture.
435-
for (auto user : svi->getUsers()) {
436-
if (isa<PartialApplyInst>(user)) {
437-
LLVM_DEBUG(llvm::dbgs() << "captured by "<< *user);
438-
diagnose(loc, diag::manualownership_copy_captured, *name);
439-
return false;
440-
}
441-
}
441+
copied = svi;
442+
} else if (auto cai = dyn_cast<CopyAddrInst>(inst)) {
443+
copied = cai->getSrc();
444+
}
442445

443-
// There's no hope of borrowing access if there's a consuming use.
444-
for (auto op : svi->getUses()) {
445-
auto useKind = op->getOperandOwnership();
446-
447-
// Only some DestroyingConsume's, like 'store', are interesting.
448-
if (useKind == OperandOwnership::ForwardingConsume
449-
|| isa<StoreInst>(op->getUser())) {
450-
LLVM_DEBUG(llvm::dbgs() << "demanded by "<< *(op->getUser()));
451-
diagnose(loc, diag::manualownership_copy_demanded, *name);
452-
return false;
453-
}
454-
}
446+
// Find a name for that copied thing.
447+
std::optional<Identifier> name;
448+
if (copied)
449+
name = VariableNameInferrer::inferName(copied);
450+
451+
if (!name) {
452+
// Emit a rudimentary diagnostic.
453+
diagnose(loc, diag::manualownership_copy);
454+
return false;
455+
}
455456

456-
diagnose(loc, diag::manualownership_copy_happened, *name);
457+
// Try to tailor the diagnostic based on usages.
458+
459+
// Simplistic check for whether this is a closure capture.
460+
for (auto user : copied->getUsers()) {
461+
if (isa<PartialApplyInst>(user)) {
462+
LLVM_DEBUG(llvm::dbgs() << "captured by "<< *user);
463+
diagnose(loc, diag::manualownership_copy_captured, name->get());
457464
return false;
458465
}
459466
}
460467

461-
// Back-up diagnostic, when all-else fails.
462-
diagnose(loc, diag::manualownership_copy);
463-
return false; // Don't bail-out early; diagnose more issues in the func.
468+
// There's no hope of borrowing access if there's a consuming use.
469+
for (auto op : copied->getUses()) {
470+
auto useKind = op->getOperandOwnership();
471+
472+
// Only some DestroyingConsume's, like 'store', are interesting.
473+
if (useKind == OperandOwnership::ForwardingConsume
474+
|| isa<StoreInst>(op->getUser())) {
475+
LLVM_DEBUG(llvm::dbgs() << "demanded by "<< *(op->getUser()));
476+
diagnose(loc, diag::manualownership_copy_demanded, *name);
477+
return false;
478+
}
479+
}
480+
481+
// Catch-all diagnostic for when we at least have the name.
482+
diagnose(loc, diag::manualownership_copy_happened, *name);
483+
return false;
464484
}
465485
}
466486
return false;

0 commit comments

Comments
 (0)