EnzymeAD/Enzyme.jl

Implement besseli

オープン

#1,603 opened on 2024/07/02

 (0 件のコメント) (0 件のリアクション) (0 人の担当者)Julia (96 件のフォーク)batch import
help wanted

Repository metrics

Stars
 (563 個のスター)
PR merge metrics
 (平均マージ 5d 1h) (30d で 76 merged PRs)

説明

MWE:

module MWE

using SpecialFunctions: libopenspecfun
using Enzyme

Enzyme.API.printall!(true)

function besseli(nu, z)
    kode = Int32(1)
    ai1, ai2 = Ref{Float64}(), Ref{Float64}()
    ae1, ae2 = Ref{Int32}(), Ref{Int32}()

    ccall((:zbesi_,libopenspecfun), Cvoid,
          (Ref{Float64}, Ref{Float64}, Ref{Float64}, Ref{Int32}, Ref{Int32},
           Ref{Float64}, Ref{Float64}, Ref{Int32}, Ref{Int32}),
           z, 0.0, 1.0, kode, 1,
           ai1, ai2, ae1, ae2)

    if ae2[] == 0
        return 2*nu
    else
        throw(AssertionError())
    end
end

f(x) = besseli(x, 2.7)

Enzyme.autodiff(Enzyme.Forward, f, Duplicated(1.0, 1.0))

end

Output:

after simplification :
; Function Attrs: mustprogress willreturn
define "enzyme_type"="{[-1]:Float@double}" double @preprocess_julia_f_15293(double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %0) local_unnamed_addr #7 !dbg !63 {
top:
  %1 = call {}*** @julia.get_pgcstack() #8
  %ptls_field3 = getelementptr inbounds {}**, {}*** %1, i64 2
  %2 = bitcast {}*** %ptls_field3 to i64***
  %ptls_load45 = load i64**, i64*** %2, align 8, !tbaa !10
  %3 = getelementptr inbounds i64*, i64** %ptls_load45, i64 2
  %safepoint = load i64*, i64** %3, align 8, !tbaa !14
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #8, !dbg !64
  fence syncscope("singlethread") seq_cst
  %4 = call fastcc double @julia_besseli_15296(double %0) #8, !dbg !64
  ret double %4, !dbg !64
}

after simplification :
; Function Attrs: mustprogress willreturn
define internal fastcc "enzyme_type"="{[-1]:Float@double}" double @preprocess_julia_besseli_15296(double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %0) unnamed_addr #8 !dbg !77 {
top:
  %1 = alloca i64, align 16
  %2 = bitcast i64* %1 to i8*
  %3 = alloca i64, align 16
  %4 = bitcast i64* %3 to i8*
  %5 = alloca i32, align 8
  %6 = bitcast i32* %5 to i8*
  %7 = alloca i32, align 8
  %8 = bitcast i32* %7 to i8*
  %9 = alloca i64, align 16
  %10 = bitcast i64* %9 to i8*
  %11 = alloca i64, align 16
  %12 = bitcast i64* %11 to i8*
  %13 = alloca i64, align 16
  %14 = bitcast i64* %13 to i8*
  %15 = alloca i32, align 8
  %16 = bitcast i32* %15 to i8*
  %17 = alloca i32, align 8
  %18 = bitcast i32* %17 to i8*
  %19 = call {}*** @julia.get_pgcstack() #9
  %ptls_field67 = getelementptr inbounds {}**, {}*** %19, i64 2
  %20 = bitcast {}*** %ptls_field67 to i64***
  %ptls_load6869 = load i64**, i64*** %20, align 8, !tbaa !10
  %21 = getelementptr inbounds i64*, i64** %ptls_load6869, i64 2
  %safepoint = load i64*, i64** %21, align 8, !tbaa !14
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #9, !dbg !78
  fence syncscope("singlethread") seq_cst
  %22 = bitcast i64* %9 to double*, !dbg !79
  store double 2.700000e+00, double* %22, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  %memcpy_refined_dst = bitcast i64* %11 to double*, !dbg !79
  store double 0.000000e+00, double* %memcpy_refined_dst, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  %memcpy_refined_dst15 = bitcast i64* %13 to double*, !dbg !79
  store double 1.000000e+00, double* %memcpy_refined_dst15, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  store i32 1, i32* %15, align 8, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  store i32 1, i32* %17, align 8, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  call void @zbesi_(i8* noundef nonnull %10, i8* noundef nonnull %12, i8* noundef nonnull %14, i8* noundef nonnull %16, i8* noundef nonnull %18, i8* noundef nonnull %2, i8* noundef nonnull %4, i8* noundef nonnull %6, i8* noundef nonnull %8) #9 [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !82
  %23 = load i32, i32* %7, align 8, !dbg !86, !tbaa !29, !alias.scope !33, !noalias !49
  %.not = icmp eq i32 %23, 0, !dbg !89
  br i1 %.not, label %L114, label %L116, !dbg !88

L114:                                             ; preds = %top
  %24 = fmul double %0, 2.000000e+00, !dbg !91
  ret double %24, !dbg !93

L116:                                             ; preds = %top
  %current_task166 = getelementptr inbounds {}**, {}*** %19, i64 -14
  %current_task1 = bitcast {}*** %current_task166 to {}**
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %2) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %4) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %6) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %8) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %10) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %12) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %14) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %16) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %18) #9
  %box = call noalias nonnull dereferenceable(8) "enzyme_inactive" "enzyme_type"="{[-1]:Pointer, [-1,-1]:Pointer}" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task1, i64 noundef 8, {} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 4826099712 to {}*) to {} addrspace(10)*)) #10, !dbg !94
  %25 = bitcast {} addrspace(10)* %box to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !94
  %26 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %25, i64 0, i64 0, !dbg !94
  store {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4965887920 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspace(10)* %26, align 8, !dbg !94, !tbaa !61, !alias.scope !33, !noalias !83
  %27 = addrspacecast {} addrspace(10)* %box to {} addrspace(12)*, !dbg !94
  call void @ijl_throw({} addrspace(12)* %27) #11, !dbg !94
  unreachable, !dbg !94
}

; Function Attrs: mustprogress willreturn
define internal fastcc double @fwddiffejulia_besseli_15296(double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %0, double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %"'") unnamed_addr #8 !dbg !95 {
top:
  %"'ipa" = alloca i64, align 16
  store i64 0, i64* %"'ipa", align 16
  %1 = alloca i64, align 16
  %"'ipc" = bitcast i64* %"'ipa" to i8*
  %2 = bitcast i64* %1 to i8*
  %"'ipa16" = alloca i64, align 16
  store i64 0, i64* %"'ipa16", align 16
  %3 = alloca i64, align 16
  %"'ipc17" = bitcast i64* %"'ipa16" to i8*
  %4 = bitcast i64* %3 to i8*
  %"'ipa18" = alloca i32, align 8
  store i32 0, i32* %"'ipa18", align 8
  %5 = alloca i32, align 8
  %"'ipc19" = bitcast i32* %"'ipa18" to i8*
  %6 = bitcast i32* %5 to i8*
  %"'ipa20" = alloca i32, align 8
  store i32 0, i32* %"'ipa20", align 8
  %7 = alloca i32, align 8
  %"'ipc21" = bitcast i32* %"'ipa20" to i8*
  %8 = bitcast i32* %7 to i8*
  %"'ipa22" = alloca i64, align 16
  store i64 0, i64* %"'ipa22", align 16
  %9 = alloca i64, align 16
  %"'ipc23" = bitcast i64* %"'ipa22" to i8*
  %10 = bitcast i64* %9 to i8*
  %"'ipa24" = alloca i64, align 16
  store i64 0, i64* %"'ipa24", align 16
  %11 = alloca i64, align 16
  %"'ipc25" = bitcast i64* %"'ipa24" to i8*
  %12 = bitcast i64* %11 to i8*
  %"'ipa26" = alloca i64, align 16
  store i64 0, i64* %"'ipa26", align 16
  %13 = alloca i64, align 16
  %"'ipc27" = bitcast i64* %"'ipa26" to i8*
  %14 = bitcast i64* %13 to i8*
  %15 = alloca i32, align 8
  %16 = bitcast i32* %15 to i8*
  %17 = alloca i32, align 8
  %18 = bitcast i32* %17 to i8*
  %19 = call {}*** @julia.get_pgcstack() #9
  %ptls_field67 = getelementptr inbounds {}**, {}*** %19, i64 2
  %20 = bitcast {}*** %ptls_field67 to i64***
  %ptls_load6869 = load i64**, i64*** %20, align 8, !tbaa !10, !alias.scope !96, !noalias !99
  %21 = getelementptr inbounds i64*, i64** %ptls_load6869, i64 2
  %safepoint = load i64*, i64** %21, align 8, !tbaa !14, !alias.scope !101, !noalias !104
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #9, !dbg !106
  fence syncscope("singlethread") seq_cst
  %"'ipc28" = bitcast i64* %"'ipa22" to double*, !dbg !107
  %22 = bitcast i64* %9 to double*, !dbg !107
  store double 0.000000e+00, double* %"'ipc28", align 16, !dbg !107, !tbaa !29, !alias.scope !111, !noalias !114
  store double 2.700000e+00, double* %22, align 16, !dbg !107, !tbaa !29, !alias.scope !116, !noalias !117
  %"memcpy_refined_dst'ipc" = bitcast i64* %"'ipa24" to double*, !dbg !107
  %memcpy_refined_dst = bitcast i64* %11 to double*, !dbg !107
  store double 0.000000e+00, double* %"memcpy_refined_dst'ipc", align 16, !dbg !107, !tbaa !29, !alias.scope !118, !noalias !121
  store double 0.000000e+00, double* %memcpy_refined_dst, align 16, !dbg !107, !tbaa !29, !alias.scope !123, !noalias !124
  %"memcpy_refined_dst15'ipc" = bitcast i64* %"'ipa26" to double*, !dbg !107
  %memcpy_refined_dst15 = bitcast i64* %13 to double*, !dbg !107
  store double 0.000000e+00, double* %"memcpy_refined_dst15'ipc", align 16, !dbg !107, !tbaa !29, !alias.scope !125, !noalias !128
  store double 1.000000e+00, double* %memcpy_refined_dst15, align 16, !dbg !107, !tbaa !29, !alias.scope !130, !noalias !131
  store i32 1, i32* %15, align 8, !dbg !107, !tbaa !29, !alias.scope !33, !noalias !132
  store i32 1, i32* %17, align 8, !dbg !107, !tbaa !29, !alias.scope !33, !noalias !132
  call void inttoptr (i64 13170132768 to void (i8*)*)(i8* getelementptr inbounds ([5193 x i8], [5193 x i8]* @0, i32 0, i32 0)) #10, !dbg !110
  call void @fwddiffezbesi_(i8* %10, i8* %"'ipc23", i8* %12, i8* %"'ipc25", i8* %14, i8* %"'ipc27", i8* %16, i8* %18, i8* %2, i8* %"'ipc", i8* %4, i8* %"'ipc17", i8* %6, i8* %"'ipc19", i8* %8, i8* %"'ipc21") [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !110
  %23 = load i32, i32* %7, align 8, !dbg !135, !tbaa !29, !alias.scope !138, !noalias !141
  %.not = icmp eq i32 %23, 0, !dbg !143
  br i1 %.not, label %L114, label %L116, !dbg !137

L114:                                             ; preds = %top
  %24 = fmul fast double %"'", 2.000000e+00, !dbg !145
  ret double %24

L116:                                             ; preds = %top
  %current_task166 = getelementptr inbounds {}**, {}*** %19, i64 -14
  %current_task1 = bitcast {}*** %current_task166 to {}**
  %box = call noalias nonnull dereferenceable(8) "enzyme_inactive" "enzyme_type"="{[-1]:Pointer, [-1,-1]:Pointer}" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task1, i64 noundef 8, {} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 4826099712 to {}*) to {} addrspace(10)*)) #11, !dbg !146
  %25 = bitcast {} addrspace(10)* %box to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !146
  %26 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %25, i64 0, i64 0, !dbg !146
  store {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4965887920 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspace(10)* %26, align 8, !dbg !146, !tbaa !61, !alias.scope !33, !noalias !132
  %27 = addrspacecast {} addrspace(10)* %box to {} addrspace(12)*, !dbg !146
  call void @ijl_throw({} addrspace(12)* %27) #12, !dbg !146
  unreachable, !dbg !146
}

; Function Attrs: mustprogress willreturn
define internal double @fwddiffejulia_f_15293(double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %0, double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %"'") local_unnamed_addr #7 !dbg !65 {
top:
  %1 = call {}*** @julia.get_pgcstack() #9
  %ptls_field3 = getelementptr inbounds {}**, {}*** %1, i64 2
  %2 = bitcast {}*** %ptls_field3 to i64***
  %ptls_load45 = load i64**, i64*** %2, align 8, !tbaa !10, !alias.scope !66, !noalias !69
  %3 = getelementptr inbounds i64*, i64** %ptls_load45, i64 2
  %safepoint = load i64*, i64** %3, align 8, !tbaa !14, !alias.scope !71, !noalias !74
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #9, !dbg !76
  fence syncscope("singlethread") seq_cst
  %4 = call fast fastcc double @fwddiffejulia_besseli_15296(double %0, double %"'"), !dbg !76
  ret double %4
}

ERROR: Enzyme execution failed.
Enzyme compilation failed.
Current scope:
; Function Attrs: mustprogress willreturn
define internal fastcc "enzyme_type"="{[-1]:Float@double}" double @preprocess_julia_besseli_15296(double "enzyme_type"="{[-1]:Float@double}" "enzymejl_parmtype"="4897950928" "enzymejl_parmtype_ref"="0" %0) unnamed_addr #8 !dbg !77 {
top:
  %1 = alloca i64, align 16
  %2 = bitcast i64* %1 to i8*
  %3 = alloca i64, align 16
  %4 = bitcast i64* %3 to i8*
  %5 = alloca i32, align 8
  %6 = bitcast i32* %5 to i8*
  %7 = alloca i32, align 8
  %8 = bitcast i32* %7 to i8*
  %9 = alloca i64, align 16
  %10 = bitcast i64* %9 to i8*
  %11 = alloca i64, align 16
  %12 = bitcast i64* %11 to i8*
  %13 = alloca i64, align 16
  %14 = bitcast i64* %13 to i8*
  %15 = alloca i32, align 8
  %16 = bitcast i32* %15 to i8*
  %17 = alloca i32, align 8
  %18 = bitcast i32* %17 to i8*
  %19 = call {}*** @julia.get_pgcstack() #9
  %ptls_field67 = getelementptr inbounds {}**, {}*** %19, i64 2
  %20 = bitcast {}*** %ptls_field67 to i64***
  %ptls_load6869 = load i64**, i64*** %20, align 8, !tbaa !10
  %21 = getelementptr inbounds i64*, i64** %ptls_load6869, i64 2
  %safepoint = load i64*, i64** %21, align 8, !tbaa !14
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #9, !dbg !78
  fence syncscope("singlethread") seq_cst
  %22 = bitcast i64* %9 to double*, !dbg !79
  store double 2.700000e+00, double* %22, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  %memcpy_refined_dst = bitcast i64* %11 to double*, !dbg !79
  store double 0.000000e+00, double* %memcpy_refined_dst, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  %memcpy_refined_dst15 = bitcast i64* %13 to double*, !dbg !79
  store double 1.000000e+00, double* %memcpy_refined_dst15, align 16, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  store i32 1, i32* %15, align 8, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  store i32 1, i32* %17, align 8, !dbg !79, !tbaa !29, !alias.scope !33, !noalias !83
  call void @zbesi_(i8* noundef nonnull %10, i8* noundef nonnull %12, i8* noundef nonnull %14, i8* noundef nonnull %16, i8* noundef nonnull %18, i8* noundef nonnull %2, i8* noundef nonnull %4, i8* noundef nonnull %6, i8* noundef nonnull %8) #9 [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !82
  %23 = load i32, i32* %7, align 8, !dbg !86, !tbaa !29, !alias.scope !33, !noalias !49
  %.not = icmp eq i32 %23, 0, !dbg !89
  br i1 %.not, label %L114, label %L116, !dbg !88

L114:                                             ; preds = %top
  %24 = fmul double %0, 2.000000e+00, !dbg !91
  ret double %24, !dbg !93

L116:                                             ; preds = %top
  %current_task166 = getelementptr inbounds {}**, {}*** %19, i64 -14
  %current_task1 = bitcast {}*** %current_task166 to {}**
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %2) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %4) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %6) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %8) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %10) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %12) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 8, i8* noundef nonnull %14) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %16) #9
  call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull %18) #9
  %box = call noalias nonnull dereferenceable(8) "enzyme_inactive" "enzyme_type"="{[-1]:Pointer, [-1,-1]:Pointer}" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task1, i64 noundef 8, {} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 4826099712 to {}*) to {} addrspace(10)*)) #10, !dbg !94
  %25 = bitcast {} addrspace(10)* %box to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !94
  %26 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %25, i64 0, i64 0, !dbg !94
  store {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4965887920 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspace(10)* %26, align 8, !dbg !94, !tbaa !61, !alias.scope !33, !noalias !83
  %27 = addrspacecast {} addrspace(10)* %box to {} addrspace(12)*, !dbg !94
  call void @ijl_throw({} addrspace(12)* %27) #11, !dbg !94
  unreachable, !dbg !94
}

No forward mode derivative found for zbesi_
 at context:   call void @zbesi_(i8* noundef nonnull %10, i8* noundef nonnull %12, i8* noundef nonnull %14, i8* noundef nonnull %16, i8* noundef nonnull %18, i8* noundef nonnull %2, i8* noundef nonnull %4, i8* noundef nonnull %6, i8* noundef nonnull %8) #9 [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !26

Stacktrace:
 [1] besseli
   @ ./REPL[10]:13


Stacktrace:
  [1] throwerr(cstr::Cstring)
    @ Enzyme.Compiler ~/.julia/packages/Enzyme/7ZLaZ/src/compiler.jl:1620
  [2] besseli
    @ ./REPL[10]:13
  [3] f
    @ ./REPL[10]:26 [inlined]
  [4] fwddiffejulia_f_15293wrap
    @ ./REPL[10]:0
  [5] macro expansion
    @ ~/.julia/packages/Enzyme/7ZLaZ/src/compiler.jl:6606 [inlined]
  [6] enzyme_call
    @ ~/.julia/packages/Enzyme/7ZLaZ/src/compiler.jl:6207 [inlined]
  [7] ForwardModeThunk
    @ ~/.julia/packages/Enzyme/7ZLaZ/src/compiler.jl:6087 [inlined]
  [8] autodiff
    @ ~/.julia/packages/Enzyme/7ZLaZ/src/Enzyme.jl:417 [inlined]
  [9] autodiff
    @ ~/.julia/packages/Enzyme/7ZLaZ/src/Enzyme.jl:333 [inlined]
 [10] autodiff(mode::ForwardMode{FFIABI}, f::typeof(Main.MWE.f), args::Duplicated{Float64})
    @ Enzyme ~/.julia/packages/Enzyme/7ZLaZ/src/Enzyme.jl:318
 [11] top-level scope
    @ REPL[10]:28

コントリビューターガイド