Open anhi opened 1 week ago
So it looks liek the issue here is that staticarrays is actually type unstable in this case.
julia> tup = (Active(@SVector([0.0, 0.0, 0.0])), Active(@SMatrix([1.0])))
(Active{SVector{3, Float64}}([0.0, 0.0, 0.0]), Active{SMatrix{1, 1, Float64, 1}}([1.0;;]))
julia> @code_typed tup[1].val / tup[2].val
CodeInfo(
1 ── nothing::Nothing
│ %2 = StaticArrays.getfield(B, :data)::Tuple{Float64}
│ %3 = Base.getfield(%2, 1, true)::Float64
│ %4 = StaticArrays.tuple(%3)::Tuple{Float64}
│ %5 = %new(SMatrix{1, 1, Float64, 1}, %4)::SMatrix{1, 1, Float64, 1}
│ %6 = %new(LinearAlgebra.Adjoint{Float64, SVector{3, Float64}}, A)::LinearAlgebra.Adjoint{Float64, SVector{3, Float64}}
│ %7 = invoke LinearAlgebra.:\(%5::SMatrix{1, 1, Float64, 1}, %6::LinearAlgebra.Adjoint{Float64, SVector{3, Float64}})::Union{LinearAlgebra.Adjoint{Float64, MVector{3, Float64}}, SMatrix{1, 3, Float64, 3}, MMatrix{1, 3, Float64, 3}}
│ %8 = (isa)(%7, SMatrix{1, 3, Float64, 3})::Bool
└─── goto #3 if not %8
2 ── %10 = π (%7, SMatrix{1, 3, Float64, 3})
│ %11 = StaticArrays.getfield(%10, :data)::Tuple{Float64, Float64, Float64}
│ %12 = Base.getfield(%11, 1, true)::Float64
│ %13 = StaticArrays.getfield(%10, :data)::Tuple{Float64, Float64, Float64}
│ %14 = Base.getfield(%13, 2, true)::Float64
│ %15 = StaticArrays.getfield(%10, :data)::Tuple{Float64, Float64, Float64}
│ %16 = Base.getfield(%15, 3, true)::Float64
│ %17 = StaticArrays.tuple(%12, %14, %16)::Tuple{Float64, Float64, Float64}
└─── goto #28
3 ── %19 = (isa)(%7, LinearAlgebra.Adjoint{Float64, MVector{3, Float64}})::Bool
└─── goto #5 if not %19
4 ── %21 = π (%7, LinearAlgebra.Adjoint{Float64, MVector{3, Float64}})
│ %22 = Base.getfield(%21, :parent)::MVector{3, Float64}
└─── goto #28
5 ── %24 = (isa)(%7, MMatrix{1, 3, Float64, 3})::Bool
└─── goto #27 if not %24
6 ── %26 = π (%7, MMatrix{1, 3, Float64, 3})
└─── goto #11 if not true
7 ── %28 = Core.tuple(1)::Tuple{Int64}
│ %29 = Base.sle_int(1, 1)::Bool
│ %30 = Base.sle_int(1, 3)::Bool
│ %31 = Base.and_int(%29, %30)::Bool
└─── goto #9 if not %31
8 ── goto #10
9 ── invoke Base.throw_boundserror(%26::MMatrix{1, 3, Float64, 3}, %28::Tuple{Int64})::Union{}
└─── unreachable
10 ─ nothing::Nothing
11 ┄ %37 = $(Expr(:gc_preserve_begin, :(%26)))
│ %38 = $(Expr(:foreigncall, :(:jl_value_ptr), Ptr{Nothing}, svec(Any), 0, :(:ccall), :(%26)))::Ptr{Nothing}
│ %39 = Base.bitcast(Ptr{Float64}, %38)::Ptr{Float64}
│ %40 = Base.pointerref(%39, 1, 1)::Float64
│ $(Expr(:gc_preserve_end, :(%37)))
└─── goto #12
12 ─ goto #17 if not true
13 ─ %44 = Core.tuple(2)::Tuple{Int64}
│ %45 = Base.sle_int(1, 2)::Bool
│ %46 = Base.sle_int(2, 3)::Bool
│ %47 = Base.and_int(%45, %46)::Bool
└─── goto #15 if not %47
14 ─ goto #16
15 ─ invoke Base.throw_boundserror(%26::MMatrix{1, 3, Float64, 3}, %44::Tuple{Int64})::Union{}
└─── unreachable
16 ─ nothing::Nothing
17 ┄ %53 = $(Expr(:gc_preserve_begin, :(%26)))
│ %54 = $(Expr(:foreigncall, :(:jl_value_ptr), Ptr{Nothing}, svec(Any), 0, :(:ccall), :(%26)))::Ptr{Nothing}
│ %55 = Base.bitcast(Ptr{Float64}, %54)::Ptr{Float64}
│ %56 = Base.pointerref(%55, 2, 1)::Float64
│ $(Expr(:gc_preserve_end, :(%53)))
└─── goto #18
18 ─ goto #23 if not true
19 ─ %60 = Core.tuple(3)::Tuple{Int64}
│ %61 = Base.sle_int(1, 3)::Bool
│ %62 = Base.sle_int(3, 3)::Bool
│ %63 = Base.and_int(%61, %62)::Bool
└─── goto #21 if not %63
20 ─ goto #22
21 ─ invoke Base.throw_boundserror(%26::MMatrix{1, 3, Float64, 3}, %60::Tuple{Int64})::Union{}
└─── unreachable
22 ─ nothing::Nothing
23 ┄ %69 = $(Expr(:gc_preserve_begin, :(%26)))
│ %70 = $(Expr(:foreigncall, :(:jl_value_ptr), Ptr{Nothing}, svec(Any), 0, :(:ccall), :(%26)))::Ptr{Nothing}
│ %71 = Base.bitcast(Ptr{Float64}, %70)::Ptr{Float64}
│ %72 = Base.pointerref(%71, 3, 1)::Float64
│ $(Expr(:gc_preserve_end, :(%69)))
└─── goto #24
24 ─ %75 = StaticArrays.tuple(%40, %56, %72)::Tuple{Float64, Float64, Float64}
│ %76 = %new(MMatrix{3, 1, Float64, 3}, %75)::MMatrix{3, 1, Float64, 3}
└─── goto #25
25 ─ goto #26
26 ─ goto #28
27 ─ Core.throw(ErrorException("fatal error in type inference (type bound)"))::Union{}
└─── unreachable
28 ┄ %82 = φ (#2 => true, #4 => false, #26 => false)::Bool
│ %83 = φ (#2 => %17)::Tuple{Float64, Float64, Float64}
│ %84 = φ (#2 => false, #4 => true, #26 => false)::Bool
│ %85 = φ (#2 => false, #4 => false, #26 => true)::Bool
│ %86 = φ (#4 => %22, #26 => %76)::Union{MVector{3, Float64}, MMatrix{3, 1, Float64, 3}}
└─── goto #30 if not %82
29 ─ %88 = %new(SMatrix{3, 1, Float64, 3}, %83)::SMatrix{3, 1, Float64, 3}
└─── goto #35
30 ─ goto #32 if not %84
31 ─ %91 = π (%86, MVector{3, Float64})
│ %92 = StaticArrays.getfield(%91, :data)::Tuple{Float64, Float64, Float64}
│ %93 = %new(MVector{3, Float64}, %92)::MVector{3, Float64}
└─── goto #35
32 ─ goto #34 if not %85
33 ─ %96 = π (%86, MMatrix{3, 1, Float64, 3})
│ %97 = StaticArrays.getfield(%96, :data)::Tuple{Float64, Float64, Float64}
│ %98 = %new(MMatrix{3, 1, Float64, 3}, %97)::MMatrix{3, 1, Float64, 3}
└─── goto #35
34 ─ Core.throw(ErrorException("fatal error in type inference (type bound)"))::Union{}
└─── unreachable
35 ┄ %102 = φ (#29 => %88, #31 => %93, #33 => %98)::Union{MVector{3, Float64}, SMatrix{3, 1, Float64, 3}, MMatrix{3, 1, Float64, 3}}
└─── return %102
) => Union{MVector{3, Float64}, SMatrix{3, 1, Float64, 3}, MMatrix{3, 1, Float64, 3}}
This produces a union which causes us to yell.
This produces a union which causes us to yell.
Could we produce a better error in this case? Or does one of the hidden flags help?
The following line works in Julia:
but throws an illegal type analysis error in autodiff:
autodiff(Reverse, /, Active, Active(@SVector([0.0, 0.0, 0.0])), Active(@SMatrix([1.0])))
Versions:
Enzyme v0.12.36 StaticArrays v1.9.7
julia> versioninfo() Julia Version 1.10.4 Commit 48d4fd48430 (2024-06-04 10:41 UTC) Build Info: Official https://julialang.org/ release Platform Info: OS: macOS (arm64-apple-darwin22.4.0) CPU: 8 × Apple M2 WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1) Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)