@@ -506,14 +506,19 @@ bb0(%0 : ${ var Int64 }):
506
506
// }
507
507
// Preserve the scope of the outer inout access. Runtime trap expected.
508
508
//
509
+ // FIXME: The optimization should be able to merge these accesses, but
510
+ // it must first prove that no other conflicting read accesses occur
511
+ // within the existing read access scopes.
512
+ //
509
513
// CHECK-LABEL: sil @$s17enforce_with_opts24testInoutWriteEscapeReadyyF : $@convention(thin) () -> () {
510
514
// CHECK: [[BOX:%.*]] = alloc_box ${ var Int64 }, var, name "x"
511
515
// CHECK: [[BOXADR:%.*]] = project_box [[BOX]] : ${ var Int64 }, 0
512
516
// CHECK: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[BOXADR]] : $*Int64
513
517
// CHECK: apply
514
- // CHECK-NOT: begin_access
515
518
// CHECK: end_access [[BEGIN]]
516
- // CHECK-NOT: begin_access
519
+ // CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[BOXADR]] : $*Int64
520
+ // CHECK: load [[BEGIN2]]
521
+ // CHECK: end_access [[BEGIN2]]
517
522
// CHECK-LABEL: } // end sil function '$s17enforce_with_opts24testInoutWriteEscapeReadyyF'
518
523
sil @$s17enforce_with_opts24testInoutWriteEscapeReadyyF : $@convention(thin) () -> () {
519
524
bb0:
@@ -579,14 +584,19 @@ bb0(%0 : ${ var Int64 }):
579
584
// }
580
585
// Preserve the scope of the outer inout access. Runtime trap expected.
581
586
//
587
+ // FIXME: The optimization should be able to merge these accesses, but
588
+ // it must first prove that no other conflicting read accesses occur
589
+ // within the existing read access scopes.
590
+ //
582
591
// CHECK-LABEL: sil @$s17enforce_with_opts020testInoutWriteEscapeF0yyF : $@convention(thin) () -> () {
583
592
// CHECK: [[BOX:%.*]] = alloc_box ${ var Int64 }, var, name "x"
584
593
// CHECK: [[BOXADR:%.*]] = project_box [[BOX]] : ${ var Int64 }, 0
585
594
// CHECK: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[BOXADR]] : $*Int64
586
595
// CHECK: apply
587
- // CHECK-NOT: begin_access
588
596
// CHECK: end_access [[BEGIN]]
589
- // CHECK-NOT: begin_access
597
+ // CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[BOXADR]] : $*Int64
598
+ // CHECK: load [[BEGIN2]]
599
+ // CHECK: end_access [[BEGIN2]]
590
600
// CHECK-LABEL: } // end sil function '$s17enforce_with_opts020testInoutWriteEscapeF0yyF'
591
601
sil @$s17enforce_with_opts020testInoutWriteEscapeF0yyF : $@convention(thin) () -> () {
592
602
bb0:
@@ -999,14 +1009,21 @@ bb0:
999
1009
// public func testOldToNewMapWrite) {
1000
1010
// Checks merging of 3 scopes resulting in a larger modify scope
1001
1011
//
1012
+ // FIXME: The optimization should be able to merge these accesses, but
1013
+ // it must first prove that no other conflicting read accesses occur
1014
+ // within the existing read access scopes.
1015
+ //
1002
1016
// CHECK-LABEL: sil @testOldToNewMapWrite : $@convention(thin) () -> () {
1003
1017
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1004
- // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] : $*X
1005
- // CHECK-NEXT: load [[BEGIN]] : $*X
1006
- // CHECK: store {{.*}} to [[BEGIN]] : $*X
1018
+ // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1007
1019
// CHECK-NEXT: load [[BEGIN]] : $*X
1008
1020
// CHECK-NEXT: end_access [[BEGIN]] : $*X
1009
- // CHECK-NOT: begin_access
1021
+ // CHECK: [[BEGIN2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1022
+ // CHECK-NEXT: store {{.*}} to [[BEGIN2]] : $*X
1023
+ // CHECK-NEXT: end_access [[BEGIN2]] : $*X
1024
+ // CHECK: [[BEGIN3:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1025
+ // CHECK-NEXT: load [[BEGIN3]] : $*X
1026
+ // CHECK-NEXT: end_access [[BEGIN3]] : $*X
1010
1027
// CHECK-LABEL: } // end sil function 'testOldToNewMapWrite'
1011
1028
sil @testOldToNewMapWrite : $@convention(thin) () -> () {
1012
1029
bb0:
@@ -1031,15 +1048,20 @@ bb0:
1031
1048
// public func testDataFlowAcrossBBs() {
1032
1049
// Checks merging of scopes across basic blocks - propagating that information
1033
1050
//
1051
+ // FIXME: The optimization should be able to merge these accesses, but
1052
+ // it must first prove that no other conflicting read accesses occur
1053
+ // within the existing read access scopes.
1054
+ //
1034
1055
// CHECK-LABEL: sil @testDataFlowAcrossBBs : $@convention(thin) () -> () {
1035
1056
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1036
- // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] : $*X
1057
+ // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [ [GLOBAL]] : $*X
1037
1058
// CHECK-NEXT: load [[BEGIN]] : $*X
1059
+ // CHECK-NEXT: end_access [[BEGIN]] : $*X
1038
1060
// CHECK-NEXT: br bb1
1039
1061
// CHECK: br bb2
1040
- // CHECK: load [[BEGIN ]] : $*X
1041
- // CHECK-NEXT: end_access [[BEGIN ]] : $*X
1042
- // CHECK-NOT: begin_access
1062
+ // CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL ]] : $*X
1063
+ // CHECK-NEXT: load [[BEGIN2 ]] : $*X
1064
+ // CHECK-NEXT: end_access [[BEGIN2]] : $*X
1043
1065
// CHECK-LABEL: } // end sil function 'testDataFlowAcrossBBs'
1044
1066
sil @testDataFlowAcrossBBs : $@convention(thin) () -> () {
1045
1067
bb0:
@@ -1063,15 +1085,20 @@ bb2:
1063
1085
// public func testDataFlowAcrossInnerLoop() {
1064
1086
// Checks merging of scopes across an inner loop
1065
1087
//
1088
+ // FIXME: The optimization should be able to merge these accesses, but
1089
+ // it must first prove that no other conflicting read accesses occur
1090
+ // within the existing read access scopes.
1091
+ //
1066
1092
// CHECK-LABEL: sil @testDataFlowAcrossInnerLoop : $@convention(thin) () -> () {
1067
1093
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1068
- // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] : $*X
1094
+ // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [ [GLOBAL]] : $*X
1069
1095
// CHECK-NEXT: load [[BEGIN]] : $*X
1096
+ // CHECK-NEXT: end_access [[BEGIN]] : $*X
1070
1097
// CHECK-NEXT: br bb1
1071
1098
// CHECK: cond_br {{.*}}, bb1, bb2
1072
- // CHECK: load [[BEGIN ]] : $*X
1073
- // CHECK-NEXT: end_access [[BEGIN ]] : $*X
1074
- // CHECK-NOT: begin_access
1099
+ // CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL ]] : $*X
1100
+ // CHECK-NEXT: load [[BEGIN2 ]] : $*X
1101
+ // CHECK-NEXT: end_access [[BEGIN2]] : $*X
1075
1102
// CHECK-LABEL: } // end sil function 'testDataFlowAcrossInnerLoop'
1076
1103
sil @testDataFlowAcrossInnerLoop : $@convention(thin) () -> () {
1077
1104
bb0:
@@ -1248,13 +1275,19 @@ bb4:
1248
1275
// Checks detection of irreducible control flow / bail + parts that we *can* merge
1249
1276
// See disableCrossBlock in the algorithm: this detects this corner case
1250
1277
//
1278
+ // FIXME: The optimization should be able to merge these accesses, but
1279
+ // it must first prove that no other conflicting read accesses occur
1280
+ // within the existing read access scopes.
1281
+ //
1251
1282
// CHECK-LABEL: sil @testIrreducibleGraph2 : $@convention(thin) () -> () {
1252
1283
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1253
- // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify ] [dynamic] [[GLOBAL]] : $*X
1284
+ // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [read ] [dynamic] [no_nested_conflict ] [[GLOBAL]] : $*X
1254
1285
// CHECK-NEXT: load [[BEGIN]] : $*X
1255
- // CHECK-NEXT: br bb1
1256
- // CHECK: load [[BEGIN]] : $*X
1257
1286
// CHECK-NEXT: end_access [[BEGIN]] : $*X
1287
+ // CHECK-NEXT: br bb1
1288
+ // CHECK: [[BEGIN1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1289
+ // CHECK-NEXT: load [[BEGIN1]] : $*X
1290
+ // CHECK-NEXT: end_access [[BEGIN1]] : $*X
1258
1291
// CHECK: cond_br {{.*}}, bb2, bb3
1259
1292
// CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1260
1293
// CHECK-NEXT: load [[BEGIN2]] : $*X
@@ -1390,13 +1423,19 @@ bb0(%0 : $RefElemNoConflictClass):
1390
1423
// During the merge optimization,
1391
1424
// Check that we don't merge cross strongly component boundaries for now
1392
1425
//
1426
+ // FIXME: The optimization should be able to merge these accesses, but
1427
+ // it must first prove that no other conflicting read accesses occur
1428
+ // within the existing read access scopes.
1429
+ //
1393
1430
// CHECK-LABEL: sil @testStronglyConnectedComponent : $@convention(thin) () -> () {
1394
1431
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1395
- // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify ] [dynamic] [[GLOBAL]] : $*X
1432
+ // CHECK-NEXT: [[BEGIN:%.*]] = begin_access [read ] [dynamic] [no_nested_conflict ] [[GLOBAL]] : $*X
1396
1433
// CHECK-NEXT: load [[BEGIN]] : $*X
1397
- // CHECK-NEXT: br bb1
1398
- // CHECK: load [[BEGIN]] : $*X
1399
1434
// CHECK-NEXT: end_access [[BEGIN]] : $*X
1435
+ // CHECK-NEXT: br bb1
1436
+ // CHECK: [[BEGIN1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1437
+ // CHECK-NEXT: load [[BEGIN1]] : $*X
1438
+ // CHECK-NEXT: end_access [[BEGIN1]] : $*X
1400
1439
// CHECK: cond_br {{.*}}, bb2, bb3
1401
1440
// CHECK: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1402
1441
// CHECK-NEXT: load [[BEGIN2]] : $*X
@@ -1555,3 +1594,59 @@ bb3(%1 : $*X):
1555
1594
return %10 : $()
1556
1595
}
1557
1596
1597
+ // --- rdar://48239213: Fatal access conflict detected.
1598
+ //
1599
+ // The read/modify pair of accesses in testReadModifyConflictPair
1600
+ // cannot be merged without introducing a false conflict.
1601
+
1602
+ public class TestClass {
1603
+ @_hasStorage @_hasInitialValue var flags: Int64 { get set }
1604
+ }
1605
+
1606
+ // CHECK-LABEL: sil hidden [noinline] @readFlags : $@convention(method) (Int64, @guaranteed TestClass) -> Bool {
1607
+ // CHECK: bb0(%0 : $Int64, %1 : $TestClass):
1608
+ // CHECK: [[ADR:%.*]] = ref_element_addr %1 : $TestClass, #TestClass.flags
1609
+ // CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[ADR]] : $*Int64
1610
+ // CHECK: load %4 : $*Builtin.Int64
1611
+ // CHECK: end_access
1612
+ // CHECK-LABEL: } // end sil function 'readFlags'
1613
+ sil hidden [noinline] @readFlags : $@convention(method) (Int64, @guaranteed TestClass) -> Bool {
1614
+ bb0(%0 : $Int64, %1 : $TestClass):
1615
+ %2 = ref_element_addr %1 : $TestClass, #TestClass.flags
1616
+ %3 = begin_access [read] [dynamic] [no_nested_conflict] %2 : $*Int64
1617
+ %4 = struct_element_addr %3 : $*Int64, #Int64._value
1618
+ %5 = load %4 : $*Builtin.Int64
1619
+ end_access %3 : $*Int64
1620
+ %7 = struct_extract %0 : $Int64, #Int64._value
1621
+ %8 = builtin "cmp_eq_Int64"(%5 : $Builtin.Int64, %7 : $Builtin.Int64) : $Builtin.Int1
1622
+ %9 = struct $Bool (%8 : $Builtin.Int1)
1623
+ return %9 : $Bool
1624
+ }
1625
+
1626
+ // CHECK-LABEL: sil @testReadModifyConflictPair : $@convention(method) (@guaranteed TestClass) -> () {
1627
+ // CHECK: bb0(%0 : $TestClass):
1628
+ // CHECK: [[ADR:%.*]] = ref_element_addr %0 : $TestClass, #TestClass.flags
1629
+ // CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[ADR]] : $*Int64
1630
+ // CHECK: load
1631
+ // CHECK: end_access
1632
+ // CHECK: apply {{.*}} : $@convention(method) (Int64, @guaranteed TestClass) -> Bool
1633
+ // CHECK: begin_access [modify] [dynamic] [no_nested_conflict] [[ADR]] : $*Int64
1634
+ // CHECK: store
1635
+ // CHECK: end_access
1636
+ // CHECK-LABEL: } // end sil function 'testReadModifyConflictPair'
1637
+ sil @testReadModifyConflictPair : $@convention(method) (@guaranteed TestClass) -> () {
1638
+ bb0(%0 : $TestClass):
1639
+ %1 = ref_element_addr %0 : $TestClass, #TestClass.flags
1640
+ %2 = begin_access [read] [dynamic] %1 : $*Int64
1641
+ %3 = load %2 : $*Int64
1642
+ end_access %2 : $*Int64
1643
+ %5 = function_ref @readFlags : $@convention(method) (Int64, @guaranteed TestClass) -> Bool
1644
+ %6 = apply %5(%3, %0) : $@convention(method) (Int64, @guaranteed TestClass) -> Bool
1645
+ %7 = integer_literal $Builtin.Int64, 3
1646
+ %8 = struct $Int64 (%7 : $Builtin.Int64)
1647
+ %9 = begin_access [modify] [dynamic] %1 : $*Int64
1648
+ store %8 to %9 : $*Int64
1649
+ end_access %9 : $*Int64
1650
+ %12 = tuple ()
1651
+ return %12 : $()
1652
+ }
0 commit comments