Skip to content

Commit 4d715e6

Browse files
authored
Merge pull request swiftlang#29276 from atrick/test-stackpromote
Add test cases for EscapeAnalysis.
2 parents 5d3e8b5 + 17cfa93 commit 4d715e6

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// RUN: %target-sil-opt %s -escapes-dump -o /dev/null | %FileCheck %s
2+
3+
// REQUIRES: asserts
4+
// REQUIRES: OS=macosx
5+
// REQUIRES: PTRSIZE=64
6+
7+
sil_stage canonical
8+
9+
import Builtin
10+
import Swift
11+
import SwiftShims
12+
13+
// =============================================================================
14+
// Test call to array.uninitialized that has extra release_value uses
15+
16+
class C {
17+
var c: C
18+
}
19+
20+
class DummyArrayStorage<Element> {
21+
@_hasStorage var count: Int { get }
22+
@_hasStorage var capacity: Int { get }
23+
init()
24+
}
25+
26+
// init_any_array_with_buffer
27+
sil [_semantics "array.uninitialized"] @init_any_array_with_buffer : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
28+
29+
// CHECK-LABEL: CG of testBadArrayUninit
30+
// CHECK-NEXT: Val [ref] %2 Esc: , Succ: (%2.1)
31+
// CHECK-NEXT: Con [int] %2.1 Esc: G, Succ: (%2.2)
32+
// CHECK-NEXT: Con [ref] %2.2 Esc: G, Succ:
33+
// CHECK-NEXT: Val %5 Esc: , Succ: (%5.1)
34+
// CHECK-NEXT: Con %5.1 Esc: G, Succ: %10
35+
// CHECK-NEXT: Val [ref] %10 Esc: G, Succ: (%10.1)
36+
// CHECK-NEXT: Con %10.1 Esc: G, Succ:
37+
// CHECK-LABEL: End
38+
sil hidden @testBadArrayUninit : $@convention(thin) (Builtin.Word, Int32) -> () {
39+
bb0(%0 : $Builtin.Word, %1 : $Int32):
40+
// create an array
41+
%2 = alloc_ref [tail_elems $AnyObject * %0 : $Builtin.Word] $DummyArrayStorage<AnyObject>
42+
%3 = metatype $@thin Array<AnyObject>.Type
43+
%4 = function_ref @init_any_array_with_buffer : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
44+
%5 = apply %4(%2, %1, %3) : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
45+
%6 = tuple_extract %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>), 0
46+
%7 = tuple_extract %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>), 1
47+
%8 = struct_extract %7 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
48+
%9 = pointer_to_address %8 : $Builtin.RawPointer to [strict] $*AnyObject
49+
50+
// store an elt
51+
%10 = alloc_ref $C
52+
%11 = init_existential_ref %10 : $C : $C, $AnyObject
53+
store %11 to %9 : $*AnyObject
54+
55+
// extra use of the call
56+
release_value %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>) // id: %228
57+
%13 = tuple ()
58+
return %13 : $()
59+
}
60+
61+
// =============================================================================
62+
// testArrayEscapeToBox: test that an array is marked escaping when
63+
// assigned to a box. When multiple arrays are merged into the same
64+
// box, ensure that a previous mapping from the project_box address to
65+
// the box's content is not lost during the merge.
66+
67+
class ElementClass {
68+
init()
69+
}
70+
71+
class StagedContext {
72+
init()
73+
}
74+
75+
class VFSStagedContext : StagedContext {
76+
override init()
77+
}
78+
79+
// specialized Array.init()
80+
sil @$sS2ayxGycfCSo12ElementClassC_Tg5 : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass>
81+
82+
// specialized Array._getCount()
83+
sil @$sSa9_getCountSiyFSo12ElementClassC_Tg5 : $@convention(method) (@guaranteed Array<ElementClass>) -> Int
84+
85+
// specialized static Array._adoptStorage(_:count:)
86+
sil shared [_semantics "array.uninitialized"] @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) {
87+
// %0 // users: %13, %3
88+
// %1 // users: %9, %4
89+
bb0(%0 : $_ContiguousArrayStorage<ElementClass>, %1 : $Int, %2 : $@thin Array<ElementClass>.Type):
90+
%3 = upcast %0 : $_ContiguousArrayStorage<ElementClass> to $__ContiguousArrayStorageBase // users: %17, %11
91+
%4 = struct_extract %1 : $Int, #Int._value // user: %6
92+
%5 = integer_literal $Builtin.Int64, 1 // users: %7, %6
93+
%6 = builtin "shl_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 // user: %7
94+
%7 = builtin "or_Int64"(%6 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 // user: %8
95+
%8 = struct $UInt (%7 : $Builtin.Int64) // user: %9
96+
%9 = struct $_SwiftArrayBodyStorage (%1 : $Int, %8 : $UInt) // user: %10
97+
%10 = struct $_ArrayBody (%9 : $_SwiftArrayBodyStorage) // user: %12
98+
%11 = ref_element_addr %3 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity // user: %12
99+
store %10 to %11 : $*_ArrayBody // id: %12
100+
%13 = unchecked_ref_cast %0 : $_ContiguousArrayStorage<ElementClass> to $Builtin.BridgeObject // user: %14
101+
%14 = struct $_BridgeStorage<__ContiguousArrayStorageBase> (%13 : $Builtin.BridgeObject) // user: %15
102+
%15 = struct $_ArrayBuffer<ElementClass> (%14 : $_BridgeStorage<__ContiguousArrayStorageBase>) // user: %16
103+
%16 = struct $Array<ElementClass> (%15 : $_ArrayBuffer<ElementClass>) // user: %20
104+
%17 = ref_tail_addr %3 : $__ContiguousArrayStorageBase, $ElementClass // user: %18
105+
%18 = address_to_pointer %17 : $*ElementClass to $Builtin.RawPointer // user: %19
106+
%19 = struct $UnsafeMutablePointer<ElementClass> (%18 : $Builtin.RawPointer) // user: %20
107+
%20 = tuple (%16 : $Array<ElementClass>, %19 : $UnsafeMutablePointer<ElementClass>) // user: %21
108+
return %20 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // id: %21
109+
}
110+
111+
// testArrayUsePointsClosure1
112+
sil @testArrayUsePointsClosure1 : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> ()
113+
114+
// testArrayUsePointsClosure2
115+
sil @testArrayUsePointsClosure2 : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> ()
116+
117+
// Make sure both locally allocated array's are globally escaping.
118+
//
119+
// CHECK-LABEL: CG of testArrayEscapeToBox
120+
// CHECK-NEXT: Arg [ref] %0 Esc: A, Succ: (%21)
121+
// CHECK-NEXT: Val [ref] %1 Esc: , Succ: (%21)
122+
// CHECK-NEXT: Val [ref] %4 Esc: , Succ: %0, %1
123+
// CHECK-NEXT: Val [ref] %8 Esc: , Succ: (%21)
124+
// CHECK-NEXT: Val [ref] %12 Esc: G, Succ: (%21)
125+
// CHECK-NEXT: Val [ref] %17 Esc: G, Succ: (%21)
126+
// CHECK-NEXT: Val [ref] %20 Esc: G, Succ: %17
127+
// CHECK-NEXT: Con [int] %21 Esc: G, Succ: (%39)
128+
// CHECK-NEXT: Val [ref] %31 Esc: G, Succ: (%21)
129+
// CHECK-NEXT: Val [ref] %34 Esc: G, Succ: %31
130+
// CHECK-NEXT: Con %39 Esc: G, Succ: (%21), %12, %20, %34
131+
// CHECK-NEXT: Val [ref] %45 Esc: , Succ: %0, %8, %39
132+
// CHECK-NEXT: End
133+
sil private @testArrayEscapeToBox : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> () {
134+
// %0 // users: %54, %51, %47, %45, %5, %4
135+
bb0(%0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()):
136+
%1 = alloc_box ${ var Optional<VFSStagedContext> }, var, name "context" // users: %59, %6, %4, %2
137+
%2 = project_box %1 : ${ var Optional<VFSStagedContext> }, 0 // user: %44
138+
// function_ref testArrayUsePointsClosure1
139+
%3 = function_ref @testArrayUsePointsClosure1 : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> () // user: %4
140+
%4 = partial_apply [callee_guaranteed] %3(%1, %0) : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> ()
141+
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %5
142+
strong_retain %1 : ${ var Optional<VFSStagedContext> } // id: %6
143+
br bb1 // id: %7
144+
145+
bb1: // Preds: bb0
146+
%8 = alloc_box ${ var Array<ElementClass> }, var, name "intents" // users: %58, %56, %52, %48, %45, %9
147+
%9 = project_box %8 : ${ var Array<ElementClass> }, 0 // users: %41, %36, %27, %22, %13
148+
%10 = metatype $@thin Array<ElementClass>.Type // users: %33, %19, %12
149+
// function_ref specialized Array.init()
150+
%11 = function_ref @$sS2ayxGycfCSo12ElementClassC_Tg5 : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass> // user: %12
151+
%12 = apply %11(%10) : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass> // user: %13
152+
store %12 to %9 : $*Array<ElementClass> // id: %13
153+
cond_br undef, bb2, bb3 // id: %14
154+
155+
bb2: // Preds: bb1
156+
%15 = integer_literal $Builtin.Int64, 1 // user: %16
157+
%16 = struct $Int (%15 : $Builtin.Int64) // user: %19
158+
%17 = alloc_ref [tail_elems $ElementClass * undef : $Builtin.Word] $_ContiguousArrayStorage<ElementClass> // user: %19
159+
// function_ref specialized static Array._adoptStorage(_:count:)
160+
%18 = function_ref @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // user: %19
161+
%19 = apply %18(%17, %16, %10) : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // users: %21, %20
162+
%20 = tuple_extract %19 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 0 // user: %27
163+
%21 = tuple_extract %19 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 1
164+
%22 = struct_element_addr %9 : $*Array<ElementClass>, #Array._buffer // user: %23
165+
%23 = struct_element_addr %22 : $*_ArrayBuffer<ElementClass>, #_ArrayBuffer._storage // user: %24
166+
%24 = struct_element_addr %23 : $*_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue // user: %25
167+
%25 = load %24 : $*Builtin.BridgeObject // user: %26
168+
strong_release %25 : $Builtin.BridgeObject // id: %26
169+
store %20 to %9 : $*Array<ElementClass> // id: %27
170+
br bb4 // id: %28
171+
172+
bb3: // Preds: bb1
173+
%29 = integer_literal $Builtin.Int64, 1 // user: %30
174+
%30 = struct $Int (%29 : $Builtin.Int64) // user: %33
175+
%31 = alloc_ref [tail_elems $ElementClass * undef : $Builtin.Word] $_ContiguousArrayStorage<ElementClass> // user: %33
176+
// function_ref specialized static Array._adoptStorage(_:count:)
177+
%32 = function_ref @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // user: %33
178+
%33 = apply %32(%31, %30, %10) : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // users: %35, %34
179+
%34 = tuple_extract %33 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 0 // user: %41
180+
%35 = tuple_extract %33 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 1
181+
%36 = struct_element_addr %9 : $*Array<ElementClass>, #Array._buffer // user: %37
182+
%37 = struct_element_addr %36 : $*_ArrayBuffer<ElementClass>, #_ArrayBuffer._storage // user: %38
183+
%38 = struct_element_addr %37 : $*_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue // user: %39
184+
%39 = load %38 : $*Builtin.BridgeObject // user: %40
185+
strong_release %39 : $Builtin.BridgeObject // id: %40
186+
store %34 to %9 : $*Array<ElementClass> // id: %41
187+
br bb4 // id: %42
188+
189+
bb4: // Preds: bb3 bb2
190+
// function_ref testArrayUsePointsClosure2
191+
%43 = function_ref @testArrayUsePointsClosure2 : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> () // user: %45
192+
%44 = load %2 : $*Optional<VFSStagedContext> // users: %55, %53, %49, %45
193+
%45 = partial_apply [callee_guaranteed] %43(%0, %44, %8) : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> () // user: %57
194+
// function_ref specialized Array._getCount()
195+
%46 = function_ref @$sSa9_getCountSiyFSo12ElementClassC_Tg5 : $@convention(method) (@guaranteed Array<ElementClass>) -> Int
196+
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %47
197+
strong_retain %8 : ${ var Array<ElementClass> } // id: %48
198+
retain_value %44 : $Optional<VFSStagedContext> // id: %49
199+
br bb5 // id: %50
200+
201+
bb5: // Preds: bb4
202+
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %51
203+
strong_retain %8 : ${ var Array<ElementClass> } // id: %52
204+
retain_value %44 : $Optional<VFSStagedContext> // id: %53
205+
strong_release %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %54
206+
release_value %44 : $Optional<VFSStagedContext> // id: %55
207+
strong_release %8 : ${ var Array<ElementClass> } // id: %56
208+
strong_release %45 : $@callee_guaranteed () -> () // id: %57
209+
strong_release %8 : ${ var Array<ElementClass> } // id: %58
210+
strong_release %1 : ${ var Optional<VFSStagedContext> } // id: %59
211+
br bb6 // id: %60
212+
213+
bb6: // Preds: bb5
214+
%61 = tuple () // user: %62
215+
return %61 : $() // id: %62
216+
}

0 commit comments

Comments
 (0)