Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AbstractInterpreter to parameterize compilation pipeline #33955

Merged
merged 2 commits into from
May 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 75 additions & 72 deletions base/compiler/abstractinterpretation.jl

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions base/compiler/bootstrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
# since we won't be able to specialize & infer them at runtime

let fs = Any[typeinf_ext, typeinf, typeinf_edge, pure_eval_call, run_passes],
world = get_world_counter()
world = get_world_counter(),
interp = NativeInterpreter(world)

for x in T_FFUNC_VAL
push!(fs, x[3])
end
Expand All @@ -27,7 +29,7 @@ let fs = Any[typeinf_ext, typeinf, typeinf_edge, pure_eval_call, run_passes],
typ[i] = typ[i].ub
end
end
typeinf_type(m[3], Tuple{typ...}, m[2], Params(world))
typeinf_type(interp, m[3], Tuple{typ...}, m[2])
end
end
end
4 changes: 2 additions & 2 deletions base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ using .Sort
# compiler #
############

include("compiler/types.jl")
include("compiler/utilities.jl")
include("compiler/validation.jl")

include("compiler/inferenceresult.jl")
include("compiler/params.jl")
include("compiler/inferencestate.jl")

include("compiler/typeutils.jl")
Expand All @@ -111,7 +111,7 @@ include("compiler/typeinfer.jl")
include("compiler/optimize.jl") # TODO: break this up further + extract utilities

include("compiler/bootstrap.jl")
ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext)
ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext_toplevel)

end # baremodule Compiler
))
12 changes: 0 additions & 12 deletions base/compiler/inferenceresult.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@

const EMPTY_VECTOR = Vector{Any}()

mutable struct InferenceResult
linfo::MethodInstance
argtypes::Vector{Any}
overridden_by_const::BitVector
result # ::Type, or InferenceState if WIP
src #::Union{CodeInfo, OptimizationState, Nothing} # if inferred copy is available
function InferenceResult(linfo::MethodInstance, given_argtypes = nothing)
argtypes, overridden_by_const = matching_cache_argtypes(linfo, given_argtypes)
return new(linfo, argtypes, overridden_by_const, Any, nothing)
end
end

function is_argtype_match(@nospecialize(given_argtype),
@nospecialize(cache_argtype),
overridden_by_const::Bool)
Expand Down
18 changes: 9 additions & 9 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const LineNum = Int

mutable struct InferenceState
params::Params # describes how to compute the result
params::InferenceParams
result::InferenceResult # remember where to put the result
linfo::MethodInstance
sptypes::Vector{Any} # types of static parameter
Expand All @@ -13,6 +13,7 @@ mutable struct InferenceState

# info on the state of inference and the linfo
src::CodeInfo
world::UInt
min_valid::UInt
max_valid::UInt
nargs::Int
Expand Down Expand Up @@ -47,7 +48,7 @@ mutable struct InferenceState

# src is assumed to be a newly-allocated CodeInfo, that can be modified in-place to contain intermediate results
function InferenceState(result::InferenceResult, src::CodeInfo,
cached::Bool, params::Params)
cached::Bool, interp::AbstractInterpreter)
linfo = result.linfo
code = src.code::Array{Any,1}
toplevel = !isa(linfo.def, Method)
Expand Down Expand Up @@ -95,9 +96,9 @@ mutable struct InferenceState
max_valid = src.max_world == typemax(UInt) ?
get_world_counter() : src.max_world
frame = new(
params, result, linfo,
InferenceParams(interp), result, linfo,
sp, slottypes, inmodule, 0,
src, min_valid, max_valid,
src, get_world_counter(interp), min_valid, max_valid,
nargs, s_types, s_edges,
Union{}, W, 1, n,
cur_hand, handler_at, n_handlers,
Expand All @@ -108,17 +109,17 @@ mutable struct InferenceState
cached, false, false, false,
IdDict{Any, Tuple{Any, UInt, UInt}}())
result.result = frame
cached && push!(params.cache, result)
cached && push!(get_inference_cache(interp), result)
return frame
end
end

function InferenceState(result::InferenceResult, cached::Bool, params::Params)
function InferenceState(result::InferenceResult, cached::Bool, interp::AbstractInterpreter)
# prepare an InferenceState object for inferring lambda
src = retrieve_code_info(result.linfo)
src === nothing && return nothing
validate_code_in_debug_mode(result.linfo, src, "lowered")
return InferenceState(result, src, cached, params)
return InferenceState(result, src, cached, interp)
end

function sptypes_from_meth_instance(linfo::MethodInstance)
Expand Down Expand Up @@ -195,8 +196,7 @@ _topmod(sv::InferenceState) = _topmod(sv.mod)
function update_valid_age!(min_valid::UInt, max_valid::UInt, sv::InferenceState)
sv.min_valid = max(sv.min_valid, min_valid)
sv.max_valid = min(sv.max_valid, max_valid)
@assert(sv.min_valid <= sv.params.world <= sv.max_valid,
"invalid age range update")
@assert(sv.min_valid <= sv.world <= sv.max_valid, "invalid age range update")
nothing
end

Expand Down
50 changes: 26 additions & 24 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,38 @@
#####################

mutable struct OptimizationState
params::OptimizationParams
linfo::MethodInstance
calledges::Vector{Any}
src::CodeInfo
mod::Module
nargs::Int
world::UInt
min_valid::UInt
max_valid::UInt
params::Params
sptypes::Vector{Any} # static parameters
slottypes::Vector{Any}
const_api::Bool
# cached results of calling `_methods_by_ftype` from inference, including
# `min_valid` and `max_valid`
matching_methods_cache::IdDict{Any, Tuple{Any, UInt, UInt}}
function OptimizationState(frame::InferenceState)
# TODO: This will be eliminated once optimization no longer needs to do method lookups
interp::AbstractInterpreter
function OptimizationState(frame::InferenceState, params::OptimizationParams, interp::AbstractInterpreter)
s_edges = frame.stmt_edges[1]
if s_edges === nothing
s_edges = []
frame.stmt_edges[1] = s_edges
end
src = frame.src
return new(frame.linfo,
return new(params, frame.linfo,
s_edges::Vector{Any},
src, frame.mod, frame.nargs,
frame.min_valid, frame.max_valid,
frame.params, frame.sptypes, frame.slottypes, false,
frame.matching_methods_cache)
frame.world, frame.min_valid, frame.max_valid,
frame.sptypes, frame.slottypes, false,
frame.matching_methods_cache, interp)
end
function OptimizationState(linfo::MethodInstance, src::CodeInfo,
params::Params)
function OptimizationState(linfo::MethodInstance, src::CodeInfo, params::OptimizationParams, interp::AbstractInterpreter)
# prepare src for running optimization passes
# if it isn't already
nssavalues = src.ssavaluetypes
Expand All @@ -57,19 +59,19 @@ mutable struct OptimizationState
inmodule = linfo.def::Module
nargs = 0
end
return new(linfo,
return new(params, linfo,
s_edges::Vector{Any},
src, inmodule, nargs,
UInt(1), get_world_counter(),
params, sptypes_from_meth_instance(linfo), slottypes, false,
IdDict{Any, Tuple{Any, UInt, UInt}}())
get_world_counter(), UInt(1), get_world_counter(),
sptypes_from_meth_instance(linfo), slottypes, false,
IdDict{Any, Tuple{Any, UInt, UInt}}(), interp)
end
end

function OptimizationState(linfo::MethodInstance, params::Params)
function OptimizationState(linfo::MethodInstance, params::OptimizationParams, interp::AbstractInterpreter)
src = retrieve_code_info(linfo)
src === nothing && return nothing
return OptimizationState(linfo, src, params)
return OptimizationState(linfo, src, params, interp)
end


Expand Down Expand Up @@ -109,7 +111,7 @@ _topmod(sv::OptimizationState) = _topmod(sv.mod)
function update_valid_age!(min_valid::UInt, max_valid::UInt, sv::OptimizationState)
sv.min_valid = max(sv.min_valid, min_valid)
sv.max_valid = min(sv.max_valid, max_valid)
@assert(sv.min_valid <= sv.params.world <= sv.max_valid,
@assert(sv.min_valid <= sv.world <= sv.max_valid,
"invalid age range update")
nothing
end
Expand All @@ -127,10 +129,10 @@ function add_backedge!(li::CodeInstance, caller::OptimizationState)
nothing
end

function isinlineable(m::Method, me::OptimizationState, bonus::Int=0)
function isinlineable(m::Method, me::OptimizationState, params::OptimizationParams, bonus::Int=0)
# compute the cost (size) of inlining this code
inlineable = false
cost_threshold = me.params.inline_cost_threshold
cost_threshold = params.inline_cost_threshold
if m.module === _topmod(m.module)
# a few functions get special treatment
name = m.name
Expand All @@ -145,7 +147,7 @@ function isinlineable(m::Method, me::OptimizationState, bonus::Int=0)
end
end
if !inlineable
inlineable = inline_worthy(me.src.code, me.src, me.sptypes, me.slottypes, me.params, cost_threshold + bonus)
inlineable = inline_worthy(me.src.code, me.src, me.sptypes, me.slottypes, params, cost_threshold + bonus)
end
return inlineable
end
Expand All @@ -168,7 +170,7 @@ function stmt_affects_purity(@nospecialize(stmt), ir)
end

# run the optimization work
function optimize(opt::OptimizationState, @nospecialize(result))
function optimize(opt::OptimizationState, params::OptimizationParams, @nospecialize(result))
def = opt.linfo.def
nargs = Int(opt.nargs) - 1
@timeit "optimizer" ir = run_passes(opt.src, nargs, opt)
Expand Down Expand Up @@ -247,13 +249,13 @@ function optimize(opt::OptimizationState, @nospecialize(result))
else
bonus = 0
if result ⊑ Tuple && !isbitstype(widenconst(result))
bonus = opt.params.inline_tupleret_bonus
bonus = params.inline_tupleret_bonus
end
if opt.src.inlineable
# For functions declared @inline, increase the cost threshold 20x
bonus += opt.params.inline_cost_threshold*19
bonus += params.inline_cost_threshold*19
end
opt.src.inlineable = isinlineable(def, opt, bonus)
opt.src.inlineable = isinlineable(def, opt, params, bonus)
end
end
nothing
Expand Down Expand Up @@ -282,7 +284,7 @@ plus_saturate(x::Int, y::Int) = max(x, y, x+y)
# known return type
isknowntype(@nospecialize T) = (T === Union{}) || isa(T, Const) || isconcretetype(widenconst(T))

function statement_cost(ex::Expr, line::Int, src::CodeInfo, sptypes::Vector{Any}, slottypes::Vector{Any}, params::Params)
function statement_cost(ex::Expr, line::Int, src::CodeInfo, sptypes::Vector{Any}, slottypes::Vector{Any}, params::OptimizationParams)
head = ex.head
if is_meta_expr_head(head)
return 0
Expand Down Expand Up @@ -372,7 +374,7 @@ function statement_cost(ex::Expr, line::Int, src::CodeInfo, sptypes::Vector{Any}
end

function inline_worthy(body::Array{Any,1}, src::CodeInfo, sptypes::Vector{Any}, slottypes::Vector{Any},
params::Params, cost_threshold::Integer=params.inline_cost_threshold)
params::OptimizationParams, cost_threshold::Integer=params.inline_cost_threshold)
bodycost::Int = 0
for line = 1:length(body)
stmt = body[line]
Expand Down
72 changes: 0 additions & 72 deletions base/compiler/params.jl

This file was deleted.

Loading