From 2dea3ca3fc77533c28dead0e25fd76cc37b453f6 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Tue, 16 Sep 2025 14:33:43 -0700 Subject: [PATCH] sil: load [copy] affects reference counting Based on what I see from OwnershipModelEliminator, `%x = load [copy] %y` can turn into a plain load followed by a retain of the loaded value. See `NonTrivialLoadableTypeLowering::emitLoad` --- docs/SIL/Instructions.md | 6 +++--- lib/SIL/Utils/InstructionUtils.cpp | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/SIL/Instructions.md b/docs/SIL/Instructions.md index d9fd4a00ceb7c..e4bbe28a3b072 100644 --- a/docs/SIL/Instructions.md +++ b/docs/SIL/Instructions.md @@ -832,7 +832,7 @@ load-ownership-kind ::= 'take' ``` Loads the value at address `%0` from memory. `T` must be a loadable -type. This does not affect the reference count, if any, of the loaded +type. An unqualified load does not affect the reference count, if any, of the loaded value; the value must be retained explicitly if necessary. It is undefined behavior to load from uninitialized memory or to load from an address that points to deallocated storage. @@ -840,8 +840,8 @@ address that points to deallocated storage. In OSSA the ownership kind specifies how to handle ownership: - **trivial**: the loaded value is trivial and no further action must be taken than to load the raw bits of the value -- **copy**: the loaded value is copied and the original value stays in the - memory location. +- **copy**: the loaded value is copied (e.g., retained) and the original value + stays in the memory location. - **take**: the value is _moved_ from the memory location without copying. After the `load`, the memory location remains uninitialized. diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index c4c569b79a10f..60e73bf267ee6 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -552,7 +552,6 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst: case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst: case SILInstructionKind::UncheckedOwnershipConversionInst: - case SILInstructionKind::LoadInst: case SILInstructionKind::LoadBorrowInst: case SILInstructionKind::BeginBorrowInst: case SILInstructionKind::BorrowedFromInst: @@ -626,6 +625,14 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::TypeValueInst: case SILInstructionKind::IgnoredUseInst: return RuntimeEffect::NoEffect; + + case SILInstructionKind::LoadInst: { + if (cast(inst)->getOwnershipQualifier() == LoadOwnershipQualifier::Copy) { + return ifNonTrivial(inst->getOperand(0)->getType(), + RuntimeEffect::RefCounting); + } + return RuntimeEffect::NoEffect; + } case SILInstructionKind::OpenExistentialMetatypeInst: case SILInstructionKind::OpenExistentialBoxInst: