@@ -9,6 +9,7 @@ import Builtin
99//////////////////
1010
1111typealias AnyObject = Builtin.AnyObject
12+ protocol Error {}
1213
1314enum MyNever {}
1415enum FakeOptional<T> {
@@ -1525,3 +1526,107 @@ bb3(%7 : @owned $FakeOptional<Builtin.NativeObject>):
15251526 %9999 = tuple()
15261527 return %9999 : $()
15271528}
1529+
1530+ // SemanticARCOptVisitor::performGuaranteedCopyValueOptimization should not optimize this case.
1531+ //
1532+ // CHECK-LABEL: sil [ossa] @testDeadInterleavedBorrow : $@convention(c) (@owned FakeOptional<AnyObject>) -> () {
1533+ // CHECK: [[B:%.*]] = begin_borrow [lexical] %0 : $FakeOptional<AnyObject>
1534+ // CHECK: copy_value
1535+ // CHECK: switch_enum
1536+ // CHECK: bb{{.*}}([[COPY:%.*]] : @owned $AnyObject):
1537+ // CHECK: begin_borrow [lexical] [[COPY]] : $AnyObject
1538+ // CHECK: end_borrow [[B]] : $FakeOptional<AnyObject>
1539+ // CHECK: end_borrow
1540+ // CHECK: destroy_value [[COPY]] : $AnyObject
1541+ // CHECK-LABEL: } // end sil function 'testDeadInterleavedBorrow'
1542+ sil [ossa] @testDeadInterleavedBorrow : $@convention(c) (@owned FakeOptional<AnyObject>) -> () {
1543+ bb0(%opt : @owned $FakeOptional<AnyObject>):
1544+ %opt_borrow = begin_borrow [lexical] %opt : $FakeOptional<AnyObject>
1545+ %opt_borrow_copy = copy_value %opt_borrow : $FakeOptional<AnyObject>
1546+ switch_enum %opt_borrow_copy : $FakeOptional<AnyObject>, case #FakeOptional.some!enumelt: some, case #FakeOptional.none!enumelt: none
1547+
1548+ some(%obj : @owned $AnyObject):
1549+ %_borrow = begin_borrow [lexical] %obj : $AnyObject
1550+ end_borrow %opt_borrow : $FakeOptional<AnyObject>
1551+ end_borrow %_borrow : $AnyObject
1552+ destroy_value %obj : $AnyObject
1553+ br die
1554+
1555+ die:
1556+ unreachable
1557+
1558+ none:
1559+ end_borrow %opt_borrow : $FakeOptional<AnyObject>
1560+ br exit
1561+
1562+ exit:
1563+ destroy_value %opt : $FakeOptional<AnyObject>
1564+ %res = tuple ()
1565+ return %res : $()
1566+ }
1567+
1568+ // SemanticARCOptVisitor::performGuaranteedCopyValueOptimization should not optimize this case.
1569+ //
1570+ // CHECK-LABEL: sil [ossa] @testDeadAndAliveInterleavedBorrow : $@convention(c) (@owned FakeOptional<AnyObject>) -> () {
1571+ // CHECK: [[B:%.*]] = begin_borrow [lexical] %0 : $FakeOptional<AnyObject>
1572+ // CHECK: copy_value
1573+ // CHECK: switch_enum
1574+ //
1575+ // CHECK: bb{{.*}}([[COPY:%.*]] : @owned $AnyObject):
1576+ // CHECK: [[BB:%.*]] = begin_borrow [lexical] [[COPY]] : $AnyObject
1577+ //
1578+ // CHECK: try_apply undef
1579+ //
1580+ // CHECK: [[RESULT:%.*]] = apply undef(%{{.*}}) : $@convention(method) (@guaranteed AnyObject) -> @owned FakeOptional<AnyObject>
1581+ // CHECK: switch_enum [[RESULT]] : $FakeOptional<AnyObject>, case #FakeOptional.some!enumelt: {{.*}}, case #FakeOptional.none!enumelt: [[NONEBB:bb[0-9]?]]
1582+ //
1583+ // CHECK: [[NONEBB]]:
1584+ // CHECK: end_borrow [[B]] : $FakeOptional<AnyObject>
1585+ // CHECK: end_borrow [[BB]] : $AnyObject
1586+ // CHECK: destroy_value [[COPY]] : $AnyObject
1587+ // CHECK: destroy_value %0 : $FakeOptional<AnyObject>
1588+ // CHECK-LABEL: } // end sil function 'testDeadAndAliveInterleavedBorrow'
1589+ sil [ossa] @testDeadAndAliveInterleavedBorrow : $@convention(c) (@owned FakeOptional<AnyObject>) -> () {
1590+ bb0(%opt : @owned $FakeOptional<AnyObject>):
1591+ %opt_borrow = begin_borrow [lexical] %opt : $FakeOptional<AnyObject>
1592+ %opt_borrow_copy = copy_value %opt_borrow : $FakeOptional<AnyObject>
1593+ switch_enum %opt_borrow_copy : $FakeOptional<AnyObject>, case #FakeOptional.some!enumelt: some, case #FakeOptional.none!enumelt: none
1594+
1595+ some(%obj : @owned $AnyObject):
1596+ %obj_borrow = begin_borrow [lexical] %obj : $AnyObject
1597+ %obj_borrow_copy = copy_value %obj_borrow : $AnyObject
1598+ try_apply undef(%obj_borrow_copy) : $@convention(method) (@owned AnyObject) -> (@owned AnyObject, @error Error), normal good, error bad
1599+
1600+ good(%obj2 : @owned $AnyObject):
1601+ %obj3 = apply undef(%obj2) : $@convention(method) (@guaranteed AnyObject) -> @owned FakeOptional<AnyObject>
1602+ destroy_value %obj2 : $AnyObject
1603+ switch_enum %obj3 : $FakeOptional<AnyObject>, case #FakeOptional.some!enumelt: good_some, case #FakeOptional.none!enumelt: good_none
1604+
1605+ good_some(%obj4 : @owned $AnyObject):
1606+ destroy_value %obj4 : $AnyObject
1607+ end_borrow %obj_borrow : $AnyObject
1608+ destroy_value %obj : $AnyObject
1609+ br exit
1610+
1611+ good_none:
1612+ end_borrow %opt_borrow : $FakeOptional<AnyObject>
1613+ end_borrow %obj_borrow : $AnyObject
1614+ destroy_value %obj : $AnyObject
1615+ destroy_value %opt : $FakeOptional<AnyObject>
1616+ br die
1617+
1618+ bad(%error1 : @owned $Error):
1619+ br die
1620+
1621+ die:
1622+ unreachable
1623+
1624+ none:
1625+ br exit
1626+
1627+ exit:
1628+ end_borrow %opt_borrow : $FakeOptional<AnyObject>
1629+ destroy_value %opt : $FakeOptional<AnyObject>
1630+ %res = tuple ()
1631+ return %res : $()
1632+ }
0 commit comments