// RUN: %target-sil-opt -enable-sil-verify-all -array-count-propagation %s | %FileCheck %s sil_stage canonical import Builtin import Swift struct MyInt { @_hasStorage var _value: Builtin.Int64 } struct MyBool {} struct _MyBridgeStorage { @_hasStorage var rawValue : Builtin.BridgeObject } struct _MyArrayBuffer { @_hasStorage var _storage : _MyBridgeStorage } struct MyArray { @_hasStorage var _buffer : _MyArrayBuffer } class Klass { } sil [ossa] @swift_bufferAllocate : $@convention(thin)() -> @owned AnyObject sil [ossa] [_semantics "array.uninitialized"] @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) sil [ossa] [_semantics "array.get_count"] @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt sil [ossa] [_semantics "array.get_element"] @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray) -> @out MyInt sil [ossa] [_semantics "array.uninitialized"] @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) sil [ossa] [_semantics "array.finalize_intrinsic"] @finalize : $@convention(thin) (@owned MyArray) -> @owned MyArray sil [ossa] [_semantics "array.init"] @initRepeatedValueCount : $@convention(thin) (@in MyInt, MyInt, @thin MyArray.Type) -> @owned MyArray sil [ossa] [_semantics "array.init"] @initEmpty : $@convention(thin) (@thin MyArray.Type) -> @owned MyArray // CHECK-LABEL: sil [ossa] @test_adoptStorage1 : // CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3 // CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]] // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK-NOT: apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_adoptStorage1' sil [ossa] @test_adoptStorage1 : $@convention(thin) () -> MyInt { bb0: %0 = integer_literal $Builtin.Int64, 3 %1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject %2 = apply %1() : $@convention(thin) () -> @owned AnyObject %3 = struct $MyInt(%0 : $Builtin.Int64) %4 = metatype $@thin MyArray.Type %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) %6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) (%7, %8a) = destructure_tuple %6 : $(MyArray, UnsafeMutablePointer) %8 = mark_dependence %8a : $UnsafeMutablePointer on %7 : $MyArray debug_value %7 : $MyArray %f = function_ref @finalize : $@convention(thin) (@owned MyArray) -> @owned MyArray %a = apply %f(%7) : $@convention(thin) (@owned MyArray) -> @owned MyArray %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%a) : $@convention(method) (@guaranteed MyArray) -> MyInt destroy_value %a : $MyArray return %10 : $MyInt } // CHECK-LABEL: sil [ossa] @test_allocateUninitialized : // CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3 // CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]] // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK-NOT: apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_allocateUninitialized' sil [ossa] @test_allocateUninitialized : $@convention(thin) () -> MyInt { bb0: %0 = integer_literal $Builtin.Int64, 3 %3 = struct $MyInt(%0 : $Builtin.Int64) %4 = metatype $@thin MyArray.Type %5 = function_ref @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) %6 = apply %5(%3, %4) : $@convention(thin) (MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) (%7, %8a) = destructure_tuple %6 : $(MyArray, UnsafeMutablePointer) %8 = mark_dependence %8a : $UnsafeMutablePointer on %7 : $MyArray debug_value %7 : $MyArray %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray) -> MyInt %15 = function_ref @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray) -> @out MyInt %16 = alloc_stack $MyInt %17 = struct $MyBool() %18 = apply %15(%16, %3, %17, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray) -> @out MyInt destroy_value %7 : $MyArray dealloc_stack %16 : $*MyInt return %10 : $MyInt } // CHECK-LABEL: sil [ossa] @test_initRepeatedValueCount : // CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3 // CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]] // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK-NOT: apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_initRepeatedValueCount' sil [ossa] @test_initRepeatedValueCount : $@convention(thin) () -> MyInt { bb0: %0 = integer_literal $Builtin.Int64, 3 %1 = alloc_stack $MyInt %3 = struct $MyInt(%0 : $Builtin.Int64) store %3 to [trivial] %1: $*MyInt %4 = metatype $@thin MyArray.Type %5 = function_ref @initRepeatedValueCount : $@convention(thin) (@in MyInt, MyInt, @thin MyArray.Type) -> @owned MyArray %6 = apply %5(%1, %3, %4) : $@convention(thin) (@in MyInt, MyInt, @thin MyArray.Type) -> @owned MyArray debug_value %6 : $MyArray %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%6) : $@convention(method) (@guaranteed MyArray) -> MyInt %15 = function_ref @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray) -> @out MyInt %16 = alloc_stack $MyInt %17 = struct $MyBool() %18 = apply %15(%16, %3, %17, %6) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray) -> @out MyInt destroy_value %6 : $MyArray dealloc_stack %16 : $*MyInt dealloc_stack %1 : $*MyInt return %10 : $MyInt } // CHECK-LABEL: sil [ossa] @test_escape : // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_escape' sil [ossa] @test_escape : $@convention(thin) () -> MyInt { bb0: %0 = integer_literal $Builtin.Int64, 3 %15 = alloc_stack $MyArray %1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject %2 = apply %1() : $@convention(thin) () -> @owned AnyObject %3 = struct $MyInt(%0 : $Builtin.Int64) %4 = metatype $@thin MyArray.Type %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) %6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) (%7, %8a) = destructure_tuple %6 : $(MyArray, UnsafeMutablePointer) %8 = mark_dependence %8a : $UnsafeMutablePointer on %7 : $MyArray %copy7 = copy_value %7 : $MyArray debug_value %7 : $MyArray store %7 to [init] %15 : $*MyArray %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%copy7) : $@convention(method) (@guaranteed MyArray) -> MyInt destroy_value %copy7 : $MyArray destroy_addr %15 : $*MyArray dealloc_stack %15 : $*MyArray return %10 : $MyInt } sil [ossa] @mayWrite : $@convention(thin) (@guaranteed MyArray) -> () // CHECK-LABEL: sil [ossa] @test_mayWrite : // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_mayWrite' sil [ossa] @test_mayWrite : $@convention(thin) () -> MyInt { bb0: %0 = integer_literal $Builtin.Int64, 3 %1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject %2 = apply %1() : $@convention(thin) () -> @owned AnyObject %3 = struct $MyInt(%0 : $Builtin.Int64) %4 = metatype $@thin MyArray.Type %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) %6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray.Type) -> @owned (MyArray, UnsafeMutablePointer) (%7, %8a) = destructure_tuple %6 : $(MyArray, UnsafeMutablePointer) %8 = mark_dependence %8a : $UnsafeMutablePointer on %7 : $MyArray debug_value %7 : $MyArray %15 = function_ref @mayWrite : $@convention(thin) (@guaranteed MyArray) -> () %16 = apply %15(%7) : $@convention(thin) (@guaranteed MyArray) -> () %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray) -> MyInt destroy_value %7 : $MyArray return %10 : $MyInt } // We don't handle empty array allocations yet. // CHECK-LABEL: sil [ossa] @test_initEmpty : // CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount // CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]] // CHECK-LABEL: } // end sil function 'test_initEmpty' sil [ossa] @test_initEmpty : $@convention(thin) () -> MyInt { bb0: %4 = metatype $@thin MyArray.Type %5 = function_ref @initEmpty : $@convention(thin) (@thin MyArray.Type) -> @owned MyArray %6 = apply %5(%4) : $@convention(thin) (@thin MyArray.Type) -> @owned MyArray debug_value %6 : $MyArray %9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray) -> MyInt %10 = apply %9(%6) : $@convention(method) (@guaranteed MyArray) -> MyInt destroy_value %6 : $MyArray return %10 : $MyInt }