Skip to content

Commit 7673d66

Browse files
authored
Merge pull request swiftlang#15645 from atrick/cpf-guaranteed
Suppress NRVO in copy forwarding unless the copy is just a move.
2 parents f604f1e + 1416739 commit 7673d66

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

lib/SILOptimizer/Transforms/CopyForwarding.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,18 @@ void CopyForwarding::forwardCopiesOf(SILValue Def, SILFunction *F) {
13011301
/// ... // no writes
13021302
/// return
13031303
static bool canNRVO(CopyAddrInst *CopyInst) {
1304+
// Don't perform NRVO unless the copy is a [take]. This is the easiest way
1305+
// to determine that the local variable has ownership of its value and ensures
1306+
// that removing a copy is a reference count neutral operation. For example,
1307+
// this copy can't be trivially eliminated without adding a retain.
1308+
// sil @f : $@convention(thin) (@guaranteed T) -> @out T
1309+
// bb0(%in : $*T, %out : $T):
1310+
// %local = alloc_stack $T
1311+
// store %in to %local : $*T
1312+
// copy_addr %local to [initialization] %out : $*T
1313+
if (!CopyInst->isTakeOfSrc())
1314+
return false;
1315+
13041316
if (!isa<AllocStackInst>(CopyInst->getSrc()))
13051317
return false;
13061318

test/SILOptimizer/copyforward.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,3 +776,21 @@ bb0(%0 : $*T, %1 : $*T):
776776
%r1 = tuple ()
777777
return %r1 : $()
778778
}
779+
780+
// Suppress NRVO when a guaranteed argument is stored into a local without
781+
// making a copy first. By eliminating the copy into the outgoing argument, NRVO
782+
// would be propagating an unowned (+0) local value into an owned (+1) result.
783+
// CHECK-LABEL: sil @foo : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @out Builtin.NativeObject {
784+
// CHECK: bb0(%0 : $*Builtin.NativeObject, %1 : $Builtin.NativeObject):
785+
// CHECK: [[LOCAL:%.*]] = alloc_stack $Builtin.NativeObject
786+
// CHECK: copy_addr [[LOCAL]] to [initialization] %0 : $*Builtin.NativeObject
787+
// CHECK-LABEL: } // end sil function 'foo'
788+
sil @foo : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @out Builtin.NativeObject {
789+
bb0(%0 : $*Builtin.NativeObject, %1 : $Builtin.NativeObject):
790+
%2 = alloc_stack $Builtin.NativeObject
791+
store %1 to %2 : $*Builtin.NativeObject
792+
copy_addr %2 to [initialization] %0 : $*Builtin.NativeObject
793+
dealloc_stack %2 : $*Builtin.NativeObject
794+
%6 = tuple ()
795+
return %6 : $()
796+
}

0 commit comments

Comments
 (0)