Skip to content

Commit e357fb4

Browse files
committed
[OpaqueValues] Handle Builtin.copy.
Specify the operand ownership of the Builtin differently depending on whether lowered addresses are used. Handle rewriting the value version of the builtin as the address version of the builtin in AddressLowering.
1 parent 332750d commit e357fb4

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,14 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, PoundAssert)
821821
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GlobalStringTablePointer)
822822
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TypePtrAuthDiscriminator)
823823
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TargetOSVersionAtLeast)
824-
BUILTIN_OPERAND_OWNERSHIP(UnownedInstantaneousUse, Copy)
824+
OperandOwnership OperandOwnershipBuiltinClassifier::visitCopy(BuiltinInst *bi,
825+
StringRef) {
826+
if (bi->getFunction()->getConventions().useLoweredAddresses()) {
827+
return OperandOwnership::UnownedInstantaneousUse;
828+
} else {
829+
return OperandOwnership::DestroyingConsume;
830+
}
831+
}
825832
BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, StartAsyncLet)
826833
BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, EndAsyncLet)
827834
BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, StartAsyncLetWithLocalBuffer)

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2617,6 +2617,19 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
26172617
vmi->setOperand(opAddr);
26182618
}
26192619

2620+
void visitBuiltinInst(BuiltinInst *bi) {
2621+
switch (bi->getBuiltinKind().getValueOr(BuiltinValueKind::None)) {
2622+
case BuiltinValueKind::Copy: {
2623+
SILValue opAddr = addrMat.materializeAddress(use->get());
2624+
bi->setOperand(0, opAddr);
2625+
break;
2626+
}
2627+
default:
2628+
bi->dump();
2629+
llvm::report_fatal_error("^^^ Unimplemented builtin opaque value use.");
2630+
}
2631+
}
2632+
26202633
void visitBeginBorrowInst(BeginBorrowInst *borrow);
26212634

26222635
void visitEndBorrowInst(EndBorrowInst *end) {}
@@ -3112,6 +3125,22 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
31123125
ApplyRewriter(bai, pass).convertBeginApplyWithOpaqueYield();
31133126
}
31143127

3128+
void visitBuiltinInst(BuiltinInst *bi) {
3129+
switch (bi->getBuiltinKind().getValueOr(BuiltinValueKind::None)) {
3130+
case BuiltinValueKind::Copy: {
3131+
SILValue addr = addrMat.materializeAddress(bi);
3132+
builder.createBuiltin(
3133+
bi->getLoc(), bi->getName(),
3134+
SILType::getEmptyTupleType(bi->getType().getASTContext()),
3135+
bi->getSubstitutions(), {addr, bi->getOperand(0)});
3136+
break;
3137+
}
3138+
default:
3139+
bi->dump();
3140+
llvm::report_fatal_error("^^^ Unimplemented builtin opaque value def.");
3141+
}
3142+
}
3143+
31153144
// Rewrite the apply for an indirect result.
31163145
void visitDestructureTupleInst(DestructureTupleInst *destructure) {
31173146
SILValue srcVal = destructure->getOperand();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// 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
2+
3+
// Like opaque_values_Onone.swift but for code that needs to be compiled with
4+
// -parse-stdlib.
5+
6+
class X {}
7+
8+
func consume(_ x : __owned X) {}
9+
10+
func foo(@_noImplicitCopy _ x: __owned X) {
11+
consume(_copy(x))
12+
consume(x)
13+
}
14+
15+
// CHECK-LABEL: sil [transparent] [_semantics "lifetimemanagement.copy"] @_copy : {{.*}} {
16+
// CHECK: {{bb[0-9]+}}([[OUT_ADDR:%[^,]+]] : $*T, [[IN_ADDR:%[^,]+]] : $*T):
17+
// CHECK: [[TMP_ADDR:%[^,]+]] = alloc_stack $T
18+
// CHECK: copy_addr [[IN_ADDR]] to [init] [[TMP_ADDR]] : $*T
19+
// CHECK: [[REGISTER_5:%[^,]+]] = builtin "copy"<T>([[OUT_ADDR]] : $*T, [[TMP_ADDR]] : $*T) : $()
20+
// CHECK: dealloc_stack [[TMP_ADDR]] : $*T
21+
// CHECK: return {{%[^,]+}} : $()
22+
// CHECK-LABEL: } // end sil function '_copy'
23+
@_transparent
24+
@_semantics("lifetimemanagement.copy")
25+
@_silgen_name("_copy")
26+
public func _copy<T>(_ value: T) -> T {
27+
#if $BuiltinCopy
28+
Builtin.copy(value)
29+
#else
30+
value
31+
#endif
32+
}
33+
34+

0 commit comments

Comments
 (0)