1
- // RUN: %target-sil-opt -silgen-cleanup %s | %FileCheck %s
1
+ // RUN: %target-sil-opt -opt-mode=none -silgen-cleanup -sil-verify-all %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB
2
+ // RUN: %target-sil-opt -opt-mode=speed -silgen-cleanup -sil-verify-all %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT
2
3
3
4
import Builtin
4
5
5
6
sil_stage raw
6
7
7
- class Klass {}
8
+ class Klass {
9
+ var property: Builtin.Int64
10
+ }
8
11
class SubKlass : Klass {}
9
12
10
13
sil @use_klass_guaranteed : $@convention(thin) (@guaranteed Klass) -> ()
@@ -33,13 +36,13 @@ struct UInt8 {
33
36
// =============================================================================
34
37
35
38
// CHECK-LABEL: sil [ossa] @struct_extract_load_to_load_struct_element_addr
36
- // CHECK : bb0([[IN:%[0-9]+]] : $*UInt8):
37
- // CHECK -NEXT: [[IN_GEP:%[0-9]+]] = struct_element_addr [[IN]] : $*UInt8, #UInt8._value
38
- // CHECK -NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
39
- // CHECK -NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
40
- // CHECK -NEXT: [[UINT8:%.*]] = struct $UInt8 ([[LITERAL]] : $Builtin.Int8)
41
- // CHECK -NEXT: store [[UINT8]] to [trivial] [[IN]] : $*UInt8
42
- // CHECK -NEXT: return [[IN_LOADED]] : $Builtin.Int8
39
+ // CHECKOPT : bb0([[IN:%[0-9]+]] : $*UInt8):
40
+ // CHECKOPT -NEXT: [[IN_GEP:%[0-9]+]] = struct_element_addr [[IN]] : $*UInt8, #UInt8._value
41
+ // CHECKOPT -NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
42
+ // CHECKOPT -NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
43
+ // CHECKOPT -NEXT: [[UINT8:%.*]] = struct $UInt8 ([[LITERAL]] : $Builtin.Int8)
44
+ // CHECKOPT -NEXT: store [[UINT8]] to [trivial] [[IN]] : $*UInt8
45
+ // CHECKOPT -NEXT: return [[IN_LOADED]] : $Builtin.Int8
43
46
sil [ossa] @struct_extract_load_to_load_struct_element_addr : $@convention(thin) (@inout UInt8) -> (Builtin.Int8) {
44
47
bb0(%0 : $*UInt8):
45
48
%1 = load [trivial] %0 : $*UInt8
@@ -51,13 +54,13 @@ bb0(%0 : $*UInt8):
51
54
}
52
55
53
56
// CHECK-LABEL: sil [ossa] @tuple_extract_load_to_load_tuple_element_addr
54
- // CHECK : bb0([[IN:%[0-9]+]] : $*(Builtin.Int8, Builtin.Int8)):
55
- // CHECK -NEXT: [[IN_GEP:%[0-9]+]] = tuple_element_addr [[IN]] : $*(Builtin.Int8, Builtin.Int8), 0
56
- // CHECK -NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
57
- // CHECK -NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
58
- // CHECK -NEXT: [[IN_STORE_GEP:%[0-9]+]] = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
59
- // CHECK -NEXT: store [[LITERAL]] to [trivial] [[IN_STORE_GEP]] : $*Builtin.Int8
60
- // CHECK -NEXT: return [[IN_LOADED]] : $Builtin.Int8
57
+ // CHECKOPT : bb0([[IN:%[0-9]+]] : $*(Builtin.Int8, Builtin.Int8)):
58
+ // CHECKOPT -NEXT: [[IN_GEP:%[0-9]+]] = tuple_element_addr [[IN]] : $*(Builtin.Int8, Builtin.Int8), 0
59
+ // CHECKOPT -NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
60
+ // CHECKOPT -NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
61
+ // CHECKOPT -NEXT: [[IN_STORE_GEP:%[0-9]+]] = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
62
+ // CHECKOPT -NEXT: store [[LITERAL]] to [trivial] [[IN_STORE_GEP]] : $*Builtin.Int8
63
+ // CHECKOPT -NEXT: return [[IN_LOADED]] : $Builtin.Int8
61
64
sil [ossa] @tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> (Builtin.Int8) {
62
65
bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
63
66
%1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
@@ -101,6 +104,7 @@ bb0(%0 : $*UInt8):
101
104
// CHECK-NEXT: tuple_extract
102
105
// CHECK-NEXT: tuple
103
106
// CHECK-NEXT: return
107
+ // CHECK-LABEL: } // end sil function 'multiple_use_tuple_extract_load_to_load_tuple_element_addr'
104
108
sil [ossa] @multiple_use_tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> ((Builtin.Int8, Builtin.Int8), Builtin.Int8) {
105
109
bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
106
110
%1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
@@ -122,18 +126,18 @@ struct X1 {
122
126
}
123
127
124
128
// CHECK-LABEL: sil private [ossa] @testLoadNontrivial : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
125
- // CHECK -LABEL: bb0(%0 : $*X1):
126
- // CHECK : [[ACCESS:%.*]] = begin_access [read] [unknown] %0 : $*X1
127
- // CHECK : [[AA:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.a
128
- // CHECK : load [trivial] [[AA]] : $*Int
129
- // CHECK : [[OA1:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj1
130
- // CHECK : [[OV1:%.*]] = load [copy] [[OA1]] : $*Builtin.NativeObject
131
- // CHECK : [[OA2:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj2
132
- // CHECK : [[OV2:%.*]] = load [copy] [[OA2]] : $*Builtin.NativeObject
133
- // CHECK : end_access [[ACCESS]] : $*X1
134
- // CHECK : copy_value [[OV1]] : $Builtin.NativeObject
135
- // CHECK : copy_value [[OV2]] : $Builtin.NativeObject
136
- // CHECK : return
129
+ // CHECKOPT -LABEL: bb0(%0 : $*X1):
130
+ // CHECKOPT : [[ACCESS:%.*]] = begin_access [read] [unknown] %0 : $*X1
131
+ // CHECKOPT : [[AA:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.a
132
+ // CHECKOPT : load [trivial] [[AA]] : $*Int
133
+ // CHECKOPT : [[OA1:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj1
134
+ // CHECKOPT : [[OV1:%.*]] = load [copy] [[OA1]] : $*Builtin.NativeObject
135
+ // CHECKOPT : [[OA2:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj2
136
+ // CHECKOPT : [[OV2:%.*]] = load [copy] [[OA2]] : $*Builtin.NativeObject
137
+ // CHECKOPT : end_access [[ACCESS]] : $*X1
138
+ // CHECKOPT : copy_value [[OV1]] : $Builtin.NativeObject
139
+ // CHECKOPT : copy_value [[OV2]] : $Builtin.NativeObject
140
+ // CHECKOPT : return
137
141
// CHECK-LABEL: } // end sil function 'testLoadNontrivial'
138
142
sil private [ossa] @testLoadNontrivial : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
139
143
bb0(%0 : $*X1):
@@ -162,18 +166,18 @@ bb0(%0 : $*X1):
162
166
}
163
167
164
168
// CHECK-LABEL: sil private [ossa] @testLoadBorrowNontrivial : $@convention(thin) (@in_guaranteed X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
165
- // CHECK : bb0([[ADDRESS:%.*]] : $*X1):
166
- // CHECK : [[AA:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.a
167
- // CHECK : load [trivial] [[AA]] : $*Int
168
- // CHECK : [[OA1:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.obj1
169
- // CHECK : [[OV1:%.*]] = load_borrow [[OA1]] : $*Builtin.NativeObject
170
- // CHECK : [[OA2:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.obj2
171
- // CHECK : [[OV2:%.*]] = load_borrow [[OA2]] : $*Builtin.NativeObject
172
- // CHECK : copy_value [[OV1]] : $Builtin.NativeObject
173
- // CHECK : copy_value [[OV2]] : $Builtin.NativeObject
174
- // CHECK : end_borrow [[OV1]]
175
- // CHECK : end_borrow [[OV2]]
176
- // CHECK : return
169
+ // CHECKOPT : bb0([[ADDRESS:%.*]] : $*X1):
170
+ // CHECKOPT : [[AA:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.a
171
+ // CHECKOPT : load [trivial] [[AA]] : $*Int
172
+ // CHECKOPT : [[OA1:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.obj1
173
+ // CHECKOPT : [[OV1:%.*]] = load_borrow [[OA1]] : $*Builtin.NativeObject
174
+ // CHECKOPT : [[OA2:%.*]] = struct_element_addr [[ADDRESS]] : $*X1, #X1.obj2
175
+ // CHECKOPT : [[OV2:%.*]] = load_borrow [[OA2]] : $*Builtin.NativeObject
176
+ // CHECKOPT : copy_value [[OV1]] : $Builtin.NativeObject
177
+ // CHECKOPT : copy_value [[OV2]] : $Builtin.NativeObject
178
+ // CHECKOPT : end_borrow [[OV1]]
179
+ // CHECKOPT : end_borrow [[OV2]]
180
+ // CHECKOPT : return
177
181
// CHECK-LABEL: } // end sil function 'testLoadBorrowNontrivial'
178
182
sil private [ossa] @testLoadBorrowNontrivial : $@convention(thin) (@in_guaranteed X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
179
183
bb0(%0 : $*X1):
@@ -193,11 +197,29 @@ bb0(%0 : $*X1):
193
197
return %result : $(Int, Builtin.NativeObject, Builtin.NativeObject)
194
198
}
195
199
200
+ // FIXME rdar85638376: At -Onone, either preserve the original load
201
+ // with its debug_value. But somehow prevent exclusivity diagnostics
202
+ // from seeing the original load. At -O, generate the following fragments after the loads:
203
+ // HECKOPT: debug_value [[V1]] : $Int, let, name "x1", type $X1, expr op_fragment:#X1.a
204
+ // HECKOPT: debug_value [[V2]] : $Builtin.NativeObject, let, name "x1", type $X1, expr op_fragment:#X1.obj1
205
+ // HECKOPT: debug_value [[V3]] : $Builtin.NativeObject, let, name "x1", type $X1, expr op_fragment:#X1.obj2
206
+ //
207
+ // CHECK-LABEL: sil private [ossa] @testLoadWithDebugInfo : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
208
+ // CHECK: bb0(%0 : $*X1):
209
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] %0 : $*X1
210
+ // CHECK: [[A1:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.a
211
+ // CHECK: [[V1:%.*]] = load [trivial] [[A1]] : $*Int
212
+ // CHECK: [[A2:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj1
213
+ // CHECK: [[V2:%.*]] = load [copy] [[A2]] : $*Builtin.NativeObject
214
+ // CHECK: [[A3:%.*]] = struct_element_addr [[ACCESS]] : $*X1, #X1.obj2
215
+ // CHECK: [[V3:%.*]] = load [copy] [[A3]] : $*Builtin.NativeObject
216
+ // CHECK: end_access [[ACCESS]] : $*X1
217
+ // CHECK-LABEL: } // end sil function 'testLoadWithDebugInfo'
196
218
sil private [ossa] @testLoadWithDebugInfo : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
197
219
bb0(%0 : $*X1):
198
220
%access = begin_access [read] [unknown] %0 : $*X1
199
221
%load = load [copy] %access : $*X1
200
- debug_value %load : $Int , let, name "x1"
222
+ debug_value %load : $X1 , let, name "x1"
201
223
end_access %access : $*X1
202
224
203
225
%borrowa = begin_borrow %load : $X1
@@ -260,10 +282,10 @@ bb0(%0 : $*X3, %1 : @guaranteed $Builtin.NativeObject):
260
282
// We used to hit a memory error on this test.
261
283
//
262
284
// CHECK-LABEL: sil [ossa] @testDestructureTupleNoCrash : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.NativeObject)) -> () {
263
- // CHECK : bb0(
264
- // CHECK -NEXT: destroy_value
265
- // CHECK -NEXT: tuple
266
- // CHECK -NEXT: return
285
+ // CHECKOPT : bb0(
286
+ // CHECKOPT -NEXT: destroy_value
287
+ // CHECKOPT -NEXT: tuple
288
+ // CHECKOPT -NEXT: return
267
289
// CHECK: } // end sil function 'testDestructureTupleNoCrash'
268
290
sil [ossa] @testDestructureTupleNoCrash : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.NativeObject)) -> () {
269
291
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.NativeObject)):
@@ -278,4 +300,65 @@ bb0(%0 : @owned $(Builtin.NativeObject, Builtin.NativeObject)):
278
300
destroy_value %1 : $Builtin.NativeObject
279
301
%9999 = tuple()
280
302
return %9999 : $()
281
- }
303
+ }
304
+
305
+ // debug_value must be preserved after eliminating the borrow.
306
+ //
307
+ // CHECK-LABEL: sil [ossa] @testBorrowElimination : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
308
+ // CHECK: bb0(%0 : @guaranteed $Builtin.NativeObject):
309
+ // CHECK: debug_value %0 : $Builtin.NativeObject, let, name "var"
310
+ // CHECK: [[CP:%.*]] = copy_value %0 : $Builtin.NativeObject
311
+ // CHECK: return [[CP]] : $Builtin.NativeObject
312
+ // CHECK-LABEL: } // end sil function 'testBorrowElimination'
313
+ sil [ossa] @testBorrowElimination : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
314
+ bb0(%0 : @guaranteed $Builtin.NativeObject):
315
+ %1 = begin_borrow %0 : $Builtin.NativeObject
316
+ debug_value %1 : $Builtin.NativeObject, let, name "var"
317
+ %3 = copy_value %1 : $Builtin.NativeObject
318
+ end_borrow %1 : $Builtin.NativeObject
319
+ return %3 : $Builtin.NativeObject
320
+ }
321
+
322
+ // debug_value must be preserved after eliminating the copy.
323
+ //
324
+ // FIXME: eliminateSimpleCopies removes all debug_values. Instead,
325
+ // debug_value should be canonicalized first, before SILGenCleanup
326
+ // eliminates copies.
327
+ //
328
+ // CHECK-LABEL: sil [ossa] @testCopyElimination : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
329
+ // CHECK: bb0(%0 : @guaranteed $Builtin.NativeObject):
330
+ // CHECK: [[CP:%.*]] = copy_value %0 : $Builtin.NativeObject
331
+ // CHECKDEB: [[CP2:%.*]] = copy_value %0 : $Builtin.NativeObject
332
+ // CHECKDEB: debug_value [[CP2]] : $Builtin.NativeObject, let, name "var"
333
+ // CHECK: return [[CP]] : $Builtin.NativeObject
334
+ // CHECK-LABEL: } // end sil function 'testCopyElimination'
335
+ sil [ossa] @testCopyElimination : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
336
+ bb0(%0 : @guaranteed $Builtin.NativeObject):
337
+ %1 = copy_value %0 : $Builtin.NativeObject
338
+ %2 = copy_value %0 : $Builtin.NativeObject
339
+ debug_value %2 : $Builtin.NativeObject, let, name "var"
340
+ destroy_value %2 : $Builtin.NativeObject
341
+ return %1 : $Builtin.NativeObject
342
+ }
343
+
344
+ // Test SemanticARCOpts eliminateSimpleCopies. At -O, remove the
345
+ // debug_value with the copy to avoid a lifetime violation. -Onone, do nothing.
346
+ //
347
+ // CHECK-LABEL: sil [ossa] @testSimpleCopyWithDebug : $@convention(thin) (@owned Klass) -> Builtin.Int64 {
348
+ // CHECKOPT-NOT: copy_value
349
+ // CHECKOPT-NOT: debug_value
350
+ // CHECKDEB: copy_value
351
+ // CHECKDEB: debug_value
352
+ // CHECK-LABEL: } // end sil function 'testSimpleCopyWithDebug'
353
+ sil [ossa] @testSimpleCopyWithDebug : $@convention(thin) (@owned Klass) -> Builtin.Int64 {
354
+ bb9(%0 : @owned $Klass):
355
+ %borrow = begin_borrow %0 : $Klass
356
+ %p = ref_element_addr %borrow : $Klass, #Klass.property
357
+ %v = load [trivial] %p : $*Builtin.Int64
358
+ %copy = copy_value %borrow : $Klass
359
+ end_borrow %borrow : $Klass
360
+ debug_value %copy : $Klass, let, name "c"
361
+ destroy_value %copy : $Klass
362
+ destroy_value %0 : $Klass
363
+ return %v : $Builtin.Int64
364
+ }
0 commit comments