Skip to content

Commit

Permalink
inline abstract, single, constant-prop'ed match
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed Nov 23, 2021
1 parent 8cc91a6 commit 4a4f363
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 11 deletions.
20 changes: 9 additions & 11 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ function analyze_single_call!(
item = analyze_method!(match, argtypes, flag, state)
item === nothing && return
push!(cases, InliningCase(match.spec_types, item))
fully_covered = atype <: match.spec_types
fully_covered = match.fully_covers
else
fully_covered &= atype <: signature_union
end
Expand Down Expand Up @@ -1242,17 +1242,15 @@ function maybe_handle_const_call!(

# if the signature is fully covered and there is only one applicable method,
# we can try to inline it even if the signature is not a dispatch tuple
if atype <: signature_union
if length(cases) == 0 && length(results) == 1
(; mi) = item = InliningTodo(results[1]::InferenceResult, argtypes)
state.mi_cache !== nothing && (item = resolve_todo(item, state, flag))
validate_sparams(mi.sparam_vals) || return true
item === nothing && return true
push!(cases, InliningCase(mi.specTypes, item))
fully_covered = true
end
if length(cases) == 0 && length(results) == 1
(; mi) = item = InliningTodo(results[1]::InferenceResult, argtypes)
state.mi_cache !== nothing && (item = resolve_todo(item, state, flag))
validate_sparams(mi.sparam_vals) || return true
item === nothing && return true
push!(cases, InliningCase(mi.specTypes, item))
fully_covered = atype <: mi.specTypes
else
fully_covered = false
fully_covered &= atype <: signature_union
end

# If we only have one case and that case is fully covered, we may either
Expand Down
13 changes: 13 additions & 0 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,19 @@ let # aggressive inlining of single, abstract method match
@test count(iscall((src,isGoodType)), src.code) == 1
end

@inline isGoodType2(cnd, @nospecialize x::Type) =
x !== Any && !(@noinline (cnd ? Core.Compiler.isType : Base.has_free_typevars)(x))
let # aggressive inlining of single, abstract method match (with constant-prop'ed)
src = code_typed((Type, Any,)) do x, y
isGoodType2(true, x), isGoodType2(true, y)
end |> only |> first
# both callsite should be inlined with constant-prop'ed result
@test count(isinvoke(:isType), src.code) == 2
@test count(isinvoke(:has_free_typevars), src.code) == 0
# `isGoodType(y::Any)` isn't fully convered, thus a runtime type check and fallback dynamic dispatch should be inserted
@test count(iscall((src,isGoodType2)), src.code) == 1
end

@noinline function checkBadType!(@nospecialize x::Type)
if x === Any || Base.has_free_typevars(x)
println(x)
Expand Down

0 comments on commit 4a4f363

Please sign in to comment.