Skip to content

Commit 2d71c60

Browse files
committed
Emit enum element arguments directly into the enum payload.
This generates significantly better code directly out of SILGen, at the cost of having to reimplement a little bit of the argument-emission logic to handle default arguments. But it also neatly sidesteps the problems we have with splitting tuple RValues when the tuple contains a pack expansion, which will require some significant surgery to RValue to fix. That, in turn, fixes rdar://121489308.
1 parent 633051e commit 2d71c60

10 files changed

+324
-127
lines changed

lib/SILGen/SILGenApply.cpp

+199-68
Large diffs are not rendered by default.

lib/SILGen/SILGenConstructor.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -898,12 +898,21 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
898898
LoweredParamsInContextGenerator loweredParams(*this);
899899

900900
// Emit the exploded constructor argument.
901-
ArgumentSource payload;
901+
SmallVector<ArgumentSource, 2> payloads;
902902
if (element->hasAssociatedValues()) {
903-
auto eltArgTy = element->getArgumentInterfaceType()->getCanonicalType();
904-
RValue arg = emitImplicitValueConstructorArg(*this, Loc, eltArgTy, element,
905-
loweredParams);
906-
payload = ArgumentSource(Loc, std::move(arg));
903+
auto elementFnTy =
904+
cast<AnyFunctionType>(
905+
cast<AnyFunctionType>(element->getInterfaceType()->getCanonicalType())
906+
.getResult());
907+
auto elementParams = elementFnTy.getParams();
908+
payloads.reserve(elementParams.size());
909+
910+
for (auto param: elementParams) {
911+
auto paramType = param.getParameterType();
912+
RValue arg = emitImplicitValueConstructorArg(*this, Loc, paramType,
913+
element, loweredParams);
914+
payloads.emplace_back(Loc, std::move(arg));
915+
}
907916
}
908917

909918
// Emit the metatype argument.
@@ -913,7 +922,7 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
913922

914923
// If possible, emit the enum directly into the indirect return.
915924
SGFContext C = (dest ? SGFContext(dest.get()) : SGFContext());
916-
ManagedValue mv = emitInjectEnum(Loc, std::move(payload),
925+
ManagedValue mv = emitInjectEnum(Loc, payloads,
917926
enumTI.getLoweredType(),
918927
element, C);
919928

lib/SILGen/SILGenConvert.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,34 @@ ManagedValue SILGenFunction::manageOpaqueValue(ManagedValue value,
10261026
return value.copyUnmanaged(*this, loc);
10271027
}
10281028

1029+
ManagedValue SILGenFunction::emitAsOrig(SILLocation loc,
1030+
AbstractionPattern origType,
1031+
CanType substType,
1032+
SILType expectedTy,
1033+
SGFContext C,
1034+
ValueProducerRef produceValue) {
1035+
// If the lowered substituted type already matches the substitution,
1036+
// we can just emit directly.
1037+
if (getLoweredType(substType).getASTType() == expectedTy.getASTType()) {
1038+
auto result = produceValue(*this, loc, C);
1039+
1040+
// For convenience, force the result into the destination.
1041+
if (auto init = C.getEmitInto(); init && !result.isInContext()) {
1042+
result.forwardInto(*this, loc, init);
1043+
return ManagedValue::forInContext();
1044+
}
1045+
return result;
1046+
}
1047+
1048+
auto conversion =
1049+
Conversion::getSubstToOrig(origType, substType, expectedTy);
1050+
auto result = emitConvertedRValue(loc, conversion, C, produceValue);
1051+
1052+
// emitConvertedRValue always forces results into the context.
1053+
assert((C.getEmitInto() != nullptr) == result.isInContext());
1054+
return result;
1055+
}
1056+
10291057
ManagedValue SILGenFunction::emitConvertedRValue(Expr *E,
10301058
const Conversion &conversion,
10311059
SGFContext C) {

lib/SILGen/SILGenFunction.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
13001300
//===--------------------------------------------------------------------===//
13011301

13021302
ManagedValue emitInjectEnum(SILLocation loc,
1303-
ArgumentSource &&payload,
1303+
MutableArrayRef<ArgumentSource> payload,
13041304
SILType enumTy,
13051305
EnumElementDecl *element,
13061306
SGFContext C);
@@ -1562,6 +1562,22 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15621562
SGFContext C,
15631563
ValueProducerRef produceValue);
15641564

1565+
/// Call the produceValue function and convert the result to the given
1566+
/// original abstraction pattern.
1567+
///
1568+
/// The SGFContext provided to the produceValue function includes the
1569+
/// conversion, if it's non-trivial, and thus permits it to be peepholed
1570+
/// and combined with other conversions. This can result in substantially
1571+
/// more efficient code than just emitting the value and reabstracting
1572+
/// it afterwards.
1573+
///
1574+
/// If the provided SGFContext includes an initialization, the result
1575+
/// will always be ManagedValue::forInContext().
1576+
ManagedValue emitAsOrig(SILLocation loc, AbstractionPattern origType,
1577+
CanType substType, SILType expectedTy,
1578+
SGFContext C,
1579+
ValueProducerRef produceValue);
1580+
15651581
/// Emit the given expression as an r-value that follows the
15661582
/// abstraction patterns of the original type.
15671583
ManagedValue emitRValueAsOrig(Expr *E, AbstractionPattern origPattern,

test/IRGen/enum_resilience.swift

+1-13
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,11 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium {
135135
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], [[INT]] -1
136136
// CHECK-NEXT: [[VWT:%.*]] = load ptr, ptr [[VWT_ADDR]]
137137

138-
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, ptr [[VWT]], i32 0, i32 8
139-
// CHECK-NEXT: [[WITNESS_FOR_SIZE:%size]] = load [[INT]], ptr [[WITNESS_ADDR]]
140-
// CHECK-NEXT: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
141-
// CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i32|i64)}} -1, ptr [[ALLOCA]])
142-
143138
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 2
144139
// CHECK-NEXT: [[WITNESS:%.*]] = load ptr, ptr [[WITNESS_ADDR]]
145140
// CHECK-arm64e-NEXT: ptrtoint ptr [[WITNESS_ADDR]] to i64
146141
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
147-
// CHECK-NEXT: call ptr [[WITNESS]](ptr noalias [[ALLOCA]], ptr noalias %1, ptr [[METADATA]])
148-
149-
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 4
150-
// CHECK-NEXT: [[WITNESS:%.*]] = load ptr, ptr [[WITNESS_ADDR]]
151-
// CHECK-arm64e-NEXT: ptrtoint ptr [[WITNESS_ADDR]] to i64
152-
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
153-
// CHECK-NEXT: call ptr [[WITNESS]](ptr noalias %0, ptr noalias [[ALLOCA]], ptr [[METADATA]])
142+
// CHECK-NEXT: call ptr [[WITNESS]](ptr noalias %0, ptr noalias %1, ptr [[METADATA]])
154143

155144
// CHECK-NEXT: [[TAG:%.*]] = load i32, ptr @"$s14resilient_enum6MediumO8PostcardyAC0A7_struct4SizeVcACmFWC"
156145
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s14resilient_enum6MediumOMa"([[INT]] 0)
@@ -165,7 +154,6 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium {
165154
// CHECK-arm64e-NEXT: ptrtoint ptr [[WITNESS_ADDR]] to i64
166155
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
167156
// CHECK-NEXT: call void [[WITNESS_FN]](ptr noalias %0, i32 [[TAG]], ptr [[METADATA2]])
168-
// CHECK-NEXT: call void @llvm.lifetime.end.p0({{(i32|i64)}} -1, ptr [[ALLOCA]])
169157

170158
// CHECK-NEXT: ret void
171159

test/SILGen/enum.swift

+27-9
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,13 @@ func AddressOnly_cases(_ s: S) {
6363
_ = AddressOnly.nought
6464

6565
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
66-
// CHECK-NEXT: [[P_BUF:%.*]] = alloc_stack $any P
67-
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[P_BUF]]
68-
// CHECK-NEXT: store %0 to [trivial] [[PAYLOAD_ADDR]]
6966
// CHECK-NEXT: [[MERE:%.*]] = alloc_stack $AddressOnly
7067
// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]]
71-
// CHECK-NEXT: copy_addr [take] [[P_BUF]] to [init] [[PAYLOAD]] : $*any P
68+
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[PAYLOAD]]
69+
// CHECK-NEXT: store %0 to [trivial] [[PAYLOAD_ADDR]]
7270
// CHECK-NEXT: inject_enum_addr [[MERE]]
7371
// CHECK-NEXT: destroy_addr [[MERE]]
7472
// CHECK-NEXT: dealloc_stack [[MERE]]
75-
// CHECK-NEXT: dealloc_stack [[P_BUF]] : $*any P
7673
_ = AddressOnly.mere(s)
7774

7875
// Address-only enum vs loadable payload
@@ -105,15 +102,12 @@ func PolyOptionable_cases<T>(_ t: T) {
105102
_ = PolyOptionable<T>.nought
106103

107104
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<T>.Type
108-
// CHECK-NEXT: [[T_BUF:%.*]] = alloc_stack $T
109-
// CHECK-NEXT: copy_addr %0 to [init] [[T_BUF]]
110105
// CHECK-NEXT: [[MERE:%.*]] = alloc_stack $PolyOptionable<T>
111106
// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]]
112-
// CHECK-NEXT: copy_addr [take] [[T_BUF]] to [init] [[PAYLOAD]] : $*T
107+
// CHECK-NEXT: copy_addr %0 to [init] [[PAYLOAD]] : $*T
113108
// CHECK-NEXT: inject_enum_addr [[MERE]]
114109
// CHECK-NEXT: destroy_addr [[MERE]]
115110
// CHECK-NEXT: dealloc_stack [[MERE]]
116-
// CHECK-NEXT: dealloc_stack [[T_BUF]] : $*T
117111
_ = PolyOptionable<T>.mere(t)
118112

119113
// CHECK-NOT: destroy_addr %0
@@ -265,3 +259,27 @@ enum rdar81817725 {
265259
}
266260
}
267261
}
262+
263+
enum Indirected {
264+
case a
265+
case b
266+
indirect case c(Int)
267+
}
268+
func throwingFunction() throws -> Int { return 0 }
269+
270+
// CHECK-LABEL: sil hidden [ossa] @$s4enum29throwInIndirectConstructorArgAA10IndirectedOyKF
271+
// CHECK: [[BOX:%.*]] = alloc_box ${ var Int }
272+
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = project_box [[BOX]]
273+
// CHECK-NEXT: // function_ref
274+
// CHECK-NEXT: [[FN:%.*]] = function_ref
275+
// CHECK-NEXT: try_apply [[FN]]()
276+
// CHECK: bb1([[RESULT:%.*]] : $Int):
277+
// CHECK-NEXT: store [[RESULT]] to [trivial] [[PAYLOAD_ADDR]]
278+
// CHECK-NEXT: [[ENUM:%.*]] = enum $Indirected, #Indirected.c!enumelt, [[BOX]]
279+
// CHECK-NEXT: return [[ENUM]] : $Indirected
280+
// CHECK: bb2([[ERROR:%.*]] : @owned $any Error):
281+
// CHECK-NEXT: dealloc_box [[BOX]]
282+
// CHECK-NEXT: throw [[ERROR]]
283+
func throwInIndirectConstructorArg() throws -> Indirected {
284+
return .c(try throwingFunction())
285+
}

test/SILGen/generic_closures.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ class NestedGeneric<U> {
132132
// CHECK-LABEL: sil hidden [ossa] @$s16generic_closures13NestedGenericC20nested_reabstraction{{[_0-9a-zA-Z]*}}F
133133
// CHECK: [[REABSTRACT:%.*]] = function_ref @$sIeg_ytIegr_TR
134134
// CHECK: partial_apply [callee_guaranteed] [[REABSTRACT]]
135-
func nested_reabstraction<T>(_ x: T) -> Optionable<() -> ()> {
136-
return .some({})
135+
func nested_reabstraction<T>(_ x: T, fn: @escaping () -> ()) -> Optionable<() -> ()> {
136+
return .some(fn)
137137
}
138138
}
139139

test/SILGen/indirect_enum.swift

+9-21
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,21 @@ func TreeA_cases<T>(_ t: T, l: TreeA<T>, r: TreeA<T>) {
1616
let _ = TreeA<T>.Nil
1717

1818
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
19-
// CHECK-NEXT: [[T_BUF:%.*]] = alloc_stack $T
20-
// CHECK-NEXT: copy_addr [[ARG1]] to [init] [[T_BUF]] : $*T
2119
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <T>
2220
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
23-
// CHECK-NEXT: copy_addr [take] [[T_BUF]] to [init] [[PB]]
21+
// CHECK-NEXT: copy_addr [[ARG1]] to [init] [[PB]]
2422
// CHECK-NEXT: [[LEAF:%.*]] = enum $TreeA<T>, #TreeA.Leaf!enumelt, [[BOX]]
2523
// CHECK-NEXT: destroy_value [[LEAF]]
26-
// CHECK-NEXT: dealloc_stack [[T_BUF]] : $*T
2724
let _ = TreeA<T>.Leaf(t)
2825

2926
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
30-
// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
31-
// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]]
3227
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>
3328
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
3429
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 0
3530
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 1
31+
// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
3632
// CHECK-NEXT: store [[ARG2_COPY]] to [init] [[LEFT]]
33+
// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]]
3734
// CHECK-NEXT: store [[ARG3_COPY]] to [init] [[RIGHT]]
3835
// CHECK-NEXT: [[BRANCH:%.*]] = enum $TreeA<T>, #TreeA.Branch!enumelt, [[BOX]]
3936
// CHECK-NEXT: destroy_value [[BRANCH]]
@@ -46,9 +43,9 @@ func TreeA_cases<T>(_ t: T, l: TreeA<T>, r: TreeA<T>) {
4643
func TreeA_reabstract(_ f: @escaping (Int) -> Int) {
4744
// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (Int) -> Int):
4845
// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeA<(Int) -> Int>.Type
49-
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
5046
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(Int) -> Int>
5147
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
48+
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
5249
// CHECK: [[THUNK:%.*]] = function_ref @$sS2iIegyd_S2iIegnr_TR
5350
// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG_COPY]])
5451
// CHECK-NEXT: [[FNC:%.*]] = convert_function [[FN]]
@@ -77,36 +74,27 @@ func TreeB_cases<T>(_ t: T, l: TreeB<T>, r: TreeB<T>) {
7774
let _ = TreeB<T>.Nil
7875

7976
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
80-
// CHECK-NEXT: [[T_BUF:%.*]] = alloc_stack $T
81-
// CHECK-NEXT: copy_addr %0 to [init] [[T_BUF]]
8277
// CHECK-NEXT: [[LEAF:%.*]] = alloc_stack $TreeB<T>
8378
// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[LEAF]] : $*TreeB<T>, #TreeB.Leaf!enumelt
84-
// CHECK-NEXT: copy_addr [take] [[T_BUF]] to [init] [[PAYLOAD]]
79+
// CHECK-NEXT: copy_addr %0 to [init] [[PAYLOAD]]
8580
// CHECK-NEXT: inject_enum_addr [[LEAF]] : $*TreeB<T>, #TreeB.Leaf!enumelt
8681
// CHECK-NEXT: destroy_addr [[LEAF]]
8782
// CHECK-NEXT: dealloc_stack [[LEAF]]
88-
// CHECK-NEXT: dealloc_stack [[T_BUF]]
8983
let _ = TreeB<T>.Leaf(t)
9084

9185
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
92-
// CHECK-NEXT: [[ARG1_COPY:%.*]] = alloc_stack $TreeB<T>
93-
// CHECK-NEXT: copy_addr %1 to [init] [[ARG1_COPY]] : $*TreeB<T>
94-
// CHECK-NEXT: [[ARG2_COPY:%.*]] = alloc_stack $TreeB<T>
95-
// CHECK-NEXT: copy_addr %2 to [init] [[ARG2_COPY]] : $*TreeB<T>
9686
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeB<τ_0_0>, right: TreeB<τ_0_0>) } <T>
9787
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
9888
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
9989
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
100-
// CHECK-NEXT: copy_addr [take] [[ARG1_COPY]] to [init] [[LEFT]] : $*TreeB<T>
101-
// CHECK-NEXT: copy_addr [take] [[ARG2_COPY]] to [init] [[RIGHT]] : $*TreeB<T>
90+
// CHECK-NEXT: copy_addr %1 to [init] [[LEFT]] : $*TreeB<T>
91+
// CHECK-NEXT: copy_addr %2 to [init] [[RIGHT]] : $*TreeB<T>
10292
// CHECK-NEXT: [[BRANCH:%.*]] = alloc_stack $TreeB<T>
10393
// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[BRANCH]]
10494
// CHECK-NEXT: store [[BOX]] to [init] [[PAYLOAD]]
10595
// CHECK-NEXT: inject_enum_addr [[BRANCH]] : $*TreeB<T>, #TreeB.Branch!enumelt
10696
// CHECK-NEXT: destroy_addr [[BRANCH]]
10797
// CHECK-NEXT: dealloc_stack [[BRANCH]]
108-
// CHECK-NEXT: dealloc_stack [[ARG2_COPY]]
109-
// CHECK-NEXT: dealloc_stack [[ARG1_COPY]]
11098
let _ = TreeB<T>.Branch(left: l, right: r)
11199

112100
// CHECK: return
@@ -126,13 +114,13 @@ func TreeInt_cases(_ t: Int, l: TreeInt, r: TreeInt) {
126114
let _ = TreeInt.Leaf(t)
127115

128116
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeInt.Type
129-
// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] : $TreeInt
130-
// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]] : $TreeInt
131117
// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var (left: TreeInt, right: TreeInt) }
132118
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
133119
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
134120
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
121+
// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] : $TreeInt
135122
// CHECK-NEXT: store [[ARG2_COPY]] to [init] [[LEFT]]
123+
// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]] : $TreeInt
136124
// CHECK-NEXT: store [[ARG3_COPY]] to [init] [[RIGHT]]
137125
// CHECK-NEXT: [[BRANCH:%.*]] = enum $TreeInt, #TreeInt.Branch!enumelt, [[BOX]]
138126
// CHECK-NEXT: destroy_value [[BRANCH]]

test/SILGen/variadic-generic-tuples.swift

+24
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,27 @@ func test() {
399399
let tuple = identityOnVariadicTuples((1, 2, 3))
400400
takesVariadicTuple(tuple: tuple)
401401
}
402+
403+
func createTuple<each T>(including: repeat Stored<each T>, from: Int) -> (repeat each T) {
404+
fatalError()
405+
}
406+
407+
// rdar://121489308
408+
func testTupleExpansionInEnumConstructor<each T>(
409+
from: repeat Stored<each T>,
410+
to: @escaping (Result<(repeat each T), Error>) -> ()
411+
) {
412+
_ = {
413+
let tuple = createTuple(including: repeat each from,
414+
from: 42)
415+
to(.success(tuple))
416+
}
417+
}
418+
// CHECK-LABEL: sil {{.*}}@$s4main35testTupleExpansionInEnumConstructor4from2toyAA6StoredVyxGxQp_ys6ResultOyxxQp_ts5Error_pGctRvzlFyycfU_ :
419+
// CHECK: [[VAR:%.*]] = alloc_stack [lexical] $(repeat each T), let, name "tuple"
420+
// (a few moments later)
421+
// CHECK: metatype $@thin Result<(repeat each T), any Error>.Type
422+
// CHECK: [[RESULT_TEMP:%.*]] = alloc_stack $Result<(repeat each T), any Error>
423+
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_enum_data_addr [[RESULT_TEMP]] : $*Result<(repeat each T), any Error>, #Result.success
424+
// CHECK-NEXT: copy_addr [[VAR]] to [init] [[PAYLOAD_ADDR]] : $*(repeat each T)
425+
// CHECK-NEXT: inject_enum_addr [[RESULT_TEMP]] : $*Result<(repeat each T), any Error>, #Result.success

test/SILOptimizer/access_marker_verify.swift

+2-7
Original file line numberDiff line numberDiff line change
@@ -334,14 +334,9 @@ func testInitGenericEnum<T>(t: T) -> GenericEnum<T>? {
334334
// CHECK: alloc_box $<τ_0_0> { var GenericEnum<τ_0_0> } <T>, var, name "self"
335335
// CHECK: mark_uninitialized [delegatingself] %3 : $<τ_0_0> { var GenericEnum<τ_0_0> } <T>
336336
// CHECK: [[PROJ:%.*]] = project_box
337-
// CHECK: [[ADR1:%.*]] = alloc_stack $T
338-
// CHECK-NOT: begin_access
339-
// CHECK: copy_addr %1 to [init] [[ADR1]] : $*T
340337
// CHECK: [[STK:%.*]] = alloc_stack $GenericEnum<T>
341338
// CHECK: [[ENUMDATAADDR:%.*]] = init_enum_data_addr [[STK]]
342-
// CHECK: [[ACCESSENUM:%.*]] = begin_access [modify] [unsafe] [[ENUMDATAADDR]] : $*T
343-
// CHECK: copy_addr [take] [[ADR1]] to [init] [[ACCESSENUM]] : $*T
344-
// CHECK: end_access [[ACCESSENUM]] : $*T
339+
// CHECK: copy_addr %1 to [init] [[ENUMDATAADDR]] : $*T
345340
// CHECK: inject_enum_addr
346341
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJ]]
347342
// CHECK: copy_addr [take] %{{.*}} to [[ACCESS]] : $*GenericEnum<T>
@@ -362,9 +357,9 @@ func testIndirectEnum() -> IndirectEnum {
362357
}
363358
// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify16testIndirectEnumAA0eF0OyF : $@convention(thin) () -> @owned IndirectEnum {
364359
// CHECK: bb0:
365-
// CHECK: apply
366360
// CHECK: alloc_box ${ var Int }
367361
// CHECK: [[PROJ:%.*]] = project_box
362+
// CHECK: apply
368363
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]]
369364
// CHECK: store %{{.*}} to [trivial] [[ACCESS]] : $*Int
370365
// CHECK: end_access

0 commit comments

Comments
 (0)