Skip to content

Commit

Permalink
Merge branch 'master' into gb/sched-refact
Browse files Browse the repository at this point in the history
  • Loading branch information
gbaraldi authored Jan 24, 2025
2 parents df83c27 + 6eb42db commit 911ab19
Show file tree
Hide file tree
Showing 167 changed files with 2,743 additions and 2,161 deletions.
3 changes: 0 additions & 3 deletions .devcontainer/Dockerfile

This file was deleted.

16 changes: 10 additions & 6 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"extensions": [
"julialang.language-julia",
"ms-vscode.cpptools"
],

"dockerFile": "Dockerfile"
"image": "docker.io/library/julia:latest",
"customizations": {
"vscode": {
"extensions": [
"julialang.language-julia",
"ms-vscode.cpptools"
]
}
},
"onCreateCommand": "apt-get update && apt-get install -y build-essential libatomic1 python3 gfortran perl wget m4 cmake pkg-config git"
}
2 changes: 1 addition & 1 deletion Compiler/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Compiler"
uuid = "807dbc54-b67e-4c79-8afb-eafe4df6f2e1"
version = "0.0.2"
version = "0.0.3"

[compat]
julia = "1.10"
Expand Down
114 changes: 58 additions & 56 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
for i in 1:length(split_argtypes)
arg_n = split_argtypes[i]::Vector{Any}
sig_n = argtypes_to_type(arg_n)
sig_n === Bottom && continue
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
mt = mt::MethodTable
Expand Down Expand Up @@ -614,7 +615,7 @@ function abstract_call_method(interp::AbstractInterpreter,
sigtuple = unwrap_unionall(sig)
sigtuple isa DataType ||
return Future(MethodCallResult(Any, Any, Effects(), nothing, false, false))
all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) ||
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) ||
return Future(MethodCallResult(Union{}, Any, EFFECTS_THROWS, nothing, false, false)) # catch bad type intersections early

if is_nospecializeinfer(method)
Expand Down Expand Up @@ -2395,7 +2396,8 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s
if M isa Const && s isa Const
M, s = M.val, s.val
if M isa Module && s isa Symbol
return CallMeta(abstract_eval_globalref(interp, GlobalRef(M, s), saw_latestworld, sv), NoCallInfo())
(ret, bpart) = abstract_eval_globalref(interp, GlobalRef(M, s), saw_latestworld, sv)
return CallMeta(ret, bpart === nothing ? NoCallInfo() : GlobalAccessInfo(bpart))
end
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
elseif !hasintersect(widenconst(M), Module) || !hasintersect(widenconst(s), Symbol)
Expand Down Expand Up @@ -2473,8 +2475,8 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
if isa(M, Const) && isa(s, Const)
M, s = M.val, s.val
if M isa Module && s isa Symbol
rt, exct = global_assignment_rt_exct(interp, sv, saw_latestworld, GlobalRef(M, s), v)
return CallMeta(rt, exct, Effects(setglobal!_effects, nothrow=exct===Bottom), NoCallInfo())
(rt, exct), partition = global_assignment_rt_exct(interp, sv, saw_latestworld, GlobalRef(M, s), v)
return CallMeta(rt, exct, Effects(setglobal!_effects, nothrow=exct===Bottom), GlobalAccessInfo(partition))
end
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
end
Expand Down Expand Up @@ -2512,15 +2514,15 @@ function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState,
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
scm.rt === Bottom && return scm
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s)
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), scm.info)
end

function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool,
@nospecialize(M), @nospecialize(s), @nospecialize(v), @nospecialize(order))
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v, order)
scm.rt === Bottom && return scm
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s, order)
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), scm.info)
end

function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
Expand Down Expand Up @@ -2569,7 +2571,7 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
end
exct = Union{rte.exct, global_assignment_binding_rt_exct(interp, partition, v)[2]}
effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=exct===Bottom))
sg = CallMeta(Any, exct, effects, NoCallInfo())
sg = CallMeta(Any, exct, effects, GlobalAccessInfo(partition))
else
sg = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
end
Expand Down Expand Up @@ -2839,6 +2841,7 @@ function abstract_call_unknown(interp::AbstractInterpreter, @nospecialize(ft),
end
# non-constant function, but the number of arguments is known and the `f` is not a builtin or intrinsic
atype = argtypes_to_type(arginfo.argtypes)
atype === Bottom && return Future(CallMeta(Union{}, Union{}, EFFECTS_THROWS, NoCallInfo())) # accidentally unreachable
return abstract_call_gf_by_type(interp, nothing, arginfo, si, atype, sv, max_methods)::Future
end

Expand Down Expand Up @@ -2937,7 +2940,8 @@ function abstract_eval_special_value(interp::AbstractInterpreter, @nospecialize(
return RTEffects(sv.ir.argtypes[e.n], Union{}, EFFECTS_TOTAL) # TODO frame_argtypes(sv)[e.n] and remove the assertion
end
elseif isa(e, GlobalRef)
return abstract_eval_globalref(interp, e, sstate.saw_latestworld, sv)
# No need for an edge since an explicit GlobalRef will be picked up by the source scan
return abstract_eval_globalref(interp, e, sstate.saw_latestworld, sv)[1]
end
if isa(e, QuoteNode)
e = e.value
Expand Down Expand Up @@ -3193,14 +3197,31 @@ function abstract_eval_isdefined_expr(interp::AbstractInterpreter, e::Expr, ssta
end
return RTEffects(rt, Union{}, EFFECTS_TOTAL)
end
return abstract_eval_isdefined(interp, sym, sstate.saw_latestworld, sv)
rt = Bool
effects = EFFECTS_TOTAL
exct = Union{}
if isexpr(sym, :static_parameter)
n = sym.args[1]::Int
if 1 <= n <= length(sv.sptypes)
sp = sv.sptypes[n]
if !sp.undef
rt = Const(true)
elseif sp.typ === Bottom
rt = Const(false)
end
end
else
effects = EFFECTS_UNKNOWN
exct = Any
end
return RTEffects(rt, exct, effects)
end

const generic_isdefinedglobal_effects = Effects(EFFECTS_TOTAL, consistent=ALWAYS_FALSE, nothrow=false)
function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, mod::Module, sym::Symbol, allow_import::Union{Bool, Nothing}, saw_latestworld::Bool, sv::AbsIntState)
rt = Bool
if saw_latestworld
return RTEffects(rt, Union{}, Effects(generic_isdefinedglobal_effects, nothrow=true))
return CallMeta(RTEffects(rt, Union{}, Effects(generic_isdefinedglobal_effects, nothrow=true)), NoCallInfo())
end

effects = EFFECTS_TOTAL
Expand All @@ -3222,7 +3243,7 @@ function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, mod::Module,
effects = Effects(generic_isdefinedglobal_effects, nothrow=true)
end
end
return RTEffects(rt, Union{}, effects)
return CallMeta(RTEffects(rt, Union{}, effects), GlobalAccessInfo(partition))
end

function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, @nospecialize(M), @nospecialize(s), @nospecialize(allow_import_arg), @nospecialize(order_arg), saw_latestworld::Bool, sv::AbsIntState)
Expand All @@ -3247,7 +3268,7 @@ function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, @nospecializ
if M isa Const && s isa Const
M, s = M.val, s.val
if M isa Module && s isa Symbol
return merge_exct(CallMeta(abstract_eval_isdefinedglobal(interp, M, s, allow_import, saw_latestworld, sv), NoCallInfo()), exct)
return merge_exct(abstract_eval_isdefinedglobal(interp, M, s, allow_import, saw_latestworld, sv), exct)
end
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
elseif !hasintersect(widenconst(M), Module) || !hasintersect(widenconst(s), Symbol)
Expand All @@ -3258,26 +3279,6 @@ function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, @nospecializ
return CallMeta(Bool, Union{exct, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo())
end

function abstract_eval_isdefined(interp::AbstractInterpreter, @nospecialize(sym), saw_latestworld::Bool, sv::AbsIntState)
rt = Bool
effects = EFFECTS_TOTAL
exct = Union{}
if isexpr(sym, :static_parameter)
n = sym.args[1]::Int
if 1 <= n <= length(sv.sptypes)
sp = sv.sptypes[n]
if !sp.undef
rt = Const(true)
elseif sp.typ === Bottom
rt = Const(false)
end
end
else
effects = EFFECTS_UNKNOWN
end
return RTEffects(rt, exct, effects)
end

function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr, sstate::StatementState, sv::AbsIntState)
condt = abstract_eval_value(interp, e.args[2], sstate, sv)
condval = maybe_extract_const_bool(condt)
Expand Down Expand Up @@ -3455,10 +3456,10 @@ world_range(ir::IRCode) = ir.valid_worlds
world_range(ci::CodeInfo) = WorldRange(ci.min_world, ci.max_world)
world_range(compact::IncrementalCompact) = world_range(compact.ir)

function force_binding_resolution!(g::GlobalRef)
function force_binding_resolution!(g::GlobalRef, world::UInt)
# Force resolution of the binding
# TODO: This will go away once we switch over to fully partitioned semantics
ccall(:jl_globalref_boundp, Cint, (Any,), g)
ccall(:jl_force_binding_resolution, Cvoid, (Any, Csize_t), g, world)
return nothing
end

Expand All @@ -3476,7 +3477,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
# This method is surprisingly hot. For performance, don't ask the runtime to resolve
# the binding unless necessary - doing so triggers an additional lookup, which though
# not super expensive is hot enough to show up in benchmarks.
force_binding_resolution!(g)
force_binding_resolution!(g, min_world(worlds))
return abstract_eval_globalref_type(g, src, false)
end
# return Union{}
Expand All @@ -3489,7 +3490,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
end

function lookup_binding_partition!(interp::AbstractInterpreter, g::GlobalRef, sv::AbsIntState)
force_binding_resolution!(g)
force_binding_resolution!(g, get_inference_world(interp))
partition = lookup_binding_partition(get_inference_world(interp), g)
update_valid_age!(sv, WorldRange(partition.min_world, partition.max_world))
partition
Expand Down Expand Up @@ -3533,26 +3534,30 @@ end

function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, saw_latestworld::Bool, sv::AbsIntState)
if saw_latestworld
return RTEffects(Any, Any, generic_getglobal_effects)
return Pair{RTEffects, Union{Nothing, Core.BindingPartition}}(RTEffects(Any, Any, generic_getglobal_effects), nothing)
end
partition = abstract_eval_binding_partition!(interp, g, sv)
ret = abstract_eval_partition_load(interp, partition)
if ret.rt !== Union{} && ret.exct === UndefVarError && InferenceParams(interp).assume_bindings_static
if isdefined(g, :binding) && isdefined(g.binding, :value)
return RTEffects(ret.rt, Union{}, Effects(generic_getglobal_effects, nothrow=true))
b = convert(Core.Binding, g)
if isdefined(b, :value)
ret = RTEffects(ret.rt, Union{}, Effects(generic_getglobal_effects, nothrow=true))
end
# We do not assume in general that assigned global bindings remain assigned.
# The existence of pkgimages allows them to revert in practice.
end
return ret
return Pair{RTEffects, Union{Nothing, Core.BindingPartition}}(ret, partition)
end

function global_assignment_rt_exct(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, g::GlobalRef, @nospecialize(newty))
if saw_latestworld
return Pair{Any,Any}(newty, Union{ErrorException, TypeError})
return Pair{Pair{Any,Any}, Union{Core.BindingPartition, Nothing}}(
Pair{Any,Any}(newty, Union{ErrorException, TypeError}), nothing)
end
partition = abstract_eval_binding_partition!(interp, g, sv)
return global_assignment_binding_rt_exct(interp, partition, newty)
return Pair{Pair{Any,Any}, Union{Core.BindingPartition, Nothing}}(
global_assignment_binding_rt_exct(interp, partition, newty),
partition)
end

function global_assignment_binding_rt_exct(interp::AbstractInterpreter, partition::Core.BindingPartition, @nospecialize(newty))
Expand All @@ -3573,18 +3578,6 @@ function global_assignment_binding_rt_exct(interp::AbstractInterpreter, partitio
return Pair{Any,Any}(newty, Bottom)
end

function handle_global_assignment!(interp::AbstractInterpreter, frame::InferenceState, saw_latestworld::Bool, lhs::GlobalRef, @nospecialize(newty))
effect_free = ALWAYS_FALSE
nothrow = global_assignment_rt_exct(interp, frame, saw_latestworld, lhs, ignorelimited(newty))[2] === Union{}
inaccessiblememonly = ALWAYS_FALSE
if !nothrow
sub_curr_ssaflag!(frame, IR_FLAG_NOTHROW)
end
sub_curr_ssaflag!(frame, IR_FLAG_EFFECT_FREE)
merge_effects!(interp, frame, Effects(EFFECTS_TOTAL; effect_free, nothrow, inaccessiblememonly))
return nothing
end

abstract_eval_ssavalue(s::SSAValue, sv::InferenceState) = abstract_eval_ssavalue(s, sv.ssavaluetypes)

function abstract_eval_ssavalue(s::SSAValue, ssavaluetypes::Vector{Any})
Expand Down Expand Up @@ -3718,7 +3711,7 @@ end
if isa(rt, PartialStruct)
fields = copy(rt.fields)
anyrefine = !isvarargtype(rt.fields[end]) &&
length(rt.fields) > datatype_min_ninitialized(unwrap_unionall(rt.typ))
length(rt.fields) > datatype_min_ninitialized(rt.typ)
𝕃 = typeinf_lattice(info.interp)
= strictpartialorder(𝕃)
for i in 1:length(fields)
Expand Down Expand Up @@ -3795,14 +3788,23 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
slottypes = frame.slottypes
rt = widenreturn(rt, BestguessInfo(interp, bestguess, nargs, slottypes, currstate))
# narrow representation of bestguess slightly to prepare for tmerge with rt
if rt isa InterConditional && bestguess isa Const
if rt isa InterConditional && bestguess isa Const && bestguess.val isa Bool
slot_id = rt.slot
old_id_type = widenconditional(slottypes[slot_id])
if bestguess.val === true && rt.elsetype !== Bottom
bestguess = InterConditional(slot_id, old_id_type, Bottom)
elseif bestguess.val === false && rt.thentype !== Bottom
bestguess = InterConditional(slot_id, Bottom, old_id_type)
end
# or narrow representation of rt slightly to prepare for tmerge with bestguess
elseif bestguess isa InterConditional && rt isa Const && rt.val isa Bool
slot_id = bestguess.slot
old_id_type = widenconditional(slottypes[slot_id])
if rt.val === true && bestguess.elsetype !== Bottom
rt = InterConditional(slot_id, old_id_type, Bottom)
elseif rt.val === false && bestguess.thentype !== Bottom
rt = InterConditional(slot_id, Bottom, old_id_type)
end
end
# copy limitations to return value
if !isempty(frame.pclimitations)
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
# types of call arguments only once `slot2reg` converts this `IRCode` to the SSA form
# and eliminates slots (see below)
argtypes = sv.slottypes
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, WorldRange(ci.min_world, ci.max_world))
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, world_range(ci))
end

function process_meta!(meta::Vector{Expr}, @nospecialize stmt)
Expand Down
1 change: 1 addition & 0 deletions Compiler/src/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,7 @@ function handle_call!(todo::Vector{Pair{Int,Any}},
cases === nothing && return nothing
cases, handled_all_cases, fully_covered, joint_effects = cases
atype = argtypes_to_type(sig.argtypes)
atype === Union{} && return nothing # accidentally actually unreachable
handle_cases!(todo, ir, idx, stmt, atype, cases, handled_all_cases, fully_covered, joint_effects)
end

Expand Down
4 changes: 2 additions & 2 deletions Compiler/src/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ struct IRCode
function IRCode(stmts::InstructionStream, cfg::CFG, debuginfo::DebugInfoStream,
argtypes::Vector{Any}, meta::Vector{Expr}, sptypes::Vector{VarState},
valid_worlds=WorldRange(typemin(UInt), typemax(UInt)))
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta)
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta, valid_worlds)
end
function IRCode(ir::IRCode, stmts::InstructionStream, cfg::CFG, new_nodes::NewNodeStream)
di = ir.debuginfo
Expand Down Expand Up @@ -1462,7 +1462,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
result[result_idx][:stmt] = GotoNode(label)
result_idx += 1
elseif isa(stmt, GlobalRef)
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
flag = result[result_idx][:flag]
if has_flag(flag, total_flags)
ssa_rename[idx] = stmt
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/ssair/legacy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{A
di = DebugInfoStream(nothing, ci.debuginfo, nstmts)
stmts = InstructionStream(code, ssavaluetypes, info, di.codelocs, ci.ssaflags)
meta = Expr[]
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, WorldRange(ci.min_world, ci.max_world))
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, world_range(ci))
end

"""
Expand Down
12 changes: 9 additions & 3 deletions Compiler/src/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ end

if !isdefined(@__MODULE__, Symbol("@verify_error"))
macro verify_error(arg)
arg isa String && return esc(:(print && println(stderr, $arg)))
arg isa String && return esc(:(print && println($(GlobalRef(Core, :stderr)), $arg)))
isexpr(arg, :string) || error("verify_error macro expected a string expression")
pushfirst!(arg.args, GlobalRef(Core, :stderr))
pushfirst!(arg.args, :println)
Expand Down Expand Up @@ -61,8 +61,14 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
raise_error()
end
elseif isa(op, GlobalRef)
if !isdefined(op.mod, op.name) || !isconst(op.mod, op.name)
@verify_error "Unbound GlobalRef not allowed in value position"
force_binding_resolution!(op, min_world(ir.valid_worlds))
bpart = lookup_binding_partition(min_world(ir.valid_worlds), op)
while is_some_imported(binding_kind(bpart)) && max_world(ir.valid_worlds) <= bpart.max_world
imported_binding = partition_restriction(bpart)::Core.Binding
bpart = lookup_binding_partition(min_world(ir.valid_worlds), imported_binding)
end
if !is_defined_const_binding(binding_kind(bpart)) || (bpart.max_world < max_world(ir.valid_worlds))
@verify_error "Unbound or partitioned GlobalRef not allowed in value position"
raise_error()
end
elseif isa(op, Expr)
Expand Down
Loading

0 comments on commit 911ab19

Please sign in to comment.