mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The intent for `@inline(always)` is to act as an optimization control. The user can rely on inlining to happen or the compiler will emit an error message. Because function values can be dynamic (closures, protocol/class lookup) this guarantee can only be upheld for direct function references. In cases where the optimizer can resolve dynamic function values the attribute shall be respected. rdar://148608854
178 lines
7.0 KiB
Plaintext
178 lines
7.0 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-inline-generics=true -sil-print-generic-specialization-info | %FileCheck %s
|
|
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-inline-generics=false | %FileCheck --check-prefix=DISABLED-GENERIC-INLINING-CHECK %s
|
|
// RUN: %target-swift-frontend -O -emit-ir %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
public func genericFoo<T>(_ t: T) -> T
|
|
|
|
public func testInliningOfGenerics<T>(_ t: T) -> T
|
|
|
|
public protocol P : class {
|
|
func getSelf() -> Self
|
|
}
|
|
|
|
extension P {
|
|
func combine<T>(first: T) -> (T) -> Bool
|
|
}
|
|
|
|
public func callClosure<T>(arg: P) -> (T) -> Bool where T : P
|
|
|
|
sil @genericFoo : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
copy_addr [take] %1 to [init] %0 : $*T
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
} // end sil function 'genericFoo'
|
|
|
|
|
|
// Check that the generic call was inlined.
|
|
// CHECK-LABEL: sil @testInliningOfGenerics
|
|
// CHECK-NOT: apply
|
|
// CHECK: end sil function 'testInliningOfGenerics'
|
|
sil @testInliningOfGenerics : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
// function_ref genericFoo<A> (A) -> A
|
|
%3 = function_ref @genericFoo : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%4 = alloc_stack $T
|
|
copy_addr %1 to [init] %4 : $*T
|
|
%6 = apply %3<T>(%0, %4) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
dealloc_stack %4 : $*T
|
|
destroy_addr %1 : $*T
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
} // end sil function 'testInliningOfGenerics'
|
|
|
|
// thunk
|
|
sil shared [transparent] [reabstraction_thunk] @thunk1 : $@convention(thin) (@owned P, @owned @callee_owned (@in P) -> Bool) -> Bool {
|
|
bb0(%0 : $P, %1 : $@callee_owned (@in P) -> Bool):
|
|
%2 = alloc_stack $P
|
|
store %0 to %2 : $*P
|
|
%4 = apply %1(%2) : $@callee_owned (@in P) -> Bool
|
|
dealloc_stack %2 : $*P
|
|
return %4 : $Bool
|
|
} // end sil function 'thunk1'
|
|
|
|
// thunk
|
|
sil shared [transparent] [reabstraction_thunk] @thunk2 : $@convention(thin) <T where T : P> (@owned T, @owned @callee_owned (@owned P) -> Bool) -> Bool {
|
|
bb0(%0 : $T, %1 : $@callee_owned (@owned P) -> Bool):
|
|
%2 = init_existential_ref %0 : $T : $T, $P
|
|
%3 = apply %1(%2) : $@callee_owned (@owned P) -> Bool
|
|
return %3 : $Bool
|
|
} // end sil function 'thunk2'
|
|
|
|
|
|
sil [heuristic_always_inline] @alwaysInlineGenericCallee : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
copy_addr [take] %1 to [init] %0 : $*T
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
} // end sil function 'alwaysInlineGenericCallee'
|
|
|
|
sil [transparent] @transparentGenericCallee : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
copy_addr [take] %1 to [init] %0 : $*T
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
} // end sil function 'transparentInlineGenericCallee'
|
|
|
|
|
|
// Check that [heuristic_always_inline] and [transparent] functions are inlined even if
|
|
// inlining of generics is disabled. Regular generic functions should not be
|
|
// inlined.
|
|
// DISABLED-GENERIC-INLINING-CHECK-LABEL: sil @testComplexInliningOfGenerics
|
|
// DISABLED-GENERIC-INLINING-CHECK-NOT: function_ref @{{.*}}
|
|
// DISABLED-GENERIC-INLINING-CHECK-NOT: apply
|
|
// DISABLED-GENERIC-INLINING-CHECK: [[FUNC:%[0-9]+]] = function_ref @genericFoo
|
|
// DISABLED-GENERIC-INLINING-CHECK: apply [[FUNC]]
|
|
// DISABLED-GENERIC-INLINING-CHECK-NOT: function_ref
|
|
// DISABLED-GENERIC-INLINING-CHECK-NOT: apply
|
|
// DISABLED-GENERIC-INLINING-CHECK: end sil function 'testComplexInliningOfGenerics'
|
|
|
|
// Check that all callees are inlined if inlining of generics is enabled.
|
|
// CHECK-LABEL: sil @testComplexInliningOfGenerics
|
|
// CHECK-NOT: apply
|
|
// CHECK: end sil function 'testComplexInliningOfGenerics'
|
|
sil @testComplexInliningOfGenerics : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
|
|
// Call an [heuristic_always_inline] function.
|
|
%3 = function_ref @alwaysInlineGenericCallee : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%4 = alloc_stack $T
|
|
copy_addr %1 to [init] %4 : $*T
|
|
%6 = apply %3<T>(%0, %4) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
dealloc_stack %4 : $*T
|
|
|
|
// Call a [transparent] function.
|
|
%8 = function_ref @transparentGenericCallee : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%9 = alloc_stack $T
|
|
copy_addr %1 to [init] %9 : $*T
|
|
%10 = apply %8<T>(%0, %9) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
dealloc_stack %9 : $*T
|
|
|
|
// Call a regular function.
|
|
// function_ref genericFoo<A> (A) -> A
|
|
%12 = function_ref @genericFoo : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%13 = alloc_stack $T
|
|
copy_addr %1 to [init] %13 : $*T
|
|
%15 = apply %12<T>(%0, %13) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
dealloc_stack %13 : $*T
|
|
|
|
destroy_addr %1 : $*T
|
|
%18 = tuple ()
|
|
return %18 : $()
|
|
} // end sil function 'testComplexInliningOfGenerics'
|
|
|
|
sil_default_witness_table P {
|
|
no_default
|
|
}
|
|
|
|
protocol SomeProto : class {}
|
|
protocol OtherProto {}
|
|
|
|
class MyObject {}
|
|
extension MyObject : OtherProto {}
|
|
|
|
class MyNumber : MyObject {}
|
|
extension MyNumber : SomeProto {}
|
|
|
|
sil_vtable MyObject {}
|
|
sil_vtable MyNumber {}
|
|
|
|
// Make sure we substitute the correct conformance when inlining. When
|
|
// substituting we need to pick up the normal_conformance.
|
|
|
|
// CHECK-LABEL: sil @test_inlining : $@convention(objc_method) (@owned MyNumber) -> () {
|
|
// CHECK-NOT: Generic specialization information for call-site dootherstuff <MyNumber & SomeProto> conformances <(abstract_conformance protocol="OtherProto")>
|
|
// CHECK: Generic specialization information
|
|
// CHECK: (normal_conformance type="MyObject" protocol="OtherProto"
|
|
// CHECK: end sil function 'test_inlining'
|
|
|
|
sil @test_inlining : $@convention(objc_method) (@owned MyNumber) -> () {
|
|
bb0(%0 : $MyNumber):
|
|
%12 = init_existential_ref %0 : $MyNumber : $MyNumber, $MyNumber & SomeProto
|
|
%14 = open_existential_ref %12 : $MyNumber & SomeProto to $@opened("B9711AE4-946E-11EA-A871-ACDE48001122", MyNumber & SomeProto) Self
|
|
%15 = alloc_stack $OtherProto
|
|
%16 = init_existential_addr %15 : $*OtherProto, $@opened("B9711AE4-946E-11EA-A871-ACDE48001122", MyNumber & SomeProto) Self
|
|
store %14 to %16 : $*@opened("B9711AE4-946E-11EA-A871-ACDE48001122", MyNumber & SomeProto) Self
|
|
%18 = function_ref @doStuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
|
|
%20 = apply %18<@opened("B9711AE4-946E-11EA-A871-ACDE48001122", MyNumber & SomeProto) Self>(%16) : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %15 : $*OtherProto
|
|
dealloc_stack %15 : $*OtherProto
|
|
%27 = tuple ()
|
|
return %27 : $()
|
|
}
|
|
|
|
sil @dootherstuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
|
|
|
|
sil shared [signature_optimized_thunk] [heuristic_always_inline] @doStuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> () {
|
|
bb0(%0 : $*τ_0_0):
|
|
%2 = function_ref @dootherstuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
|
|
%3 = apply %2<τ_0_0>(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
|
|
return %3 : $()
|
|
}
|