Skip to content

Commit 2a021fa

Browse files
committed
optimizer: handle GlobalRef based on assume_bindings_static
Following up #53750. External abstract interpreters with `assume_bindings_static` enabled assume nothrow-ness of defined `GlobalRef`s no matter if they are constant during abstract interpretation. However, post-#53750, the optimizer’s verification switched to stricter checks, causing errors in such interpreters. This commit makes `IRCode` hold `assume_bindings_static::Bool` info to ensure that inlining and verification behaviors are synced with abstract interpretation.
1 parent baca8ba commit 2a021fa

File tree

4 files changed

+31
-19
lines changed

4 files changed

+31
-19
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,7 +2836,7 @@ function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, sv::
28362836
rt = abstract_eval_globalref_type(g)
28372837
consistent = inaccessiblememonly = ALWAYS_FALSE
28382838
nothrow = false
2839-
if isa(rt, Const)
2839+
if isa(rt, Const) # implies `isdefinedconst_globalref(g) === true`
28402840
consistent = ALWAYS_TRUE
28412841
nothrow = true
28422842
if is_mutation_free_argtype(rt)
@@ -2849,8 +2849,6 @@ function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, sv::
28492849
else
28502850
rt = Union{}
28512851
end
2852-
elseif isdefinedconst_globalref(g)
2853-
nothrow = true
28542852
end
28552853
return RTEffects(rt, nothrow ? Union{} : UndefVarError, Effects(EFFECTS_TOTAL; consistent, nothrow, inaccessiblememonly))
28562854
end

base/compiler/optimize.jl

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ function new_expr_effect_flags(𝕃ₒ::AbstractLattice, args::Vector{Any}, src:
288288
return (false, true, true)
289289
end
290290

291+
assume_bindings_static(ir::IRCode) = ir.assume_bindings_static
292+
assume_bindings_static(compact::IncrementalCompact) = assume_bindings_static(compact.ir)
293+
291294
# Returns a tuple of `(:consistent, :removable, :nothrow)` flags for a given statement.
292295
function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospecialize(rt), src::Union{IRCode,IncrementalCompact})
293296
# TODO: We're duplicating analysis from inference here.
@@ -298,7 +301,12 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
298301
isa(stmt, GotoNode) && return (true, false, true)
299302
isa(stmt, GotoIfNot) && return (true, false, (𝕃ₒ, argextype(stmt.cond, src), Bool))
300303
if isa(stmt, GlobalRef)
301-
nothrow = consistent = isdefinedconst_globalref(stmt)
304+
if assume_bindings_static(src)
305+
nothrow = isdefined_globalref(stmt)
306+
consistent = nothrow & isconst(stmt)
307+
else
308+
nothrow = consistent = isdefinedconst_globalref(stmt)
309+
end
302310
return (consistent, nothrow, nothrow)
303311
elseif isa(stmt, Expr)
304312
(; head, args) = stmt
@@ -1129,7 +1137,6 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
11291137
# Go through and add an unreachable node after every
11301138
# Union{} call. Then reindex labels.
11311139
stmtinfo = sv.stmt_info
1132-
meta = Expr[]
11331140
idx = 1
11341141
oldidx = 1
11351142
nstmts = length(code)
@@ -1229,25 +1236,28 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
12291236
renumber_cfg_stmts!(sv.cfg, blockchangemap)
12301237
end
12311238

1232-
for i = 1:length(code)
1233-
code[i] = process_meta!(meta, code[i])
1234-
end
1239+
meta = process_meta!(code)
12351240
strip_trailing_junk!(code, ssavaluetypes, ssaflags, di, sv.cfg, stmtinfo)
12361241
types = Any[]
12371242
stmts = InstructionStream(code, types, stmtinfo, codelocs, ssaflags)
12381243
# NOTE this `argtypes` contains types of slots yet: it will be modified to contain the
12391244
# types of call arguments only once `slot2reg` converts this `IRCode` to the SSA form
12401245
# and eliminates slots (see below)
12411246
argtypes = sv.slottypes
1242-
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes)
1247+
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes,
1248+
InferenceParams(sv.inlining.interp).assume_bindings_static)
12431249
end
12441250

1245-
function process_meta!(meta::Vector{Expr}, @nospecialize stmt)
1246-
if isexpr(stmt, :meta) && length(stmt.args) 1
1247-
push!(meta, stmt)
1248-
return nothing
1251+
function process_meta!(code::Vector{Any})
1252+
meta = Expr[]
1253+
for i = 1:length(code)
1254+
stmt = code[i]
1255+
if isexpr(stmt, :meta) && length(stmt.args) 1
1256+
push!(meta, stmt)
1257+
code[i] = nothing
1258+
end
12491259
end
1250-
return stmt
1260+
return meta
12511261
end
12521262

12531263
function slot2reg(ir::IRCode, ci::CodeInfo, sv::OptimizationState)

base/compiler/ssair/ir.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -428,22 +428,26 @@ struct IRCode
428428
cfg::CFG
429429
new_nodes::NewNodeStream
430430
meta::Vector{Expr}
431+
assume_bindings_static::Bool # XXX propagate `interp::AbstractInterpreter` here?
431432

432-
function IRCode(stmts::InstructionStream, cfg::CFG, debuginfo::DebugInfoStream, argtypes::Vector{Any}, meta::Vector{Expr}, sptypes::Vector{VarState})
433-
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta)
433+
function IRCode(stmts::InstructionStream, cfg::CFG, debuginfo::DebugInfoStream,
434+
argtypes::Vector{Any}, meta::Vector{Expr}, sptypes::Vector{VarState},
435+
assume_bindings_static::Bool=false)
436+
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta, assume_bindings_static)
434437
end
435438
function IRCode(ir::IRCode, stmts::InstructionStream, cfg::CFG, new_nodes::NewNodeStream)
436439
di = ir.debuginfo
437440
@assert di.codelocs === stmts.line
438-
return new(stmts, ir.argtypes, ir.sptypes, di, cfg, new_nodes, ir.meta)
441+
return new(stmts, ir.argtypes, ir.sptypes, di, cfg, new_nodes, ir.meta, ir.assume_bindings_static)
439442
end
440443
global function copy(ir::IRCode)
441444
di = ir.debuginfo
442445
stmts = copy(ir.stmts)
443446
di = copy(di)
444447
di.edges = copy(di.edges)
445448
di.codelocs = stmts.line
446-
return new(stmts, copy(ir.argtypes), copy(ir.sptypes), di, copy(ir.cfg), copy(ir.new_nodes), copy(ir.meta))
449+
return new(stmts, copy(ir.argtypes), copy(ir.sptypes), di, copy(ir.cfg),
450+
copy(ir.new_nodes), copy(ir.meta), ir.assume_bindings_static)
447451
end
448452
end
449453

base/compiler/ssair/verify.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
5656
error("")
5757
end
5858
elseif isa(op, GlobalRef)
59-
if !isdefined(op.mod, op.name) || !isconst(op.mod, op.name)
59+
if !(assume_bindings_static(ir) ? isdefined_globalref(op) : isdefinedconst_globalref(op))
6060
@verify_error "Unbound GlobalRef not allowed in value position"
6161
error("")
6262
end

0 commit comments

Comments
 (0)