diff --git a/lib/SIL/IR/OperandOwnership.cpp b/lib/SIL/IR/OperandOwnership.cpp index fade6f9b17c..99d70ff4244 100644 --- a/lib/SIL/IR/OperandOwnership.cpp +++ b/lib/SIL/IR/OperandOwnership.cpp @@ -821,7 +821,14 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, PoundAssert) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GlobalStringTablePointer) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TypePtrAuthDiscriminator) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TargetOSVersionAtLeast) -BUILTIN_OPERAND_OWNERSHIP(UnownedInstantaneousUse, Copy) +OperandOwnership OperandOwnershipBuiltinClassifier::visitCopy(BuiltinInst *bi, + StringRef) { + if (bi->getFunction()->getConventions().useLoweredAddresses()) { + return OperandOwnership::UnownedInstantaneousUse; + } else { + return OperandOwnership::DestroyingConsume; + } +} BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, StartAsyncLet) BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, EndAsyncLet) BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, StartAsyncLetWithLocalBuffer) diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp index 774266ffc91..ba7a52a835e 100644 --- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp +++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp @@ -2617,6 +2617,19 @@ protected: vmi->setOperand(opAddr); } + void visitBuiltinInst(BuiltinInst *bi) { + switch (bi->getBuiltinKind().getValueOr(BuiltinValueKind::None)) { + case BuiltinValueKind::Copy: { + SILValue opAddr = addrMat.materializeAddress(use->get()); + bi->setOperand(0, opAddr); + break; + } + default: + bi->dump(); + llvm::report_fatal_error("^^^ Unimplemented builtin opaque value use."); + } + } + void visitBeginBorrowInst(BeginBorrowInst *borrow); void visitEndBorrowInst(EndBorrowInst *end) {} @@ -3112,6 +3125,22 @@ protected: ApplyRewriter(bai, pass).convertBeginApplyWithOpaqueYield(); } + void visitBuiltinInst(BuiltinInst *bi) { + switch (bi->getBuiltinKind().getValueOr(BuiltinValueKind::None)) { + case BuiltinValueKind::Copy: { + SILValue addr = addrMat.materializeAddress(bi); + builder.createBuiltin( + bi->getLoc(), bi->getName(), + SILType::getEmptyTupleType(bi->getType().getASTContext()), + bi->getSubstitutions(), {addr, bi->getOperand(0)}); + break; + } + default: + bi->dump(); + llvm::report_fatal_error("^^^ Unimplemented builtin opaque value def."); + } + } + // Rewrite the apply for an indirect result. void visitDestructureTupleInst(DestructureTupleInst *destructure) { SILValue srcVal = destructure->getOperand(); diff --git a/test/SILOptimizer/opaque_values_Onone_stdlib.swift b/test/SILOptimizer/opaque_values_Onone_stdlib.swift new file mode 100644 index 00000000000..19c4ab8bc0e --- /dev/null +++ b/test/SILOptimizer/opaque_values_Onone_stdlib.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-frontend -parse-stdlib -enable-experimental-move-only -module-name main -enable-sil-opaque-values -parse-as-library -emit-sil -Onone %s | %FileCheck %s + +// Like opaque_values_Onone.swift but for code that needs to be compiled with +// -parse-stdlib. + +class X {} + +func consume(_ x : __owned X) {} + +func foo(@_noImplicitCopy _ x: __owned X) { + consume(_copy(x)) + consume(x) +} + +// CHECK-LABEL: sil [transparent] [_semantics "lifetimemanagement.copy"] @_copy : {{.*}} { +// CHECK: {{bb[0-9]+}}([[OUT_ADDR:%[^,]+]] : $*T, [[IN_ADDR:%[^,]+]] : $*T): +// CHECK: [[TMP_ADDR:%[^,]+]] = alloc_stack $T +// CHECK: copy_addr [[IN_ADDR]] to [init] [[TMP_ADDR]] : $*T +// CHECK: [[REGISTER_5:%[^,]+]] = builtin "copy"([[OUT_ADDR]] : $*T, [[TMP_ADDR]] : $*T) : $() +// CHECK: dealloc_stack [[TMP_ADDR]] : $*T +// CHECK: return {{%[^,]+}} : $() +// CHECK-LABEL: } // end sil function '_copy' +@_transparent +@_semantics("lifetimemanagement.copy") +@_silgen_name("_copy") +public func _copy(_ value: T) -> T { + #if $BuiltinCopy + Builtin.copy(value) + #else + value + #endif +} + +