-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -838,7 +838,7 @@ function compileable_specialization(match::MethodMatch, effects::Effects, | |
end | ||
|
||
struct InferredResult | ||
src::Any | ||
src::Any # CodeInfo or IRCode | ||
effects::Effects | ||
InferredResult(@nospecialize(src), effects::Effects) = new(src, effects) | ||
end | ||
|
@@ -849,11 +849,9 @@ end | |
# in this case function can be inlined to a constant | ||
return ConstantCase(quoted(code.rettype_const)) | ||
end | ||
src = @atomic :monotonic code.inferred | ||
effects = decode_effects(code.ipo_purity_bits) | ||
return InferredResult(src, effects) | ||
return code | ||
end | ||
return InferredResult(nothing, Effects()) | ||
return nothing | ||
end | ||
@inline function get_local_result(inf_result::InferenceResult) | ||
effects = inf_result.ipo_effects | ||
|
@@ -887,7 +885,15 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult, | |
add_inlining_backedge!(et, mi) | ||
return inferred_result | ||
end | ||
(; src, effects) = inferred_result | ||
if inferred_result isa InferredResult | ||
(; src, effects) = inferred_result | ||
elseif inferred_result isa CodeInstance | ||
src = @atomic :monotonic inferred_result.inferred | ||
effects = decode_effects(inferred_result.ipo_purity_bits) | ||
else | ||
src = nothing | ||
effects = Effects() | ||
end | ||
|
||
# the duplicated check might have been done already within `analyze_method!`, but still | ||
# we need it here too since we may come here directly using a constant-prop' result | ||
|
@@ -896,12 +902,13 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult, | |
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
end | ||
|
||
src = inlining_policy(state.interp, src, info, flag) | ||
src === nothing && return compileable_specialization(mi, effects, et, info; | ||
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
src_inlining_policy(state.interp, src, info, flag) || | ||
return compileable_specialization(mi, effects, et, info; | ||
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
|
||
add_inlining_backedge!(et, mi) | ||
ir = retrieve_ir_for_inlining(mi, src, preserve_local_sources) | ||
ir = inferred_result isa CodeInstance ? retrieve_ir_for_inlining(inferred_result, src) : | ||
retrieve_ir_for_inlining(mi, src, preserve_local_sources) | ||
return InliningTodo(mi, ir, effects) | ||
end | ||
|
||
|
@@ -919,14 +926,22 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U | |
add_inlining_backedge!(et, mi) | ||
return cached_result | ||
end | ||
(; src, effects) = cached_result | ||
|
||
src = inlining_policy(state.interp, src, info, flag) | ||
|
||
src === nothing && return nothing | ||
if cached_result isa InferredResult | ||
(; src, effects) = cached_result | ||
elseif cached_result isa CodeInstance | ||
src = @atomic :monotonic cached_result.inferred | ||
effects = decode_effects(cached_result.ipo_purity_bits) | ||
else | ||
src = nothing | ||
effects = Effects() | ||
end | ||
|
||
preserve_local_sources = true | ||
src_inlining_policy(state.interp, src, info, flag) || return nothing | ||
ir = cached_result isa CodeInstance ? retrieve_ir_for_inlining(cached_result, src) : | ||
retrieve_ir_for_inlining(mi, src, preserve_local_sources) | ||
add_inlining_backedge!(et, mi) | ||
return InliningTodo(mi, retrieve_ir_for_inlining(mi, src), effects) | ||
return InliningTodo(mi, ir, effects) | ||
end | ||
|
||
function validate_sparams(sparams::SimpleVector) | ||
|
@@ -979,17 +994,17 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, | |
return resolve_todo(mi, volatile_inf_result, info, flag, state; invokesig) | ||
end | ||
|
||
function retrieve_ir_for_inlining(mi::MethodInstance, src::String, ::Bool=true) | ||
src = _uncompressed_ir(mi.def, src) | ||
return inflate_ir!(src, mi) | ||
function retrieve_ir_for_inlining(cached_result::CodeInstance, src::MaybeCompressed) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
vtjnash
Author
Member
|
||
src = _uncompressed_ir(cached_result, src)::CodeInfo | ||
return inflate_ir!(src, cached_result.def) | ||
end | ||
function retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo, preserve_local_sources::Bool=true) | ||
function retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo, preserve_local_sources::Bool) | ||
if preserve_local_sources | ||
src = copy(src) | ||
end | ||
return inflate_ir!(src, mi) | ||
end | ||
function retrieve_ir_for_inlining(::MethodInstance, ir::IRCode, preserve_local_sources::Bool=true) | ||
function retrieve_ir_for_inlining(mi::MethodInstance, ir::IRCode, preserve_local_sources::Bool) | ||
if preserve_local_sources | ||
ir = copy(ir) | ||
end | ||
|
@@ -1494,13 +1509,13 @@ function semiconcrete_result_item(result::SemiConcreteResult, | |
return compileable_specialization(mi, result.effects, et, info; | ||
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
end | ||
ir = inlining_policy(state.interp, result.ir, info, flag) | ||
ir === nothing && return compileable_specialization(mi, result.effects, et, info; | ||
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
src_inlining_policy(state.interp, result.ir, info, flag) || | ||
return compileable_specialization(mi, result.effects, et, info; | ||
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) | ||
|
||
add_inlining_backedge!(et, mi) | ||
preserve_local_sources = OptimizationParams(state.interp).preserve_local_sources | ||
ir = retrieve_ir_for_inlining(mi, ir, preserve_local_sources) | ||
ir = retrieve_ir_for_inlining(mi, result.ir, preserve_local_sources) | ||
return InliningTodo(mi, ir, result.effects) | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -310,11 +310,20 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult; | |
end | ||
end | ||
relocatability = 0x0 | ||
owner = cache_owner(interp) | ||
if const_flags == 0x3 && can_discard_trees | ||
inferred_result = nothing | ||
relocatability = 0x1 | ||
else | ||
inferred_result = transform_result_for_cache(interp, result.linfo, result.valid_worlds, result, can_discard_trees) | ||
if inferred_result isa CodeInfo | ||
uncompressed = inferred_result | ||
inferred_result = maybe_compress_codeinfo(interp, result.linfo, inferred_result, can_discard_trees) | ||
result.is_src_volatile |= uncompressed !== inferred_result | ||
This comment has been minimized.
Sorry, something went wrong.
aviatesk
Member
|
||
elseif owner === nothing | ||
# The global cache can only handle objects that codegen understands | ||
inferred_result = nothing | ||
end | ||
if isa(inferred_result, String) | ||
t = @_gc_preserve_begin inferred_result | ||
relocatability = unsafe_load(unsafe_convert(Ptr{UInt8}, inferred_result), Core.sizeof(inferred_result)) | ||
|
@@ -323,15 +332,21 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult; | |
relocatability = 0x1 | ||
end | ||
end | ||
# relocatability = isa(inferred_result, String) ? inferred_result[end] : UInt8(0) | ||
return CodeInstance(result.linfo, cache_owner(interp), | ||
# n.b. relocatability = (isa(inferred_result, String) && inferred_result[end]) || inferred_result === nothing | ||
return CodeInstance(result.linfo, owner, | ||
widenconst(result_type), widenconst(result.exc_result), rettype_const, inferred_result, | ||
const_flags, first(result.valid_worlds), last(result.valid_worlds), | ||
# TODO: Actually do something with non-IPO effects | ||
encode_effects(result.ipo_effects), encode_effects(result.ipo_effects), result.analysis_results, | ||
relocatability) | ||
end | ||
|
||
function transform_result_for_cache(interp::AbstractInterpreter, | ||
linfo::MethodInstance, valid_worlds::WorldRange, result::InferenceResult, | ||
can_discard_trees::Bool=may_discard_trees(interp)) | ||
return result.src | ||
end | ||
|
||
function maybe_compress_codeinfo(interp::AbstractInterpreter, linfo::MethodInstance, ci::CodeInfo, | ||
can_discard_trees::Bool=may_discard_trees(interp)) | ||
def = linfo.def | ||
|
@@ -354,22 +369,6 @@ function maybe_compress_codeinfo(interp::AbstractInterpreter, linfo::MethodInsta | |
end | ||
end | ||
|
||
function transform_result_for_cache(interp::AbstractInterpreter, | ||
linfo::MethodInstance, valid_worlds::WorldRange, result::InferenceResult, | ||
can_discard_trees::Bool=may_discard_trees(interp)) | ||
inferred_result = result.src | ||
if inferred_result isa CodeInfo | ||
uncompressed = inferred_result | ||
inferred_result = maybe_compress_codeinfo(interp, linfo, inferred_result, can_discard_trees) | ||
result.is_src_volatile |= uncompressed !== inferred_result | ||
end | ||
# The global cache can only handle objects that codegen understands | ||
if !isa(inferred_result, MaybeCompressed) | ||
inferred_result = nothing | ||
end | ||
return inferred_result | ||
end | ||
|
||
function cache_result!(interp::AbstractInterpreter, result::InferenceResult) | ||
if last(result.valid_worlds) == get_world_counter() | ||
# if we've successfully recorded all of the backedges in the global reverse-cache, | ||
|
@@ -874,7 +873,7 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize | |
exc_bestguess = refine_exception_type(frame.exc_bestguess, effects) | ||
# propagate newly inferred source to the inliner, allowing efficient inlining w/o deserialization: | ||
# note that this result is cached globally exclusively, we can use this local result destructively | ||
volatile_inf_result = isinferred && (force_inline || inlining_policy(interp, result.src, NoCallInfo(), IR_FLAG_NULL) !== nothing) ? | ||
volatile_inf_result = isinferred && (force_inline || src_inlining_policy(interp, result.src, NoCallInfo(), IR_FLAG_NULL) !== nothing) ? | ||
VolatileInferenceResult(result) : nothing | ||
return EdgeCallResult(frame.bestguess, exc_bestguess, edge, effects, volatile_inf_result) | ||
elseif frame === true | ||
|
@@ -1092,6 +1091,8 @@ function ci_meets_requirement(code::CodeInstance, source_mode::UInt8, ci_is_cach | |
return false | ||
end | ||
|
||
_uncompressed_ir(ci::Core.CodeInstance, s::String) = ccall(:jl_uncompress_ir, Any, (Any, Any, Any), ci.def.def::Method, ci, s)::CodeInfo | ||
|
||
# compute (and cache) an inferred AST and return type | ||
function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance, source_mode::UInt8) | ||
start_time = ccall(:jl_typeinf_timing_begin, UInt64, ()) | ||
|
This design of forcing external abstract interpreters that use custom cache data to overload
retrieve_ir_for_inlining
doesn't seem ideal, as it ends up making those interpreters invalidate the base compiler pipeline seriously. The previous design whereinlining_policy(interp, ...)
returns data specialized for eachinterp
would avoid this issue of invalidation.