blob: 8f9b69e00c0d197e078f18fbb0f9121e80c7882a [file] [log] [blame]
// RUN: %target-sil-opt -array-element-propagation %s | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
struct MyInt {
@_hasStorage var _value: Builtin.Word
}
struct MyBool {}
struct _MyDependenceToken {}
struct _MyBridgeStorage {
@_hasStorage var rawValue : Builtin.BridgeObject
}
struct _MyArrayBuffer<T> {
@_hasStorage var _storage : _MyBridgeStorage
}
struct MyArray<T> {
@_hasStorage var _buffer : _MyArrayBuffer<T>
}
class MyKlass {
}
sil @swift_bufferAllocate : $@convention(thin)() -> @owned _ContiguousArrayStorage<MyKlass>
sil [_semantics "array.uninitialized"] @adoptStorage : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
sil [_semantics "array.props.isNativeTypeChecked"] @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
sil [_semantics "array.check_subscript"] @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
sil [_semantics "array.get_element"] @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
sil @unknown_array_use : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
sil [_semantics "array.uninitialized"] @arrayAdoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin Array<MyInt>.Type) -> @owned (Array<MyInt>, UnsafeMutablePointer<MyInt>)
sil @arrayInit : $@convention(method) (@thin Array<MyInt>.Type) -> @owned Array<MyInt>
sil [_semantics "array.finalize_intrinsic"] @finalize : $@convention(thin) (@owned MyArray<MyKlass>) -> @owned MyArray<MyKlass>
sil [_semantics "array.append_contentsOf"] @arrayAppendContentsOf : $@convention(method) (@owned Array<MyInt>, @inout Array<MyInt>) -> ()
// CHECK-LABEL: sil [ossa] @propagate_with_get_element_returning_direct_result :
// CHECK: [[V0:%.*]] = copy_value %0 : $MyKlass
// CHECK: [[V1:%.*]] = copy_value %1 : $MyKlass
// CHECK: [[V2:%.*]] = copy_value %2 : $MyKlass
// CHECK: [[S0:%.*]] = alloc_stack $MyKlass
// CHECK: [[HFUN:%.*]] = function_ref @hoistableIsNativeTypeChecked
// CHECK-NOT: apply [[HFUN]]
// CHECK: [[CFUN:%.*]] = function_ref @checkSubscript
// CHECK-NOT: apply [[CFUN]]
// CHECK: [[GFUN:%.*]] = function_ref @getElement
// CHECK-NOT: apply [[GFUN]]
// CHECK-NOT: apply [[HFUN]]
// CHECK-NOT: apply [[CFUN]]
// CHECK-NOT: apply [[GFUN]]
// CHECK: store [[V0]] to [init] [[S0]]
// CHECK: [[S1:%.*]] = alloc_stack $MyKlass
// CHECK: store [[V1]] to [init] [[S1]]
// CHECK: [[S2:%.*]] = alloc_stack $MyKlass
// CHECK: store [[V2]] to [init] [[S2]]
// CHECK-LABEL: } // end sil function 'propagate_with_get_element_returning_direct_result'
sil [ossa] @propagate_with_get_element_returning_direct_result : $@convention(thin) (@owned MyKlass, @owned MyKlass, @owned MyKlass) -> () {
bb0(%arg0 : @owned $MyKlass, %arg1 : @owned $MyKlass, %arg2 : @owned $MyKlass):
%0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%1 = integer_literal $Builtin.Word, 3
%2 = struct $MyInt (%1 : $Builtin.Word)
%3 = apply %0() : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%4 = metatype $@thin MyArray<MyKlass>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
%6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
debug_value %7 : $MyArray<MyKlass>
debug_value %8 : $UnsafeMutablePointer<MyKlass>
%9 = struct_extract %8 : $UnsafeMutablePointer<MyKlass>, #UnsafeMutablePointer._rawValue
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyKlass
%11 = integer_literal $Builtin.Word, 0
%11a = struct $MyInt (%11 : $Builtin.Word)
store %arg0 to [init] %10 : $*MyKlass
%13 = integer_literal $Builtin.Word, 1
%13a = struct $MyInt (%13 : $Builtin.Word)
%14 = index_addr %10 : $*MyKlass, %13 : $Builtin.Word
store %arg1 to [init] %14 : $*MyKlass
%17 = integer_literal $Builtin.Word, 2
%17a = struct $MyInt (%17 : $Builtin.Word)
%18 = index_addr %10 : $*MyKlass, %17 : $Builtin.Word
store %arg2 to [init] %18 : $*MyKlass
%copy7 = copy_value %7 : $MyArray<MyKlass>
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyKlass>) -> @owned MyArray<MyKlass>
%a = apply %f(%copy7) : $@convention(thin) (@owned MyArray<MyKlass>) -> @owned MyArray<MyKlass>
%borrowa = begin_borrow %a : $MyArray<MyKlass>
%23 = struct_extract %borrowa : $MyArray<MyKlass>, #MyArray._buffer
%24 = struct_extract %23 : $_MyArrayBuffer<MyKlass>, #_MyArrayBuffer._storage
%25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
end_borrow %borrowa : $MyArray<MyKlass>
%26 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
%27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
%28 = apply %27(%a) : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
debug_value %28 : $MyBool
%29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
%30 = apply %29(%11a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %30 : $_MyDependenceToken
%31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
%32 = apply %31(%11a, %28, %30, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %32 to [init] %26 : $*MyKlass
%35 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
debug_value %28 : $MyBool
%36 = apply %29(%13a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %36 : $_MyDependenceToken
%37 = apply %31(%13a, %28, %36, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %37 to [init] %35 : $*MyKlass
%44 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
debug_value %28 : $MyBool
%45 = apply %29(%17a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %45 : $_MyDependenceToken
%46 = apply %31(%17a, %28, %45, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %46 to [init] %44 : $*MyKlass
destroy_addr %44 : $*MyKlass
destroy_addr %35 : $*MyKlass
destroy_addr %26 : $*MyKlass
dealloc_stack %44 : $*MyKlass
dealloc_stack %35 : $*MyKlass
dealloc_stack %26 : $*MyKlass
destroy_value %a : $(MyArray<MyKlass>)
destroy_value %7 : $MyArray<MyKlass>
%52 = tuple ()
return %52 : $()
}
// CHECK-LABEL: sil [ossa] @repeated_initialization :
// CHECK: [[GFUN:%.*]] = function_ref @getElement
// CHECK: apply [[GFUN]]
// CHECK: apply [[GFUN]]
// CHECK-LABEL: } // end sil function 'repeated_initialization'
sil [ossa] @repeated_initialization : $@convention(thin) (@owned MyKlass, @owned MyKlass, @owned MyKlass) -> () {
bb0(%arg0 : @owned $MyKlass, %arg1 : @owned $MyKlass, %arg2 : @owned $MyKlass):
%0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%1 = integer_literal $Builtin.Word, 3
%2 = struct $MyInt (%1 : $Builtin.Word)
%3 = apply %0() : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%4 = metatype $@thin MyArray<MyKlass>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
%6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
debug_value %7 : $MyArray<MyKlass>
debug_value %8 : $UnsafeMutablePointer<MyKlass>
%9 = struct_extract %8 : $UnsafeMutablePointer<MyKlass>, #UnsafeMutablePointer._rawValue
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyKlass
%11 = integer_literal $Builtin.Word, 0
%11a = struct $MyInt (%11 : $Builtin.Word)
store %arg0 to [init] %10 : $*MyKlass
%13 = integer_literal $Builtin.Word, 0
%13a = struct $MyInt (%13 : $Builtin.Word)
%14 = index_addr %10 : $*MyKlass, %13 : $Builtin.Word
store %arg1 to [init] %14 : $*MyKlass
%17 = integer_literal $Builtin.Word, 1
%17a = struct $MyInt (%17 : $Builtin.Word)
%18 = index_addr %10 : $*MyKlass, %17 : $Builtin.Word
store %arg2 to [init] %18 : $*MyKlass
%copy7 = copy_value %7 : $MyArray<MyKlass>
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyKlass>) -> @owned MyArray<MyKlass>
%a = apply %f(%copy7) : $@convention(thin) (@owned MyArray<MyKlass>) -> @owned MyArray<MyKlass>
%borrowa = begin_borrow %a : $MyArray<MyKlass>
%23 = struct_extract %borrowa : $MyArray<MyKlass>, #MyArray._buffer
%24 = struct_extract %23 : $_MyArrayBuffer<MyKlass>, #_MyArrayBuffer._storage
%25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
end_borrow %borrowa : $MyArray<MyKlass>
%26 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
%27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
%28 = apply %27(%a) : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
debug_value %28 : $MyBool
%29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
%30 = apply %29(%11a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %30 : $_MyDependenceToken
%31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
%32 = apply %31(%11a, %28, %30, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %32 to [init] %26 : $*MyKlass
%35 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
debug_value %28 : $MyBool
%36 = apply %29(%13a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %36 : $_MyDependenceToken
%37 = apply %31(%13a, %28, %36, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %37 to [init] %35 : $*MyKlass
%44 = alloc_stack $MyKlass
debug_value %a : $MyArray<MyKlass>
debug_value %28 : $MyBool
%45 = apply %29(%17a, %28, %a) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %45 : $_MyDependenceToken
%46 = apply %31(%17a, %28, %45, %a) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %46 to [init] %44 : $*MyKlass
destroy_addr %44 : $*MyKlass
destroy_addr %35 : $*MyKlass
destroy_addr %26 : $*MyKlass
dealloc_stack %44 : $*MyKlass
dealloc_stack %35 : $*MyKlass
dealloc_stack %26 : $*MyKlass
destroy_value %a : $(MyArray<MyKlass>)
destroy_value %7 : $MyArray<MyKlass>
%52 = tuple ()
return %52 : $()
}
sil [ossa] @unkown_use : $@convention(thin) (@owned MyKlass) -> () {
bb0(%arg0 : @owned $MyKlass):
%0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%1 = integer_literal $Builtin.Word, 1
%2 = struct $MyInt (%1 : $Builtin.Word)
%3 = apply %0() : $@convention(thin) () -> @owned _ContiguousArrayStorage<MyKlass>
%4 = metatype $@thin MyArray<MyKlass>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
%6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin MyArray<MyKlass>.Type) -> @owned (MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyKlass>, UnsafeMutablePointer<MyKlass>)
debug_value %7 : $MyArray<MyKlass>
debug_value %8 : $UnsafeMutablePointer<MyKlass>
%9 = struct_extract %8 : $UnsafeMutablePointer<MyKlass>, #UnsafeMutablePointer._rawValue
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyKlass
%11 = integer_literal $Builtin.Word, 0
%11a = struct $MyInt (%11 : $Builtin.Word)
store %arg0 to [init] %10 : $*MyKlass
%borrow7 = begin_borrow %7 : $MyArray<MyKlass>
%23 = struct_extract %borrow7 : $MyArray<MyKlass>, #MyArray._buffer
%24 = struct_extract %23 : $_MyArrayBuffer<MyKlass>, #_MyArrayBuffer._storage
%25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
end_borrow %borrow7 : $MyArray<MyKlass>
%26 = alloc_stack $MyKlass
debug_value %7 : $MyArray<MyKlass>
%27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
%28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
debug_value %28 : $MyBool
%29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
%30 = apply %29(%11a, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyKlass>) -> _MyDependenceToken
debug_value %30 : $_MyDependenceToken
%31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
%32 = apply %31(%11a, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyKlass>) -> @owned MyKlass
store %32 to [init] %26 : $*MyKlass
%33 = function_ref @unknown_array_use : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
%34 = apply %33(%7) : $@convention(method) (@guaranteed MyArray<MyKlass>) -> MyBool
destroy_addr %26 : $*MyKlass
dealloc_stack %26 : $*MyKlass
destroy_value %7 : $MyArray<MyKlass>
%52 = tuple ()
return %52 : $()
}
sil [_semantics "array.uninitialized"] @adoptStorageMyKlass : $@convention(method) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin Array<MyKlass>.Type) -> (@owned Array<MyKlass>, UnsafeMutablePointer<MyKlass>)
sil [_semantics "array.append_contentsOf"] @arrayAppendContentsOfMyKlass : $@convention(method) (@owned Array<MyKlass>, @inout Array<MyKlass>) -> ()
// CHECK-LABEL: sil [ossa] @append_contentsOf_class :
// CHECK: [[ASFUN:%.*]] = function_ref @adoptStorageMyKlass
// CHECK-NEXT: [[ARR:%.*]] = apply [[ASFUN]]
// CHECK-NEXT: ([[OWNER:%[0-9]+]], [[PTR:%[0-9]+]]) = destructure_tuple [[ARR]]{{.*}}
// CHECK: [[COPY1:%.*]] = copy_value %1 : $MyKlass
// CHECK-NEXT: [[COPY2:%.*]] = copy_value [[COPY1]] : $MyKlass
// CHECK-NEXT: store [[COPY1]] to [init] %{{[0-9]+}} : $*MyKlass
// CHECK-NOT: apply
// CHECK: [[AEFUN:%.*]] = function_ref @$sSa6appendyyxnF
// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $MyKlass
// CHECK-NEXT: store [[COPY2]] to [init] [[STACK]]
// CHECK-NEXT: apply [[AEFUN]]<MyKlass>([[STACK]], %0)
// CHECK-NEXT: dealloc_stack [[STACK]]
// CHECK-NEXT: destroy_value [[OWNER]]
// CHECK-LABEL: } // end sil function 'append_contentsOf_class'
sil [ossa] @append_contentsOf_class : $@convention(thin) (@inout Array<MyKlass>, @owned MyKlass) -> @owned MyKlass {
bb0(%0 : $*Array<MyKlass>, %1 : @owned $MyKlass):
%4 = integer_literal $Builtin.Word, 1
%6 = struct $MyInt (%4 : $Builtin.Word)
%7 = alloc_ref [tail_elems $MyKlass * %4 : $Builtin.Word] $_ContiguousArrayStorage<MyKlass>
%8 = metatype $@thin Array<MyKlass>.Type
%9 = function_ref @adoptStorageMyKlass : $@convention(method) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin Array<MyKlass>.Type) -> (@owned Array<MyKlass>, UnsafeMutablePointer<MyKlass>)
%10 = apply %9(%7, %6, %8) : $@convention(method) (@owned _ContiguousArrayStorage<MyKlass>, MyInt, @thin Array<MyKlass>.Type) -> (@owned Array<MyKlass>, UnsafeMutablePointer<MyKlass>)
(%11, %12) = destructure_tuple %10 : $(Array<MyKlass>, UnsafeMutablePointer<MyKlass>)
%13 = struct_extract %12 : $UnsafeMutablePointer<MyKlass>, #UnsafeMutablePointer._rawValue
%22 = pointer_to_address %13 : $Builtin.RawPointer to [strict] $*MyKlass
%copy1 = copy_value %1 : $MyKlass
store %copy1 to [init] %22 : $*MyKlass
%25 = function_ref @arrayAppendContentsOfMyKlass : $@convention(method) (@owned Array<MyKlass>, @inout Array<MyKlass>) -> ()
%26 = apply %25(%11, %0) : $@convention(method) (@owned Array<MyKlass>, @inout Array<MyKlass>) -> ()
return %1 : $MyKlass
}