Skip to content

Commit edfb86f

Browse files
authored
Merge pull request #19988 from gottesmm/pr-06c8b35dac1dd99058fd565cad7fd824a0c1de92
[silgenpattern] Allow the initial switch value to be at +0 if it is loadable.
2 parents cbbc03a + d8243c8 commit edfb86f

File tree

10 files changed

+100
-76
lines changed

10 files changed

+100
-76
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,9 +2046,8 @@ ManagedValue SILGenFunction::getManagedValue(SILLocation loc,
20462046
if (value.getOwnershipKind() == ValueOwnershipKind::Trivial)
20472047
return ManagedValue::forUnmanaged(value.getValue());
20482048

2049-
// Otherwise, retain and enter a release cleanup.
2050-
valueTL.emitCopyValue(B, loc, value.getValue());
2051-
return emitManagedRValueWithCleanup(value.getValue(), valueTL);
2049+
// Otherwise, copy the value and return.
2050+
return value.getFinalManagedValue().copy(*this, loc);
20522051
}
20532052

20542053
// Otherwise, produce a temporary and copy into that.

lib/SILGen/SILGenPattern.cpp

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -741,22 +741,28 @@ forwardIntoSubtree(SILGenFunction &SGF, SILLocation loc,
741741

742742
auto consumptionKind = outerCMV.getFinalConsumption();
743743
(void)consumptionKind;
744+
745+
// If we have an object and it is take always, we need to borrow the value
746+
// since we do not own the value at this point.
747+
if (outerMV.getType().isObject()) {
748+
assert(consumptionKind == CastConsumptionKind::TakeAlways &&
749+
"Object without cleanup that is not take_always?!");
750+
return {outerMV.borrow(SGF, loc), CastConsumptionKind::BorrowAlways};
751+
}
752+
753+
// Only address only values use TakeOnSuccess.
754+
assert(outerMV.getType().isAddressOnly(SGF.getModule()) &&
755+
"TakeOnSuccess can only be used with address only values");
756+
744757
assert((consumptionKind == CastConsumptionKind::TakeAlways ||
745758
consumptionKind == CastConsumptionKind::TakeOnSuccess) &&
746759
"non-+1 consumption with a cleanup?");
747760
scope.pushCleanupState(outerMV.getCleanup(),
748761
CleanupState::PersistentlyActive);
749762

750-
// If SILOwnership is enabled and we have an object, borrow instead of take on
751-
// success.
752-
if (SGF.F.getModule().getOptions().EnableSILOwnership &&
753-
outerMV.getType().isObject()) {
754-
return {outerMV.borrow(SGF, loc), CastConsumptionKind::BorrowAlways};
755-
}
756-
757763
// Success means that we won't end up in the other branch,
758764
// but failure doesn't.
759-
return { outerMV, CastConsumptionKind::TakeOnSuccess };
765+
return {outerMV, CastConsumptionKind::TakeOnSuccess};
760766
}
761767

762768
/// Forward a value down into an irrefutable branch of the decision tree.
@@ -2728,9 +2734,39 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
27282734
PatternMatchContext switchContext = { emission };
27292735
SwitchStack.push_back(&switchContext);
27302736

2731-
// Emit the subject value. Dispatching will consume it.
2732-
ManagedValue subjectMV = emitRValueAsSingleValue(S->getSubjectExpr());
2733-
auto subject = ConsumableManagedValue::forOwned(subjectMV);
2737+
// Emit the subject value. If at +1, dispatching will consume it. If it is at
2738+
// +0, we just forward down borrows.
2739+
ManagedValue subjectMV = emitRValueAsSingleValue(
2740+
S->getSubjectExpr(), SGFContext::AllowGuaranteedPlusZero);
2741+
2742+
// Inline constructor for subject.
2743+
auto subject = ([&]() -> ConsumableManagedValue {
2744+
// If we have a plus one value...
2745+
if (subjectMV.isPlusOne(*this)) {
2746+
// And we have an address that is loadable, perform a load [take].
2747+
if (subjectMV.getType().isAddress() &&
2748+
subjectMV.getType().isLoadable(getModule())) {
2749+
subjectMV = B.createLoadTake(S, subjectMV);
2750+
}
2751+
return {subjectMV, CastConsumptionKind::TakeAlways};
2752+
}
2753+
2754+
// If we have a loadable address and +0, perform a load borrow.
2755+
if (subjectMV.getType().isAddress() &&
2756+
subjectMV.getType().isLoadable(getModule())) {
2757+
subjectMV = B.createLoadBorrow(S, subjectMV);
2758+
}
2759+
2760+
// If then we have an object, return it at +0.
2761+
if (subjectMV.getType().isObject()) {
2762+
return {subjectMV, CastConsumptionKind::BorrowAlways};
2763+
}
2764+
2765+
// If we have an address only type returned without a cleanup, we
2766+
// need to do a copy just to be safe. So for efficiency we pass it
2767+
// down take_always.
2768+
return {subjectMV.copy(*this, S), CastConsumptionKind::TakeAlways};
2769+
}());
27342770

27352771
auto failure = [&](SILLocation location) {
27362772
// If we fail to match anything, we trap. This can happen with a switch

test/SIL/ownership-verifier/over_consume.sil

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ case some(T)
2222
case none
2323
}
2424

25-
class SuperKlass {}
25+
class SuperKlass {
26+
func doSomething()
27+
}
28+
29+
class Klass : SuperKlass {
30+
}
2631

2732
///////////
2833
// Tests //
@@ -434,3 +439,21 @@ bb3:
434439
%9999 = tuple()
435440
return %9999 : $()
436441
}
442+
443+
// CHECK-LABEL: Function: 'consume_with_classmethod'
444+
// CHECK: Found use after free?!
445+
// CHECK: Value: %2 = upcast %0 : $Klass to $SuperKlass
446+
// CHECK: Consuming User: store %2 to [init] %1 : $*SuperKlass
447+
// CHECK: Non Consuming User: %4 = class_method %2 : $SuperKlass, #SuperKlass.doSomething!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> ()
448+
// CHECK: Block: bb0
449+
sil @consume_with_classmethod : $@convention(thin) (@owned Klass) -> () {
450+
bb0(%0 : @owned $Klass):
451+
%1 = alloc_stack $SuperKlass
452+
%2 = upcast %0 : $Klass to $SuperKlass
453+
store %2 to [init] %1 : $*SuperKlass
454+
%3 = class_method %2 : $SuperKlass, #SuperKlass.doSomething!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> ()
455+
destroy_addr %1 : $*SuperKlass
456+
dealloc_stack %1 : $*SuperKlass
457+
%9999 = tuple()
458+
return %9999 : $()
459+
}

test/SILGen/class_bound_protocols.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen -enable-sil-ownership -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
33

44
enum Optional<T> {
55
case some(T)
@@ -132,8 +132,9 @@ func class_bound_method(x: ClassBound) {
132132
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*ClassBound
133133
// CHECK: [[X:%.*]] = load [copy] [[READ]] : $*ClassBound
134134
// CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $ClassBound to $[[OPENED:@opened(.*) ClassBound]]
135+
// CHECK: [[BORROWED_PROJ:%.*]] = begin_borrow [[PROJ]]
135136
// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #ClassBound.classBoundMethod!1
136-
// CHECK: apply [[METHOD]]<[[OPENED]]>([[PROJ]])
137+
// CHECK: apply [[METHOD]]<[[OPENED]]>([[BORROWED_PROJ]])
137138
// CHECK: destroy_value [[PROJ]]
138139
// CHECK: destroy_value [[XBOX]]
139140
}

test/SILGen/indirect_enum.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,8 @@ func d() {}
149149
// CHECK-LABEL: sil hidden @$s13indirect_enum11switchTreeAyyAA0D1AOyxGlF : $@convention(thin) <T> (@guaranteed TreeA<T>) -> () {
150150
func switchTreeA<T>(_ x: TreeA<T>) {
151151
// CHECK: bb0([[ARG:%.*]] : @guaranteed $TreeA<T>):
152-
// -- x +2
153-
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
154-
// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
155-
// CHECK: switch_enum [[BORROWED_ARG_COPY]] : $TreeA<T>,
152+
// -- x +0
153+
// CHECK: switch_enum [[ARG]] : $TreeA<T>,
156154
// CHECK: case #TreeA.Nil!enumelt: [[NIL_CASE:bb1]],
157155
// CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE:bb2]],
158156
// CHECK: case #TreeA.Branch!enumelt.1: [[BRANCH_CASE:bb3]],
@@ -168,7 +166,7 @@ func switchTreeA<T>(_ x: TreeA<T>) {
168166
// CHECK: function_ref @$s13indirect_enum1b{{[_0-9a-zA-Z]*}}F
169167
// CHECK: destroy_addr [[X]]
170168
// CHECK: dealloc_stack [[X]]
171-
// -- x +1
169+
// -- x +0
172170
// CHECK: br [[OUTER_CONT]]
173171
case .Leaf(let x):
174172
b(x)
@@ -204,8 +202,7 @@ func switchTreeA<T>(_ x: TreeA<T>) {
204202
c(x, y)
205203

206204
// CHECK: [[DEFAULT]]:
207-
// -- x +1
208-
// CHECK: destroy_value [[ARG_COPY]]
205+
// -- x +0
209206
default:
210207
d()
211208
}

test/SILGen/switch.swift

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,7 @@ class E : C {}
413413
// CHECK-LABEL: sil hidden @$s6switch16test_isa_class_11xyAA1BC_tF : $@convention(thin) (@guaranteed B) -> () {
414414
func test_isa_class_1(x: B) {
415415
// CHECK: bb0([[X:%.*]] : @guaranteed $B):
416-
// CHECK: [[X_COPY:%.*]] = copy_value [[X]]
417-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
418-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
416+
// CHECK: checked_cast_br [[X]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
419417
switch x {
420418

421419
// CHECK: [[IS_D1]]([[CAST_D1:%.*]] : @guaranteed $D1):
@@ -427,40 +425,32 @@ func test_isa_class_1(x: B) {
427425
case is D1 where runced():
428426
// CHECK: destroy_value [[CAST_D1_COPY]]
429427
// CHECK: end_borrow [[CAST_D1]]
430-
// CHECK: end_borrow [[BORROWED_X_COPY]]
431-
// CHECK: destroy_value [[X_COPY]]
432428
// CHECK: function_ref @$s6switch1ayyF
433429
// CHECK: br [[CONT:bb[0-9]+]]
434430
a()
435431

436432
// CHECK: [[NO_CASE1]]:
437433
// CHECK-NEXT: destroy_value [[CAST_D1_COPY]]
438434
// CHECK-NEXT: end_borrow [[CAST_D1]]
439-
// CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
440435
// CHECK: br [[NEXT_CASE:bb[0-9]+]]
441436

442437
// CHECK: [[IS_NOT_D1]]([[CASTFAIL_D1:%.*]] : @guaranteed $B):
443438
// CHECK-NEXT: end_borrow [[CASTFAIL_D1]]
444-
// CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
445439
// CHECK-NEXT: br [[NEXT_CASE]]
446440

447441
// CHECK: [[NEXT_CASE]]:
448-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
449-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D2, [[IS_D2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
442+
// CHECK: checked_cast_br [[X]] : $B to $D2, [[IS_D2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
450443
case is D2:
451444
// CHECK: [[IS_D2]]([[CAST_D2:%.*]] : @guaranteed $D2):
452445
// CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
453446
// CHECK: destroy_value [[CAST_D2_COPY]]
454-
// CHECK: end_borrow [[BORROWED_X_COPY]]
455-
// CHECK: destroy_value [[X_COPY]]
456447
// CHECK: function_ref @$s6switch1byyF
457448
// CHECK: br [[CONT]]
458449
b()
459450

460451
// CHECK: [[IS_NOT_D2]]([[CASTFAIL_D2:%.*]] : @guaranteed $B):
461452
// CHECK: end_borrow [[CASTFAIL_D2]]
462-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
463-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
453+
// CHECK: checked_cast_br [[X]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
464454
case is E where funged():
465455
// CHECK: [[IS_E]]([[CAST_E:%.*]] : @guaranteed $E):
466456
// CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
@@ -469,40 +459,34 @@ func test_isa_class_1(x: B) {
469459

470460
// CHECK: [[CASE3]]:
471461
// CHECK: destroy_value [[CAST_E_COPY]]
472-
// CHECK: end_borrow [[BORROWED_X_COPY]]
473-
// CHECK: destroy_value [[X_COPY]]
474462
// CHECK: function_ref @$s6switch1cyyF
475463
// CHECK: br [[CONT]]
476464
c()
477465

478466
// CHECK: [[NO_CASE3]]:
479467
// CHECK-NEXT: destroy_value [[CAST_E_COPY]]
480468
// CHECK-NEXT: end_borrow
481-
// CHECK-NEXT: end_borrow [[BORROWED_X_COPY]]
482469
// CHECK: br [[NEXT_CASE:bb[0-9]+]]
483470

484471
// CHECK: [[IS_NOT_E]]([[NOTCAST_E:%.*]] : @guaranteed $B):
485472
// CHECK: end_borrow [[NOTCAST_E]]
486473
// CHECK: br [[NEXT_CASE]]
487474

488475
// CHECK: [[NEXT_CASE]]:
489-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
490-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $C, [[IS_C:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
476+
// CHECK: checked_cast_br [[X]] : $B to $C, [[IS_C:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
491477

492478
case is C:
493479
// CHECK: [[IS_C]]([[CAST_C:%.*]] : @guaranteed $C):
494480
// CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
495481
// CHECK: destroy_value [[CAST_C_COPY]]
496482
// CHECK: end_borrow [[CAST_C]]
497-
// CHECK: destroy_value [[X_COPY]]
498483
// CHECK: function_ref @$s6switch1dyyF
499484
// CHECK: br [[CONT]]
500485
d()
501486

502487
// CHECK: [[IS_NOT_C]]([[NOCAST_C:%.*]] : @guaranteed $B):
503488
// CHECK: end_borrow [[NOCAST_C]]
504489
default:
505-
// CHECK: destroy_value [[X_COPY]]
506490
// CHECK: function_ref @$s6switch1eyyF
507491
// CHECK: br [[CONT]]
508492
e()
@@ -517,11 +501,9 @@ func test_isa_class_1(x: B) {
517501
// CHECK-LABEL: sil hidden @$s6switch16test_isa_class_21xyXlAA1BC_tF : $@convention(thin)
518502
func test_isa_class_2(x: B) -> AnyObject {
519503
// CHECK: bb0([[X:%.*]] : @guaranteed $B):
520-
// CHECK: [[X_COPY:%.*]] = copy_value [[X]]
521-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
522504
switch x {
523505

524-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
506+
// CHECK: checked_cast_br [[X]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
525507
case let y as D1 where runced():
526508
// CHECK: [[IS_D1]]([[CAST_D1:%.*]] : @guaranteed $D1):
527509
// CHECK: [[CAST_D1_COPY:%.*]] = copy_value [[CAST_D1]]
@@ -535,8 +517,6 @@ func test_isa_class_2(x: B) -> AnyObject {
535517
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D1_COPY_COPY]]
536518
// CHECK: end_borrow [[BORROWED_CAST_D1_COPY]]
537519
// CHECK: destroy_value [[CAST_D1_COPY]]
538-
// CHECK: end_borrow [[BORROWED_X_COPY]]
539-
// CHECK: destroy_value [[X_COPY]] : $B
540520
// CHECK: br [[CONT:bb[0-9]+]]([[RET]] : $AnyObject)
541521
a()
542522
return y
@@ -550,8 +530,7 @@ func test_isa_class_2(x: B) -> AnyObject {
550530
// CHECK: br [[NEXT_CASE]]
551531

552532
// CHECK: [[NEXT_CASE]]:
553-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
554-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $D2, [[CASE2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
533+
// CHECK: checked_cast_br [[X]] : $B to $D2, [[CASE2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
555534
case let y as D2:
556535
// CHECK: [[CASE2]]([[CAST_D2:%.*]] : @guaranteed $D2):
557536
// CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
@@ -561,16 +540,13 @@ func test_isa_class_2(x: B) -> AnyObject {
561540
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D2_COPY_COPY]]
562541
// CHECK: end_borrow [[BORROWED_CAST_D2_COPY]]
563542
// CHECK: destroy_value [[CAST_D2_COPY]]
564-
// CHECK: end_borrow [[BORROWED_X_COPY]]
565-
// CHECK: destroy_value [[X_COPY]]
566543
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
567544
b()
568545
return y
569546

570547
// CHECK: [[IS_NOT_D2]]([[NOCAST_D2:%.*]] : @guaranteed $B):
571548
// CHECK: end_borrow [[NOCAST_D2]]
572-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
573-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
549+
// CHECK: checked_cast_br [[X]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
574550
case let y as E where funged():
575551
// CHECK: [[IS_E]]([[CAST_E:%.*]] : @guaranteed $E):
576552
// CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
@@ -585,7 +561,6 @@ func test_isa_class_2(x: B) -> AnyObject {
585561
// CHECK: end_borrow [[BORROWED_CAST_E_COPY]]
586562
// CHECK: destroy_value [[CAST_E_COPY]]
587563
// CHECK: end_borrow [[CAST_E]]
588-
// CHECK: destroy_value [[X_COPY]] : $B
589564
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
590565
c()
591566
return y
@@ -599,8 +574,7 @@ func test_isa_class_2(x: B) -> AnyObject {
599574
// CHECK: br [[NEXT_CASE]]
600575

601576
// CHECK: [[NEXT_CASE]]
602-
// CHECK: [[BORROWED_X_COPY:%.*]] = begin_borrow [[X_COPY]]
603-
// CHECK: checked_cast_br [[BORROWED_X_COPY]] : $B to $C, [[CASE4:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
577+
// CHECK: checked_cast_br [[X]] : $B to $C, [[CASE4:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
604578
case let y as C:
605579
// CHECK: [[CASE4]]([[CAST_C:%.*]] : @guaranteed $C):
606580
// CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
@@ -610,16 +584,13 @@ func test_isa_class_2(x: B) -> AnyObject {
610584
// CHECK: [[RET:%.*]] = init_existential_ref [[CAST_C_COPY_COPY]]
611585
// CHECK: end_borrow [[BORROWED_CAST_C_COPY]]
612586
// CHECK: destroy_value [[CAST_C_COPY]]
613-
// CHECK: end_borrow [[BORROWED_X_COPY]]
614-
// CHECK: destroy_value [[X_COPY]]
615587
// CHECK: br [[CONT]]([[RET]] : $AnyObject)
616588
d()
617589
return y
618590

619591
// CHECK: [[IS_NOT_C]]([[NOCAST_C:%.*]] : @guaranteed $B):
620592
// CHECK: end_borrow [[NOCAST_C]]
621593
default:
622-
// CHECK: destroy_value [[X_COPY]]
623594
// CHECK: function_ref @$s6switch1eyyF
624595
// CHECK: [[X_COPY_2:%.*]] = copy_value [[X]]
625596
// CHECK: [[RET:%.*]] = init_existential_ref [[X_COPY_2]]
@@ -663,17 +634,15 @@ func test_union_1(u: MaybePair) {
663634
// CHECK: br [[CONT]]
664635
b()
665636

666-
// CHECK: [[IS_RIGHT]]([[STR:%.*]] : @owned $String):
637+
// CHECK: [[IS_RIGHT]]([[STR:%.*]] : @guaranteed $String):
667638
case var .Right:
668-
// CHECK: destroy_value [[STR]] : $String
669639
// CHECK: function_ref @$s6switch1cyyF
670640
// CHECK: br [[CONT]]
671641
c()
672642

673-
// CHECK: [[IS_BOTH]]([[TUP:%.*]] : @owned $(Int, String)):
643+
// CHECK: [[IS_BOTH]]([[TUP:%.*]] : @guaranteed $(Int, String)):
674644
case .Both:
675645
// CHECK: ({{%.*}}, [[TUP_STR:%.*]]) = destructure_tuple [[TUP]]
676-
// CHECK: destroy_value [[TUP_STR]] : $String
677646
// CHECK: function_ref @$s6switch1dyyF
678647
// CHECK: br [[CONT]]
679648
d()
@@ -688,9 +657,7 @@ func test_union_1(u: MaybePair) {
688657
// CHECK-LABEL: sil hidden @$s6switch12test_union_31uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
689658
func test_union_3(u: MaybePair) {
690659
// CHECK: bb0([[ARG:%.*]] : @guaranteed $MaybePair):
691-
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
692-
// CHECK: [[SUBJECT:%.*]] = begin_borrow [[ARG_COPY]]
693-
// CHECK: switch_enum [[SUBJECT]] : $MaybePair,
660+
// CHECK: switch_enum [[ARG]] : $MaybePair,
694661
// CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
695662
// CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
696663
// CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
@@ -716,7 +683,6 @@ func test_union_3(u: MaybePair) {
716683

717684
// CHECK: [[DEFAULT]](
718685
// -- Ensure the fully-opaque value is destroyed in the default case.
719-
// CHECK: destroy_value [[ARG_COPY]] :
720686
// CHECK: function_ref @$s6switch1dyyF
721687
// CHECK: br [[CONT]]
722688

0 commit comments

Comments
 (0)