Skip to content

Forward-over-reverse through DiffEqBase.solve_call hits LLVM verifier failure after getfield fix #3299

Description

@ChrisRackauckas-Claude

Summary

The isolated Enzyme-only reducer from #3296 is fixed for me on Enzyme v0.13.177, but the original ODE-shaped case is not solved end-to-end. With Enzyme v0.13.177, the old idx_jl_getfield_aug calling convention mismatch is gone and the inner reverse-mode gradient succeeds, but the outer forward-over-reverse call now fails later with an LLVM verifier error.

This reducer no longer needs SciMLSensitivity; it only imports OrdinaryDiffEq, DiffEqBase, and Enzyme.

MWE

import OrdinaryDiffEq as ODE
import DiffEqBase
import Enzyme

f(u, p, t) = -p[1] .* u
u0 = [1.0]
tspan = (0.0, 1.0)
ts = range(0.0, 1.0, length = 5)

function loss(p)
    prob = ODE.ODEProblem(f, u0, tspan, p)
    sol = ODE.solve(
        prob,
        ODE.Tsit5();
        saveat = ts,
        sensealg = DiffEqBase.SensitivityADPassThrough(),
    )
    sum(abs2, Array(sol))
end

const RA_R = Enzyme.set_runtime_activity(Enzyme.Reverse)
const RA_F = Enzyme.set_runtime_activity(Enzyme.Forward)

@noinline function grad(p)
    dp = zero(p)
    Enzyme.autodiff(RA_R, Enzyme.Const(loss), Enzyme.Active, Enzyme.Duplicated(p, dp))
    dp
end

@show grad([0.5])
@show Enzyme.autodiff(RA_F, Enzyme.Const(p -> sum(grad(p))), Enzyme.Duplicated([0.5], [1.0]))

Observed

The inner reverse-mode gradient succeeds:

grad([0.5]) = [-2.4402421907949057]

The outer forward-over-reverse call then fails with:

Instruction does not dominate all uses!
...
Terminator found in the middle of a basic block!
...
ERROR: LoadError: LLVM error: Broken module found, compilation aborted!

The relevant stack path is:

Enzyme.Compiler.check_ir! ... validation.jl:1298
Enzyme.Compiler.runtime_generic_fwd(... typeof(Enzyme.Compiler.runtime_generic_augfwd) ..., typeof(Core.kwcall), ..., typeof(DiffEqBase.solve_call), ...)
DiffEqBase.solve_up
loss
grad

Versions tested

Julia 1.11.9
Enzyme v0.13.177
DiffEqBase v7.6.0
OrdinaryDiffEq v7.1.1
SciMLBase v3.32.0

For comparison, on Enzyme v0.13.176 this same original case failed earlier at the idx_jl_getfield_aug calling convention mismatch. On Enzyme v0.13.177, that part appears fixed and this verifier failure is exposed instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions