SILGen: avoid double copies with 'copy' expr

This commit is contained in:
Kavon Farvardin
2025-05-29 19:47:20 -07:00
parent 393465262b
commit 32f1ebcfab
3 changed files with 10 additions and 25 deletions

View File

@@ -7222,7 +7222,9 @@ RValue RValueEmitter::visitCopyExpr(CopyExpr *E, SGFContext C) {
}
if (subType.isLoadable(SGF.F)) {
ManagedValue mv = SGF.emitRValue(subExpr).getAsSingleValue(SGF, subExpr);
ManagedValue mv =
SGF.emitRValue(subExpr, SGFContext::AllowImmediatePlusZero)
.getAsSingleValue(SGF, subExpr);
if (mv.getType().isTrivial(SGF.F))
return RValue(SGF, {mv}, subType.getASTType());
{

View File

@@ -29,8 +29,7 @@ struct ContainKlass {
// CHECK: [[X:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thin ContainKlass.Type) -> @owned ContainKlass
// CHECK: [[MOVE:%.*]] = move_value [lexical] [var_decl] [[X]]
// CHECK: [[BORROW:%.*]] = begin_borrow [[MOVE]]
// CHECK: [[COPY_BORROW:%.*]] = copy_value [[BORROW]]
// CHECK: explicit_copy_value [[COPY_BORROW]]
// CHECK: [[COPY_BORROW:%.*]] = explicit_copy_value [[BORROW]]
// CHECK: } // end sil function '$s9copy_expr22testCopyLoadableRValueyyF'
func testCopyLoadableRValue() {
let x = ContainKlass()
@@ -121,43 +120,35 @@ func testCopyAddressOnlyLValueArg<T : P>(_ x: inout T) {
// CHECK: [[X:%.*]] = begin_borrow [[MOVE]]
//
// Calling consumeFunc.
// CHECK: [[COPY_X:%.*]] = copy_value [[X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[COPY_X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[X]]
// CHECK: [[FUNC:%.*]] = function_ref @$s9copy_expr12ContainKlassV11consumeFuncyyF : $@convention(method) (@owned ContainKlass) -> ()
// CHECK: apply [[FUNC]]([[EXPLICIT_COPY_X]])
// CHECK: destroy_value [[COPY_X]]
//
// Calling borrowingFunc.
// CHECK: [[X:%.*]] = begin_borrow [[MOVE]]
// CHECK: [[COPY_X:%.*]] = copy_value [[X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[COPY_X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[X]]
// CHECK: [[FUNC:%.*]] = function_ref @$s9copy_expr12ContainKlassV13borrowingFuncyyF : $@convention(method) (@guaranteed ContainKlass) -> ()
// CHECK: apply [[FUNC]]([[EXPLICIT_COPY_X]])
// CHECK: destroy_value [[EXPLICIT_COPY_X]]
// CHECK: destroy_value [[COPY_X]]
//
// Calling computedK. It is borrowed.
// CHECK: [[X:%.*]] = begin_borrow [[MOVE]]
// CHECK: [[COPY_X:%.*]] = copy_value [[X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[COPY_X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[X]]
// CHECK: [[BORROW_EXPLICIT_COPY_X:%.*]] = begin_borrow [[EXPLICIT_COPY_X]]
// CHECK: [[FUNC:%.*]] = function_ref @$s9copy_expr12ContainKlassV9computedKAA0D0Cvg : $@convention(method) (@guaranteed ContainKlass) -> @owned Klass
// CHECK: apply [[FUNC]]([[BORROW_EXPLICIT_COPY_X]])
// CHECK: end_borrow [[BORROW_EXPLICIT_COPY_X]]
// CHECK: destroy_value [[EXPLICIT_COPY_X]]
// CHECK: destroy_value [[COPY_X]]
//
// Calling computed getter.
// CHECK: [[X:%.*]] = begin_borrow [[MOVE]]
// CHECK: [[COPY_X:%.*]] = copy_value [[X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[COPY_X]]
// CHECK: [[EXPLICIT_COPY_X:%.*]] = explicit_copy_value [[X]]
// CHECK: [[BORROW_EXPLICIT_COPY_X:%.*]] = begin_borrow [[EXPLICIT_COPY_X]]
// CHECK: [[COPY_BORROW_EXPLICIT_COPY_X:%.*]] = copy_value [[BORROW_EXPLICIT_COPY_X]]
// CHECK: [[FUNC:%.*]] = function_ref @$s9copy_expr12ContainKlassV18consumingComputedKAA0D0Cvg : $@convention(method) (@owned ContainKlass) -> @owned Klass
// CHECK: apply [[FUNC]]([[COPY_BORROW_EXPLICIT_COPY_X]])
// CHECK: end_borrow [[BORROW_EXPLICIT_COPY_X]]
// CHECK: destroy_value [[EXPLICIT_COPY_X]]
// CHECK: destroy_value [[COPY_X]]
// CHECK: } // end sil function '$s9copy_expr31testCallMethodOnLoadableLetCopyyyF'
func testCallMethodOnLoadableLetCopy() {
let x = ContainKlass()

View File

@@ -11,9 +11,7 @@ class Klass {}
// CHECK-LABEL: sil [ossa] @$s8moveonly7useCopyyAA5KlassCADF : {{.*}} {
// CHECK: bb0([[ARG:%.*]] :
// CHECK-NEXT: debug_value
// CHECK-NEXT: [[COPY:%[^,]+]] = copy_value [[ARG]]
// CHECK-NEXT: [[EXPLICIT_COPY:%[^,]+]] = explicit_copy_value [[COPY]]
// CHECK-NEXT: destroy_value [[COPY]]
// CHECK-NEXT: [[EXPLICIT_COPY:%[^,]+]] = explicit_copy_value [[ARG]]
// CHECK-NEXT: return [[EXPLICIT_COPY]]
// CHECK-LABEL: } // end sil function '$s8moveonly7useCopyyAA5KlassCADF'
@@ -21,8 +19,6 @@ class Klass {}
// CHECK-SIL: bb0([[ARG:%.*]] : $Klass):
// CHECK-SIL-NEXT: debug_value
// CHECK-SIL-NEXT: strong_retain [[ARG]]
// CHECK-SIL-NEXT: strong_retain [[ARG]]
// CHECK-SIL-NEXT: strong_release [[ARG]]
// CHECK-SIL-NEXT: return [[ARG]] : $Klass
// CHECK-SIL-LABEL: } // end sil function '$s8moveonly7useCopyyAA5KlassCADF'
@@ -39,9 +35,7 @@ public func useCopy(_ k: Klass) -> Klass {
// CHECK-LABEL: sil [ossa] @$s8moveonly7useCopyyxxRlzClF : $@convention(thin) <T where T : AnyObject> (@guaranteed T) -> @owned T {
// CHECK: bb0([[ARG:%.*]] :
// CHECK-NEXT: debug_value
// CHECK-NEXT: [[COPY:%[^,]+]] = copy_value [[ARG]]
// CHECK-NEXT: [[EXPLICIT_COPY:%[^,]+]] = explicit_copy_value [[COPY]]
// CHECK-NEXT: destroy_value [[COPY]]
// CHECK-NEXT: [[EXPLICIT_COPY:%[^,]+]] = explicit_copy_value [[ARG]]
// CHECK-NEXT: return [[EXPLICIT_COPY]]
// CHECK-LABEL: } // end sil function '$s8moveonly7useCopyyxxRlzClF'
@@ -49,8 +43,6 @@ public func useCopy(_ k: Klass) -> Klass {
// CHECK-SIL: bb0([[ARG:%.*]] :
// CHECK-SIL-NEXT: debug_value
// CHECK-SIL-NEXT: strong_retain [[ARG]]
// CHECK-SIL-NEXT: strong_retain [[ARG]]
// CHECK-SIL-NEXT: strong_release [[ARG]]
// CHECK-SIL-NEXT: return [[ARG]]
// CHECK-SIL-LABEL: } // end sil function '$s8moveonly7useCopyyxxRlzClF'