Files
swift-mirror/test/SILOptimizer/capture_propagation.sil
Andrew Trick be7fa4a765 Fix the specialized mangler.
Pass correct argument indices to the mangler for function specialization. This
has probably always been broken. The demangler doesn't support these manglings
anyway. It doesn't seem to have mattered in practice yet (aside from the
confusion of devs) like me. It will matter once we begin exposing public
specializations.
2017-01-26 15:35:48 -08:00

345 lines
17 KiB
Plaintext

// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -capture-prop | %FileCheck %s
// Check the CapturePropagation specialized the reabstraction thunk.
sil_stage raw
import Builtin
import Swift
sil @capture_helper_2 : $@convention(thin) (Int32) -> ()
// CHECK-LABEL: test_capture_propagation
// CHECK: %[[FR:[0-9]+]] = function_ref @_TTSf3n_cpfr24_TF8capturep6helperFSiT____TTRXFo_dSi_dT__XFo_iSi_dT__ : $@convention(thin) (@in Int32) -> ()
// CHECK: thin_to_thick_function %[[FR]] : $@convention(thin) (@in Int32) -> ()
sil private @test_capture_propagation : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $Int32 // users: %3, %9, %10
%1 = integer_literal $Builtin.Int32, 3 // user: %2
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %3
store %2 to %0 : $*Int32 // id: %3
// function_ref capturep.helper (Swift.Int32) -> ()
%4 = function_ref @_TF8capturep6helperFSiT_ : $@convention(thin) (Int32) -> () // user: %5
%5 = thin_to_thick_function %4 : $@convention(thin) (Int32) -> () to $@callee_owned (Int32) -> () // user: %7
// function_ref reabstraction thunk helper from @callee_owned (@unowned Swift.Int32) -> (@unowned ()) to @callee_owned (@in Swift.Int32) -> (@unowned ())
%6 = function_ref @_TTRXFo_dSi_dT__XFo_iSi_dT__ : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> () // user: %7
%7 = partial_apply %6(%5) : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> () // user: %9
// function_ref specialization <Swift.Int32> of capturep.generic <A>(A, (A) -> ()) -> ()
%8 = function_ref @_TTSgSi___TF8capturep7genericU__FTQ_FQ_T__T_ : $@convention(thin) (@in Int32, @owned @callee_owned (@in Int32) -> ()) -> () // user: %9
%9 = apply %8(%0, %7) : $@convention(thin) (@in Int32, @owned @callee_owned (@in Int32) -> ()) -> ()
%11 = thin_to_thick_function %4 : $@convention(thin) (Int32) -> () to $@callee_owned (Int32) -> () // user: %7
%12 = function_ref @bad_thunk : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> ()
%13 = partial_apply %12(%11) : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> () // user: %9
%14 = apply %8(%0, %13) : $@convention(thin) (@in Int32, @owned @callee_owned (@in Int32) -> ()) -> ()
dealloc_stack %0 : $*Int32 // id: %10
%15 = tuple () // user: %12
return %15 : $() // id: %12
}
// capturep.helper (Swift.Int32) -> ()
sil @_TF8capturep6helperFSiT_ : $@convention(thin) (Int32) -> () {
bb0(%0 : $Int32):
%1 = tuple () // user: %2
return %1 : $() // id: %2
}
sil @bad_thunk : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> ()
// reabstraction thunk helper from @callee_owned (@unowned Swift.Int32) -> (@unowned ()) to @callee_owned (@in Swift.Int32) -> (@unowned ())
sil shared [transparent] @_TTRXFo_dSi_dT__XFo_iSi_dT__ : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> () {
bb0(%0 : $*Int32, %1 : $@callee_owned (Int32) -> ()):
%2 = load %0 : $*Int32 // user: %3
%3 = apply %1(%2) : $@callee_owned (Int32) -> () // user: %4
return %3 : $() // id: %4
}
// specialization <Swift.Int32> of capturep.generic <A>(A, (A) -> ()) -> ()
sil shared [noinline] @_TTSgSi___TF8capturep7genericU__FTQ_FQ_T__T_ : $@convention(thin) (@in Int32, @owned @callee_owned (@in Int32) -> ()) -> () {
bb0(%0 : $*Int32, %1 : $@callee_owned (@in Int32) -> ()):
%2 = alloc_stack $Int32 // users: %4, %5, %6
%3 = load %0 : $*Int32 // user: %4
store %3 to %2 : $*Int32 // id: %4
%5 = apply %1(%2) : $@callee_owned (@in Int32) -> ()
dealloc_stack %2 : $*Int32 // id: %6
%7 = tuple () // user: %8
return %7 : $() // id: %8
}
/*
// reabstraction thunk helper from @callee_owned (@unowned Swift.Int32) -> (@unowned ()) to @callee_owned (@in Swift.Int32) -> (@unowned ())
sil shared [transparent] @_TTRXFo_dSi_dT__XFo_iSi_dT__ : $@convention(thin) (@in Int32, @owned @callee_owned (Int32) -> ()) -> () {
bb0(%0 : $*Int32, %1 : $@callee_owned (Int32) -> ()):
%2 = load %0 : $*Int32 // user: %3
%3 = apply %1(%2) : $@callee_owned (Int32) -> () // user: %4
return %3 : $() // id: %4
}
*/
sil @_TFtest_capture_propagation2_closure : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> () {
bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*Builtin.Word):
%9999 = tuple()
return %9999 : $()
}
sil_global [fragile] @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $Builtin.Word
sil @test_capture_propagation2_caller : $@convention(thin) () -> () {
%0 = integer_literal $Builtin.Int32, 0
%1 = float_literal $Builtin.FPIEEE32, 0
%2 = string_literal utf8 "123"
%3 = global_addr @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $*Builtin.Word
%4 = function_ref @_TFtest_capture_propagation2_closure : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
%5 = thin_to_thick_function %4 : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> () to $@callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
%6 = function_ref @test_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
%7 = function_ref @test_capture_propagation2_thunk : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @owned @callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> ()
%8 = partial_apply %7(%0, %1, %2, %3, %5) : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @owned @callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> ()
apply %6(%8) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
%9999 = tuple()
return %9999 : $()
}
sil shared @test_capture_propagation2_thunk : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @owned @callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> () {
bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*Builtin.Word, %4 : $@callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()):
apply %4(%0, %1, %2, %3) : $@callee_owned (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
%9999 = tuple()
return %9999 : $()
}
sil shared @test_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
bb0(%0 : $@callee_owned () -> ()):
apply %0() : $@callee_owned () -> ()
%9999 = tuple()
return %9999 : $()
}
// Test dead partial applied arguments
sil @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
sil @nonthrowing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> Bool
return %4 : $Bool
}
// CHECK-LABEL: sil @return_nonthrowing_closure
// CHECK: [[F:%[0-9]+]] = function_ref @specialized_nonthrowing_closure
// CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]]
// CHECK: return [[R]]
sil @return_nonthrowing_closure : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> Bool {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @nonthrowing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
sil @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error)
sil @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error)
try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2
bb1(%5 : $Bool):
return %5 : $Bool
bb2(%7 : $Error):
throw %7 : $Error
}
// CHECK-LABEL: sil @return_throwing_closure
// CHECK: [[F:%[0-9]+]] = function_ref @specialized_throwing_closure
// CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]]
// CHECK: return [[R]]
sil @return_throwing_closure : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
}
// Negative tests
sil @swapped_arguments : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
%4 = apply %3(%1, %0) : $@convention(thin) (Int32, Int32) -> Bool
return %4 : $Bool
}
// CHECK-LABEL: sil @return_swapped_arguments
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @swapped_arguments
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_swapped_arguments : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> Bool {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @swapped_arguments : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
sil @wrong_return1 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> Bool
%i = integer_literal $Builtin.Int1, 0
%b = struct $Bool (%i : $Builtin.Int1)
return %b : $Bool
}
// CHECK-LABEL: sil @return_wrong_return1
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @wrong_return1
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_wrong_return1 : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> Bool {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @wrong_return1 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
sil @second_apply : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
%u = apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> Bool
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> Bool
return %4 : $Bool
}
// CHECK-LABEL: sil @return_second_apply
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @second_apply
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_second_apply : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> Bool {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @second_apply : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
class X { }
sil @other_inst : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_nonthrowing_closure : $@convention(thin) (Int32, Int32) -> Bool
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> Bool
%r = alloc_ref $X
strong_release %r : $X
return %4 : $Bool
}
// CHECK-LABEL: sil @return_other_inst
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @other_inst
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_other_inst : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> Bool {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @other_inst : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
sil @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error)
try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2
bb1(%5 : $Bool):
%r = alloc_ref $X
strong_release %r : $X
return %5 : $Bool
bb2(%7 : $Error):
throw %7 : $Error
}
// CHECK-LABEL: sil @return_other_inst_in_returnblock
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @other_inst_in_returnblock
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_other_inst_in_returnblock : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
}
sil @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error)
try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2
bb1(%5 : $Bool):
%i = integer_literal $Builtin.Int1, 0
%b = struct $Bool (%i : $Builtin.Int1)
return %b : $Bool
bb2(%7 : $Error):
throw %7 : $Error
}
// CHECK-LABEL: sil @return_wrong_return2
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @wrong_return2
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_wrong_return2 : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
}
sil @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) {
bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
%3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error)
try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2
bb1(%5 : $Bool):
return %5 : $Bool
bb2(%7 : $Error):
br bb3
bb3:
%i = integer_literal $Builtin.Int1, 1
cond_fail %i : $Builtin.Int1
unreachable
}
// CHECK-LABEL: sil @return_wrong_terminator
// CHECK: [[M:%[0-9]+]] = metatype
// CHECK: [[F:%[0-9]+]] = function_ref @wrong_terminator
// CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]])
// CHECK: return [[R]]
sil @return_wrong_terminator : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) {
bb0:
%0 = metatype $@thin Int32.Type
%1 = function_ref @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error)
return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
}