diff --git a/include/swift/SIL/OwnershipUtils.h b/include/swift/SIL/OwnershipUtils.h index 35d11727a9f75..c2d6b45336597 100644 --- a/include/swift/SIL/OwnershipUtils.h +++ b/include/swift/SIL/OwnershipUtils.h @@ -502,6 +502,10 @@ struct OwnedValueIntroducerKind { /// owned. Struct, + /// An owned value that is from a tuple that has multiple operands that are + /// owned. + Tuple, + /// An owned value that is a function argument. FunctionArgument, @@ -528,6 +532,8 @@ struct OwnedValueIntroducerKind { return OwnedValueIntroducerKind(BeginApply); case ValueKind::StructInst: return OwnedValueIntroducerKind(Struct); + case ValueKind::TupleInst: + return OwnedValueIntroducerKind(Tuple); case ValueKind::SILPhiArgument: { auto *phiArg = cast(value); if (dyn_cast_or_null(phiArg->getSingleTerminator())) { @@ -621,6 +627,7 @@ struct OwnedValueIntroducer { case OwnedValueIntroducerKind::LoadTake: case OwnedValueIntroducerKind::Phi: case OwnedValueIntroducerKind::Struct: + case OwnedValueIntroducerKind::Tuple: case OwnedValueIntroducerKind::FunctionArgument: case OwnedValueIntroducerKind::PartialApplyInit: case OwnedValueIntroducerKind::AllocBoxInit: @@ -639,6 +646,7 @@ struct OwnedValueIntroducer { case OwnedValueIntroducerKind::Phi: return true; case OwnedValueIntroducerKind::Struct: + case OwnedValueIntroducerKind::Tuple: case OwnedValueIntroducerKind::Copy: case OwnedValueIntroducerKind::LoadCopy: case OwnedValueIntroducerKind::Apply: diff --git a/lib/SIL/Utils/OwnershipUtils.cpp b/lib/SIL/Utils/OwnershipUtils.cpp index 836895a103a9c..d696a9b1db227 100644 --- a/lib/SIL/Utils/OwnershipUtils.cpp +++ b/lib/SIL/Utils/OwnershipUtils.cpp @@ -488,6 +488,9 @@ void OwnedValueIntroducerKind::print(llvm::raw_ostream &os) const { case OwnedValueIntroducerKind::Struct: os << "Struct"; return; + case OwnedValueIntroducerKind::Tuple: + os << "Tuple"; + return; case OwnedValueIntroducerKind::FunctionArgument: os << "FunctionArgument"; return; diff --git a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index 8b22cc85b36af..f1fb26fe516a7 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -55,6 +55,7 @@ class OwnershipPhiOperand { enum Kind { Branch, Struct, + Tuple, }; private: @@ -67,6 +68,7 @@ class OwnershipPhiOperand { switch (op->getUser()->getKind()) { case SILInstructionKind::BranchInst: case SILInstructionKind::StructInst: + case SILInstructionKind::TupleInst: return {{const_cast(op)}}; default: return None; @@ -79,6 +81,8 @@ class OwnershipPhiOperand { return Kind::Branch; case SILInstructionKind::StructInst: return Kind::Struct; + case SILInstructionKind::TupleInst: + return Kind::Tuple; default: llvm_unreachable("unhandled case?!"); } @@ -104,6 +108,7 @@ class OwnershipPhiOperand { switch (getKind()) { case Kind::Branch: return true; + case Kind::Tuple: case Kind::Struct: return false; } @@ -121,6 +126,8 @@ class OwnershipPhiOperand { switch (getKind()) { case Kind::Struct: return visitor(cast(getInst())); + case Kind::Tuple: + return visitor(cast(getInst())); case Kind::Branch: { auto *br = cast(getInst()); unsigned opNum = getOperandNumber(); @@ -589,6 +596,11 @@ static SILValue convertIntroducerToGuaranteed(OwnedValueIntroducer introducer) { si->setOwnershipKind(ValueOwnershipKind::Guaranteed); return si; } + case OwnedValueIntroducerKind::Tuple: { + auto *ti = cast(introducer.value); + ti->setOwnershipKind(ValueOwnershipKind::Guaranteed); + return ti; + } case OwnedValueIntroducerKind::Copy: case OwnedValueIntroducerKind::LoadCopy: case OwnedValueIntroducerKind::Apply: diff --git a/test/SILOptimizer/semantic-arc-opts-canonical.sil b/test/SILOptimizer/semantic-arc-opts-canonical.sil index 9da28deee23a9..10d4f07699762 100644 --- a/test/SILOptimizer/semantic-arc-opts-canonical.sil +++ b/test/SILOptimizer/semantic-arc-opts-canonical.sil @@ -323,8 +323,6 @@ bb0(%0 : @guaranteed $StructMemberTest): // multiple trivial arguments), we can. // // CHECK-LABEL: sil [ossa] @multiple_arg_forwarding_inst_test : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject, Builtin.Int32) -> () { -// CHECK: copy_value -// CHECK: copy_value // CHECK-NOT: copy_value // CHECK: } // end sil function 'multiple_arg_forwarding_inst_test' sil [ossa] @multiple_arg_forwarding_inst_test : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject, Builtin.Int32) -> () { diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil index f36740dc8c9d2..aac4e3eb35ddf 100644 --- a/test/SILOptimizer/semantic-arc-opts.sil +++ b/test/SILOptimizer/semantic-arc-opts.sil @@ -347,13 +347,7 @@ bb0(%0 : @guaranteed $StructMemberTest): return %7 : $Builtin.Int32 } -// Make sure that in a case where we have multiple non-trivial values passed to -// a forwarding instruction we do not optimize... but if we only have one (and -// multiple trivial arguments), we can. -// // CHECK-LABEL: sil [ossa] @multiple_arg_forwarding_inst_test : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject, Builtin.Int32) -> () { -// CHECK: copy_value -// CHECK: copy_value // CHECK-NOT: copy_value // CHECK: } // end sil function 'multiple_arg_forwarding_inst_test' sil [ossa] @multiple_arg_forwarding_inst_test : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject, Builtin.Int32) -> () { @@ -2560,4 +2554,17 @@ bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObje destroy_value %2 : $NativeObjectPair %9999 = tuple() return %9999 : $() -} \ No newline at end of file +} + +// CHECK-LABEL: sil [ossa] @tuple_with_multiple_nontrivial_operands : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { +// CHECK-NOT: copy_value +// CHECK: } // end sil function 'tuple_with_multiple_nontrivial_operands' +sil [ossa] @tuple_with_multiple_nontrivial_operands : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { +bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject): + %0a = copy_value %0 : $Builtin.NativeObject + %1a = copy_value %1 : $Builtin.NativeObject + %2 = tuple (%0a : $Builtin.NativeObject, %1a : $Builtin.NativeObject) + destroy_value %2 : $(Builtin.NativeObject, Builtin.NativeObject) + %9999 = tuple() + return %9999 : $() +}