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
23
34import Builtin
45
56sil_stage raw
67
7- class Klass {}
8+ class Klass {
9+ var property: Builtin.Int64
10+ }
811class SubKlass : Klass {}
912
1013sil @use_klass_guaranteed : $@convention(thin) (@guaranteed Klass) -> ()
@@ -33,13 +36,13 @@ struct UInt8 {
3336// =============================================================================
3437
3538// 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
4346sil [ossa] @struct_extract_load_to_load_struct_element_addr : $@convention(thin) (@inout UInt8) -> (Builtin.Int8) {
4447bb0(%0 : $*UInt8):
4548 %1 = load [trivial] %0 : $*UInt8
@@ -51,13 +54,13 @@ bb0(%0 : $*UInt8):
5154}
5255
5356// 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
6164sil [ossa] @tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> (Builtin.Int8) {
6265bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
6366 %1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
@@ -101,6 +104,7 @@ bb0(%0 : $*UInt8):
101104// CHECK-NEXT: tuple_extract
102105// CHECK-NEXT: tuple
103106// CHECK-NEXT: return
107+ // CHECK-LABEL: } // end sil function 'multiple_use_tuple_extract_load_to_load_tuple_element_addr'
104108sil [ossa] @multiple_use_tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> ((Builtin.Int8, Builtin.Int8), Builtin.Int8) {
105109bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
106110 %1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
@@ -122,18 +126,18 @@ struct X1 {
122126}
123127
124128// 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
137141// CHECK-LABEL: } // end sil function 'testLoadNontrivial'
138142sil private [ossa] @testLoadNontrivial : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
139143bb0(%0 : $*X1):
@@ -162,18 +166,18 @@ bb0(%0 : $*X1):
162166}
163167
164168// 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
177181// CHECK-LABEL: } // end sil function 'testLoadBorrowNontrivial'
178182sil private [ossa] @testLoadBorrowNontrivial : $@convention(thin) (@in_guaranteed X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
179183bb0(%0 : $*X1):
@@ -193,11 +197,29 @@ bb0(%0 : $*X1):
193197 return %result : $(Int, Builtin.NativeObject, Builtin.NativeObject)
194198}
195199
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'
196218sil private [ossa] @testLoadWithDebugInfo : $@convention(thin) (@inout_aliasable X1) -> (Int, @owned Builtin.NativeObject, @owned Builtin.NativeObject) {
197219bb0(%0 : $*X1):
198220 %access = begin_access [read] [unknown] %0 : $*X1
199221 %load = load [copy] %access : $*X1
200- debug_value %load : $Int , let, name "x1"
222+ debug_value %load : $X1 , let, name "x1"
201223 end_access %access : $*X1
202224
203225 %borrowa = begin_borrow %load : $X1
@@ -260,10 +282,10 @@ bb0(%0 : $*X3, %1 : @guaranteed $Builtin.NativeObject):
260282// We used to hit a memory error on this test.
261283//
262284// 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
267289// CHECK: } // end sil function 'testDestructureTupleNoCrash'
268290sil [ossa] @testDestructureTupleNoCrash : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.NativeObject)) -> () {
269291bb0(%0 : @owned $(Builtin.NativeObject, Builtin.NativeObject)):
@@ -278,4 +300,65 @@ bb0(%0 : @owned $(Builtin.NativeObject, Builtin.NativeObject)):
278300 destroy_value %1 : $Builtin.NativeObject
279301 %9999 = tuple()
280302 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