// 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) } // CHECK-LABEL: sil @testDirectClosure // CHECK: [[C:%[0-9]+]] = thin_to_thick_function // CHECK: apply [[C]]( // CHECK: return // CHECK-LOG-LABEL: Inline into caller: testDirectClosure // CHECK-LOG-NEXT: decision {{.*}}, b=70, sil @testDirectClosure : $@convention(thin) () -> Int32 { bb0: %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 = apply %0(%2) : $@convention(thin) (@owned @callee_guaranteed (Int32) -> Int32) -> Int32 return %3 : $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 %2 = struct $Int32 (%1 : $Builtin.Int32) %3 = enum $Optional, #Optional.some!enumelt, %2 : $Int32 %4 = apply %0(%3) : $@convention(thin) (Optional) -> 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 %1 = integer_literal $Builtin.Int32, 27 %2 = struct $Int32 (%1 : $Builtin.Int32) %3 = enum $Optional, #Optional.some!enumelt, %2 : $Int32 %4 = apply %0(%3) : $@convention(thin) (Optional) -> Int32 %5 = tuple () return %5 : $() } sil @switchEnumCallee : $@convention(thin) (Optional) -> Int32 { bb0(%0 : $Optional): switch_enum %0 : $Optional, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2 bb1: %2 = unchecked_enum_data %0 : $Optional, #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) (@in T) -> () { bb0(%0 : $*T): destroy_addr %0 : $*T %3 = tuple () return %3 : $() } // end sil function 'action' // checkSpecializationAfterGenericInlining (A, B) -> () sil hidden @checkSpecializationAfterGenericInlining : $@convention(thin) (@in T, @in U) -> () { bb0(%0 : $*T, %1 : $*U): // function_ref action (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(%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) (@in U) -> () { bb0(%0 : $*U): // function_ref checkSpecializationAfterGenericInlining (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(%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 }