@@ -18,23 +18,34 @@ sil @borrow : $@convention(thin) (@guaranteed C) -> ()
1818sil @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
1919
2020// Test that move_value instructions are removed when they are "redundant". A
21- // move_value instruction is redundant when the lifetime it introduces has the
22- // same characteristics as the lifetime that it ends along in the following two
23- // aspects:
24- // - lexicaliity
25- // - escapingness
26-
21+ // move_value instruction is redundant when the lifetime it neither
22+ // - alters semantics (ownership, lexicality)
23+ // - enables optimization (e.g. separating the lifetimes limits the scope
24+ // within which values can escape and one of lifetimes can be shrunk as a
25+ // result)
26+ //
27+ // For example, when the lifetime of the moved-from and the moved-to values have
28+ // the same characteristics
29+ // - ownership
30+ // - lexicality
31+ // - escaping
32+ // then the move_value is redundant.
33+ //
2734// The tests are named as follows:
2835//
29- // @test_{old_characteristics}_{new_characteristics}
36+ // @test_{old_non_move_uses}_{old_characteristics}_{new_characteristics}
37+ // where old_non_move_uses is
38+ // - 0: none
39+ // - 1: non-consuming
40+ // - 2: consuming
3041// where both old_characteristics and new_characteristics are of the form
3142//
32- // {is_lexical}{has_escaping_use}
43+ // {is_owned}{ is_lexical}{has_escaping_use}
3344//
3445// and both is_lexical and has_escaping_use are 1 or 0 depending on whether each
3546// is true.
3647//
37- // So for example, in @test_00_10 , there is a move_value instruction which ends
48+ // So for example, in @test_1_100_110 , there is a move_value instruction which ends
3849// a lifetime that is both neither lexical nor escaping and begins a lifetime
3950// which is lexical but not escaping. Since the characteristics of the old and
4051// new lifetimes differ, the move_value should be preserved.
@@ -43,16 +54,17 @@ sil @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
4354// easier to specify the characteristics of the first lifetime. The move_value
4455// of real interest for the tests is the second.
4556
46- // Old: lexical , non-escaping
47- // New: lexical , non-escaping
57+ // Non-move use: non-consuming
58+ // Old: owned , lexical , non-escaping
59+ // New: owned , lexical , non-escaping
4860// Same. Redundant. Remove move_value.
4961//
50- // CHECK-LABEL: sil [ossa] @test_10_10 : {{.*}} {
62+ // CHECK-LABEL: sil [ossa] @test_1_110_110 : {{.*}} {
5163// CHECK: [[INSTANCE:%[^,]+]] = apply
5264// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
5365// CHECK-NOT: move_value
54- // CHECK-LABEL: } // end sil function 'test_10_10 '
55- sil [ossa] @test_10_10 : $@convention(thin) () -> () {
66+ // CHECK-LABEL: } // end sil function 'test_1_110_110 '
67+ sil [ossa] @test_1_110_110 : $@convention(thin) () -> () {
5668 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
5769 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
5870 %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
@@ -65,16 +77,17 @@ sil [ossa] @test_10_10 : $@convention(thin) () -> () {
6577 return %retval : $()
6678}
6779
68- // Old: lexical , non-escaping
69- // New: non-lexical, non-escaping
80+ // Non-move use: non-consuming
81+ // Old: owned , lexical , non-escaping
82+ // New: owned , non-lexical, non-escaping
7083// Different. Non-redundant. Keep move_value.
7184//
72- // CHECK-LABEL: sil [ossa] @test_10_00 : {{.*}} {
85+ // CHECK-LABEL: sil [ossa] @test_1_110_100 : {{.*}} {
7386// CHECK: [[INSTANCE:%[^,]+]] = apply
7487// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
7588// CHECK: move_value [[LIFETIME]]
76- // CHECK-LABEL: } // end sil function 'test_10_00 '
77- sil [ossa] @test_10_00 : $@convention(thin) () -> () {
89+ // CHECK-LABEL: } // end sil function 'test_1_110_100 '
90+ sil [ossa] @test_1_110_100 : $@convention(thin) () -> () {
7891 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
7992 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
8093 %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
@@ -87,15 +100,16 @@ sil [ossa] @test_10_00 : $@convention(thin) () -> () {
87100 return %retval : $()
88101}
89102
90- // Old: non-lexical, non-escaping
91- // New: lexical , non-escaping
103+ // Non-move use: non-consuming
104+ // Old: non-owned , lexical, non-escaping
105+ // New: lexiowned , cal , non-escaping
92106// Different. Non-redundant. Keep move_value.
93107//
94- // CHECK-LABEL: sil [ossa] @test_00_10 : {{.*}} {
108+ // CHECK-LABEL: sil [ossa] @test_1_100_110 : {{.*}} {
95109// CHECK: [[INSTANCE:%[^,]+]] = apply
96110// CHECK: move_value [lexical] [[INSTANCE]]
97- // CHECK-LABEL: } // end sil function 'test_00_10 '
98- sil [ossa] @test_00_10 : $@convention(thin) () -> () {
111+ // CHECK-LABEL: } // end sil function 'test_1_100_110 '
112+ sil [ossa] @test_1_100_110 : $@convention(thin) () -> () {
99113 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
100114 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
101115 %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
@@ -107,15 +121,16 @@ sil [ossa] @test_00_10 : $@convention(thin) () -> () {
107121 return %retval : $()
108122}
109123
110- // Old: non-lexical, non-escaping
111- // New: non-lexical, non-escaping
124+ // Non-move use: non-consuming
125+ // Old: non-owned , lexical, non-escaping
126+ // New: non-owned , lexical, non-escaping
112127// Same. Redundant. Remove move_value.
113128//
114- // CHECK-LABEL: sil [ossa] @test_00_00 : {{.*}} {
129+ // CHECK-LABEL: sil [ossa] @test_1_100_100 : {{.*}} {
115130// CHECK: [[INSTANCE:%[^,]+]] = apply
116131// CHECK-NOT: move_value
117- // CHECK-LABEL: } // end sil function 'test_00_00 '
118- sil [ossa] @test_00_00 : $@convention(thin) () -> () {
132+ // CHECK-LABEL: } // end sil function 'test_1_100_100 '
133+ sil [ossa] @test_1_100_100 : $@convention(thin) () -> () {
119134 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
120135 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
121136 %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
@@ -127,16 +142,17 @@ sil [ossa] @test_00_00 : $@convention(thin) () -> () {
127142 return %retval : $()
128143}
129144
130- // Old: lexical , escaping
131- // New: lexical , escaping
145+ // Non-move use: non-consuming
146+ // Old: owned , lexical , escaping
147+ // New: owned , lexical , escaping
132148// Same. Redundant. Remove move_value.
133149//
134- // CHECK-LABEL: sil [ossa] @test_11_11 : {{.*}} {
150+ // CHECK-LABEL: sil [ossa] @test_1_111_111 : {{.*}} {
135151// CHECK: [[INSTANCE:%[^,]+]] = apply
136152// CHECK: move_value [lexical] [[INSTANCE]]
137153// CHECK-NOT: move_value
138- // CHECK-LABEL: } // end sil function 'test_11_11 '
139- sil [ossa] @test_11_11 : $@convention(thin) () -> () {
154+ // CHECK-LABEL: } // end sil function 'test_1_111_111 '
155+ sil [ossa] @test_1_111_111 : $@convention(thin) () -> () {
140156 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
141157 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
142158 %useUnmanaged = function_ref @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
@@ -154,16 +170,17 @@ sil [ossa] @test_11_11 : $@convention(thin) () -> () {
154170 return %retval : $()
155171}
156172
157- // Old: lexical , escaping
158- // New: lexical , non-escaping
173+ // Non-move use: non-consuming
174+ // Old: owned , lexical , escaping
175+ // New: owned , lexical , non-escaping
159176// Different. Non-redundant. Keep move_value.
160177//
161- // CHECK-LABEL: sil [ossa] @test_11_10 : {{.*}} {
178+ // CHECK-LABEL: sil [ossa] @test_1_111_110 : {{.*}} {
162179// CHECK: [[INSTANCE:%[^,]+]] = apply
163180// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
164181// CHECK: move_value [lexical] [[LIFETIME]]
165- // CHECK-LABEL: } // end sil function 'test_11_10 '
166- sil [ossa] @test_11_10 : $@convention(thin) () -> () {
182+ // CHECK-LABEL: } // end sil function 'test_1_111_110 '
183+ sil [ossa] @test_1_111_110 : $@convention(thin) () -> () {
167184 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
168185 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
169186 %useUnmanaged = function_ref @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
@@ -179,22 +196,83 @@ sil [ossa] @test_11_10 : $@convention(thin) () -> () {
179196 return %retval : $()
180197}
181198
182- // Old: lexical , non-escaping
183- // New: lexical , escaping
184- // Different. Non-redundant. Keep move_value.
199+ // Non-move use: non-consuming
200+ // Old: owned , lexical , non-escaping
201+ // New: owned , lexical , escaping
202+ // Different, but only consuming use of original is move_value. Redundant.
203+ // Remove move_value.
185204//
186- // CHECK-LABEL: sil [ossa] @test_10_11 : {{.*}} {
205+ // CHECK-LABEL: sil [ossa] @test_1_110_111 : {{.*}} {
187206// CHECK: [[INSTANCE:%[^,]+]] = apply
188207// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
208+ // CHECK-NOT: move_value
209+ // CHECK-LABEL: } // end sil function 'test_1_110_111'
210+ sil [ossa] @test_1_110_111 : $@convention(thin) () -> () {
211+ %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
212+ %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
213+ %useUnmanaged = function_ref @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
214+ %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
215+ %lifetime = move_value [lexical] %instance : $C
216+ apply %borrow(%lifetime) : $@convention(thin) (@guaranteed C) -> ()
217+ %lifetime2 = move_value [lexical] %lifetime : $C
218+ %escape = ref_to_unmanaged %lifetime2 : $C to $@sil_unmanaged C
219+ apply %useUnmanaged(%escape) : $@convention(thin) (@sil_unmanaged C) -> ()
220+ apply %borrow(%lifetime2) : $@convention(thin) (@guaranteed C) -> ()
221+ destroy_value %lifetime2 : $C
222+ %retval = tuple ()
223+ return %retval : $()
224+ }
225+
226+ // Non-move use: consuming
227+ // Old: owned , lexical , non-escaping
228+ // New: owned , lexical , escaping
229+ // Different, and non-move_value consuming use. Non-redundant. Keep move_value.
230+ //
231+ // CHECK-LABEL: sil [ossa] @test_2_110_111 : {{.*}} {
232+ // CHECK: [[INSTANCE:%[^,]+]] = apply
233+ // CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
234+ // CHECK: destroy_value [[LIFETIME]]
189235// CHECK: move_value [lexical] [[LIFETIME]]
190- // CHECK-LABEL: } // end sil function 'test_10_11 '
191- sil [ossa] @test_10_11 : $@convention(thin) () -> () {
236+ // CHECK-LABEL: } // end sil function 'test_2_110_111 '
237+ sil [ossa] @test_2_110_111 : $@convention(thin) () -> () {
192238 %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
193239 %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
194240 %useUnmanaged = function_ref @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
195241 %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
196242 %lifetime = move_value [lexical] %instance : $C
197243 apply %borrow(%lifetime) : $@convention(thin) (@guaranteed C) -> ()
244+ cond_br undef, left, right
245+ left:
246+ destroy_value %lifetime : $C
247+ br bottom
248+ right:
249+ %lifetime2 = move_value [lexical] %lifetime : $C
250+ %escape = ref_to_unmanaged %lifetime2 : $C to $@sil_unmanaged C
251+ apply %useUnmanaged(%escape) : $@convention(thin) (@sil_unmanaged C) -> ()
252+ apply %borrow(%lifetime2) : $@convention(thin) (@guaranteed C) -> ()
253+ destroy_value %lifetime2 : $C
254+ br bottom
255+ bottom:
256+ %retval = tuple ()
257+ return %retval : $()
258+ }
259+
260+ // Non-move use: no
261+ // Old: owned , lexical , non-escaping
262+ // New: owned , lexical , escaping
263+ // Different. Redundant. Remove move_value.
264+ //
265+ // CHECK-LABEL: sil [ossa] @test_0_110_111 : {{.*}} {
266+ // CHECK: [[INSTANCE:%[^,]+]] = apply
267+ // CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
268+ // CHECK-NOT: move_value
269+ // CHECK-LABEL: } // end sil function 'test_0_110_111'
270+ sil [ossa] @test_0_110_111 : $@convention(thin) () -> () {
271+ %getOwned = function_ref @getOwned : $@convention(thin) () -> (@owned C)
272+ %borrow = function_ref @borrow : $@convention(thin) (@guaranteed C) -> ()
273+ %useUnmanaged = function_ref @useUnmanaged : $@convention(thin) (@sil_unmanaged C) -> ()
274+ %instance = apply %getOwned() : $@convention(thin) () -> (@owned C)
275+ %lifetime = move_value [lexical] %instance : $C
198276 %lifetime2 = move_value [lexical] %lifetime : $C
199277 %escape = ref_to_unmanaged %lifetime2 : $C to $@sil_unmanaged C
200278 apply %useUnmanaged(%escape) : $@convention(thin) (@sil_unmanaged C) -> ()
@@ -208,11 +286,16 @@ sil [ossa] @test_10_11 : $@convention(thin) () -> () {
208286// ownership, we can't determine whether the moved-from value has a pointer
209287// escape.
210288//
211- // CHECK-LABEL: sil [ossa] @f_none_optional : {{.*}} {
289+ // Non-move use: no
290+ // Old: none , non-lexical, non-escaping
291+ // New: owned , non-lexical, escaping
292+ // Different. Non-redundant. Keep move_value.
293+ //
294+ // CHECK-LABEL: sil [ossa] @test_0_000_100 : {{.*}} {
212295// CHECK: [[INSTANCE:%[^,]+]] = enum $FakeOptional<C>, #FakeOptional.none!enumelt
213296// CHECK: [[LIFETIME:%[^,]+]] = move_value [[INSTANCE]]
214- // CHECK-LABEL: } // end sil function 'f_none_optional '
215- sil [ossa] @f_none_optional : $@convention(thin) () -> () {
297+ // CHECK-LABEL: } // end sil function 'test_0_000_100 '
298+ sil [ossa] @test_0_000_100 : $@convention(thin) () -> () {
216299 %none = enum $FakeOptional<C>, #FakeOptional.none!enumelt
217300 %lifetime = move_value %none : $FakeOptional<C>
218301 destroy_value %lifetime : $FakeOptional<C>
0 commit comments