Files
swift-mirror/test/AutoDiff/SILOptimizer/closure_specialization/single_bb.sil
T
Anton Korobeynikov 5b0746f967 Fix two Wasm test harness issues and re-enable more autodiff tests (#86931)
- Correctly construct cmake cmdline for wasmstdlib including cmake common host options. This is required in order to include e.g. `CMAKE_OSX_SYSROOT` on macOS, etc.
 - Ensure we're passing path to newly-built SDK to sil-opt

This makes almost every AutoDiff tests passing for Wasm target (the only exception is `AutoDiff/validation-test/always_emit_into_client/multi_module_struct_no_jvp.swift` as `expectCrash()` is not working properly on Wasm.
2026-02-09 19:15:52 -08:00

377 lines
28 KiB
Plaintext

// RUN: %target-sil-opt -sil-print-types -autodiff-closure-specialization -sil-combine %s -o - | %FileCheck %s --check-prefixes=COMBINE,CHECK
// REQUIRES: swift_in_compiler
sil_stage canonical
import Builtin
import Swift
import SwiftShims
import _Differentiation
////////////////////////////////////////////////////////////////
// Single closure call site where closure is passed as @owned //
////////////////////////////////////////////////////////////////
sil @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
sil private [ossa] @$pullback_f : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float {
bb0(%0 : $Float, %1 : @owned $@callee_guaranteed (Float) -> (Float, Float)):
%2 = apply %1(%0) : $@callee_guaranteed (Float) -> (Float, Float)
destroy_value %1
%4 = tuple_extract %2 : $(Float, Float), 0
%5 = tuple_extract %2 : $(Float, Float), 1
%6 = struct_extract %5 : $Float, #Float._value
%7 = struct_extract %4 : $Float, #Float._value
%8 = builtin "fadd_FPIEEE32"(%6 : $Builtin.FPIEEE32, %7 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%9 = struct $Float (%8 : $Builtin.FPIEEE32)
return %9 : $Float
}
// reverse-mode derivative of f(_:)
sil hidden [ossa] @$s4test1fyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
bb0(%0 : $Float):
// CHECK: sil private [ossa] @$s11$pullback_f12$vjpMultiplyS2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float {
// CHECK: bb0(%0 : $Float, %1 : $Float, %2 : $Float):
// CHECK: %[[#A2:]] = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// COMBINE: %[[#]] = apply %[[#A2]](%0, %1, %2) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// CHECK: sil hidden [ossa] @$s4test1fyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#A4:]] = struct_extract %0 : $Float, #Float._value
// CHECK: %[[#A5:]] = builtin "fmul_FPIEEE32"(%[[#A4]] : $Builtin.FPIEEE32, %[[#A4]] : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// CHECK: %[[#A6:]] = struct $Float (%[[#A5]] : $Builtin.FPIEEE32)
// COMBINE-NOT: function_ref @$vjpMultiply
// CHECK: %[[#A7:]] = function_ref @$s11$pullback_f12$vjpMultiplyS2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#A8:]] = partial_apply [callee_guaranteed] %[[#A7]](%0, %0) : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#A9:]] = tuple (%[[#A6]] : $Float, %[[#A8]] : $@callee_guaranteed (Float) -> Float)
// CHECK: return %[[#A9]]
%2 = struct_extract %0 : $Float, #Float._value
%3 = builtin "fmul_FPIEEE32"(%2 : $Builtin.FPIEEE32, %2 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%4 = struct $Float (%3 : $Builtin.FPIEEE32)
// function_ref closure #1 in static Float._vjpMultiply(lhs:rhs:)
%5 = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
%6 = partial_apply [callee_guaranteed] %5(%0, %0) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// function_ref pullback of f(_:)
%7 = function_ref @$pullback_f : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float
%8 = partial_apply [callee_guaranteed] %7(%6) : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float
%9 = tuple (%4 : $Float, %8 : $@callee_guaranteed (Float) -> Float)
return %9 : $(Float, @callee_guaranteed (Float) -> Float)
}
/////////////////////////////////////////////////////////////////////
// Single closure call site where closure is passed as @guaranteed //
/////////////////////////////////////////////////////////////////////
sil private [ossa] @$pullback_k : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> Float {
bb0(%0 : $Float, %1 : @guaranteed $@callee_guaranteed (Float) -> (Float, Float)):
%2 = apply %1(%0) : $@callee_guaranteed (Float) -> (Float, Float)
%3 = tuple_extract %2 : $(Float, Float), 0
%4 = tuple_extract %2 : $(Float, Float), 1
%5 = struct_extract %4 : $Float, #Float._value
%6 = struct_extract %3 : $Float, #Float._value
%7 = builtin "fadd_FPIEEE32"(%5 : $Builtin.FPIEEE32, %6 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%8 = struct $Float (%7 : $Builtin.FPIEEE32)
return %8 : $Float
} // end sil function '$pullback_k'
// reverse-mode derivative of k(_:)
sil hidden [ossa] @$s4test1kyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
bb0(%0 : $Float):
// CHECK: sil private [ossa] @$s11$pullback_k12$vjpMultiplyS2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float {
// CHECK: bb0(%0 : $Float, %1 : $Float, %2 : $Float):
// CHECK: %[[#B2:]] = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// COMBINE: %[[#]] = apply %[[#B2]](%0, %1, %2) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// CHECK: sil hidden [ossa] @$s4test1kyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#B4:]] = struct_extract %0 : $Float, #Float._value
// CHECK: %[[#B5:]] = builtin "fmul_FPIEEE32"(%[[#B4]] : $Builtin.FPIEEE32, %[[#B4]] : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// CHECK: %[[#B6:]] = struct $Float (%[[#B5]] : $Builtin.FPIEEE32)
// COMBINE-NOT: function_ref @$vjpMultiply
// CHECK: %[[#B7:]] = function_ref @$s11$pullback_k12$vjpMultiplyS2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#B8:]] = partial_apply [callee_guaranteed] %[[#B7]](%0, %0) : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#B9:]] = tuple (%[[#B6]] : $Float, %[[#B8]] : $@callee_guaranteed (Float) -> Float)
// CHECK: return %[[#B9]]
%2 = struct_extract %0 : $Float, #Float._value
%3 = builtin "fmul_FPIEEE32"(%2 : $Builtin.FPIEEE32, %2 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%4 = struct $Float (%3 : $Builtin.FPIEEE32)
// function_ref $vjpMultiply
%5 = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
%6 = partial_apply [callee_guaranteed] %5(%0, %0) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// function_ref $pullback_k
%7 = function_ref @$pullback_k : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> Float
%8 = partial_apply [callee_guaranteed] %7(%6) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> Float
%10 = tuple (%4 : $Float, %8 : $@callee_guaranteed (Float) -> Float)
return %10 : $(Float, @callee_guaranteed (Float) -> Float)
} // end sil function '$s4test1kyS2fFTJrSpSr'
///////////////////////////////
// Multiple closure callsite //
///////////////////////////////
sil @$vjpSin : $@convention(thin) (Float, Float) -> Float
sil @$vjpCos : $@convention(thin) (Float, Float) -> Float
// pullback of g(_:)
sil private [ossa] @$pullback_g : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float {
bb0(%0 : $Float, %1 : @owned $@callee_guaranteed (Float) -> Float, %2 : @owned $@callee_guaranteed (Float) -> Float, %3 : @owned $@callee_guaranteed (Float) -> (Float, Float)):
%4 = apply %3(%0) : $@callee_guaranteed (Float) -> (Float, Float)
destroy_value %3 : $@callee_guaranteed (Float) -> (Float, Float)
%6 = tuple_extract %4 : $(Float, Float), 0
%7 = tuple_extract %4 : $(Float, Float), 1
%8 = apply %2(%7) : $@callee_guaranteed (Float) -> Float
destroy_value %2 : $@callee_guaranteed (Float) -> Float
%10 = apply %1(%6) : $@callee_guaranteed (Float) -> Float
destroy_value %1 : $@callee_guaranteed (Float) -> Float
%12 = struct_extract %8 : $Float, #Float._value
%13 = struct_extract %10 : $Float, #Float._value
%14 = builtin "fadd_FPIEEE32"(%13 : $Builtin.FPIEEE32, %12 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%15 = struct $Float (%14 : $Builtin.FPIEEE32)
return %15 : $Float
}
// reverse-mode derivative of g(_:)
sil hidden [ossa] @$s4test1gyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
bb0(%0 : $Float):
// CHECK: sil private [ossa] @$s11$pullback_g7$vjpSinSf0B3CosSf0B8MultiplyS2fTf1nccc_n : $@convention(thin) (Float, Float, Float, Float, Float) -> Float {
// CHECK: bb0(%0 : $Float, %1 : $Float, %2 : $Float, %3 : $Float, %4 : $Float):
// CHECK: %[[#C4:]] = function_ref @$vjpSin : $@convention(thin) (Float, Float) -> Float
// CHECK: %[[#C6:]] = function_ref @$vjpCos : $@convention(thin) (Float, Float) -> Float
// CHECK: %[[#C8:]] = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// COMBINE: %[[#]] = apply %[[#C8]](%0, %3, %4) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// COMBINE: %[[#]] = apply %[[#C6]](%[[#]], %2) : $@convention(thin) (Float, Float) -> Float
// COMBINE: %[[#]] = apply %[[#C4]](%[[#]], %1) : $@convention(thin) (Float, Float) -> Float
// CHECK: sil hidden [ossa] @$s4test1gyS2fFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#C10:]] = struct_extract %0 : $Float, #Float._value
// CHECK: %[[#C11:]] = builtin "int_sin_FPIEEE32"(%[[#C10]] : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// CHECK: %[[#C12:]] = struct $Float (%[[#C11]] : $Builtin.FPIEEE32)
// COMBINE-NOT: function_ref @$vjpSin
// CHECK: %[[#C13:]] = builtin "int_cos_FPIEEE32"(%[[#C10]] : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// COMBINE-NOT: function_ref @$vjpCos
// COMBINE-NOT: function_ref @$vjpMultiply
// CHECK: %[[#C14:]] = struct $Float (%[[#C13]] : $Builtin.FPIEEE32)
// CHECK: %[[#C15:]] = function_ref @$s11$pullback_g7$vjpSinSf0B3CosSf0B8MultiplyS2fTf1nccc_n : $@convention(thin) (Float, Float, Float, Float, Float) -> Float
// CHECK: %[[#C16:]] = partial_apply [callee_guaranteed] %[[#C15]](%0, %0, %[[#C14]], %[[#C12]]) : $@convention(thin) (Float, Float, Float, Float, Float) -> Float
// CHECK: %[[#C17:]] = tuple (%[[#]] : $Float, %[[#C16]] : $@callee_guaranteed (Float) -> Float)
// CHECK: return %[[#C17]]
%2 = struct_extract %0 : $Float, #Float._value
%3 = builtin "int_sin_FPIEEE32"(%2 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%4 = struct $Float (%3 : $Builtin.FPIEEE32)
// function_ref closure #1 in _vjpSin(_:)
%5 = function_ref @$vjpSin : $@convention(thin) (Float, Float) -> Float
%6 = partial_apply [callee_guaranteed] %5(%0) : $@convention(thin) (Float, Float) -> Float
%7 = builtin "int_cos_FPIEEE32"(%2 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%8 = struct $Float (%7 : $Builtin.FPIEEE32)
// function_ref closure #1 in _vjpCos(_:)
%9 = function_ref @$vjpCos : $@convention(thin) (Float, Float) -> Float
%10 = partial_apply [callee_guaranteed] %9(%0) : $@convention(thin) (Float, Float) -> Float
%11 = builtin "fmul_FPIEEE32"(%3 : $Builtin.FPIEEE32, %7 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
%12 = struct $Float (%11 : $Builtin.FPIEEE32)
// function_ref closure #1 in static Float._vjpMultiply(lhs:rhs:)
%13 = function_ref @$vjpMultiply : $@convention(thin) (Float, Float, Float) -> (Float, Float)
%14 = partial_apply [callee_guaranteed] %13(%8, %4) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// function_ref pullback of g(_:)
%15 = function_ref @$pullback_g : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float
%16 = partial_apply [callee_guaranteed] %15(%6, %10, %14) : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float
%17 = tuple (%12 : $Float, %16 : $@callee_guaranteed (Float) -> Float)
return %17 : $(Float, @callee_guaranteed (Float) -> Float)
}
///////////////////////////////
/// Parameter subset thunks ///
///////////////////////////////
struct X : Differentiable {
@_hasStorage var a: Float { get set }
@_hasStorage var b: Double { get set }
struct TangentVector : AdditiveArithmetic, Differentiable {
@_hasStorage var a: Float { get set }
@_hasStorage var b: Double { get set }
static func + (lhs: X.TangentVector, rhs: X.TangentVector) -> X.TangentVector
static func - (lhs: X.TangentVector, rhs: X.TangentVector) -> X.TangentVector
@_implements(Equatable, ==(_:_:)) static func __derived_struct_equals(_ a: X.TangentVector, _ b: X.TangentVector) -> Bool
typealias TangentVector = X.TangentVector
init(a: Float, b: Double)
static var zero: X.TangentVector { get }
}
init(a: Float, b: Double)
mutating func move(by offset: X.TangentVector)
}
sil [transparent] [thunk] @subset_parameter_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float, Double) -> X.TangentVector) -> X.TangentVector
sil @pullback_f : $@convention(thin) (Float, Double) -> X.TangentVector
sil shared [ossa] @pullback_g : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> X.TangentVector) -> X.TangentVector {
bb0(%0 : $Float, %1 : @owned $@callee_guaranteed (Float) -> X.TangentVector):
%2 = apply %1(%0) : $@callee_guaranteed (Float) -> X.TangentVector
destroy_value %1 : $@callee_guaranteed (Float) -> X.TangentVector
return %2 : $X.TangentVector
}
sil hidden [ossa] @$s5test21g1xSfAA1XV_tFTJrSpSr : $@convention(thin) (X) -> (Float, @owned @callee_guaranteed (Float) -> X.TangentVector) {
bb0(%0 : $X):
// CHECK: sil shared [ossa] @$s10pullback_g0A2_fTf1nc_n : $@convention(thin) (Float) -> X.TangentVector {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#D3:]] = function_ref @subset_parameter_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float, Double) -> X.TangentVector) -> X.TangentVector
// CHECK: %[[#D1:]] = function_ref @pullback_f : $@convention(thin) (Float, Double) -> X.TangentVector
// CHECK: %[[#D2:]] = thin_to_thick_function %[[#D1]] : $@convention(thin) (Float, Double) -> X.TangentVector to $@callee_guaranteed (Float, Double) -> X.TangentVector
// COMBINE: %[[#D5:]] = apply %[[#D3]](%0, %[[#D2]]) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float, Double) -> X.TangentVector) -> X.TangentVector
// CHECK: return %[[#D5]]
// CHECK: sil hidden [ossa] @$s5test21g1xSfAA1XV_tFTJrSpSr : $@convention(thin) (X) -> (Float, @owned @callee_guaranteed (Float) -> X.TangentVector) {
// CHECK: bb0(%0 : $X):
// CHECK: %[[#D6:]] = struct_extract %0 : $X, #X.a
// COMBINE-NOT: function_ref @pullback_f
// COMBINE-NOT: function_ref @subset_parameter_thunk
// CHECK: %[[#D7:]] = function_ref @$s10pullback_g0A2_fTf1nc_n : $@convention(thin) (Float) -> X.TangentVector
// COMBINE: %[[#D8:]] = thin_to_thick_function %[[#D7]] : $@convention(thin) (Float) -> X.TangentVector to $@callee_guaranteed (Float) -> X.TangentVector
// CHECK: %[[#D9:]] = tuple (%[[#D6]] : $Float, %[[#D8]] : $@callee_guaranteed (Float) -> X.TangentVector)
// CHECK: return %[[#D9]]
%1 = struct_extract %0 : $X, #X.a
// function_ref pullback_f
%2 = function_ref @pullback_f : $@convention(thin) (Float, Double) -> X.TangentVector
%3 = thin_to_thick_function %2 : $@convention(thin) (Float, Double) -> X.TangentVector to $@callee_guaranteed (Float, Double) -> X.TangentVector
// function_ref subset_parameter_thunk
%4 = function_ref @subset_parameter_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float, Double) -> X.TangentVector) -> X.TangentVector
%5 = partial_apply [callee_guaranteed] %4(%3) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (Float, Double) -> X.TangentVector) -> X.TangentVector
// function_ref pullback_g
%6 = function_ref @pullback_g : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> X.TangentVector) -> X.TangentVector
%7 = partial_apply [callee_guaranteed] %6(%5) : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> X.TangentVector) -> X.TangentVector
%8 = tuple (%1 : $Float, %7 : $@callee_guaranteed (Float) -> X.TangentVector)
return %8 : $(Float, @callee_guaranteed (Float) -> X.TangentVector)
}
///////////////////////////////////////////////////////////////////////
///////// Specialized generic closures - PartialApply Closure /////////
///////////////////////////////////////////////////////////////////////
// closure #1 in static Float._vjpMultiply(lhs:rhs:)
sil @$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbacktSf_SftFZSf_SftSfcfU_ : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// thunk for @escaping @callee_guaranteed (@unowned Float) -> (@unowned Float, @unowned Float)
sil [transparent] [reabstraction_thunk] @$sS3fIegydd_S3fIegnrr_TR : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> (@out Float, @out Float)
// function_ref specialized pullback of f<A>(a:)
sil [transparent] [thunk] @pullback_f_specialized : $@convention(thin) (@in_guaranteed Float, @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>) -> @out Float
// thunk for @escaping @callee_guaranteed (@in_guaranteed Float) -> (@out Float)
sil [transparent] [reabstraction_thunk] @$sS2fIegnr_S2fIegyd_TR : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
sil private [signature_optimized_thunk] [heuristic_always_inline] [ossa] @pullback_h : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float {
bb0(%0 : $Float, %1 : @owned $@callee_guaranteed (Float) -> Float):
%2 = apply %1(%0) : $@callee_guaranteed (Float) -> Float
destroy_value %1 : $@callee_guaranteed (Float) -> Float
return %2 : $Float
}
// reverse-mode derivative of h(x:)
sil hidden [ossa] @$s5test21h1xS2f_tFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
bb0(%0 : $Float):
// CHECK: sil private [signature_optimized_thunk] [heuristic_always_inline] [ossa] @$s10pullback_h073$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbackti1_j5FZSf_J6SfcfU_S2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float {
// CHECK: bb0(%0 : $Float, %1 : $Float, %2 : $Float):
// CHECK: %[[#E8:]] = function_ref @$sS2fIegnr_S2fIegyd_TR : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
// CHECK: %[[#E6:]] = function_ref @pullback_f_specialized : $@convention(thin) (@in_guaranteed Float, @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>) -> @out Float
// CHECK: %[[#E3:]] = function_ref @$sS3fIegydd_S3fIegnrr_TR : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> (@out Float, @out Float)
// CHECK: %[[#E1:]] = function_ref @$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbacktSf_SftFZSf_SftSfcfU_ : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// CHECK: %[[#E2:]] = partial_apply [callee_guaranteed] %[[#E1]](%1, %2) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// CHECK: %[[#E4:]] = partial_apply [callee_guaranteed] %[[#E3]](%[[#E2]]) : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> (@out Float, @out Float)
// CHECK: %[[#E5:]] = convert_function %[[#E4]] : $@callee_guaranteed (@in_guaranteed Float) -> (@out Float, @out Float) to $@callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>
// CHECK: %[[#E7:]] = partial_apply [callee_guaranteed] %[[#E6]](%[[#E5]]) : $@convention(thin) (@in_guaranteed Float, @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>) -> @out Float
// COMBINE: %[[#E10:]] = apply %[[#E8]](%0, %[[#E7]]) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
// COMBINE: destroy_value %[[#E7]] : $@callee_guaranteed (@in_guaranteed Float) -> @out Float
// CHECK: return %[[#E10]]
// CHECK: sil hidden [ossa] @$s5test21h1xS2f_tFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#E11:]] = struct_extract %0 : $Float, #Float._value
// CHECK: %[[#E12:]] = builtin "fmul_FPIEEE32"(%[[#E11]] : $Builtin.FPIEEE32, %1 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// COMBINE-NOT: function_ref @$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbacktSf_SftFZSf_SftSfcfU_
// COMBINE-NOT: function_ref @$sS3fIegydd_S3fIegnrr_TR
// COMBINE-NOT: function_ref @pullback_f_specialized
// COMBINE-NOT: function_ref @$sS2fIegnr_S2fIegyd_TR
// CHECK: %[[#E13:]] = struct $Float (%[[#E12]] : $Builtin.FPIEEE32)
// CHECK: %[[#E14:]] = function_ref @$s10pullback_h073$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbackti1_j5FZSf_J6SfcfU_S2fTf1nc_n : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#E15:]] = partial_apply [callee_guaranteed] %[[#E14]](%0, %0) : $@convention(thin) (Float, Float, Float) -> Float
// CHECK: %[[#E16:]] = tuple (%[[#E13]] : $Float, %[[#E15]] : $@callee_guaranteed (Float) -> Float)
// CHECK: return %[[#E16]]
%1 = struct_extract %0 : $Float, #Float._value
%2 = builtin "fmul_FPIEEE32"(%1 : $Builtin.FPIEEE32, %1 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
// function_ref closure #1 in static Float._vjpMultiply(lhs:rhs:)
%3 = function_ref @$sSf16_DifferentiationE12_vjpMultiply3lhs3rhsSf5value_Sf_SftSfc8pullbacktSf_SftFZSf_SftSfcfU_ : $@convention(thin) (Float, Float, Float) -> (Float, Float)
%4 = partial_apply [callee_guaranteed] %3(%0, %0) : $@convention(thin) (Float, Float, Float) -> (Float, Float)
// function_ref thunk for @escaping @callee_guaranteed (@unowned Float) -> (@unowned Float, @unowned Float)
%5 = function_ref @$sS3fIegydd_S3fIegnrr_TR : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> (@out Float, @out Float)
%6 = partial_apply [callee_guaranteed] %5(%4) : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> (@out Float, @out Float)
%7 = convert_function %6 : $@callee_guaranteed (@in_guaranteed Float) -> (@out Float, @out Float) to $@callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>
// function_ref pullback_f_specialized
%8 = function_ref @pullback_f_specialized : $@convention(thin) (@in_guaranteed Float, @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>) -> @out Float
%9 = partial_apply [callee_guaranteed] %8(%7) : $@convention(thin) (@in_guaranteed Float, @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @out τ_0_2) for <Float, Float, Float>) -> @out Float
// function_ref thunk for @escaping @callee_guaranteed (@in_guaranteed Float) -> (@out Float)
%10 = function_ref @$sS2fIegnr_S2fIegyd_TR : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
%11 = partial_apply [callee_guaranteed] %10(%9) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
%12 = struct $Float (%2 : $Builtin.FPIEEE32)
// function_ref pullback_h
%13 = function_ref @pullback_h : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float
%14 = partial_apply [callee_guaranteed] %13(%11) : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float
%15 = tuple (%12 : $Float, %14 : $@callee_guaranteed (Float) -> Float)
return %15 : $(Float, @callee_guaranteed (Float) -> Float)
}
//////////////////////////////////////////////////////////////////////////////
///////// Specialized generic closures - ThinToThickFunction closure /////////
//////////////////////////////////////////////////////////////////////////////
sil [transparent] [thunk] @pullback_y_specialized : $@convention(thin) (@in_guaranteed Float) -> @out Float
sil [transparent] [reabstraction_thunk] @reabstraction_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
sil private [signature_optimized_thunk] [heuristic_always_inline] [ossa] @pullback_z : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float {
bb0(%0 : $Float, %1 : @owned $@callee_guaranteed (Float) -> Float):
%2 = apply %1(%0) : $@callee_guaranteed (Float) -> Float
destroy_value %1 : $@callee_guaranteed (Float) -> Float
return %2 : $Float
}
sil hidden [ossa] @$s5test21z1xS2f_tFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
bb0(%0 : $Float):
// CHECK: sil private [signature_optimized_thunk] [heuristic_always_inline] [ossa] @$s10pullback_z0A14_y_specializedTf1nc_n : $@convention(thin) (Float) -> Float {
// CHECK: bb0(%0 : $Float):
// CHECK: %[[#F3:]] = function_ref @reabstraction_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
// CHECK: %[[#F1:]] = function_ref @pullback_y_specialized : $@convention(thin) (@in_guaranteed Float) -> @out Float
// CHECK: %[[#F2:]] = thin_to_thick_function %[[#F1]] : $@convention(thin) (@in_guaranteed Float) -> @out Float to $@callee_guaranteed (@in_guaranteed Float) -> @out Float
// COMBINE: %[[#F5:]] = apply %[[#F3]](%0, %[[#F2]]) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
// CHECK: return %[[#F5]]
// CHECK: sil hidden [ossa] @$s5test21z1xS2f_tFTJrSpSr : $@convention(thin) (Float) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
// CHECK: bb0(%0 : $Float):
// COMBINE-NOT: function_ref @pullback_y_specialized
// COMBINE-NOT: function_ref @reabstraction_thunk
// CHECK: %[[#F6:]] = function_ref @$s10pullback_z0A14_y_specializedTf1nc_n : $@convention(thin) (Float) -> Float
// COMBINE: %[[#F7:]] = thin_to_thick_function %[[#F6]] : $@convention(thin) (Float) -> Float to $@callee_guaranteed (Float) -> Float
// CHECK: %[[#F8:]] = tuple (%0 : $Float, %[[#F7]] : $@callee_guaranteed (Float) -> Float)
// CHECK: return %[[#F8]]
// function_ref pullback_y_specialized
%1 = function_ref @pullback_y_specialized : $@convention(thin) (@in_guaranteed Float) -> @out Float
%2 = thin_to_thick_function %1 : $@convention(thin) (@in_guaranteed Float) -> @out Float to $@callee_guaranteed (@in_guaranteed Float) -> @out Float
// function_ref reabstraction_thunk
%3 = function_ref @reabstraction_thunk : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
%4 = partial_apply [callee_guaranteed] %3(%2) : $@convention(thin) (Float, @guaranteed @callee_guaranteed (@in_guaranteed Float) -> @out Float) -> Float
// function_ref pullback_z
%5 = function_ref @pullback_z : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float
%6 = partial_apply [callee_guaranteed] %5(%4) : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> Float) -> Float
%7 = tuple (%0 : $Float, %6 : $@callee_guaranteed (Float) -> Float)
return %7 : $(Float, @callee_guaranteed (Float) -> Float)
}