Skip to content
Closed
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
271 changes: 154 additions & 117 deletions base/compiler/abstractinterpretation.jl

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ include("compiler/methodtable.jl")
include("compiler/inferenceresult.jl")
include("compiler/inferencestate.jl")

include("compiler/ssair/basicblock.jl")
include("compiler/ssair/domtree.jl")
include("compiler/ssair/ir.jl")

include("compiler/typeutils.jl")
include("compiler/typelimits.jl")
include("compiler/typelattice.jl")
Expand All @@ -139,7 +143,7 @@ include("compiler/stmtinfo.jl")

include("compiler/abstractinterpretation.jl")
include("compiler/typeinfer.jl")
include("compiler/optimize.jl") # TODO: break this up further + extract utilities
include("compiler/optimize.jl")

# required for bootstrap
# TODO: find why this is needed and remove it.
Expand Down
55 changes: 31 additions & 24 deletions base/compiler/inferenceresult.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,36 @@ function is_forwardable_argtype(@nospecialize x)
isa(x, PartialOpaque)
end

function va_process_argtypes(given_argtypes::Vector{Any}, mi::MethodInstance,
condargs::Union{Vector{Tuple{Int,Int}}, Nothing}=nothing)
isva = mi.def.isva
nargs = Int(mi.def.nargs)
if isva || isvarargtype(given_argtypes[end])
isva_given_argtypes = Vector{Any}(undef, nargs)
for i = 1:(nargs - isva)
isva_given_argtypes[i] = argtype_by_index(given_argtypes, i)
end
if isva
if length(given_argtypes) < nargs && isvarargtype(given_argtypes[end])
last = length(given_argtypes)
else
last = nargs
end
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[last:end])
# invalidate `Conditional` imposed on varargs
if condargs !== nothing
for (slotid, i) in condargs
if slotid ≥ last
isva_given_argtypes[i] = widenconditional(isva_given_argtypes[i])
end
end
end
end
return isva_given_argtypes
end
return given_argtypes
end

# In theory, there could be a `cache` containing a matching `InferenceResult`
# for the provided `linfo` and `given_argtypes`. The purpose of this function is
# to return a valid value for `cache_lookup(linfo, argtypes, cache).argtypes`,
Expand Down Expand Up @@ -55,30 +85,7 @@ function matching_cache_argtypes(
end
given_argtypes[i] = widenconditional(argtype)
end
isva = linfo.def.isva
if isva || isvarargtype(given_argtypes[end])
isva_given_argtypes = Vector{Any}(undef, nargs)
for i = 1:(nargs - isva)
isva_given_argtypes[i] = argtype_by_index(given_argtypes, i)
end
if isva
if length(given_argtypes) < nargs && isvarargtype(given_argtypes[end])
last = length(given_argtypes)
else
last = nargs
end
isva_given_argtypes[nargs] = tuple_tfunc(given_argtypes[last:end])
# invalidate `Conditional` imposed on varargs
if condargs !== nothing
for (slotid, i) in condargs
if slotid ≥ last
isva_given_argtypes[i] = widenconditional(isva_given_argtypes[i])
end
end
end
end
given_argtypes = isva_given_argtypes
end
given_argtypes = va_process_argtypes(given_argtypes, linfo, condargs)
@assert length(given_argtypes) == nargs
for i in 1:nargs
given_argtype = given_argtypes[i]
Expand Down
6 changes: 6 additions & 0 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ function in(idx::Int, bsbmp::BitSetBoundedMinPrioritySet)
return idx in bsbmp.elems
end

function append!(bsbmp::BitSetBoundedMinPrioritySet, itr)
for val in itr
push!(bsbmp, val)
end
end

mutable struct InferenceState
params::InferenceParams
result::InferenceResult # remember where to put the result
Expand Down
3 changes: 2 additions & 1 deletion base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import Core.Compiler: # Core.Compiler specific definitions
isbitstype, isexpr, is_meta_expr_head, println, widenconst, argextype, singleton_type,
fieldcount_noerror, try_compute_field, try_compute_fieldidx, hasintersect, ⊑,
intrinsic_nothrow, array_builtin_common_typecheck, arrayset_typecheck,
setfield!_nothrow, alloc_array_ndims, stmt_effect_free, check_effect_free!
setfield!_nothrow, alloc_array_ndims, stmt_effect_free, check_effect_free!,
SemiConcreteResult

include(x) = _TOP_MOD.include(@__MODULE__, x)
if _TOP_MOD === Core.Compiler
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/EscapeAnalysis/interprocedural.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Core.Compiler:
call_sig, argtypes_to_type, is_builtin, is_return_type, istopfunction, validate_sparams,
specialize_method, invoke_rewrite

const Linfo = Union{MethodInstance,InferenceResult}
const Linfo = Union{MethodInstance,InferenceResult,SemiConcreteResult}
struct CallInfo
linfos::Vector{Linfo}
nothrow::Bool
Expand Down
4 changes: 1 addition & 3 deletions base/compiler/ssair/driver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ function stmt_effect_free end # imported by EscapeAnalysis
function alloc_array_ndims end # imported by EscapeAnalysis
function try_compute_field end # imported by EscapeAnalysis

include("compiler/ssair/basicblock.jl")
include("compiler/ssair/domtree.jl")
include("compiler/ssair/ir.jl")
include("compiler/ssair/slot2ssa.jl")
include("compiler/ssair/inlining.jl")
include("compiler/ssair/verify.jl")
include("compiler/ssair/legacy.jl")
include("compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl")
include("compiler/ssair/passes.jl")
include("compiler/ssair/irinterp.jl")
20 changes: 18 additions & 2 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,8 @@ function handle_const_call!(
push!(cases, InliningCase(result.mi.specTypes, case))
elseif isa(result, InferenceResult)
handled_all_cases &= handle_inf_result!(result, argtypes, flag, state, cases)
elseif isa(result, SemiConcreteResult)
handled_all_cases &= handle_semi_concrete_result!(result, cases)
else
@assert result === nothing
handled_all_cases &= handle_match!(match, argtypes, flag, state, cases)
Expand All @@ -1294,8 +1296,13 @@ function handle_const_call!(
if length(cases) == 0
length(results) == 1 || return nothing
result = results[1]
isa(result, InferenceResult) || return nothing
handle_inf_result!(result, argtypes, flag, state, cases, true) || return nothing
if isa(result, InferenceResult)
handle_inf_result!(result, argtypes, flag, state, cases, true) || return nothing
elseif isa(result, SemiConcreteResult)
handle_semi_concrete_result!(result, cases) || return nothing
else
return nothing
end
spec_types = cases[1].sig
any_covers_full = handled_all_cases = atype <: spec_types
end
Expand Down Expand Up @@ -1328,6 +1335,15 @@ function handle_inf_result!(
return true
end

function handle_semi_concrete_result!(result::SemiConcreteResult, cases::Vector{InliningCase}, allow_abstract::Bool = false)
mi = result.mi
spec_types = mi.specTypes
allow_abstract || isdispatchtuple(spec_types) || return false
validate_sparams(mi.sparam_vals) || return false
push!(cases, InliningCase(spec_types, InliningTodo(mi, result.ir, result.effects)))
return true
end

function const_result_item(result::ConstResult, state::InliningState)
if !isdefined(result, :result) || !is_inlineable_constant(result.result)
return compileable_specialization(state.et, result.mi, EFFECTS_TOTAL)
Expand Down
11 changes: 9 additions & 2 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1030,15 +1030,22 @@ function renumber_ssa2!(@nospecialize(stmt), ssanums::Vector{Any}, used_ssas::Ve
end

# Used in inlining before we start compacting - Only works at the CFG level
function kill_edge!(bbs::Vector{BasicBlock}, from::Int, to::Int)
function kill_edge!(bbs::Vector{BasicBlock}, from::Int, to::Int, callback=nothing)
preds, succs = bbs[to].preds, bbs[from].succs
deleteat!(preds, findfirst(x->x === from, preds)::Int)
deleteat!(succs, findfirst(x->x === to, succs)::Int)
if length(preds) == 0
for succ in copy(bbs[to].succs)
kill_edge!(bbs, to, succ)
kill_edge!(bbs, to, succ, callback)
end
end
if callback !== nothing
callback(from, to)
end
end

function kill_edge!(ir::IRCode, from::Int, to::Int, callback=nothing)
kill_edge!(ir.cfg.blocks, from, to, callback)
end

# N.B.: from and to are non-renamed indices
Expand Down
Loading