Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Differentiating cholesky(::Symmetric) throws an error #1272

Closed
devmotion opened this issue Feb 7, 2024 · 0 comments · Fixed by #1273
Closed

Differentiating cholesky(::Symmetric) throws an error #1272

devmotion opened this issue Feb 7, 2024 · 0 comments · Fixed by #1273

Comments

@devmotion
Copy link
Contributor

devmotion commented Feb 7, 2024

An example (based on #1250) that illustrates the problem:

julia> using Enzyme, LinearAlgebra

julia> g(C, X) = sum(C \ X)
g (generic function with 1 method)

julia> g2(A, X) = g(cholesky(A * A' + I), X)
g2 (generic function with 1 method)

julia> A = rand(2, 2);

julia> X = rand(2, 2);

julia> ∂g2_∂A = zero(A);

julia> ∂g2_∂X = zero(X);

julia> autodiff(Reverse, g2, Active, Duplicated(A, ∂g2_∂A), Duplicated(X, ∂g2_∂X))
┌ Warning: Using fallback BLAS replacements, performance may be degraded
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/U36Ed/src/utils.jl:59
warning: didn't implement memmove, using memcpy as fallback which can result in errors
((nothing, nothing),)

but

julia> g3(A, X) = g(cholesky(Symmetric(A * A' + I)), X)
g3 (generic function with 1 method)

julia> ∂g3_∂A = zero(A);

julia> ∂g3_∂X = zero(X);

julia> autodiff(Reverse, g3, Active, Duplicated(A, ∂g3_∂A), Duplicated(X, ∂g3_∂X))
┌ Warning: Using fallback BLAS replacements, performance may be degraded
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/U36Ed/src/utils.jl:59
warning: didn't implement memmove, using memcpy as fallback which can result in errors
ERROR: Enzyme execution failed.
Enzyme compilation failed.
Current scope: 
; Function Attrs: mustprogress willreturn
define internal fastcc void @preprocess_julia_potrf__7290({ {} addrspace(10)*, i64 }* noalias nocapture noundef nonnull writeonly sret({ {} addrspace(10)*, i64 }) align 8 dereferenceable(16) %0, [1 x {} addrspace(10)*]* noalias nocapture noundef nonnull writeonly align 8 dereferenceable(8) "enzyme_inactive" "enzymejl_returnRoots" %1, i32 noundef zeroext "enzyme_inactive" %2, {} addrspace(10)* noundef nonnull align 16 dereferenceable(40) %3) unnamed_addr #87 !dbg !5906 {
top:
  %4 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !104
  %5 = bitcast i8* %4 to i64*, !enzyme_caststack !85
  %6 = bitcast i64* %5 to i8*
  %7 = call noalias nonnull dereferenceable(1) dereferenceable_or_null(1) i8* @malloc(i64 1), !enzyme_fromstack !5298
  %8 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !104
  %9 = bitcast i8* %8 to i64*, !enzyme_caststack !85
  %10 = bitcast i64* %9 to i8*
  %11 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !104
  %12 = bitcast i8* %11 to i64*, !enzyme_caststack !85
  %13 = bitcast i64* %12 to i8*
  %14 = call noalias nonnull dereferenceable(16) dereferenceable_or_null(16) i8* @malloc(i64 16), !enzyme_fromstack !1958
  %newstruct47 = bitcast i8* %14 to [2 x i64]*, !enzyme_caststack !85
  %15 = call {}*** @julia.get_pgcstack() #88
  %ptls_field53 = getelementptr inbounds {}**, {}*** %15, i64 2
  %16 = bitcast {}*** %ptls_field53 to i64***
  %ptls_load5455 = load i64**, i64*** %16, align 8, !tbaa !86
  %17 = getelementptr inbounds i64*, i64** %ptls_load5455, i64 2
  %safepoint = load i64*, i64** %17, align 8, !tbaa !90, !invariant.load !85
  fence syncscope("singlethread") seq_cst
  call void @julia.safepoint(i64* %safepoint) #88, !dbg !5907
  fence syncscope("singlethread") seq_cst
  %18 = addrspacecast {} addrspace(10)* %3 to {} addrspace(10)* addrspace(11)*, !dbg !5908
  %arraysize_ptr = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %18, i64 3, !dbg !5908
  %19 = bitcast {} addrspace(10)* addrspace(11)* %arraysize_ptr to i64 addrspace(11)*, !dbg !5908
  %arraysize = load i64, i64 addrspace(11)* %19, align 8, !dbg !5908, !tbaa !90, !range !111, !invariant.load !85, !alias.scope !95, !noalias !98
  %arraysize_ptr2 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %18, i64 4, !dbg !5908
  %20 = bitcast {} addrspace(10)* addrspace(11)* %arraysize_ptr2 to i64 addrspace(11)*, !dbg !5908
  %arraysize3 = load i64, i64 addrspace(11)* %20, align 8, !dbg !5908, !tbaa !90, !range !111, !invariant.load !85, !alias.scope !95, !noalias !98
  %.not = icmp eq i64 %arraysize, %arraysize3, !dbg !5911
  br i1 %.not, label %L13, label %L6, !dbg !5912

L6:                                               ; preds = %top
  %21 = getelementptr inbounds [2 x i64], [2 x i64]* %newstruct47, i64 0, i64 0, !dbg !5913
  store i64 %arraysize, i64* %21, align 8, !dbg !5913, !tbaa !143, !alias.scope !145, !noalias !5914
  %22 = getelementptr inbounds [2 x i64], [2 x i64]* %newstruct47, i64 0, i64 1, !dbg !5913
  store i64 %arraysize3, i64* %22, align 8, !dbg !5913, !tbaa !143, !alias.scope !145, !noalias !5914
  %23 = addrspacecast [2 x i64]* %newstruct47 to [2 x i64] addrspace(11)*, !dbg !5912
  %24 = call fastcc nonnull {} addrspace(10)* @julia_string_7210({} addrspace(10)* nofree noundef nonnull align 32 addrspacecast ({}* inttoptr (i64 4848269664 to {}*) to {} addrspace(10)*), [2 x i64] addrspace(11)* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) %23) #88, !dbg !5912
  %current_task4870 = getelementptr inbounds {}**, {}*** %15, i64 -14, !dbg !5912
  %current_task48 = bitcast {}*** %current_task4870 to {}**, !dbg !5912
  %box49 = call noalias nonnull dereferenceable(8) "enzyme_inactive" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task48, i64 8, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4795576160 to {}*) to {} addrspace(10)*)) #89, !dbg !5912
  %25 = bitcast {} addrspace(10)* %box49 to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !5912
  %26 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %25, i64 0, i64 0, !dbg !5912
  store {} addrspace(10)* %24, {} addrspace(10)* addrspace(10)* %26, align 8, !dbg !5912, !tbaa !119, !alias.scope !123, !noalias !5917
  %27 = addrspacecast {} addrspace(10)* %box49 to {} addrspace(12)*, !dbg !5912
  call void @ijl_throw({} addrspace(12)* %27) #88, !dbg !5912
  unreachable, !dbg !5912

L13:                                              ; preds = %top
  switch i32 %2, label %L24 [
    i32 1426063360, label %L61
    i32 1275068416, label %L61
  ], !dbg !5918

L24:                                              ; preds = %L13
  %28 = insertvalue { {} addrspace(10)*, i32 } { {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4848270240 to {}*) to {} addrspace(10)*), i32 0 }, i32 %2, 1, !dbg !5920
  %current_task456 = getelementptr inbounds {}**, {}*** %15, i64 -14, !dbg !5920
  %current_task4 = bitcast {}*** %current_task456 to {}**, !dbg !5920
  %newstruct = call noalias nonnull dereferenceable(16) "enzyme_inactive" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task4, i64 16, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4744073456 to {}*) to {} addrspace(10)*)) #89, !dbg !5920
  %29 = addrspacecast {} addrspace(10)* %newstruct to {} addrspace(10)* addrspace(11)*, !dbg !5920
  store {} addrspace(10)* null, {} addrspace(10)* addrspace(11)* %29, align 8, !dbg !5920, !tbaa !497, !alias.scope !123, !noalias !5917
  %30 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %29, i64 1, !dbg !5920
  store {} addrspace(10)* null, {} addrspace(10)* addrspace(11)* %30, align 8, !dbg !5920, !tbaa !497, !alias.scope !123, !noalias !5917
  %box = call noalias nonnull dereferenceable(16) "enzyme_inactive" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task4, i64 16, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4771417440 to {}*) to {} addrspace(10)*)) #89, !dbg !5920
  %31 = bitcast {} addrspace(10)* %box to { {} addrspace(10)*, i32 } addrspace(10)*, !dbg !5920
  store { {} addrspace(10)*, i32 } %28, { {} addrspace(10)*, i32 } addrspace(10)* %31, align 8, !dbg !5920, !tbaa !119, !alias.scope !123, !noalias !5917
  store atomic {} addrspace(10)* %box, {} addrspace(10)* addrspace(11)* %29 release, align 8, !dbg !5920, !tbaa !497, !alias.scope !123, !noalias !5917
  call void ({} addrspace(10)*, ...) @julia.write_barrier({} addrspace(10)* nonnull %newstruct, {} addrspace(10)* nonnull %box) #90, !dbg !5920
  %32 = addrspacecast {} addrspace(10)* %newstruct to i8 addrspace(11)*, !dbg !5920
  %33 = getelementptr inbounds i8, i8 addrspace(11)* %32, i64 8, !dbg !5920
  %34 = bitcast i8 addrspace(11)* %33 to {} addrspace(10)* addrspace(11)*, !dbg !5920
  store atomic {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4330127368 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspace(11)* %34 release, align 8, !dbg !5920, !tbaa !497, !alias.scope !123, !noalias !5917
  %box7 = call noalias nonnull dereferenceable(8) "enzyme_inactive" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task4, i64 8, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4814724592 to {}*) to {} addrspace(10)*)) #89, !dbg !5921
  %35 = bitcast {} addrspace(10)* %box7 to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !5921
  %36 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %35, i64 0, i64 0, !dbg !5921
  store {} addrspace(10)* %newstruct, {} addrspace(10)* addrspace(10)* %36, align 8, !dbg !5921, !tbaa !119, !alias.scope !123, !noalias !5917
  %37 = addrspacecast {} addrspace(10)* %box7 to {} addrspace(12)*, !dbg !5921
  call void @ijl_throw({} addrspace(12)* %37) #88, !dbg !5921
  unreachable, !dbg !5921

L61:                                              ; preds = %L13, %L13
  %.not59 = icmp eq i64 %arraysize, 0, !dbg !5922
  %38 = select i1 %.not59, i64 1, i64 %arraysize, !dbg !5925
  %39 = lshr i32 %2, 24, !dbg !5926
  %value_phi12 = trunc i32 %39 to i8, !dbg !5934
  call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %7) #88
  store i8 %value_phi12, i8* %7, align 1, !dbg !5930, !tbaa !497, !alias.scope !123, !noalias !5917
  store i64 %arraysize, i64* %9, align 16, !dbg !5930, !tbaa !497, !alias.scope !123, !noalias !5917
  store i64 %38, i64* %12, align 16, !dbg !5930, !tbaa !497, !alias.scope !123, !noalias !5917
  %40 = addrspacecast {} addrspace(10)* %3 to {} addrspace(11)*, !dbg !5935
  %41 = call nonnull {}* @julia.pointer_from_objref({} addrspace(11)* %40) #91, !dbg !5935
  %42 = bitcast {}* %41 to i8**, !dbg !5935
  %arrayptr = load i8*, i8** %42, align 8, !dbg !5935, !tbaa !90, !invariant.load !85, !alias.scope !95, !noalias !98, !nonnull !85
  %43 = ptrtoint i8* %arrayptr to i64, !dbg !5935
  %bitcast_coercion35 = ptrtoint i64* %5 to i64, !dbg !5936
  call void @dpotrf_64_(i8* nonnull %7, i8* nonnull %10, i64 %43, i8* nonnull %13, i64 %bitcast_coercion35, i64 1) #88 [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* %3, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !5933
  %44 = load i64, i64* %5, align 16, !dbg !5938, !tbaa !497, !alias.scope !123, !noalias !325
  %45 = icmp sgt i64 %44, -1, !dbg !5941
  br i1 %45, label %L122, label %L116, !dbg !5942

L116:                                             ; preds = %L61
  %current_task1062 = getelementptr inbounds {}**, {}*** %15, i64 -14, !dbg !5943
  %current_task10 = bitcast {}*** %current_task1062 to {}**, !dbg !5943
  %46 = sub i64 0, %44, !dbg !5946
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %6) #88
  call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %7) #88
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %10) #88
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %13) #88
  %47 = call noalias nonnull {} addrspace(10)* @ijl_box_int64(i64 signext %46) #92, !dbg !5947
  %48 = call nonnull {} addrspace(10)* ({} addrspace(10)* ({} addrspace(10)*, {} addrspace(10)**, i32, {} addrspace(10)*)*, {} addrspace(10)*, {} addrspace(10)*, ...) @julia.call2({} addrspace(10)* ({} addrspace(10)*, {} addrspace(10)**, i32, {} addrspace(10)*)* nonnull @ijl_invoke, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4765594848 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4744436512 to {}*) to {} addrspace(10)*), {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4848233936 to {}*) to {} addrspace(10)*), {} addrspace(10)* nonnull %47, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4848233904 to {}*) to {} addrspace(10)*)) #93, !dbg !5947
  %box39 = call noalias nonnull dereferenceable(8) "enzyme_inactive" {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task10, i64 8, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 4814724592 to {}*) to {} addrspace(10)*)) #89, !dbg !5947
  %49 = bitcast {} addrspace(10)* %box39 to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !5947
  %50 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %49, i64 0, i64 0, !dbg !5947
  store {} addrspace(10)* %48, {} addrspace(10)* addrspace(10)* %50, align 8, !dbg !5947, !tbaa !119, !alias.scope !123, !noalias !5917
  %51 = addrspacecast {} addrspace(10)* %box39 to {} addrspace(12)*, !dbg !5947
  call void @ijl_throw({} addrspace(12)* %51) #88, !dbg !5947
  unreachable, !dbg !5947

L122:                                             ; preds = %L61
  %52 = getelementptr inbounds [1 x {} addrspace(10)*], [1 x {} addrspace(10)*]* %1, i64 0, i64 0, !dbg !5948
  store {} addrspace(10)* %3, {} addrspace(10)** %52, align 8, !dbg !5948, !noalias !5949
  %.repack67 = getelementptr inbounds { {} addrspace(10)*, i64 }, { {} addrspace(10)*, i64 }* %0, i64 0, i32 0, !dbg !5948
  store {} addrspace(10)* %3, {} addrspace(10)** %.repack67, align 8, !dbg !5948, !noalias !5949
  %.repack68 = getelementptr inbounds { {} addrspace(10)*, i64 }, { {} addrspace(10)*, i64 }* %0, i64 0, i32 1, !dbg !5948
  store i64 %44, i64* %.repack68, align 8, !dbg !5948, !noalias !5949
  ret void, !dbg !5948
}

No augmented forward pass found for dpotrf_64_
 at context:   call void @dpotrf_64_(i8* nonnull %7, i8* nonnull %10, i64 %43, i8* nonnull %13, i64 %bitcast_coercion35, i64 1) #88 [ "jl_roots"({} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* %3, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !164

Stacktrace:
 [1] potrf!
   @ ~/.asdf/installs/julia/1.10.0/share/julia/stdlib/v1.10/LinearAlgebra/src/lapack.jl:3226


Stacktrace:
  [1] throwerr(cstr::Cstring)
    @ Enzyme.Compiler ~/.julia/dev/Enzyme/src/compiler.jl:1319
  [2] potrf!
    @ ~/.asdf/installs/julia/1.10.0/share/julia/stdlib/v1.10/LinearAlgebra/src/lapack.jl:3216
  [3] cholesky! (repeats 2 times)
    @ ~/.asdf/installs/julia/1.10.0/share/julia/stdlib/v1.10/LinearAlgebra/src/cholesky.jl:267 [inlined]
  [4] cholesky (repeats 2 times)
    @ ~/.asdf/installs/julia/1.10.0/share/julia/stdlib/v1.10/LinearAlgebra/src/cholesky.jl:401 [inlined]
  [5] g3
    @ ./REPL[18]:1 [inlined]
  [6] diffejulia_g3_7201wrap
    @ ./REPL[18]:0
  [7] macro expansion
    @ Enzyme.Compiler ~/.julia/dev/Enzyme/src/compiler.jl:5306 [inlined]
  [8] enzyme_call(::Val{…}, ::Ptr{…}, ::Type{…}, ::Type{…}, ::Val{…}, ::Type{…}, ::Type{…}, ::Const{…}, ::Type{…}, ::Duplicated{…}, ::Duplicated{…}, ::Float64)
    @ Enzyme.Compiler ~/.julia/dev/Enzyme/src/compiler.jl:4984
  [9] (::Enzyme.Compiler.CombinedAdjointThunk{…})(::Const{…}, ::Duplicated{…}, ::Vararg{…})
    @ Enzyme.Compiler ~/.julia/dev/Enzyme/src/compiler.jl:4926
 [10] autodiff(::ReverseMode{…}, ::Const{…}, ::Type{…}, ::Duplicated{…}, ::Vararg{…})
    @ Enzyme ~/.julia/dev/Enzyme/src/Enzyme.jl:0
 [11] autodiff(::ReverseMode{false, FFIABI}, ::typeof(g3), ::Type, ::Duplicated{Matrix{…}}, ::Vararg{Duplicated{…}})
    @ Enzyme ~/.julia/dev/Enzyme/src/Enzyme.jl:224
 [12] top-level scope
    @ REPL[21]:1
Some type information was truncated. Use `show(err)` to see complete types.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant