mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
352 lines
14 KiB
Plaintext
352 lines
14 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -onone-simplification -simplify-instruction=load | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ONONE
|
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -simplification -simplify-instruction=load | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-O
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
import Swift
|
|
import Builtin
|
|
|
|
struct Str {
|
|
@_hasStorage let x: Int64
|
|
@_hasStorage let y: (Int64, Int64)
|
|
}
|
|
|
|
sil_global [let] @gstr : $Str = {
|
|
%0 = integer_literal $Builtin.Int64, 10
|
|
%1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
%2 = integer_literal $Builtin.Int64, 27
|
|
%3 = struct $Int64 (%2 : $Builtin.Int64)
|
|
%4 = tuple (%1 : $Int64, %3 : $Int64)
|
|
%initval = struct $Str (%1 : $Int64, %4 : $(Int64, Int64))
|
|
}
|
|
|
|
class B { }
|
|
class E : B { }
|
|
|
|
sil [global_init] @gstr_addressor : $@convention(thin) () -> Builtin.RawPointer {
|
|
bb0:
|
|
%0 = global_addr @gstr : $*Str
|
|
%1 = address_to_pointer %0 : $*Str to $Builtin.RawPointer
|
|
return %1 : $Builtin.RawPointer
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_global_simple
|
|
// CHECK-DAG: [[L27:%.*]] = integer_literal $Builtin.Int64, 27
|
|
// CHECK-DAG: [[I27:%.*]] = struct $Int64 ([[L27]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[L10:%.*]] = integer_literal $Builtin.Int64, 10
|
|
// CHECK-DAG: [[I10:%.*]] = struct $Int64 ([[L10]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[T:%.*]] = tuple ([[I10]] : $Int64, [[I27]] : $Int64)
|
|
// CHECK: [[STR:%.*]] = struct $Str ([[I10]] : $Int64, [[T]] : $(Int64, Int64))
|
|
// CHECK: return [[STR]]
|
|
// CHECK: } // end sil function 'load_global_simple'
|
|
sil @load_global_simple : $@convention(thin) () -> Str {
|
|
bb0:
|
|
%0 = global_addr @gstr : $*Str
|
|
%1 = begin_access [read] [static] %0 : $*Str
|
|
%2 = load %1 : $*Str
|
|
end_access %1 : $*Str
|
|
return %2 : $Str
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_global_via_addressor
|
|
// CHECK-NOT: apply
|
|
// CHECK-DAG: [[L27:%.*]] = integer_literal $Builtin.Int64, 27
|
|
// CHECK-DAG: [[I27:%.*]] = struct $Int64 ([[L27]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[L10:%.*]] = integer_literal $Builtin.Int64, 10
|
|
// CHECK-DAG: [[I10:%.*]] = struct $Int64 ([[L10]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[T:%.*]] = tuple ([[I10]] : $Int64, [[I27]] : $Int64)
|
|
// CHECK: [[STR:%.*]] = struct $Str ([[I10]] : $Int64, [[T]] : $(Int64, Int64))
|
|
// CHECK: return [[STR]]
|
|
// CHECK: } // end sil function 'load_global_via_addressor'
|
|
sil @load_global_via_addressor : $@convention(thin) () -> Str {
|
|
bb0:
|
|
%0 = function_ref @gstr_addressor : $@convention(thin) () -> Builtin.RawPointer
|
|
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Str
|
|
%3 = load %2 : $*Str
|
|
return %3 : $Str
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_global_struct_element
|
|
// CHECK-NOT: global_addr
|
|
// CHECK-DAG: [[L10:%.*]] = integer_literal $Builtin.Int64, 10
|
|
// CHECK-DAG: [[I10:%.*]] = struct $Int64 ([[L10]] : $Builtin.Int64)
|
|
// CHECK: return [[I10]]
|
|
// CHECK: } // end sil function 'load_global_struct_element'
|
|
sil @load_global_struct_element : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @gstr : $*Str
|
|
%1 = struct_element_addr %0 : $*Str, #Str.x
|
|
%2 = load %1 : $*Int64
|
|
return %2 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_global_struct_tuple
|
|
// CHECK-NOT: global_addr
|
|
// CHECK-DAG: [[L27:%.*]] = integer_literal $Builtin.Int64, 27
|
|
// CHECK-DAG: [[I27:%.*]] = struct $Int64 ([[L27]] : $Builtin.Int64)
|
|
// CHECK: return [[I27]]
|
|
// CHECK: } // end sil function 'load_global_struct_tuple'
|
|
sil @load_global_struct_tuple : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @gstr : $*Str
|
|
%1 = struct_element_addr %0 : $*Str, #Str.y
|
|
%2 = tuple_element_addr %1 : $*(Int64, Int64), 1
|
|
%3 = load %2 : $*Int64
|
|
return %3 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_first_char_from_string_literal
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 97
|
|
// CHECK-NEXT: return %0
|
|
// CHECK: } // end sil function 'load_first_char_from_string_literal'
|
|
sil @load_first_char_from_string_literal : $@convention(thin) () -> Builtin.Int8 {
|
|
bb0:
|
|
%0 = string_literal utf8 "abc123a"
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%2 = struct_element_addr %1 : $*UInt8, #UInt8._value
|
|
%3 = load %2 : $*Builtin.Int8
|
|
return %3 : $Builtin.Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_from_string_literal
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 49
|
|
// CHECK-NEXT: return %0
|
|
// CHECK: } // end sil function 'load_from_string_literal'
|
|
sil @load_from_string_literal : $@convention(thin) () -> Builtin.Int8 {
|
|
bb0:
|
|
%0 = string_literal utf8 "abc123a"
|
|
%1 = integer_literal $Builtin.Word, 3
|
|
%2 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%3 = index_addr %2 : $*UInt8, %1 : $Builtin.Word
|
|
%4 = struct_element_addr %3 : $*UInt8, #UInt8._value
|
|
%5 = load %4 : $*Builtin.Int8
|
|
return %5 : $Builtin.Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_addrcast_to_upcast :
|
|
// CHECK: bb0(%0 : $*E):
|
|
// CHECK-NEXT: %1 = load %0
|
|
// CHECK-NEXT: %2 = upcast %1 : $E to $B
|
|
// CHECK-NEXT: return %2
|
|
// CHECK: } // end sil function 'load_addrcast_to_upcast'
|
|
sil @load_addrcast_to_upcast : $@convention(thin) (@inout E) -> B {
|
|
bb0(%0 : $*E):
|
|
%1 = unchecked_addr_cast %0 : $*E to $*B
|
|
%2 = load %1 : $*B
|
|
return %2 : $B
|
|
}
|
|
|
|
struct _SwiftEmptyArrayStorage {
|
|
}
|
|
|
|
class __EmptyArrayStorage {
|
|
}
|
|
|
|
class __ContiguousArrayStorageBase : __EmptyArrayStorage {
|
|
@_hasStorage let countAndCapacity: _ArrayBody
|
|
}
|
|
|
|
struct _ArrayBody {
|
|
@_hasStorage let _storage: _SwiftArrayBodyStorage
|
|
}
|
|
|
|
struct _SwiftArrayBodyStorage {
|
|
@_hasStorage let count: Int64
|
|
@_hasStorage let _capacityAndFlags: Int64
|
|
}
|
|
|
|
struct _SwiftEmptySetSingleton {
|
|
}
|
|
|
|
class __EmptySetSingleton {
|
|
}
|
|
|
|
class __RawSetStorage : __EmptySetSingleton {
|
|
@_hasStorage let _count: Int64
|
|
@_hasStorage let _capacity: Int64
|
|
}
|
|
|
|
struct _SwiftEmptyDictionarySingleton {
|
|
}
|
|
|
|
class __EmptyDictionarySingleton {
|
|
}
|
|
|
|
class __RawDictionaryStorage : __EmptyDictionarySingleton {
|
|
@_hasStorage let _count: Int64
|
|
@_hasStorage let _capacity: Int64
|
|
}
|
|
|
|
sil_global @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage
|
|
sil_global @_swiftEmptySetSingleton : $_SwiftEmptySetSingleton
|
|
sil_global @_swiftEmptyDictionarySingleton : $_SwiftEmptyDictionarySingleton
|
|
|
|
// CHECK-LABEL: sil @load_count_from_empty_array :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'load_count_from_empty_array'
|
|
sil @load_count_from_empty_array : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%3 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
|
|
%4 = address_to_pointer [stack_protection] %3 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
|
|
%5 = raw_pointer_to_ref %4 : $Builtin.RawPointer to $__EmptyArrayStorage
|
|
%6 = unchecked_ref_cast %5 : $__EmptyArrayStorage to $__ContiguousArrayStorageBase
|
|
%8 = ref_element_addr [immutable] %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
%9 = struct_element_addr %8 : $*_ArrayBody, #_ArrayBody._storage
|
|
%10 = struct_element_addr %9 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count
|
|
%11 = struct_element_addr %10 : $*Int64, #Int64._value
|
|
%12 = load %11 : $*Builtin.Int64
|
|
%15 = struct $Int64 (%12 : $Builtin.Int64)
|
|
return %15 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_capacity_from_empty_array :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = integer_literal $Builtin.Int64, 1
|
|
// CHECK-NEXT: %2 = builtin "lshr_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64)
|
|
// CHECK-NEXT: %3 = struct $Int64 (%2 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %3
|
|
// CHECK: } // end sil function 'load_capacity_from_empty_array'
|
|
sil @load_capacity_from_empty_array : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%3 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
|
|
%4 = address_to_pointer [stack_protection] %3 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
|
|
%5 = raw_pointer_to_ref %4 : $Builtin.RawPointer to $__EmptyArrayStorage
|
|
%6 = unchecked_ref_cast %5 : $__EmptyArrayStorage to $__ContiguousArrayStorageBase
|
|
%8 = ref_element_addr [immutable] %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
%9 = struct_element_addr %8 : $*_ArrayBody, #_ArrayBody._storage
|
|
%10 = struct_element_addr %9 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage._capacityAndFlags
|
|
%11 = struct_element_addr %10 : $*Int64, #Int64._value
|
|
%12 = load %11 : $*Builtin.Int64
|
|
%13 = integer_literal $Builtin.Int64, 1
|
|
%14 = builtin "lshr_Int64"(%12 : $Builtin.Int64, %13 : $Builtin.Int64) : $Builtin.Int64
|
|
%15 = struct $Int64 (%14 : $Builtin.Int64)
|
|
return %15 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @dont_load_capacity_and_flags_from_empty_array :
|
|
// CHECK: [[X:%.*]] = load
|
|
// CHECK: [[I:%.*]] = struct $Int64 ([[X]]
|
|
// CHECK: return [[I]]
|
|
// CHECK: } // end sil function 'dont_load_capacity_and_flags_from_empty_array'
|
|
sil @dont_load_capacity_and_flags_from_empty_array : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%3 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
|
|
%4 = address_to_pointer [stack_protection] %3 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
|
|
%5 = raw_pointer_to_ref %4 : $Builtin.RawPointer to $__EmptyArrayStorage
|
|
%6 = unchecked_ref_cast %5 : $__EmptyArrayStorage to $__ContiguousArrayStorageBase
|
|
%8 = ref_element_addr [immutable] %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
%9 = struct_element_addr %8 : $*_ArrayBody, #_ArrayBody._storage
|
|
%10 = struct_element_addr %9 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage._capacityAndFlags
|
|
%11 = struct_element_addr %10 : $*Int64, #Int64._value
|
|
%12 = load %11 : $*Builtin.Int64
|
|
%15 = struct $Int64 (%12 : $Builtin.Int64)
|
|
return %15 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_count_from_empty_set :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'load_count_from_empty_set'
|
|
sil @load_count_from_empty_set : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @_swiftEmptySetSingleton : $*_SwiftEmptySetSingleton
|
|
%1 = address_to_pointer [stack_protection] %0 : $*_SwiftEmptySetSingleton to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $__EmptySetSingleton
|
|
%3 = unchecked_ref_cast %2 : $__EmptySetSingleton to $__RawSetStorage
|
|
%5 = ref_element_addr %3 : $__RawSetStorage, #__RawSetStorage._count
|
|
%6 = struct_element_addr %5 : $*Int64, #Int64._value
|
|
%7 = load %6 : $*Builtin.Int64
|
|
%9 = struct $Int64 (%7 : $Builtin.Int64)
|
|
return %9 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_capacity_from_empty_set :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'load_capacity_from_empty_set'
|
|
sil @load_capacity_from_empty_set : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @_swiftEmptySetSingleton : $*_SwiftEmptySetSingleton
|
|
%1 = address_to_pointer [stack_protection] %0 : $*_SwiftEmptySetSingleton to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $__EmptySetSingleton
|
|
%3 = unchecked_ref_cast %2 : $__EmptySetSingleton to $__RawSetStorage
|
|
%5 = ref_element_addr %3 : $__RawSetStorage, #__RawSetStorage._capacity
|
|
%6 = struct_element_addr %5 : $*Int64, #Int64._value
|
|
%7 = load %6 : $*Builtin.Int64
|
|
%9 = struct $Int64 (%7 : $Builtin.Int64)
|
|
return %9 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_count_from_empty_dictionary :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'load_count_from_empty_dictionary'
|
|
sil @load_count_from_empty_dictionary : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @_swiftEmptyDictionarySingleton : $*_SwiftEmptyDictionarySingleton
|
|
%1 = address_to_pointer [stack_protection] %0 : $*_SwiftEmptyDictionarySingleton to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $__EmptyDictionarySingleton
|
|
%3 = unchecked_ref_cast %2 : $__EmptyDictionarySingleton to $Builtin.BridgeObject
|
|
%4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $__RawDictionaryStorage
|
|
%5 = ref_element_addr %4 : $__RawDictionaryStorage, #__RawDictionaryStorage._count
|
|
%6 = struct_element_addr %5 : $*Int64, #Int64._value
|
|
%7 = load %6 : $*Builtin.Int64
|
|
%9 = struct $Int64 (%7 : $Builtin.Int64)
|
|
return %9 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil @load_capacity_from_empty_dictionary :
|
|
// CHECK: %0 = integer_literal $Builtin.Int64, 0
|
|
// CHECK-NEXT: %1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'load_capacity_from_empty_dictionary'
|
|
sil @load_capacity_from_empty_dictionary : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @_swiftEmptyDictionarySingleton : $*_SwiftEmptyDictionarySingleton
|
|
%1 = address_to_pointer [stack_protection] %0 : $*_SwiftEmptyDictionarySingleton to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $__EmptyDictionarySingleton
|
|
%3 = unchecked_ref_cast %2 : $__EmptyDictionarySingleton to $Builtin.BridgeObject
|
|
%4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $__RawDictionaryStorage
|
|
%5 = ref_element_addr %4 : $__RawDictionaryStorage, #__RawDictionaryStorage._capacity
|
|
%6 = struct_element_addr %5 : $*Int64, #Int64._value
|
|
%7 = load %6 : $*Builtin.Int64
|
|
%9 = struct $Int64 (%7 : $Builtin.Int64)
|
|
return %9 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_dead_load :
|
|
// CHECK-NOT: load
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: } // end sil function 'remove_dead_load'
|
|
sil [ossa] @remove_dead_load : $@convention(thin) (@in_guaranteed B) -> () {
|
|
bb0(%0 : $*B):
|
|
%1 = load [copy] %0 : $*B
|
|
destroy_value %1 : $B
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_dead_load_with_debug_value :
|
|
// CHECK-ONONE: load
|
|
// CHECK-ONONE: destroy_value
|
|
// CHECK-O-NOT: load
|
|
// CHECK-O-NOT: destroy_value
|
|
// CHECK: } // end sil function 'remove_dead_load_with_debug_value'
|
|
sil [ossa] @remove_dead_load_with_debug_value : $@convention(thin) (@in_guaranteed B) -> () {
|
|
bb0(%0 : $*B):
|
|
%1 = load [copy] %0 : $*B
|
|
debug_value %1 : $B, let, name "x"
|
|
destroy_value %1 : $B
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|