mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
An interposed mark_dependence should not block the heuristic that adds a benefit when inlining a function that takes a closure argument.
605 lines
28 KiB
Plaintext
605 lines
28 KiB
Plaintext
// RUN: %empty-directory(%t)
|
|
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -compute-side-effects -inline -sil-inline-generics=true -sil-partial-specialization=false -debug-only=sil-inliner 2>%t/log | %FileCheck %s
|
|
// RUN: %FileCheck %s --check-prefix=CHECK-LOG <%t/log
|
|
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -inline -sil-inline-generics=true -sil-partial-specialization=true -generic-specializer -debug-only=sil-inliner 2>%t/log | %FileCheck %s --check-prefix=CHECK-PARTIAL-SPECIALIZATION
|
|
// REQUIRES: asserts
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
// This test checks the inline heuristics based on the debug log output of
|
|
// the performance inliner.
|
|
// Checking the final sil is just a goodie.
|
|
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
struct Cont {
|
|
var cl: (Int32) -> Int32
|
|
}
|
|
|
|
struct Cont2 {
|
|
var tp: (Int32, (Int32) -> Int32)
|
|
}
|
|
|
|
enum E {
|
|
case A
|
|
case B((Int32) -> Int32)
|
|
}
|
|
|
|
class C {
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testDirectClosure
|
|
// CHECK: [[C:%[0-9]+]] = thin_to_thick_function
|
|
// CHECK: [[MD:%[0-9]+]] = mark_dependence [[C]]
|
|
// CHECK: apply [[MD]](
|
|
// CHECK: return
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testDirectClosure
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=70,
|
|
|
|
sil @testDirectClosure : $@convention(thin) (@guaranteed C) -> Int32 {
|
|
bb0(%c : $C):
|
|
%0 = function_ref @takeDirectClosure : $@convention(thin) (@owned @callee_guaranteed (Int32) -> Int32) -> Int32
|
|
%1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_guaranteed (Int32) -> Int32
|
|
%3 = mark_dependence %2 on %c
|
|
%4 = apply %0(%3) : $@convention(thin) (@owned @callee_guaranteed (Int32) -> Int32) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
sil @takeDirectClosure : $@convention(thin) (@owned @callee_guaranteed (Int32) -> Int32) -> Int32 {
|
|
bb0(%0 : $@callee_guaranteed (Int32) -> Int32):
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = apply %0(%2) : $@callee_guaranteed (Int32) -> Int32
|
|
return %3 : $Int32
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil @testStructClosure
|
|
// CHECK: [[C:%[0-9]+]] = struct_extract
|
|
// CHECK: apply [[C]](
|
|
// CHECK: return
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testStructClosure
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=70,
|
|
|
|
sil @testStructClosure : $@convention(thin) () -> Int32 {
|
|
bb0:
|
|
%0 = function_ref @takeStructClosure : $@convention(thin) (@owned Cont) -> Int32
|
|
%1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_guaranteed (Int32) -> Int32
|
|
%3 = struct $Cont (%2 : $@callee_guaranteed (Int32) -> Int32)
|
|
%4 = apply %0(%3) : $@convention(thin) (@owned Cont) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
sil @takeStructClosure : $@convention(thin) (@owned Cont) -> Int32 {
|
|
bb0(%0 : $Cont):
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%1 = struct_extract %0 : $Cont, #Cont.cl
|
|
%2 = integer_literal $Builtin.Int32, 27
|
|
%3 = struct $Int32 (%2 : $Builtin.Int32)
|
|
%4 = apply %1(%3) : $@callee_guaranteed (Int32) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil @testStructAddrClosure
|
|
// CHECK: [[C:%[0-9]+]] = load
|
|
// CHECK: apply [[C]](
|
|
// CHECK: return
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testStructAddrClosure
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=70,
|
|
|
|
sil @testStructAddrClosure : $@convention(thin) () -> Int32 {
|
|
bb0:
|
|
%0 = alloc_stack $Cont
|
|
%1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_guaranteed (Int32) -> Int32
|
|
%3 = struct $Cont (%2 : $@callee_guaranteed (Int32) -> Int32)
|
|
store %3 to %0 : $*Cont
|
|
%5 = function_ref @takeStructAddrClosure : $@convention(thin) (@inout Cont) -> Int32
|
|
%6 = apply %5(%0) : $@convention(thin) (@inout Cont) -> Int32
|
|
%7 = struct_element_addr %0 : $*Cont, #Cont.cl
|
|
%8 = load %7 : $*@callee_guaranteed (Int32) -> Int32
|
|
strong_release %8 : $@callee_guaranteed (Int32) -> Int32
|
|
dealloc_stack %0 : $*Cont
|
|
return %6 : $Int32
|
|
}
|
|
|
|
sil @takeStructAddrClosure : $@convention(thin) (@inout Cont) -> Int32 {
|
|
bb0(%0 : $*Cont):
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%1 = struct_element_addr %0 : $*Cont, #Cont.cl
|
|
%2 = load %1 : $*@callee_guaranteed (Int32) -> Int32
|
|
%3 = integer_literal $Builtin.Int32, 27
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32)
|
|
strong_retain %2 : $@callee_guaranteed (Int32) -> Int32
|
|
%6 = apply %2(%4) : $@callee_guaranteed (Int32) -> Int32
|
|
return %6 : $Int32
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil @testTupleClosure
|
|
// CHECK: [[C:%[0-9]+]] = tuple_extract
|
|
// CHECK: apply [[C]](
|
|
// CHECK: return
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testTupleClosure
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=70,
|
|
|
|
sil @testTupleClosure : $@convention(thin) () -> Int32 {
|
|
bb0:
|
|
%0 = function_ref @takeTupleClosure : $@convention(thin) (@owned Cont2) -> Int32
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = function_ref @closure : $@convention(thin) (Int32) -> Int32
|
|
%4 = thin_to_thick_function %3 : $@convention(thin) (Int32) -> Int32 to $@callee_guaranteed (Int32) -> Int32
|
|
%5 = tuple (%2 : $Int32, %4 : $@callee_guaranteed (Int32) -> Int32)
|
|
%6 = struct $Cont2 (%5 : $(Int32, @callee_guaranteed (Int32) -> Int32))
|
|
%7 = apply %0(%6) : $@convention(thin) (@owned Cont2) -> Int32
|
|
return %7 : $Int32
|
|
}
|
|
|
|
|
|
sil @takeTupleClosure : $@convention(thin) (@owned Cont2) -> Int32 {
|
|
bb0(%0 : $Cont2):
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%1 = struct_extract %0 : $Cont2, #Cont2.tp
|
|
%2 = tuple_extract %1 : $(Int32, @callee_guaranteed (Int32) -> Int32), 1
|
|
%3 = integer_literal $Builtin.Int32, 27
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32)
|
|
%5 = apply %2(%4) : $@callee_guaranteed (Int32) -> Int32
|
|
return %5 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testEnumClosure
|
|
// CHECK: [[C:%[0-9]+]] = unchecked_enum_data
|
|
// CHECK: apply [[C]](
|
|
// CHECK: return
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testEnumClosure
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=70,
|
|
|
|
sil @testEnumClosure : $@convention(thin) () -> Int32 {
|
|
bb0:
|
|
%0 = function_ref @takeEnumClosure : $@convention(thin) (@owned E) -> Int32
|
|
%1 = function_ref @closure : $@convention(thin) (Int32) -> Int32
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) (Int32) -> Int32 to $@callee_guaranteed (Int32) -> Int32
|
|
%3 = enum $E, #E.B!enumelt, %2 : $@callee_guaranteed (Int32) -> Int32
|
|
%4 = apply %0(%3) : $@convention(thin) (@owned E) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
|
|
sil @takeEnumClosure : $@convention(thin) (@owned E) -> Int32 {
|
|
bb0(%0 : $E):
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%1 = unchecked_enum_data %0 : $E, #E.B!enumelt
|
|
%2 = integer_literal $Builtin.Int32, 27
|
|
%3 = struct $Int32 (%2 : $Builtin.Int32)
|
|
%4 = apply %1(%3) : $@callee_guaranteed (Int32) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
// The closure which is used by all tests above.
|
|
|
|
sil shared @closure : $@convention(thin) (Int32) -> Int32 {
|
|
bb0(%0 : $Int32):
|
|
%1 = integer_literal $Builtin.Int32, 1
|
|
%2 = struct_extract %0 : $Int32, #Int32._value
|
|
%3 = integer_literal $Builtin.Int1, -1
|
|
%4 = builtin "sadd_with_overflow_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32, %3 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
|
|
%5 = tuple_extract %4 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%6 = tuple_extract %4 : $(Builtin.Int32, Builtin.Int1), 1
|
|
cond_fail %6 : $Builtin.Int1
|
|
%8 = struct $Int32 (%5 : $Builtin.Int32)
|
|
return %8 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testCondBr
|
|
// CHECK-NOT: apply
|
|
// CHECK: builtin "assert_configuration"()
|
|
// CHECK-NOT: apply
|
|
// CHECK: return %{{.*}} : $()
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testCondBr
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=50,
|
|
|
|
sil @testCondBr : $@convention(thin) (Int32) -> () {
|
|
bb0(%a : $Int32):
|
|
%0 = function_ref @condBrCallee : $@convention(thin) (Int32, Int32) -> Int32
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = apply %0(%2, %a) : $@convention(thin) (Int32, Int32) -> Int32
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
sil @condBrCallee : $@convention(thin) (Int32, Int32) -> Int32 {
|
|
bb0(%0 : $Int32, %r : $Int32):
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = struct_extract %0 : $Int32, #Int32._value
|
|
%3 = builtin "cmp_eq_Word"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
|
|
cond_br %3, bb1, bb2
|
|
|
|
bb1:
|
|
br bb3(%r : $Int32)
|
|
|
|
bb2:
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%6 = struct $Int32 (%1 : $Builtin.Int32)
|
|
br bb3(%6 : $Int32)
|
|
|
|
bb3(%8 : $Int32):
|
|
return %8 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testSwitchValue
|
|
// CHECK-NOT: apply
|
|
// CHECK: builtin "assert_configuration"()
|
|
// CHECK-NOT: apply
|
|
// CHECK: return %{{.*}} : $()
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testSwitchValue
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=40,
|
|
|
|
sil @testSwitchValue : $@convention(thin) (Int32) -> () {
|
|
bb0(%a : $Int32):
|
|
|
|
%0 = function_ref @switchValueCallee : $@convention(thin) (Int32, Int32) -> Int32
|
|
%1 = integer_literal $Builtin.Int32, 28
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = apply %0(%2, %a) : $@convention(thin) (Int32, Int32) -> Int32
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
sil @switchValueCallee : $@convention(thin) (Int32, Int32) -> Int32 {
|
|
bb0(%0 : $Int32, %r : $Int32):
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = integer_literal $Builtin.Int32, 28
|
|
%3 = struct_extract %r : $Int32, #Int32._value
|
|
switch_value %3 : $Builtin.Int32, case %1 : bb1, case %2 : bb2, default bb3
|
|
|
|
bb1:
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
br bb4(%1 : $Builtin.Int32)
|
|
|
|
bb2:
|
|
br bb4(%2 : $Builtin.Int32)
|
|
|
|
bb3:
|
|
// increase the scope length
|
|
%c3 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c4 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
br bb4(%1 : $Builtin.Int32)
|
|
|
|
bb4(%8 : $Builtin.Int32):
|
|
%9 = struct $Int32 (%8 : $Builtin.Int32)
|
|
return %9 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testSwitchEnumArg
|
|
// CHECK-NOT: apply
|
|
// CHECK: builtin "assert_configuration"()
|
|
// CHECK-NOT: apply
|
|
// CHECK: return %{{.*}} : $()
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testSwitchEnumArg
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=50,
|
|
|
|
sil @testSwitchEnumArg : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%1 : $Builtin.Int32):
|
|
%0 = function_ref @switchEnumCallee : $@convention(thin) (Optional<Int32>) -> Int32
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = enum $Optional<Int32>, #Optional.some!enumelt, %2 : $Int32
|
|
%4 = apply %0(%3) : $@convention(thin) (Optional<Int32>) -> Int32
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testSwitchEnumConst
|
|
// CHECK-NOT: apply
|
|
// CHECK: builtin "assert_configuration"()
|
|
// CHECK-NOT: apply
|
|
// CHECK: return %{{.*}} : $()
|
|
|
|
// CHECK-LOG-LABEL: Inline into caller: testSwitchEnumConst
|
|
// CHECK-LOG-NEXT: pure-call decision
|
|
|
|
sil @testSwitchEnumConst : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @switchEnumCallee : $@convention(thin) (Optional<Int32>) -> Int32
|
|
%1 = integer_literal $Builtin.Int32, 27
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = enum $Optional<Int32>, #Optional.some!enumelt, %2 : $Int32
|
|
%4 = apply %0(%3) : $@convention(thin) (Optional<Int32>) -> Int32
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
sil @switchEnumCallee : $@convention(thin) (Optional<Int32>) -> Int32 {
|
|
bb0(%0 : $Optional<Int32>):
|
|
switch_enum %0 : $Optional<Int32>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1:
|
|
%2 = unchecked_enum_data %0 : $Optional<Int32>, #Optional.some!enumelt
|
|
br bb3(%2 : $Int32)
|
|
|
|
bb2:
|
|
// increase the scope length
|
|
%c1 = builtin "assert_configuration"() : $Builtin.Int32
|
|
%c2 = builtin "assert_configuration"() : $Builtin.Int32
|
|
|
|
%4 = integer_literal $Builtin.Int32, 0
|
|
%5 = struct $Int32 (%4 : $Builtin.Int32)
|
|
br bb3(%5 : $Int32)
|
|
|
|
bb3(%7 : $Int32):
|
|
return %7 : $Int32
|
|
}
|
|
|
|
// Tests of the generics inlining.
|
|
|
|
// CHECK-LABEL: sil @testSpecializationAfterGenericInlining
|
|
// CHECK-NOT: apply
|
|
// CHECK: function_ref @action
|
|
// CHECK: apply
|
|
// CHECK-NOT: apply
|
|
// CHECK: return
|
|
// CHECK: end sil function 'testSpecializationAfterGenericInlining'
|
|
|
|
// CHECK-PARTIAL-SPECIALIZATION-LABEL: sil @testSpecializationAfterGenericInlining
|
|
// CHECK-PARTIAL-SPECIALIZATION-NOT: apply
|
|
// Reference to the partial specialization of checkSpecializationAfterGenericInlining
|
|
// CHECK-PARTIAL-SPECIALIZATION: function_ref @$s39checkSpecializationAfterGenericInlinings5Int64Vq_ACRszr0_lIetyi_Tp5
|
|
// CHECK-PARTIAL-SPECIALIZATION: apply
|
|
// CHECK-PARTIAL-SPECIALIZATION-NOT: apply
|
|
// CHECK-PARTIAL-SPECIALIZATION: return
|
|
// CHECK-PARTIAL-SPECIALIZATION: end sil function 'testSpecializationAfterGenericInlining'
|
|
|
|
|
|
// Check that the inlining heuristic takes into account the possibility
|
|
// of performing a generic specialization after inlining.
|
|
// CHECK-LOG-LABEL: Inline into caller: testSpecializationAfterGenericInlining
|
|
// CHECK-LOG-NEXT: decision {{.*}}, b=320, {{.*}} checkSpecializationAfterGenericInlining
|
|
|
|
sil hidden [noinline] @action : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : $*T):
|
|
destroy_addr %0 : $*T
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
} // end sil function 'action'
|
|
|
|
// checkSpecializationAfterGenericInlining<A, B> (A, B) -> ()
|
|
sil hidden @checkSpecializationAfterGenericInlining : $@convention(thin) <T, U> (@in T, @in U) -> () {
|
|
bb0(%0 : $*T, %1 : $*U):
|
|
// function_ref action<A> (A) -> ()
|
|
%4 = function_ref @action : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
%5 = alloc_stack $T
|
|
copy_addr %0 to [init] %5 : $*T
|
|
%7 = apply %4<T>(%5) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
dealloc_stack %5 : $*T
|
|
destroy_addr %1 : $*U
|
|
destroy_addr %0 : $*T
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
} // end sil function 'checkSpecializationAfterGenericInlining'
|
|
|
|
sil @testSpecializationAfterGenericInlining : $@convention(thin) <U> (@in U) -> () {
|
|
bb0(%0 : $*U):
|
|
// function_ref checkSpecializationAfterGenericInlining<A, B> (A, B) -> ()
|
|
%2 = function_ref @checkSpecializationAfterGenericInlining : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
|
|
%3 = integer_literal $Builtin.Int64, 1
|
|
%4 = struct $Int64 (%3 : $Builtin.Int64)
|
|
%5 = alloc_stack $Int64
|
|
store %4 to %5 : $*Int64
|
|
%7 = alloc_stack $U
|
|
copy_addr %0 to [init] %7 : $*U
|
|
%9 = apply %2<Int64, U>(%5, %7) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
|
|
dealloc_stack %7 : $*U
|
|
dealloc_stack %5 : $*Int64
|
|
destroy_addr %0 : $*U
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
} // end sil function 'testSpecializationAfterGenericInlining'
|
|
|
|
// Tests of exclusivity inlining.
|
|
|
|
// CHECK-LABEL: sil @testExclusivity : $@convention(thin) () -> () {
|
|
// CHECK-NOT: apply
|
|
// CHECK: begin_access
|
|
// CHECK: return
|
|
// CHECK: end sil function 'testExclusivity'
|
|
|
|
struct X {
|
|
@_hasStorage var i: Int64 { get set }
|
|
init(i: Int64)
|
|
init()
|
|
}
|
|
|
|
var globalX: X
|
|
|
|
sil_global hidden @globalX : $X
|
|
|
|
sil @exclusivityCallee : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @globalX: $*X
|
|
%1 = begin_access [read] [dynamic] [no_nested_conflict] %0 : $*X
|
|
%2 = load %1 : $*X
|
|
end_access %1 : $*X
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
sil @testExclusivity : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @exclusivityCallee : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// TODO:
|
|
// Check that the inlining heuristic takes into account the possibility
|
|
// of performing a devirtualization after inlining.
|
|
|
|
// Test of inlining functions with many parameters
|
|
|
|
// CHECK-LABEL: sil @testManyParams : $@convention(thin) (Float,
|
|
// CHECK-NOT: apply
|
|
// CHECK: return
|
|
// CHECK: end sil function 'testManyParams'
|
|
|
|
sil @manyParamsCallee1 : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float {
|
|
bb0(%0 : $Float, %1 : $Float, %2 : $Float, %3 : $Float, %4 : $Float, %5 : $Float, %6 : $Float, %7 : $Float, %8 : $Float, %9 : $Float, %10 : $Float, %11 : $Float, %12 : $Float, %13 : $Float, %14 : $Float, %15 : $Float, %16 : $Float, %17 : $Float, %18 : $Float):
|
|
%19 = struct_extract %10 : $Float, #Float._value // user: %21
|
|
%20 = struct_extract %0 : $Float, #Float._value // users: %65, %67, %60, %53, %55, %23, %21
|
|
%21 = builtin "fmul_FPIEEE32"(%19 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %27, %25
|
|
%22 = struct_extract %11 : $Float, #Float._value // user: %23
|
|
%23 = builtin "fmul_FPIEEE32"(%22 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %28
|
|
%24 = struct_extract %8 : $Float, #Float._value // user: %25
|
|
%25 = builtin "fmul_FPIEEE32"(%24 : $Builtin.FPIEEE32, %21 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %29
|
|
%26 = struct_extract %9 : $Float, #Float._value // user: %27
|
|
%27 = builtin "fmul_FPIEEE32"(%26 : $Builtin.FPIEEE32, %21 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %28
|
|
%28 = builtin "fadd_FPIEEE32"(%27 : $Builtin.FPIEEE32, %23 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %50
|
|
%29 = builtin "fneg_FPIEEE32"(%25 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %31
|
|
%30 = struct_extract %18 : $Float, #Float._value // user: %31
|
|
%31 = builtin "fdiv_FPIEEE32"(%29 : $Builtin.FPIEEE32, %30 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %34, %32
|
|
%33 = struct_extract %17 : $Float, #Float._value // user: %34
|
|
%34 = builtin "fdiv_FPIEEE32"(%31 : $Builtin.FPIEEE32, %33 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %36
|
|
%35 = struct_extract %16 : $Float, #Float._value // user: %36
|
|
%36 = builtin "fmul_FPIEEE32"(%35 : $Builtin.FPIEEE32, %34 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %43, %37
|
|
%38 = struct_extract %14 : $Float, #Float._value // users: %41, %41
|
|
%39 = struct_extract %15 : $Float, #Float._value // user: %40
|
|
%40 = builtin "fneg_FPIEEE32"(%39 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %42
|
|
%41 = builtin "fmul_FPIEEE32"(%38 : $Builtin.FPIEEE32, %38 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %42
|
|
%42 = builtin "fdiv_FPIEEE32"(%40 : $Builtin.FPIEEE32, %41 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %43
|
|
%43 = builtin "fmul_FPIEEE32"(%42 : $Builtin.FPIEEE32, %36 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %46, %44
|
|
%45 = struct_extract %13 : $Float, #Float._value // user: %46
|
|
%46 = builtin "fdiv_FPIEEE32"(%43 : $Builtin.FPIEEE32, %45 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %48
|
|
%47 = struct_extract %12 : $Float, #Float._value // user: %48
|
|
%48 = builtin "fmul_FPIEEE32"(%47 : $Builtin.FPIEEE32, %46 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %49, %50
|
|
%50 = builtin "fadd_FPIEEE32"(%48 : $Builtin.FPIEEE32, %28 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %51, %63
|
|
%52 = struct_extract %6 : $Float, #Float._value // user: %53
|
|
%53 = builtin "fmul_FPIEEE32"(%52 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %57
|
|
%54 = struct_extract %7 : $Float, #Float._value // user: %55
|
|
%55 = builtin "fmul_FPIEEE32"(%54 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %58
|
|
%56 = struct_extract %5 : $Float, #Float._value // user: %57
|
|
%57 = builtin "fmul_FPIEEE32"(%56 : $Builtin.FPIEEE32, %53 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %58
|
|
%58 = builtin "fadd_FPIEEE32"(%57 : $Builtin.FPIEEE32, %55 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %61
|
|
%59 = struct_extract %4 : $Float, #Float._value // user: %60
|
|
%60 = builtin "fmul_FPIEEE32"(%59 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %61
|
|
%61 = builtin "fadd_FPIEEE32"(%60 : $Builtin.FPIEEE32, %58 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %62, %63
|
|
%63 = builtin "fadd_FPIEEE32"(%61 : $Builtin.FPIEEE32, %50 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %75
|
|
%64 = struct_extract %2 : $Float, #Float._value // user: %65
|
|
%65 = builtin "fmul_FPIEEE32"(%64 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %69
|
|
%66 = struct_extract %3 : $Float, #Float._value // user: %67
|
|
%67 = builtin "fmul_FPIEEE32"(%66 : $Builtin.FPIEEE32, %20 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %70
|
|
%68 = struct_extract %1 : $Float, #Float._value // user: %69
|
|
%69 = builtin "fmul_FPIEEE32"(%68 : $Builtin.FPIEEE32, %65 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %70
|
|
%70 = builtin "fadd_FPIEEE32"(%69 : $Builtin.FPIEEE32, %67 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %73
|
|
%71 = integer_literal $Builtin.Int64, 0 // user: %72
|
|
%72 = builtin "sitofp_Int64_FPIEEE32"(%71 : $Builtin.Int64) : $Builtin.FPIEEE32 // user: %73
|
|
%73 = builtin "fadd_FPIEEE32"(%72 : $Builtin.FPIEEE32, %70 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %74, %75
|
|
%75 = builtin "fadd_FPIEEE32"(%73 : $Builtin.FPIEEE32, %63 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %76
|
|
%76 = struct $Float (%75 : $Builtin.FPIEEE32) // users: %78, %77
|
|
return %76 : $Float // id: %78
|
|
}
|
|
|
|
sil @manyParamsCallee2 : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float {
|
|
bb0(%0 : $Float, %1 : $Float, %2 : $Float, %3 : $Float, %4 : $Float, %5 : $Float, %6 : $Float, %7 : $Float, %8 : $Float, %9 : $Float, %10 : $Float, %11 : $Float, %12 : $Float, %13 : $Float, %14 : $Float, %15 : $Float, %16 : $Float, %17 : $Float, %18 : $Float, %19 : $Float, %20 : $Float, %21 : $Float, %22 : $Float, %23 : $Float, %24 : $Float, %25 : $Float, %26 : $Float):
|
|
%27 = function_ref @manyParamsCallee1 : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float
|
|
%28 = apply %27(%0, %2, %3, %4, %6, %8, %9, %10, %11, %12, %13, %14, %15, %17, %19, %20, %21, %23, %25) : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float
|
|
return %28 : $Float
|
|
}
|
|
|
|
sil @testManyParams : $@convention(thin) (Float, Builtin.FPIEEE32, Builtin.FPIEEE32, Builtin.FPIEEE32) -> (Float, Float) {
|
|
bb0(%0 : $Float, %1 : @closureCapture $Builtin.FPIEEE32, %2 : @closureCapture $Builtin.FPIEEE32, %3 : @closureCapture $Builtin.FPIEEE32):
|
|
%4 = struct $Float (%3 : $Builtin.FPIEEE32)
|
|
%5 = struct $Float (%2 : $Builtin.FPIEEE32)
|
|
%11 = float_literal $Builtin.FPIEEE32, 0x47C35000 // 1.0E+5 // user: %12
|
|
%12 = builtin "fneg_FPIEEE32"(%11 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %15, %13
|
|
%13 = struct $Float (%12 : $Builtin.FPIEEE32) // user: %67
|
|
%14 = struct_extract %0 : $Float, #Float._value // users: %60, %58, %34, %23, %21, %19, %17, %15
|
|
%15 = builtin "fmul_FPIEEE32"(%12 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %17, %16
|
|
%16 = struct $Float (%15 : $Builtin.FPIEEE32) // user: %67
|
|
%17 = builtin "fmul_FPIEEE32"(%15 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %25
|
|
%19 = builtin "fmul_FPIEEE32"(%2 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %20
|
|
%20 = builtin "fadd_FPIEEE32"(%1 : $Builtin.FPIEEE32, %19 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %24
|
|
%21 = builtin "fmul_FPIEEE32"(%3 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %23, %22
|
|
%22 = struct $Float (%21 : $Builtin.FPIEEE32) // user: %67
|
|
%23 = builtin "fmul_FPIEEE32"(%21 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %24
|
|
%24 = builtin "fadd_FPIEEE32"(%20 : $Builtin.FPIEEE32, %23 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %25
|
|
%25 = builtin "fadd_FPIEEE32"(%17 : $Builtin.FPIEEE32, %24 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %61
|
|
%28 = float_literal $Builtin.FPIEEE32, 0x3C9C0EBF // 0.0190500002 // users: %50, %34, %29
|
|
%29 = struct $Float (%28 : $Builtin.FPIEEE32) // users: %67, %67, %30
|
|
%31 = float_literal $Builtin.FPIEEE32, 0x425AA3D7 // 54.6599998 // users: %48, %32
|
|
%32 = struct $Float (%31 : $Builtin.FPIEEE32) // users: %67, %33
|
|
%34 = builtin "fmul_FPIEEE32"(%14 : $Builtin.FPIEEE32, %28 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %38, %35
|
|
%35 = struct $Float (%34 : $Builtin.FPIEEE32) // user: %67
|
|
%36 = float_literal $Builtin.FPIEEE32, 0x34883033 // 2.53670436E-7 // users: %38, %37
|
|
%37 = struct $Float (%36 : $Builtin.FPIEEE32) // user: %67
|
|
%38 = builtin "fdiv_FPIEEE32"(%34 : $Builtin.FPIEEE32, %36 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %43, %39
|
|
%40 = float_literal $Builtin.FPIEEE32, 0x42800000 // 64 // users: %45, %41
|
|
%41 = struct $Float (%40 : $Builtin.FPIEEE32) // user: %67
|
|
%42 = float_literal $Builtin.FPIEEE32, 0x3C23D70A // 0.00999999977 // user: %43
|
|
%43 = builtin "fadd_FPIEEE32"(%38 : $Builtin.FPIEEE32, %42 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %45, %44
|
|
%44 = struct $Float (%43 : $Builtin.FPIEEE32) // user: %67
|
|
%45 = builtin "fdiv_FPIEEE32"(%40 : $Builtin.FPIEEE32, %43 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %48, %46
|
|
%46 = struct $Float (%45 : $Builtin.FPIEEE32) // users: %67, %47
|
|
%48 = builtin "fmul_FPIEEE32"(%45 : $Builtin.FPIEEE32, %31 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %50, %49
|
|
%49 = struct $Float (%48 : $Builtin.FPIEEE32) // user: %67
|
|
%50 = builtin "fdiv_FPIEEE32"(%48 : $Builtin.FPIEEE32, %28 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %55, %51
|
|
%51 = struct $Float (%50 : $Builtin.FPIEEE32) // users: %67, %52
|
|
%53 = float_literal $Builtin.FPIEEE32, 0x3929844A // 1.61663775E-4 // users: %55, %54
|
|
%54 = struct $Float (%53 : $Builtin.FPIEEE32) // user: %67
|
|
%55 = builtin "fdiv_FPIEEE32"(%50 : $Builtin.FPIEEE32, %53 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %56
|
|
%56 = builtin "fneg_FPIEEE32"(%55 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %58, %57
|
|
%57 = struct $Float (%56 : $Builtin.FPIEEE32) // user: %67
|
|
%58 = builtin "fmul_FPIEEE32"(%56 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // users: %60, %59
|
|
%59 = struct $Float (%58 : $Builtin.FPIEEE32) // user: %67
|
|
%60 = builtin "fmul_FPIEEE32"(%58 : $Builtin.FPIEEE32, %14 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %61
|
|
%61 = builtin "fadd_FPIEEE32"(%25 : $Builtin.FPIEEE32, %60 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32 // user: %62
|
|
%62 = struct $Float (%61 : $Builtin.FPIEEE32) // user: %69
|
|
%63 = integer_literal $Builtin.Int64, 1 // user: %64
|
|
%64 = builtin "sitofp_Int64_FPIEEE32"(%63 : $Builtin.Int64) : $Builtin.FPIEEE32
|
|
%65 = struct $Float (%64 : $Builtin.FPIEEE32)
|
|
%66 = function_ref @manyParamsCallee2 : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float
|
|
%67 = apply %66(%65, %0, %13, %0, %16, %0, %5, %0, %4, %0, %22, %0, %57, %0, %59, %29, %0, %37, %35, %44, %41, %32, %46, %29, %49, %54, %51) : $@convention(thin) (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float) -> Float // users: %69, %68
|
|
%69 = tuple (%62 : $Float, %67 : $Float) // user: %70
|
|
return %69 : $(Float, Float) // id: %70
|
|
}
|