| // 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 |
| } |
| |