You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After having some discussion with @vtjnash on #43097, I found our inlining algorithm could inline single, abstract method match more aggressively.
For example, we can inline isGoodType in the example below:
julia>@inlineisGoodType(@nospecialize x::Type) = x !== Any &&!Base.has_free_typevars(x)
isGoodType (generic function with 1 method)
julia>code_typed((Any,)) do x
isGoodType(x)
end|> only
CodeInfo(
1 ─ %1= Main.isGoodType(x)::Bool
└── return%1
) => Bool
so that it can inline it even if the call signature isn't fully covered by the method signature.
In order to assert the functionality, I think these test cases would be enough:
import Core.Compiler: argextype, singleton_type
const EMPTY_SPTYPES = Core.Compiler.EMPTY_SLOTTYPES
# check if `x` is a dynamic call of a given functioniscall(y) =@nospecialize(x) ->iscall(y, x)
functioniscall((src, f)::Tuple{Core.CodeInfo,Function}, @nospecialize(x))
returniscall(x) do@nospecialize x
singleton_type(argextype(x, src, EMPTY_SPTYPES)) === f
endendiscall(pred::Function, @nospecialize(x)) = Meta.isexpr(x, :call) &&pred(x.args[1])
# check if `x` is a statically-resolved call of a function whose name is `sym`isinvoke(y) =@nospecialize(x) ->isinvoke(y, x)
isinvoke(sym::Symbol, @nospecialize(x)) =isinvoke(mi->mi.def.name===sym, x)
isinvoke(pred::Function, @nospecialize(x)) = Meta.isexpr(x, :invoke) &&pred(x.args[1]::Core.MethodInstance)
# NOTE we actually don't need any `@nospecialize` annotation here@inlineisGoodType(@nospecialize x::Type) =
x !== Any &&!(@noinline Base.has_free_typevars(x))
let# aggressive inlining of single, abstract method match
src =code_typed((Type, Any,)) do x, y
isGoodType(x), isGoodType(y)
end|> only |> first
# both callsite should be inlined@testcount(isinvoke(:has_free_typevars), src.code) ==2# `isGoodType(y::Any)` isn't fully convered, thus the inlining should be via runtime type check@testcount(iscall((src,isGoodType)), src.code) ==1end@noinlinefunctioncheckBadType!(@nospecialize x::Type)
if x === Any || Base.has_free_typevars(x)
println(x)
endreturnnothingendlet# aggressive inlining of single, abstract method match
src =code_typed((Type, Any,)) do x, y
checkBadType!(x), checkBadType!(y)
end|> only |> first
# both callsite should be resolved statically@testcount(isinvoke(:checkBadType!), src.code) ==2# `checkBadType!(y::Any)` isn't fully convered, thus the static dispatch should be via runtime type check@testcount(iscall((src,checkBadType!)), src.code) ==1end
@ianatol / @oscardssmith do either of you want to work on this? It might be a good opportunity to get familiar with our inlining algorithm, and I'm welcome to have a review on it.
The text was updated successfully, but these errors were encountered:
After having some discussion with @vtjnash on #43097, I found our inlining algorithm could inline single, abstract method match more aggressively.
For example, we can inline
isGoodType
in the example below:Especially, we want to relax the condition here:
julia/base/compiler/ssair/inlining.jl
Line 1174 in bc8337a
so that it can inline it even if the call signature isn't fully covered by the method signature.
In order to assert the functionality, I think these test cases would be enough:
The text was updated successfully, but these errors were encountered: