Skip to content

Commit 02ee6b6

Browse files
Merge pull request #61924 from nate-chandler/opaque-values/2/20221103
[OpaqueValues] Handled more instructions.
2 parents 519df89 + 57352d7 commit 02ee6b6

File tree

4 files changed

+154
-4
lines changed

4 files changed

+154
-4
lines changed

lib/SILGen/SILGenEpilog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static SILValue buildReturnValue(SILGenFunction &SGF, SILLocation loc,
132132

133133
auto fnConv = SGF.F.getConventions();
134134
if (!fnConv.useLoweredAddresses()) {
135-
// In opaque-values code, nested @out enums are not flattened. Reconstruct
135+
// In opaque-values code, nested @out tuples are not flattened. Reconstruct
136136
// nested tuples.
137137
auto resultType = SGF.F.getLoweredType(SGF.F.mapTypeIntoContext(
138138
fnConv.getSILResultType(SGF.getTypeExpansionContext())));

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,11 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
26182618
vmi->setOperand(opAddr);
26192619
}
26202620

2621+
void visitExistentialMetatypeInst(ExistentialMetatypeInst *emi) {
2622+
SILValue opAddr = addrMat.materializeAddress(use->get());
2623+
emi->setOperand(opAddr);
2624+
}
2625+
26212626
void visitAddressOfBorrowBuiltinInst(BuiltinInst *bi, bool stackProtected) {
26222627
SILValue value = bi->getOperand(0);
26232628
SILValue addr = pass.valueStorageMap.getStorage(value).storageAddress;
@@ -2746,6 +2751,21 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
27462751

27472752
void emitExtract(SingleValueInstruction *extractInst);
27482753

2754+
void visitSelectEnumInst(SelectEnumInst *sei) {
2755+
SmallVector<std::pair<EnumElementDecl *, SILValue>> caseValues;
2756+
for (unsigned index = 0, count = sei->getNumCases(); index < count;
2757+
++index) {
2758+
caseValues.push_back(sei->getCase(index));
2759+
}
2760+
2761+
SILValue opAddr = addrMat.materializeAddress(use->get());
2762+
SILValue addr =
2763+
builder.createSelectEnumAddr(sei->getLoc(), opAddr, sei->getType(),
2764+
sei->getDefaultResult(), caseValues);
2765+
sei->replaceAllUsesWith(addr);
2766+
pass.deleter.forceDelete(sei);
2767+
}
2768+
27492769
// Extract from an opaque struct.
27502770
void visitStructExtractInst(StructExtractInst *extractInst);
27512771

@@ -2776,7 +2796,26 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
27762796
uncheckedCastInst->getLoc(), srcAddr,
27772797
uncheckedCastInst->getType().getAddressType());
27782798

2779-
markRewritten(uncheckedCastInst, destAddr);
2799+
if (uncheckedCastInst->getType().isAddressOnly(*pass.function)) {
2800+
markRewritten(uncheckedCastInst, destAddr);
2801+
return;
2802+
}
2803+
2804+
// For loadable cast destination type, replace copies with load copies.
2805+
if (Operand *use = uncheckedCastInst->getSingleUse()) {
2806+
if (auto *cvi = dyn_cast<CopyValueInst>(use->getUser())) {
2807+
auto *load = builder.createLoad(cvi->getLoc(), destAddr,
2808+
LoadOwnershipQualifier::Copy);
2809+
cvi->replaceAllUsesWith(load);
2810+
pass.deleter.forceDelete(cvi);
2811+
return;
2812+
}
2813+
}
2814+
SILValue load =
2815+
builder.emitLoadBorrowOperation(uncheckedCastInst->getLoc(), destAddr);
2816+
uncheckedCastInst->replaceAllUsesWith(load);
2817+
pass.deleter.forceDelete(uncheckedCastInst);
2818+
emitEndBorrows(load);
27802819
}
27812820

27822821
void visitUnconditionalCheckedCastInst(

test/SILOptimizer/address_lowering.sil

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,23 @@ exit_error(%47 : @owned $any Error):
13401340
throw %47 : $any Error
13411341
}
13421342

1343+
// CHECK-LABEL: sil [ossa] @selecteroo : $@convention(thin) <T> () -> () {
1344+
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Optional<T>
1345+
// CHECK: apply undef<T>([[ADDR]]) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
1346+
// CHECK: select_enum_addr [[ADDR]] : $*Optional<T>, case #Optional.some!enumelt: {{%[^,]+}}, default {{%[^,]+}} : $Builtin.Int1
1347+
// CHECK: dealloc_stack [[ADDR]] : $*Optional<T>
1348+
// CHECK-LABEL: } // end sil function 'selecteroo'
1349+
sil [ossa] @selecteroo : $@convention(thin) <T> () -> () {
1350+
bb0:
1351+
%11 = apply undef<T>() : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
1352+
%12 = integer_literal $Builtin.Int1, -1
1353+
%13 = integer_literal $Builtin.Int1, 0
1354+
%14 = select_enum %11 : $Optional<T>, case #Optional.some!enumelt: %12, default %13 : $Builtin.Int1
1355+
destroy_value %11 : $Optional<T>
1356+
%retval = tuple ()
1357+
return %retval : $()
1358+
} // end sil function '$ss17FixedWidthIntegerPsEyxSgSScfC'
1359+
13431360
sil hidden [ossa] @testBeginApplyDeadYield : $@convention(thin) <T> (@guaranteed TestGeneric<T>) -> () {
13441361
bb0(%0 : @guaranteed $TestGeneric<T>):
13451362
%2 = class_method %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric!read : <T> (TestGeneric<T>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
@@ -1554,6 +1571,53 @@ bb0(%0 : @guaranteed $T, %1 : $@thick U.Type):
15541571
return %6 : $U
15551572
}
15561573

1574+
// There's only one use and it's a copy, just rewrite it as a load [copy].
1575+
// CHECK-LABEL: sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable :
1576+
// CHECK: {{bb[0-9]+}}([[ADDR_IN:%[^,]+]] : $*T):
1577+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
1578+
// CHECK: copy_addr [[ADDR_IN]] to [init] [[STACK]]
1579+
// CHECK: [[STACK_AS_CLASS:%[^,]+]] = unchecked_addr_cast [[STACK]] : $*T to $*Klass
1580+
// CHECK: [[KLASS:%[^,]+]] = load [copy] [[STACK_AS_CLASS]]
1581+
// CHECK: destroy_addr [[STACK]]
1582+
// CHECK: dealloc_stack [[STACK]]
1583+
// CHECK: return [[KLASS]]
1584+
// CHECK-LABEL: } // end sil function 'test_unchecked_bitwise_cast_to_loadable'
1585+
sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable : $@convention(thin) <T> (@in_guaranteed T) -> @owned Klass {
1586+
bb0(%instance : @guaranteed $T):
1587+
%copy = copy_value %instance : $T
1588+
%unowned_klass = unchecked_bitwise_cast %copy : $T to $Klass
1589+
%klass = copy_value %unowned_klass : $Klass
1590+
destroy_value %copy : $T
1591+
return %klass : $Klass
1592+
}
1593+
1594+
// There is more than one use of the unchecked_addr_cast. The value should be
1595+
// load_borrow'd and uses of the original should be uses of that load.
1596+
// CHECK-LABEL: sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable_multiuse : {{.*}} {
1597+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*T):
1598+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
1599+
// CHECK: copy_addr [[INSTANCE]] to [init] [[STACK]]
1600+
// CHECK: [[STACK_AS_CLASS:%[^,]+]] = unchecked_addr_cast [[STACK]] : $*T to $*Klass
1601+
// CHECK: [[BORROWED_KLASS:%[^,]+]] = load_borrow [[STACK_AS_CLASS]]
1602+
// CHECK: [[KLASS_TO_RETURN:%[^,]+]] = copy_value [[BORROWED_KLASS]]
1603+
// CHECK: [[KLASS_TO_DESTROY:%[^,]+]] = copy_value [[BORROWED_KLASS]]
1604+
// CHECK: end_borrow [[BORROWED_KLASS]]
1605+
// CHECK: destroy_value [[KLASS_TO_DESTROY]]
1606+
// CHECK: destroy_addr [[STACK]]
1607+
// CHECK: dealloc_stack [[STACK]]
1608+
// CHECK: return [[KLASS_TO_RETURN]]
1609+
// CHECK-LABEL: } // end sil function 'test_unchecked_bitwise_cast_to_loadable_multiuse'
1610+
sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable_multiuse : $@convention(thin) <T> (@in_guaranteed T) -> @owned Klass {
1611+
bb0(%instance : @guaranteed $T):
1612+
%copy = copy_value %instance : $T
1613+
%unowned_klass = unchecked_bitwise_cast %copy : $T to $Klass
1614+
%klass = copy_value %unowned_klass : $Klass
1615+
%klass2 = copy_value %unowned_klass : $Klass
1616+
destroy_value %klass2 : $Klass
1617+
destroy_value %copy : $T
1618+
return %klass : $Klass
1619+
}
1620+
15571621
// CHECK-LABEL: sil hidden [ossa] @test_unconditional_checked_cast1 : $@convention(thin) <T> (Builtin.Int64) -> @out T {
15581622
// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int64):
15591623
// CHECK: [[INT:%.*]] = alloc_stack $Builtin.Int64

test/SILOptimizer/opaque_values_Onone_stdlib.swift

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
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
1+
// RUN: %target-swift-frontend -parse-stdlib -enable-experimental-move-only -module-name Swift -enable-sil-opaque-values -parse-as-library -emit-sil -Onone %s | %FileCheck %s
22

33
// Like opaque_values_Onone.swift but for code that needs to be compiled with
44
// -parse-stdlib.
55

6-
class X {}
6+
precedencegroup AssignmentPrecedence { assignment: true }
7+
precedencegroup CastingPrecedence {}
8+
9+
public protocol _ObjectiveCBridgeable {}
710

11+
public protocol _ExpressibleByBuiltinBooleanLiteral {
12+
init(_builtinBooleanLiteral value: Builtin.Int1)
13+
}
14+
struct Bool : _ExpressibleByBuiltinBooleanLiteral {
15+
var _value: Builtin.Int1
16+
@_silgen_name("Bool_init_noargs")
17+
init()
18+
init(_ v: Builtin.Int1) { self._value = v }
19+
init(_ value: Bool) { self = value }
20+
init(_builtinBooleanLiteral value: Builtin.Int1) {
21+
self._value = value
22+
}
23+
}
24+
25+
@_silgen_name("typeof")
26+
@_semantics("typechecker.type(of:)")
27+
public func type<T, Metatype>(of value: T) -> Metatype
28+
29+
class X {}
830
func consume(_ x : __owned X) {}
931

1032
func foo(@_noImplicitCopy _ x: __owned X) {
@@ -50,3 +72,28 @@ func getRawPointer<T>(to value: T) -> Builtin.RawPointer {
5072
func getUnprotectedRawPointer<T>(to value: T) -> Builtin.RawPointer {
5173
return Builtin.unprotectedAddressOfBorrow(value)
5274
}
75+
76+
// CHECK-LABEL: sil hidden @getBridgeObject : {{.*}} {
77+
// CHECK: [[OBJECT_ADDR:%[^,]+]] = unchecked_addr_cast {{%[^,]+}} : $*T to $*Builtin.BridgeObject
78+
// CHECK: [[OBJECT:%[^,]+]] = load [[OBJECT_ADDR]]
79+
// CHECK: return [[OBJECT]]
80+
// CHECK-LABEL: } // end sil function 'getBridgeObject'
81+
@_silgen_name("getBridgeObject")
82+
func toObject<T>(_ object: inout T) -> Builtin.BridgeObject {
83+
Builtin.reinterpretCast(object)
84+
}
85+
86+
// CHECK-LABEL: sil hidden @getAnotherType : {{.*}} {
87+
// CHECK: {{bb[0-9]+}}([[RETADDR:%[^,]+]] : $*U, {{%[^,]+}} : $*T, {{%[^,]+}} : $@thick U.Type):
88+
// CHECK: [[OTHER_TY_ADDR:%[^,]+]] = unchecked_addr_cast {{%[^,]+}} : $*T to $*U
89+
// CHECK: copy_addr [[OTHER_TY_ADDR]] to [init] [[RETADDR]] : $*U
90+
// CHECK-LABEL: } // end sil function 'getAnotherType'
91+
@_silgen_name("getAnotherType")
92+
func getAnotherType<T, U>(_ object: inout T, to ty: U.Type) -> U {
93+
Builtin.reinterpretCast(object)
94+
}
95+
96+
@_silgen_name("isOfTypeOfAnyObjectType")
97+
func isOfTypeOfAnyObjectType(fromAny any: Any) -> Bool {
98+
type(of: any) is Builtin.AnyObject.Type
99+
}

0 commit comments

Comments
 (0)