No BLAS fallback for complex mat mul (e.g. zgemm) in reverse mode?
- Dominant language
- Julia
- Stars
- 586
- Forks
- 108
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 44
Description
MWE (julia 1.11.7, Enzyme 0.13.111):
```julia
using LinearAlgebra
import Enzyme
function f(u, c, tmp)
mul!(tmp, u, c)
abs2(tr(tmp))
end
function ∇f!(∂u, u, c, ∂tmps, tmps)
Enzyme.make_zero!(∂tmps)
Enzyme.make_zero!(∂u)
Enzyme.autodiff(Enzyme.Reverse,
Enzyme.Const(f),
Enzyme.Active,
Enzyme.Duplicated(u, ∂u),
Enzyme.Const(c),
Enzyme.Duplicated(tmps, ∂tmps))
nothing
end
begin
n = 4 # mul! doesn't call BLAS for 2x2 or 3x3 matrices
u = rand(ComplexF64, n, n)
c = rand(ComplexF64, n, n)
tmp = zeros(ComplexF64, n, n)
∂u = Enzyme.make_zero(u)
∂tmp = Enzyme.make_zero(tmp)
end;
∇f!(∂u, u, c, ∂tmp, tmp)
```
this yields:
> ┌ Warning: Using fallback BLAS replacements for (["zgemm_64_"]), performance may be degraded
> └ @ Enzyme.Compiler ~/.julia/packages/Enzyme/uGc5f/src/compiler.jl:5302
> ERROR: EnzymeNoDerivativeError: Current scope:
IR (click to see)
```llvm
; Function Attrs: mustprogress willreturn
define internal fastcc void @preprocess_julia_gemm__11259([2 x double] addrspace(11)* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) "enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double, [-1,8]:Float@double}" "enzymejl_parmtype"="126085921557568" "enzymejl_parmtype_ref"="1" "enzymejl_parmtype_str"="ComplexF64" %0, {} addrspace(10)* nocapture noundef nonnull readonly align 8 dereferenceable(32) "enzyme_type"="{[-1]:Pointer, [-1,0]:Pointer, [-1,0,-1]:Float@double, [-1,8]:Pointer, [-1,8,0]:Integer, [-1,8,1]:Integer, [-1,8,2]:Integer, [-1,8,3]:Integer, [-1,8,4]:Integer, [-1,8,5]:Integer, [-1,8,6]:Integer, [-1,8,7]:Integer, [-1,8,8]:Pointer, [-1,8,8,-1]:Float@double, [-1,16]:Integer, [-1,17]:Integer, [-1,18]:Integer, [-1,19]:Integer, [-1,20]:Integer, [-1,21]:Integer, [-1,22]:Integer, [-1,23]:Integer, [-1,24]:Integer, [-1,25]:Integer, [-1,26]:Integer, [-1,27]:Integer, [-1,28]:Integer, [-1,29]:Integer, [-1,30]:Integer, [-1,31]:Integer}" "enzymejl_parmtype"="126086057453904" "enzymejl_parmtype_ref"="2" "enzymejl_parmtype_str"="Matrix{ComplexF64}" %1, {} addrspace(10)* nocapture noundef nonnull readonly align 8 dereferenceable(32) "enzyme_type"="{[-1]:Pointer, [-1,0]:Pointer, [-1,0,-1]:Float@double, [-1,8]:Pointer, [-1,8,0]:Integer, [-1,8,1]:Integer, [-1,8,2]:Integer, [-1,8,3]:Integer, [-1,8,4]:Integer, [-1,8,5]:Integer, [-1,8,6]:Integer, [-1,8,7]:Integer, [-1,8,8]:Pointer, [-1,8,8,-1]:Float@double, [-1,16]:Integer, [-1,17]:Integer, [-1,18]:Integer, [-1,19]:Integer, [-1,20]:Integer, [-1,21]:Integer, [-1,22]:Integer, [-1,23]:Integer, [-1,24]:Integer, [-1,25]:Integer, [-1,26]:Integer, [-1,27]:Integer, [-1,28]:Integer, [-1,29]:Integer, [-1,30]:Integer, [-1,31]:Integer}" "enzymejl_parmtype"="126086057453904" "enzymejl_parmtype_ref"="2" "enzymejl_parmtype_str"="Matrix{ComplexF64}" %2, [2 x double] addrspace(11)* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) "enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double, [-1,8]:Float@double}" "enzymejl_parmtype"="126085921557568" "enzymejl_parmtype_ref"="1" "enzymejl_parmtype_str"="ComplexF64" %3, {} addrspace(10)* nocapture noundef nonnull readonly align 8 dereferenceable(32) "enzyme_type"="{[-1]:Pointer, [-1,0]:Pointer, [-1,0,-1]:Float@double, [-1,8]:Pointer, [-1,8,0]:Integer, [-1,8,1]:Integer, [-1,8,2]:Integer, [-1,8,3]:Integer, [-1,8,4]:Integer, [-1,8,5]:Integer, [-1,8,6]:Integer, [-1,8,7]:Integer, [-1,8,8]:Pointer, [-1,8,8,-1]:Float@double, [-1,16]:Integer, [-1,17]:Integer, [-1,18]:Integer, [-1,19]:Integer, [-1,20]:Integer, [-1,21]:Integer, [-1,22]:Integer, [-1,23]:Integer, [-1,24]:Integer, [-1,25]:Integer, [-1,26]:Integer, [-1,27]:Integer, [-1,28]:Integer, [-1,29]:Integer, [-1,30]:Integer, [-1,31]:Integer}" "enzymejl_parmtype"="126086057453904" "enzymejl_parmtype_ref"="2" "enzymejl_parmtype_str"="Matrix{ComplexF64}" %4) unnamed_addr #27 !dbg !1401 {
top:
%5 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%6 = bitcast i8* %5 to i64*, !enzyme_caststack !0
%7 = call noalias nonnull dereferenceable(16) dereferenceable_or_null(16) i8* @malloc(i64 16), !enzyme_fromstack !113
%8 = bitcast i8* %7 to [16 x i8]*, !enzyme_caststack !0
%9 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%10 = bitcast i8* %9 to i64*, !enzyme_caststack !0
%11 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%12 = bitcast i8* %11 to i64*, !enzyme_caststack !0
%13 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%14 = bitcast i8* %13 to i64*, !enzyme_caststack !0
%15 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%16 = bitcast i8* %15 to i64*, !enzyme_caststack !0
%17 = call noalias nonnull dereferenceable(1) dereferenceable_or_null(1) i8* @malloc(i64 1), !enzyme_fromstack !1402
%18 = call noalias nonnull dereferenceable(16) dereferenceable_or_null(16) i8* @malloc(i64 16), !enzyme_fromstack !113
%19 = bitcast i8* %18 to [16 x i8]*, !enzyme_caststack !0
%20 = call noalias nonnull dereferenceable(1) dereferenceable_or_null(1) i8* @malloc(i64 1), !enzyme_fromstack !1402
%21 = call noalias nonnull dereferenceable(8) dereferenceable_or_null(8) i8* @malloc(i64 8), !enzyme_fromstack !113
%22 = bitcast i8* %21 to i64*, !enzyme_caststack !0
%pgcstack = call {}*** @julia.get_pgcstack() #33
%ptls_field65 = getelementptr inbounds {}**, {}*** %pgcstack, i64 2
%23 = bitcast {}*** %ptls_field65 to i64***
%ptls_load6667 = load i64**, i64*** %23, align 8, !tbaa !29
%24 = getelementptr inbounds i64*, i64** %ptls_load6667, i64 2
%safepoint = load i64*, i64** %24, align 8, !tbaa !33
fence syncscope("singlethread") seq_cst
call void @julia.safepoint(i64* %safepoint) #34, !dbg !1403
fence syncscope("singlethread") seq_cst
%25 = bitcast {} addrspace(10)* %1 to i8 addrspace(10)*, !dbg !1404
%26 = getelementptr inbounds i8, i8 addrspace(10)* %25, i64 16, !dbg !1404
%27 = bitcast i8 addrspace(10)* %26 to i64 addrspace(10)*, !dbg !1404
%.sroa.06.0..sroa_cast = addrspacecast i64 addrspace(10)* %27 to i64 addrspace(11)*, !dbg !1404
%.sroa.06.0.copyload = load i64, i64 addrspace(11)* %.sroa.06.0..sroa_cast, align 8, !dbg !1404, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%.sroa.27.0..sroa_idx1 = getelementptr inbounds i8, i8 addrspace(10)* %25, i64 24, !dbg !1404
%28 = bitcast i8 addrspace(10)* %.sroa.27.0..sroa_idx1 to i64 addrspace(10)*, !dbg !1404
%.sroa.27.0..sroa_cast = addrspacecast i64 addrspace(10)* %28 to i64 addrspace(11)*, !dbg !1404
%.sroa.15.0.copyload = load i64, i64 addrspace(11)* %.sroa.27.0..sroa_cast, align 8, !dbg !1409, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%29 = bitcast {} addrspace(10)* %2 to i8 addrspace(10)*, !dbg !1411
%30 = getelementptr inbounds i8, i8 addrspace(10)* %29, i64 16, !dbg !1411
%31 = bitcast i8 addrspace(10)* %30 to i64 addrspace(10)*, !dbg !1411
%.sroa.03.0..sroa_cast = addrspacecast i64 addrspace(10)* %31 to i64 addrspace(11)*, !dbg !1411
%.sroa.03.0.copyload = load i64, i64 addrspace(11)* %.sroa.03.0..sroa_cast, align 8, !dbg !1411, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%.sroa.2.0..sroa_idx2 = getelementptr inbounds i8, i8 addrspace(10)* %29, i64 24, !dbg !1411
%32 = bitcast i8 addrspace(10)* %.sroa.2.0..sroa_idx2 to i64 addrspace(10)*, !dbg !1411
%.sroa.2.0..sroa_cast = addrspacecast i64 addrspace(10)* %32 to i64 addrspace(11)*, !dbg !1411
%.sroa.1.0.copyload2 = load i64, i64 addrspace(11)* %.sroa.2.0..sroa_cast, align 8, !dbg !1413, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%.not71 = icmp eq i64 %.sroa.15.0.copyload, %.sroa.03.0.copyload, !dbg !1415
br i1 %.not71, label %L77, label %top.L281_crit_edge, !dbg !1417
top.L281_crit_edge: ; preds = %top
%.phi.trans.insert = bitcast {} addrspace(10)* %4 to i8 addrspace(10)*
%.phi.trans.insert131 = getelementptr inbounds i8, i8 addrspace(10)* %.phi.trans.insert, i64 16
%33 = bitcast i8 addrspace(10)* %.phi.trans.insert131 to i64 addrspace(10)*
%.sroa.0118.0..sroa_cast.phi.trans.insert = addrspacecast i64 addrspace(10)* %33 to i64 addrspace(11)*
%.sroa.0118.0.copyload.pre = load i64, i64 addrspace(11)* %.sroa.0118.0..sroa_cast.phi.trans.insert, align 8, !dbg !1418, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
br label %L281, !dbg !1417
L77: ; preds = %top
%34 = bitcast {} addrspace(10)* %4 to i8 addrspace(10)*, !dbg !1420
%35 = getelementptr inbounds i8, i8 addrspace(10)* %34, i64 16, !dbg !1420
%36 = bitcast i8 addrspace(10)* %35 to i64 addrspace(10)*, !dbg !1420
%.sroa.0116.0..sroa_cast = addrspacecast i64 addrspace(10)* %36 to i64 addrspace(11)*, !dbg !1420
%.sroa.0116.0.copyload = load i64, i64 addrspace(11)* %.sroa.0116.0..sroa_cast, align 8, !dbg !1420, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%.not99 = icmp eq i64 %.sroa.06.0.copyload, %.sroa.0116.0.copyload, !dbg !1415
br i1 %.not99, label %L83, label %L281, !dbg !1417
L83: ; preds = %L77
%.sroa.2117.0..sroa_idx136 = getelementptr inbounds i8, i8 addrspace(10)* %34, i64 24, !dbg !1420
%37 = bitcast i8 addrspace(10)* %.sroa.2117.0..sroa_idx136 to i64 addrspace(10)*, !dbg !1420
%.sroa.2117.0..sroa_cast = addrspacecast i64 addrspace(10)* %37 to i64 addrspace(11)*, !dbg !1420
%.sroa.1.0.copyload = load i64, i64 addrspace(11)* %.sroa.2117.0..sroa_cast, align 8, !dbg !1420, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%.not100 = icmp eq i64 %.sroa.1.0.copyload2, %.sroa.1.0.copyload, !dbg !1415
br i1 %.not100, label %L109, label %L281, !dbg !1417
L109: ; preds = %L83
store i8 78, i8* %20, align 1, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
%38 = bitcast i64* %22 to i8*
%.sub135 = getelementptr inbounds [16 x i8], [16 x i8]* %19, i64 0, i64 0
%39 = bitcast i64* %16 to i8*
%40 = bitcast i64* %12 to i8*
%.sub = getelementptr inbounds [16 x i8], [16 x i8]* %8, i64 0, i64 0
%41 = bitcast i64* %6 to i8*
%42 = bitcast i64* %10 to i8*
%43 = bitcast i64* %14 to i8*
store i8 78, i8* %17, align 1, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
store i64 %.sroa.06.0.copyload, i64* %14, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
store i64 %.sroa.1.0.copyload2, i64* %10, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
store i64 %.sroa.15.0.copyload, i64* %6, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
call void @llvm.lifetime.start.p0i8(i64 noundef 16, i8* noundef nonnull align 16 dereferenceable(16) %.sub) #35
%44 = bitcast [2 x double] addrspace(11)* %0 to i8 addrspace(11)*, !dbg !1421
call void @llvm.memcpy.p0i8.p11i8.i64(i8* noundef nonnull align 16 dereferenceable(16) %.sub, i8 addrspace(11)* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) %44, i64 noundef 16, i1 noundef false) #35, !dbg !1421
%45 = bitcast {} addrspace(10)* %1 to { i8*, {} addrspace(10)* } addrspace(10)*, !dbg !1426
%46 = addrspacecast { i8*, {} addrspace(10)* } addrspace(10)* %45 to { i8*, {} addrspace(10)* } addrspace(11)*, !dbg !1426
%47 = bitcast {} addrspace(10)* %1 to i8* addrspace(10)*, !dbg !1426
%48 = addrspacecast i8* addrspace(10)* %47 to i8* addrspace(11)*, !dbg !1426
%49 = load i8*, i8* addrspace(11)* %48, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !enzyme_type !110, !enzymejl_byref_BITS_VALUE !0, !enzymejl_source_type_Ptr\7BComplexF64\7D !0
%50 = getelementptr inbounds { i8*, {} addrspace(10)* }, { i8*, {} addrspace(10)* } addrspace(11)* %46, i64 0, i32 1, !dbg !1426
%51 = load {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %50, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !dereferenceable_or_null !113, !align !114, !enzyme_type !115, !enzymejl_source_type_Memory\7BComplexF64\7D !0, !enzymejl_byref_MUT_REF !0
%.sroa.0113.0.copyload = load i64, i64 addrspace(11)* %.sroa.06.0..sroa_cast, align 8, !dbg !1427, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%52 = call i64 @llvm.smax.i64(i64 %.sroa.0113.0.copyload, i64 noundef 1) #33, !dbg !1430
store i64 %52, i64* %12, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
%53 = bitcast {} addrspace(10)* %2 to { i8*, {} addrspace(10)* } addrspace(10)*, !dbg !1426
%54 = addrspacecast { i8*, {} addrspace(10)* } addrspace(10)* %53 to { i8*, {} addrspace(10)* } addrspace(11)*, !dbg !1426
%55 = bitcast {} addrspace(10)* %2 to i8* addrspace(10)*, !dbg !1426
%56 = addrspacecast i8* addrspace(10)* %55 to i8* addrspace(11)*, !dbg !1426
%57 = load i8*, i8* addrspace(11)* %56, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !enzyme_type !110, !enzymejl_byref_BITS_VALUE !0, !enzymejl_source_type_Ptr\7BComplexF64\7D !0
%58 = getelementptr inbounds { i8*, {} addrspace(10)* }, { i8*, {} addrspace(10)* } addrspace(11)* %54, i64 0, i32 1, !dbg !1426
%59 = load {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %58, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !dereferenceable_or_null !113, !align !114, !enzyme_type !115, !enzymejl_source_type_Memory\7BComplexF64\7D !0, !enzymejl_byref_MUT_REF !0
%.sroa.0111.0.copyload = load i64, i64 addrspace(11)* %.sroa.03.0..sroa_cast, align 8, !dbg !1427, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%60 = call i64 @llvm.smax.i64(i64 %.sroa.0111.0.copyload, i64 noundef 1) #33, !dbg !1430
store i64 %60, i64* %16, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
call void @llvm.lifetime.start.p0i8(i64 noundef 16, i8* noundef nonnull align 16 dereferenceable(16) %.sub135) #35
%61 = bitcast [2 x double] addrspace(11)* %3 to i8 addrspace(11)*, !dbg !1421
call void @llvm.memcpy.p0i8.p11i8.i64(i8* noundef nonnull align 16 dereferenceable(16) %.sub135, i8 addrspace(11)* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) %61, i64 noundef 16, i1 noundef false) #35, !dbg !1421
%62 = bitcast {} addrspace(10)* %4 to { i8*, {} addrspace(10)* } addrspace(10)*, !dbg !1426
%63 = addrspacecast { i8*, {} addrspace(10)* } addrspace(10)* %62 to { i8*, {} addrspace(10)* } addrspace(11)*, !dbg !1426
%64 = bitcast {} addrspace(10)* %4 to i8* addrspace(10)*, !dbg !1426
%65 = addrspacecast i8* addrspace(10)* %64 to i8* addrspace(11)*, !dbg !1426
%66 = load i8*, i8* addrspace(11)* %65, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !enzyme_type !110, !enzymejl_byref_BITS_VALUE !0, !enzymejl_source_type_Ptr\7BComplexF64\7D !0
%67 = getelementptr inbounds { i8*, {} addrspace(10)* }, { i8*, {} addrspace(10)* } addrspace(11)* %63, i64 0, i32 1, !dbg !1426
%68 = load {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %67, align 8, !dbg !1426, !tbaa !105, !alias.scope !108, !noalias !109, !dereferenceable_or_null !113, !align !114, !enzyme_type !115, !enzymejl_source_type_Memory\7BComplexF64\7D !0, !enzymejl_byref_MUT_REF !0
%.sroa.0.0.copyload = load i64, i64 addrspace(11)* %.sroa.0116.0..sroa_cast, align 8, !dbg !1427, !tbaa !55, !alias.scope !56, !noalias !1406, !enzyme_inactive !0, !enzyme_type !66, !enzymejl_source_type_Int64 !0, !enzymejl_byref_BITS_VALUE !0
%69 = call i64 @llvm.smax.i64(i64 %.sroa.0.0.copyload, i64 noundef 1) #33, !dbg !1430
store i64 %69, i64* %22, align 16, !dbg !1421, !tbaa !75, !alias.scope !79, !noalias !1425
%70 = ptrtoint i8* %66 to i64, !dbg !1432
%71 = insertvalue { i8*, {} addrspace(10)* } zeroinitializer, i8* %66, 0, !dbg !1426
%72 = insertvalue { i8*, {} addrspace(10)* } %71, {} addrspace(10)* %68, 1, !dbg !1426
%73 = ptrtoint i8* %57 to i64, !dbg !1432
%74 = insertvalue { i8*, {} addrspace(10)* } zeroinitializer, i8* %57, 0, !dbg !1426
%75 = insertvalue { i8*, {} addrspace(10)* } %74, {} addrspace(10)* %59, 1, !dbg !1426
%76 = ptrtoint i8* %49 to i64, !dbg !1432
%77 = insertvalue { i8*, {} addrspace(10)* } zeroinitializer, i8* %49, 0, !dbg !1426
%78 = insertvalue { i8*, {} addrspace(10)* } %77, {} addrspace(10)* %51, 1, !dbg !1426
call void @"ejlstr$zgemm_64_$libblastrampoline.so.5"(i8* nofree noundef nonnull readonly dereferenceable(1) %20, i8* nofree noundef nonnull readonly dereferenceable(1) %17, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %43, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %42, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %41, i8* nofree noundef nonnull readonly align 16 dereferenceable(16) %.sub, i64 %76, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %40, i64 %73, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %39, i8* nofree noundef nonnull readonly align 16 dereferenceable(16) %.sub135, i64 %70, i8* nofree noundef nonnull readonly align 16 dereferenceable(8) %38, i64 noundef 1, i64 noundef 1) #33 [ "jl_roots"({} addrspace(10)* null, { i8*, {} addrspace(10)* } %72, {} addrspace(10)* null, {} addrspace(10)* null, { i8*, {} addrspace(10)* } %75, {} addrspace(10)* null, { i8*, {} addrspace(10)* } %78, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null, {} addrspace(10)* null) ], !dbg !1424
ret void, !dbg !1424
L281: ; preds = %L83, %L77, %top.L281_crit_edge
%.pre-phi134.in = phi i8 addrspace(10)* [ %.phi.trans.insert131, %top.L281_crit_edge ], [ %35, %L83 ], [ %35, %L77 ]
%.sroa.0118.0.copyload = phi i64 [ %.sroa.0118.0.copyload.pre, %top.L281_crit_edge ], [ %.sroa.06.0.copyload, %L83 ], [ %.sroa.0116.0.copyload, %L77 ], !dbg !1418, !enzyme_inactive !0
%.sroa.2119.0..sroa_idx137 = getelementptr inbounds i8, i8 addrspace(10)* %.pre-phi134.in, i64 8, !dbg !1418
%79 = bitcast i8 addrspace(10)* %.sroa.2119.0..sroa_idx137 to i64 addrspace(10)*, !dbg !1418
%.sroa.2119.0..sroa_cast = addrspacecast i64 addrspace(10)* %79 to i64 addrspace(11)*, !dbg !1418
%.sroa.2119.0.copyload = load i64, i64 addrspace(11)* %.sroa.2119.0..sroa_cast, align 8, !dbg !1418, !tbaa !55, !alias.scope !56, !noalias !1406
%current_task1274 = getelementptr inbounds {}**, {}*** %pgcstack, i64 -14, !dbg !1434
%80 = bitcast {}*** %current_task1274 to {}*, !dbg !1434
%81 = call noalias nonnull align 8 dereferenceable(16) "enzyme_ReadOnlyOrThrow" "enzyme_inactive" "enzyme_type"="{[-1]:Pointer}" {} addrspace(10)* @julia.gc_alloc_obj({}* nonnull %80, i64 noundef 16, {} addrspace(10)* noundef @"ejl_inserted$_Main_Base_LazyString_11138$false$126085917780544") #36, !dbg !1434
%82 = bitcast {} addrspace(10)* %81 to {} addrspace(10)* addrspace(10)*, !dbg !1434, !enzyme_inactive !0
%83 = addrspacecast {} addrspace(10)* addrspace(10)* %82 to {} addrspace(10)* addrspace(11)*, !dbg !1434, !enzyme_inactive !0
store {} addrspace(10)* null, {} addrspace(10)* addrspace(11)* %83, align 8, !dbg !1434, !tbaa !75, !alias.scope !79, !noalias !1425
%84 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(11)* %83, i64 1, !dbg !1434 store {} addrspace(10)* null, {} addrspace(10)* addrspace(11)* %84, align 8, !dbg !1434, !tbaa !75, !alias.scope !79, !noalias !1425
%85 = call noalias nonnull align 8 dereferenceable(88) "enzyme_ReadOnlyOrThrow" "enzyme_inactive" "enzyme_type"="{[-1]:Pointer, [-1,0]:Pointer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer, [-1,16]:Pointer, [-1,24]:Integer, [-1,25]:Integer, [-1,26]:Integer, [-1,27]:Integer, [-1,28]:Integer, [-1,29]:Integer, [-1,30]:Integer, [-1,31]:Integer, [-1,32]:Pointer, [-1,40]:Integer, [-1,41]:Integer, [-1,42]:Integer, [-1,43]:Integer, [-1,44]:Integer, [-1,45]:Integer, [-1,46]:Integer, [-1,47]:Integer, [-1,48]:Pointer, [-1,56]:Integer, [-1,57]:Integer, [-1,58]:Integer, [-1,59]:Integer, [-1,60]:Integer, [-1,61]:Integer, [-1,62]:Integer, [-1,63]:Integer, [-1,64]:Pointer, [-1,72]:Integer, [-1,73]:Integer, [-1,74]:Integer, [-1,75]:Integer, [-1,76]:Integer, [-1,77]:Integer, [-1,78]:Integer, [-1,79]:Integer, [-1,80]:Integer, [-1,81]:Integer, [-1,82]:Integer, [-1,83]:Integer, [-1,84]:Integer, [-1,85]:Integer, [-1,86]:Integer, [-1,87]:Integer}" {} addrspace(10)* @julia.gc_alloc_obj({}* nonnull %80, i64 noundef 88, {} addrspace(10)* noundef @"ejl_inserted$_Core_Tuple_11265$false$126086070747472") #36, !dbg !1434
%86 = bitcast {} addrspace(10)* %85 to { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)*, !dbg !1434, !enzyme_inactive !0
%.repack = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 0, !dbg !1434
store {} addrspace(10)* @"ejl_inserted$jl_global_11262$false$126086014736512", {} addrspace(10)* addrspace(10)* %.repack, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack77 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 1, !dbg !1434
store i64 %.sroa.06.0.copyload, i64 addrspace(10)* %.repack77, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack79 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 2, !dbg !1434
store {} addrspace(10)* @"ejl_inserted$jl_global_11165$false$126085985248912", {} addrspace(10)* addrspace(10)* %.repack79, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack81 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 3, !dbg !1434
store i64 %.sroa.15.0.copyload, i64 addrspace(10)* %.repack81, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack83 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 4, !dbg !1434
store {} addrspace(10)* @"ejl_inserted$jl_global_11263$false$126086014736480", {} addrspace(10)* addrspace(10)* %.repack83, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack85 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 5, !dbg !1434
store i64 %.sroa.03.0.copyload, i64 addrspace(10)* %.repack85, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack87 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 6, !dbg !1434
store {} addrspace(10)* @"ejl_inserted$jl_global_11165$false$126085985248912", {} addrspace(10)* addrspace(10)* %.repack87, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack89 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 7, !dbg !1434
store i64 %.sroa.1.0.copyload2, i64 addrspace(10)* %.repack89, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack91 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 8, !dbg !1434
store {} addrspace(10)* @"ejl_inserted$jl_global_11264$false$126086014736448", {} addrspace(10)* addrspace(10)* %.repack91, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack93.repack = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 9, i64 0, !dbg !1434
store i64 %.sroa.0118.0.copyload, i64 addrspace(10)* %.repack93.repack, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
%.repack93.repack96 = getelementptr inbounds { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] }, { {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, i64, {} addrspace(10)*, [2 x i64] } addrspace(10)* %86, i64 0, i32 9, i64 1, !dbg !1434
store i64 %.sroa.2119.0.copyload, i64 addrspace(10)* %.repack93.repack96, align 8, !dbg !1434, !tbaa !81, !alias.scope !79, !noalias !1425
store atomic {} addrspace(10)* %85, {} addrspace(10)* addrspace(11)* %83 release, align 8, !dbg !1434, !tbaa !75, !alias.scope !79, !noalias !1425
call void ({} addrspace(10)*, ...) @julia.write_barrier({} addrspace(10)* nofree noundef nonnull %81, {} addrspace(10)* nofree nonnull %85) #37, !dbg !1434
%87 = bitcast {} addrspace(10)* %81 to i8 addrspace(10)*, !dbg !1434, !enzyme_inactive !0
%88 = addrspacecast i8 addrspace(10)* %87 to i8 addrspace(11)*, !dbg !1434, !enzyme_inactive !0
%89 = getelementptr inbounds i8, i8 addrspace(11)* %88, i64 8, !dbg !1434
%90 = load {}*, {}** @jl_nothing, align 8, !dbg !1434, !tbaa !33, !alias.scope !83, !noalias !84, !nonnull !0, !enzyme_inactive !0, !enzyme_type !85, !enzymejl_source_type_Nothing !0, !enzymejl_byref_BITS_REF !0
%91 = addrspacecast {}* %90 to {} addrspace(10)*, !dbg !1434, !enzyme_inactive !0
%92 = bitcast i8 addrspace(11)* %89 to {} addrspace(10)* addrspace(11)*, !dbg !1434
store atomic {} addrspace(10)* %91, {} addrspace(10)* addrspace(11)* %92 release, align 8, !dbg !1434, !tbaa !75, !alias.scope !79, !noalias !1425
%93 = call noalias nonnull align 8 dereferenceable(8) "enzyme_ReadOnlyOrThrow" "enzyme_inactive" "enzyme_type"="{[-1]:Pointer, [-1,-1]:Pointer}" {} addrspace(10)* @julia.gc_alloc_obj({}* nonnull %80, i64 noundef 8, {} addrspace(10)* noundef @"ejl_inserted$_Main_Base_DimensionMismatch_11142$false$126085916838944") #36, !dbg !1419
%94 = bitcast {} addrspace(10)* %93 to [1 x {} addrspace(10)*] addrspace(10)*, !dbg !1419, !enzyme_inactive !0
%95 = getelementptr [1 x {} addrspace(10)*], [1 x {} addrspace(10)*] addrspace(10)* %94, i64 0, i64 0, !dbg !1419
store {} addrspace(10)* %81, {} addrspace(10)* addrspace(10)* %95, align 8, !dbg !1419, !tbaa !81, !alias.scope !79, !noalias !1425
%96 = addrspacecast {} addrspace(10)* %93 to {} addrspace(12)*, !dbg !1419, !enzyme_inactive !0
call void @ijl_throw({} addrspace(12)* %96) #38, !dbg !1419
unreachable, !dbg !1419
}
```
> gemm
> Complex inputs not yet supported in reverse mode for BLAS calls
rest of stacktrace (click to see)
>
>
> Stacktrace:
> [1] gemm!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/blas.jl:1644
>
> Failure within method:
>
> gemm!(::Char, ::Char, ::ComplexF64, ::Matrix{ComplexF64}, ::Matrix{ComplexF64}, ::ComplexF64, ::Matrix{ComplexF64})
> @ LinearAlgebra.BLAS /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/blas.jl:1625
>
> Hint: catch this exception as `err` and call `code_typed(err)` to inspect the surrounding code.
>
> Stacktrace:
> [1] gemm_wrapper!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/matmul.jl:657
> [2] generic_matmatmul!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/matmul.jl:381 [inlined]
> [3] _mul!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/matmul.jl:287 [inlined]
> [4] mul!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/matmul.jl:285 [inlined]
> [5] mul!
> @ /nix/store/7qbi1j34nn511d4qcxaiq6gxj5a6b3cz-julia-bin-1.11.7/share/julia/stdlib/v1.11/LinearAlgebra/src/matmul.jl:253 [inlined]
> [6] f
> @ ./REPL[5]:2 [inlined]
> [7] diffejulia_f_11110wrap
> @ ./REPL[5]:0
> [8] macro expansion
> @ ~/.julia/packages/Enzyme/uGc5f/src/compiler.jl:6652 [inlined]
> [9] enzyme_call
> @ ~/.julia/packages/Enzyme/uGc5f/src/compiler.jl:6131 [inlined]
> [10] CombinedAdjointThunk
> @ ~/.julia/packages/Enzyme/uGc5f/src/compiler.jl:6015 [inlined]
> [11] autodiff
> @ ~/.julia/packages/Enzyme/uGc5f/src/Enzyme.jl:521 [inlined]
> [12] ∇f!(∂u::Matrix{…}, u::Matrix{…}, c::Matrix{…}, ∂tmps::Matrix{…}, tmps::Matrix{…})
> @ Main ./REPL[6]:4
> [13] top-level scope
> @ REPL[8]:1
> [14] top-level scope
> @ none:1
> Some type information was truncated. Use `show(err)` to see complete types.
Is this the expected behavior?
The initial warning indicates a fallback will be used, and [the documentation](https://enzyme.mit.edu/julia/stable/faq/#Linear-Algebra) suggests gemm should work.
My understanding is that the tablegen BLAS implementation doesn't currently handle complex inputs in reverse mode. Should the julia side be using a fallback here?
Contributor guide
Assessment
This issue has not been assessed yet.