@@ -39,13 +39,17 @@ public enum FakeOptional<T> {
39
39
case some(T)
40
40
}
41
41
42
+ @_moveOnly struct MOS {}
42
43
43
44
sil [ossa] @getKlass : $@convention(thin) () -> @owned Klass
45
+ sil [ossa] @getNonTrivialStruct : $@convention(thin) () -> @owned NonTrivialStruct
46
+ sil [ossa] @getMOS : $@convention(thin) () -> @owned MOS
44
47
45
48
sil @unknown : $@convention(thin) () -> ()
46
49
47
50
sil [ossa] @guaranteed_user : $@convention(thin) (@guaranteed Klass) -> ()
48
51
sil [ossa] @guaranteed_user_with_result : $@convention(thin) (@guaranteed Klass) -> @out Klass
52
+ sil [ossa] @inguaranteed_user_without_result_NTS : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
49
53
50
54
sil [ossa] @inguaranteed_user_without_result : $@convention(thin) (@in_guaranteed Klass) -> () {
51
55
bb0(%0 : $*Klass):
@@ -767,8 +771,7 @@ bb0(%0 : $*Builtin.NativeObject):
767
771
//
768
772
// CHECK-LABEL: sil [ossa] @takeWithLoadRelease : $@convention(thin) (@in Builtin.NativeObject) -> () {
769
773
// CHECK: bb0(%0 : $*Builtin.NativeObject):
770
- // CHECK: [[V:%.*]] = load [copy] %0 : $*Builtin.NativeObject
771
- // CHECK: destroy_addr %0 : $*Builtin.NativeObject
774
+ // CHECK: [[V:%.*]] = load [take] %0 : $*Builtin.NativeObject
772
775
// CHECK: apply %{{.*}}([[V]]) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
773
776
// CHECK: destroy_value [[V]] : $Builtin.NativeObject
774
777
// CHECK-LABEL: } // end sil function 'takeWithLoadRelease'
@@ -1516,9 +1519,7 @@ bb2:
1516
1519
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Klass
1517
1520
// CHECK: store [[INSTANCE_1]] to [init] [[ADDR]]
1518
1521
// CHECK: apply [[USER]]([[ADDR]])
1519
- // CHECK: [[INSTANCE_2:%[^,]+]] = load [copy] [[ADDR]]
1520
- // Extra copy: ^^^^^^^^^^^
1521
- // CHECK: destroy_addr [[ADDR]]
1522
+ // CHECK: [[INSTANCE_2:%[^,]+]] = load [take] [[ADDR]]
1522
1523
// CHECK: dealloc_stack [[ADDR]]
1523
1524
// CHECK: return [[INSTANCE_2]]
1524
1525
// CHECK-LABEL: } // end sil function 'take_from_original_copy_addr__final_use_load_take'
@@ -1545,9 +1546,7 @@ sil [ossa] @take_from_original_copy_addr__final_use_load_take : $() -> @owned Kl
1545
1546
// CHECK: [[SRC:%[^,]+]] = alloc_stack $Klass
1546
1547
// CHECK: store [[INSTANCE_1]] to [init] [[SRC]]
1547
1548
// CHECK: apply [[USER]]([[SRC]])
1548
- // CHECK: copy_addr [[SRC]] to [init] [[OUT]]
1549
- // Extra copy: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1550
- // CHECK: destroy_addr [[SRC]]
1549
+ // CHECK: copy_addr [take] [[SRC]] to [init] [[OUT]]
1551
1550
// CHECK: dealloc_stack [[SRC]]
1552
1551
// CHECK-LABEL: } // end sil function 'take_from_original_copy_addr__final_use_copy_addr_take'
1553
1552
sil [ossa] @take_from_original_copy_addr__final_use_copy_addr_take : $() -> @out Klass {
@@ -1567,6 +1566,68 @@ entry(%out : $*Klass):
1567
1566
return %retval : $()
1568
1567
}
1569
1568
1569
+ // CHECK-LABEL: sil [ossa] @take_from_original_copy_addr__final_use_field_load_copy : {{.*}} {
1570
+ // CHECK: [[GET:%[^,]+]] = function_ref @getNonTrivialStruct
1571
+ // CHECK: [[USER:%[^,]+]] = function_ref @inguaranteed_user_without_result_NTS
1572
+ // CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
1573
+ // CHECK: [[SRC:%[^,]+]] = alloc_stack $NonTrivialStruct
1574
+ // CHECK: store [[INSTANCE]] to [init] [[SRC]]
1575
+ // CHECK: apply [[USER]]([[SRC]])
1576
+ // CHECK: [[FIELD_ADDR:%[^,]+]] = struct_element_addr [[SRC]]
1577
+ // CHECK: [[FIELD:%[^,]+]] = load [copy] [[FIELD_ADDR]]
1578
+ // CHECK: destroy_addr [[SRC]]
1579
+ // CHECK: dealloc_stack [[SRC]]
1580
+ // CHECK: return [[FIELD]]
1581
+ // CHECK-LABEL: } // end sil function 'take_from_original_copy_addr__final_use_field_load_copy'
1582
+ sil [ossa] @take_from_original_copy_addr__final_use_field_load_copy : $() -> @owned Klass {
1583
+ %get = function_ref @getNonTrivialStruct : $@convention(thin) () -> @owned NonTrivialStruct
1584
+ %user = function_ref @inguaranteed_user_without_result_NTS : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
1585
+ %instance_1 = apply %get() : $@convention(thin) () -> @owned NonTrivialStruct
1586
+ %src = alloc_stack $NonTrivialStruct
1587
+ store %instance_1 to [init] %src : $*NonTrivialStruct
1588
+ apply %user(%src) : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
1589
+ %tmp = alloc_stack $NonTrivialStruct
1590
+ copy_addr [take] %src to [init] %tmp : $*NonTrivialStruct
1591
+ %field_addr = struct_element_addr %tmp : $*NonTrivialStruct, #NonTrivialStruct.val
1592
+ %field = load [copy] %field_addr : $*Klass
1593
+ destroy_addr %tmp : $*NonTrivialStruct
1594
+ dealloc_stack %tmp : $*NonTrivialStruct
1595
+ dealloc_stack %src : $*NonTrivialStruct
1596
+ return %field : $Klass
1597
+ }
1598
+
1599
+ // CHECK-LABEL: sil [ossa] @take_from_original_copy_addr__final_use_field_copy_addr_take : {{.*}} {
1600
+ // CHECK: {{bb[0-9]+}}([[OUT:%[^,]+]] :
1601
+ // CHECK: [[GET:%[^,]+]] = function_ref @getNonTrivialStruct
1602
+ // CHECK: [[USER:%[^,]+]] = function_ref @inguaranteed_user_without_result_NTS
1603
+ // CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
1604
+ // CHECK: [[SRC:%[^,]+]] = alloc_stack $NonTrivialStruct
1605
+ // CHECK: store [[INSTANCE]] to [init] [[SRC]]
1606
+ // CHECK: apply [[USER]]([[SRC]])
1607
+ // CHECK: [[FIELD_ADDR:%[^,]+]] = struct_element_addr [[SRC]]
1608
+ // CHECK: copy_addr [[FIELD_ADDR]] to [init] [[OUT]]
1609
+ // CHECK: destroy_addr [[SRC]]
1610
+ // CHECK: dealloc_stack [[SRC]]
1611
+ // CHECK-LABEL: } // end sil function 'take_from_original_copy_addr__final_use_field_copy_addr_take'
1612
+ sil [ossa] @take_from_original_copy_addr__final_use_field_copy_addr_take : $() -> @out Klass {
1613
+ entry(%out : $*Klass):
1614
+ %getNonTrivialStruct = function_ref @getNonTrivialStruct : $@convention(thin) () -> @owned NonTrivialStruct
1615
+ %user = function_ref @inguaranteed_user_without_result_NTS : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
1616
+ %instance_1 = apply %getNonTrivialStruct() : $@convention(thin) () -> @owned NonTrivialStruct
1617
+ %src = alloc_stack $NonTrivialStruct
1618
+ store %instance_1 to [init] %src : $*NonTrivialStruct
1619
+ apply %user(%src) : $@convention(thin) (@in_guaranteed NonTrivialStruct) -> ()
1620
+ %tmp = alloc_stack $NonTrivialStruct
1621
+ copy_addr [take] %src to [init] %tmp : $*NonTrivialStruct
1622
+ %field_addr = struct_element_addr %tmp : $*NonTrivialStruct, #NonTrivialStruct.val
1623
+ copy_addr %field_addr to [init] %out : $*Klass
1624
+ destroy_addr %tmp : $*NonTrivialStruct
1625
+ dealloc_stack %tmp : $*NonTrivialStruct
1626
+ dealloc_stack %src : $*NonTrivialStruct
1627
+ %retval = tuple ()
1628
+ return %retval : $()
1629
+ }
1630
+
1570
1631
// CHECK-LABEL: sil [ossa] @take_from_original_copy_addr__final_use_load_copy : {{.*}} {
1571
1632
// CHECK: [[GET:%[^,]+]] = function_ref @getKlass
1572
1633
// CHECK: [[USER:%[^,]+]] = function_ref @inguaranteed_user_without_result
@@ -1703,3 +1764,31 @@ entry(%instance : $*NonTrivialStruct):
1703
1764
%retval = tuple ()
1704
1765
return %retval : $()
1705
1766
}
1767
+
1768
+ // Verify that no copy of an instance of the move-only type MOS is introduced.
1769
+ // CHECK-LABEL: sil hidden [ossa] @dont_copy_move_only_struct : {{.*}} {
1770
+ // CHECK: [[SRC:%[^,]+]] = alloc_stack $MOS
1771
+ // CHECK: [[GET:%[^,]+]] = function_ref @getMOS
1772
+ // CHECK: [[INSTANCE_1:%[^,]+]] = apply [[GET]]()
1773
+ // CHECK: store [[INSTANCE_1]] to [init] [[SRC]]
1774
+ // CHECK: [[INSTANCE_2:%[^,]+]] = load [take] [[SRC]]
1775
+ // CHECK: store [[INSTANCE_2]] to [init] [[SRC]]
1776
+ // CHECK: [[INSTANCE_3:%[^,]+]] = load [take] [[SRC]]
1777
+ // CHECK: dealloc_stack [[SRC]]
1778
+ // CHECK: return [[INSTANCE_3]]
1779
+ // CHECK-LABEL: } // end sil function 'dont_copy_move_only_struct'
1780
+ sil hidden [ossa] @dont_copy_move_only_struct : $@convention(thin) () -> @owned MOS {
1781
+ bb0:
1782
+ %src = alloc_stack $MOS
1783
+ %getMOS = function_ref @getMOS : $@convention(thin) () -> @owned MOS
1784
+ %instance_1 = apply %getMOS() : $@convention(thin) () -> @owned MOS
1785
+ store %instance_1 to [init] %src : $*MOS
1786
+ %tmp = alloc_stack $MOS
1787
+ copy_addr [take] %src to [init] %tmp : $*MOS
1788
+ %instance_2 = load [take] %tmp : $*MOS
1789
+ store %instance_2 to [init] %src : $*MOS
1790
+ %instance_3 = load [take] %src : $*MOS
1791
+ dealloc_stack %tmp : $*MOS
1792
+ dealloc_stack %src : $*MOS
1793
+ return %instance_3 : $MOS
1794
+ }
0 commit comments