Skip to content

Commit f1b3089

Browse files
Merge pull request #4632 from SebastianM-C/fix/enzyme-nonnumeric-template-inference
[AI] add static indexing for discrete/constants/nonnumeric
2 parents 9068107 + f219a98 commit f1b3089

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

lib/ModelingToolkitBase/src/systems/problem_utils.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,12 @@ function __apply_copy_template(valp, template)
772772
return p.constant[template.idx[1]][template.idx[2]]
773773
elseif template isa ParameterIndex{Nonnumeric, Tuple{Int, UnitRange{Int}}}
774774
return p.nonnumeric[template.idx[1]][template.idx[2]]
775+
elseif template isa StaticBufferIndex{SciMLStructures.Discrete}
776+
return _static_buffer(p.discrete, template)[template.range]
777+
elseif template isa StaticBufferIndex{SciMLStructures.Constants}
778+
return _static_buffer(p.constant, template)[template.range]
779+
elseif template isa StaticBufferIndex{Nonnumeric}
780+
return _static_buffer(p.nonnumeric, template)[template.range]
775781
elseif template isa UnitRange{Int}
776782
return u[template]
777783
elseif template isa ObservedWrapper
@@ -807,6 +813,27 @@ end
807813
struct IndepVarTemplate end
808814
const IV_TEMPLATE = IndepVarTemplate()
809815

816+
"""
817+
$TYPEDEF
818+
819+
Template entry for `CopyParamsByTemplate` indexing into one of the inner buffers of a
820+
multi-buffer `MTKParameters` portion (discrete/constants/nonnumeric). Unlike
821+
`ParameterIndex{P, Tuple{Int, UnitRange{Int}}}`, the buffer index `I` is lifted into the
822+
type domain so that indexing the heterogeneously-typed tuple of buffers constant-folds and
823+
infers concretely. With a runtime buffer index the result is a small `Union` of the buffer
824+
types, which Enzyme's type analysis rejects (`IllegalTypeAnalysisException`) when it flows
825+
into `reshape` inside the `CopyParamsByTemplate` compile unit.
826+
"""
827+
struct StaticBufferIndex{P, I}
828+
range::UnitRange{Int}
829+
end
830+
831+
function StaticBufferIndex{P}(idx::Tuple{Int, UnitRange{Int}}) where {P}
832+
return StaticBufferIndex{P, idx[1]}(idx[2])
833+
end
834+
835+
@inline _static_buffer(bufs::Tuple, ::StaticBufferIndex{P, I}) where {P, I} = bufs[I]
836+
810837
Base.@nospecializeinfer function __specialize_templates(template::Vector{Any}, elem_types::Set{DataType})
811838
if length(template) <= 4
812839
return Tuple(template)
@@ -927,6 +954,19 @@ function CopyParamsByTemplate(srcsys::AbstractSystem, syms::AbstractArray{Symbol
927954
end
928955
end
929956

957+
# Lift buffer indices of multi-buffer portions (discrete/constants/nonnumeric) into
958+
# the type domain. This is done as a final pass so the contiguous-range merging above
959+
# can keep operating on plain `ParameterIndex`es.
960+
for i in eachindex(template)
961+
entry = template[i]
962+
# Only lift the `(bufidx, range)` form into the type domain.
963+
if entry isa ParameterIndex && entry.portion isa Union{SciMLStructures.Discrete, SciMLStructures.Constants, Nonnumeric} && entry.idx isa Tuple{Int, UnitRange{Int}}
964+
delete!(elem_types, typeof(entry))
965+
template[i] = StaticBufferIndex{typeof(entry.portion)}(entry.idx)
966+
push!(elem_types, typeof(template[i]))
967+
end
968+
end
969+
930970
return CopyParamsByTemplate{true}(__specialize_templates(template, elem_types), size(syms))
931971
end
932972

0 commit comments

Comments
 (0)