@@ -8,6 +8,13 @@ sil_stage canonical
88import Builtin
99import Swift
1010
11+ class Storage {
12+ init()
13+ }
14+
15+ // globalArray
16+ sil_global @globalArray : $Storage
17+
1118// CHECK-LABEL: @memset
1219
1320// CHECK: bb0
@@ -1397,3 +1404,71 @@ bb6:
13971404 return %15 : $()
13981405}
13991406
1407+ struct UInt64 {
1408+ @_hasStorage var _value: Builtin.Int64 { get set }
1409+ init(_value: Builtin.Int64)
1410+ }
1411+
1412+ public struct UInt64Wrapper {
1413+ @_hasStorage public var rawValue: UInt64 { get set }
1414+ private init(_ rawValue: UInt64)
1415+ public init()
1416+ }
1417+
1418+ // rdar://92191909 (LICM assertion: isSubObjectProjection(), MemAccessUtils.h, line 1069)
1419+ //
1420+ // projectLoadValue needs to rematerialize a loaded value within the
1421+ // loop using projections and the loop-invariant address is an
1422+ // index_addr.
1423+ //
1424+ // The store inside the loop is deleted, and the load is hoisted such
1425+ // that it now loads the UInt64Wrapper instead of Builtin.Int64
1426+ // CHECK-LABEL: sil @testTailProjection : $@convention(thin) () -> () {
1427+ // CHECK: bb0:
1428+ // CHECK: [[A:%.*]] = index_addr %4 : $*UInt64Wrapper, %1 : $Builtin.Word
1429+ // CHECK: store %{{.*}} to [[A]] : $*UInt64Wrapper
1430+ // CHECK: load %5 : $*UInt64Wrapper
1431+ // CHECK: br bb1
1432+ // CHECK: bb1(%{{.*}} : $Builtin.Int64, %{{.*}} : $UInt64Wrapper, [[PHI:%.*]] : $UInt64Wrapper):
1433+ // CHECK: cond_br undef, bb3, bb2
1434+ // CHECK: bb2:
1435+ // CHECK-NOT: (load|store)
1436+ // CHECK: struct_extract [[PHI]] : $UInt64Wrapper, #UInt64Wrapper.rawValue
1437+ // CHECK: struct_extract
1438+ // CHECK: struct $UInt64
1439+ // CHECK: struct $UInt64Wrapper
1440+ // CHECK-NOT: (load|store)
1441+ // CHECK: br bb1
1442+ // CHECK: bb3:
1443+ // CHECK: store [[PHI]] to [[A]] : $*UInt64Wrapper
1444+ // CHECK-LABEL: } // end sil function 'testTailProjection'
1445+ sil @testTailProjection : $@convention(thin) () -> () {
1446+ bb0:
1447+ %0 = integer_literal $Builtin.Int64, 0
1448+ %1 = integer_literal $Builtin.Word, 1
1449+ %2 = integer_literal $Builtin.Word, 2
1450+ %3 = alloc_ref [tail_elems $UInt64Wrapper * %2 : $Builtin.Word] $Storage
1451+ %4 = ref_tail_addr %3 : $Storage, $UInt64Wrapper
1452+ %5 = index_addr %4 : $*UInt64Wrapper, %1 : $Builtin.Word
1453+ %6 = struct $UInt64 (%0 : $Builtin.Int64)
1454+ %7 = struct $UInt64Wrapper (%6 : $UInt64)
1455+ store %7 to %5 : $*UInt64Wrapper
1456+ %9 = load %5 : $*UInt64Wrapper
1457+ br bb1(%0 : $Builtin.Int64, %9 : $UInt64Wrapper)
1458+
1459+ bb1(%11 : $Builtin.Int64, %12 : $UInt64Wrapper):
1460+ cond_br undef, bb3, bb2
1461+
1462+ bb2:
1463+ %14 = struct_element_addr %5 : $*UInt64Wrapper, #UInt64Wrapper.rawValue
1464+ %15 = struct_element_addr %14 : $*UInt64, #UInt64._value
1465+ %16 = load %15 : $*Builtin.Int64
1466+ %17 = struct $UInt64 (%16 : $Builtin.Int64)
1467+ %18 = struct $UInt64Wrapper (%17 : $UInt64)
1468+ store %18 to %5 : $*UInt64Wrapper
1469+ br bb1(%16 : $Builtin.Int64, %18 : $UInt64Wrapper)
1470+
1471+ bb3:
1472+ %21 = tuple ()
1473+ return %21 : $()
1474+ }
0 commit comments