Skip to content

Type check in callee does not propagate to caller #37342

Closed
@yuyichao

Description

@yuyichao

Somewhat similar to #25632 but more general and maybe more relavant as well.

julia> isType(@nospecialize t) = isa(t, DataType) && t.name === Core.Compiler._TYPE_NAME
isType (generic function with 1 method)

julia> function f(r)
           t = r[]
           if isType(t)
               return t.parameters[1]
           end
       end
f (generic function with 1 method)

julia> @code_typed f(Ref{Any}())
CodeInfo(
1%1  = Base.getfield(r, :x)::Any%2  = (%1 isa Main.DataType)::Bool
└──       goto #3 if not %2
2%4  = π (%1, DataType)
│   %5  = Base.getfield(%4, :name)::Core.TypeName%6  = Core.Compiler::Module%7  = Base.getfield(%6, :_TYPE_NAME)::Core.TypeName%8  = (%5 === %7)::Bool
└──       goto #4
3 ─       goto #4
4%11 = φ (#2 => %8, #3 => false)::Bool
└──       goto #6 if not %11
5%13 = Base.getproperty(%1, :parameters)::Any%14 = Base.getindex(%13, 1)::Any
└──       return %14
6return nothing
) => Any

Note that the access of the parameters field and subsequent calls are not inferred. If isType is manually inlined then the function works just fine. (The @nospecialize is due to copy-and-paste from type inference and does not have any effect on the issue.)


Noticed this when testing #37303 a while ago. Dynamic dispatch like this happens everywhere in inference/optimizer code (including most callers of typeutils.jl functions) and I've verified from LLVM IR dump that this is actually happening in the final code. I don't know how much performance issue it costs but could be significant... (note that it won't be as bad as the code above since Core.Compiler.getproperty === getfield). Adding type assertions back in to inference code could be a temporary solution but fixing the inference itself would be better...

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions