Skip to content

Commit 47c47af

Browse files
committed
Allow irinterp to refine nothrow effect
This addresses a remaining todo in the irinterp code to allow it to compute whether its particular evaluation refined `nothrow`. As a result, we can re-enable it for a larger class of ir (we had previously disabled it to avoid regressing cases where regular constprop was able to prove a `nothrow` refinement, but irinterp was not).
1 parent 4d206c9 commit 47c47af

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -830,9 +830,7 @@ function concrete_eval_eligible(interp::AbstractInterpreter,
830830
if is_all_const_arg(arginfo, #=start=#2)
831831
return true
832832
else
833-
# TODO: `is_nothrow` is not an actual requirement here, this is just a hack
834-
# to avoid entering semi concrete eval while it doesn't properly override effects
835-
return is_nothrow(result.effects) ? false : nothing
833+
return false
836834
end
837835
end
838836
return nothing
@@ -1004,10 +1002,11 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter,
10041002
ir = codeinst_to_ir(interp, code)
10051003
if isa(ir, IRCode)
10061004
irsv = IRInterpretationState(interp, ir, mi, sv.world, arginfo.argtypes)
1007-
rt = ir_abstract_constant_propagation(interp, irsv)
1005+
rt, nothrow = ir_abstract_constant_propagation(interp, irsv)
10081006
@assert !(rt isa Conditional || rt isa MustAlias) "invalid lattice element returned from IR interpretation"
10091007
if !isa(rt, Type) || typeintersect(rt, Bool) === Union{}
1010-
return ConstCallResults(rt, SemiConcreteResult(mi, ir, result.effects), result.effects, mi)
1008+
new_effects = Effects(result.effects; nothrow=nothrow)
1009+
return ConstCallResults(rt, SemiConcreteResult(mi, ir, new_effects), new_effects, mi)
10111010
end
10121011
end
10131012
end

base/compiler/optimize.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
649649
insert!(codelocs, idx + 1, codelocs[idx])
650650
insert!(ssavaluetypes, idx + 1, Union{})
651651
insert!(stmtinfo, idx + 1, NoCallInfo())
652-
insert!(ssaflags, idx + 1, ssaflags[idx])
652+
insert!(ssaflags, idx + 1, IR_FLAG_NOTHROW)
653653
if ssachangemap === nothing
654654
ssachangemap = fill(0, nstmts)
655655
end

base/compiler/ssair/irinterp.jl

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,20 +144,20 @@ function concrete_eval_invoke(interp::AbstractInterpreter,
144144
inst::Expr, mi::MethodInstance, irsv::IRInterpretationState)
145145
mi_cache = WorldView(code_cache(interp), irsv.world)
146146
code = get(mi_cache, mi, nothing)
147-
code === nothing && return nothing
147+
code === nothing && return Pair{Any, Bool}(nothing, false)
148148
argtypes = collect_argtypes(interp, inst.args[2:end], nothing, irsv.ir)
149-
argtypes === nothing && return Union{}
149+
argtypes === nothing && return Pair{Any, Bool}(Union{}, false)
150150
effects = decode_effects(code.ipo_purity_bits)
151151
if is_foldable(effects) && is_all_const_arg(argtypes, #=start=#1)
152152
args = collect_const_args(argtypes, #=start=#1)
153153
world = get_world_counter(interp)
154154
value = try
155155
Core._call_in_world_total(world, args...)
156156
catch
157-
return Union{}
157+
return Pair{Any, Bool}(Union{}, false)
158158
end
159159
if is_inlineable_constant(value)
160-
return Const(value)
160+
return Pair{Any, Bool}(Const(value), true)
161161
end
162162
else
163163
ir′ = codeinst_to_ir(interp, code)
@@ -166,7 +166,7 @@ function concrete_eval_invoke(interp::AbstractInterpreter,
166166
return _ir_abstract_constant_propagation(interp, irsv′)
167167
end
168168
end
169-
return nothing
169+
return Pair{Any, Bool}(nothing, is_nothrow(effects))
170170
end
171171

172172
function abstract_eval_phi_stmt(interp::AbstractInterpreter, phi::PhiNode, ::Int, irsv::IRInterpretationState)
@@ -225,16 +225,21 @@ function reprocess_instruction!(interp::AbstractInterpreter,
225225
(; rt, effects) = abstract_eval_statement_expr(interp, inst, nothing, ir, irsv.mi)
226226
# All other effects already guaranteed effect free by construction
227227
if is_nothrow(effects)
228+
ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
228229
if isa(rt, Const) && is_inlineable_constant(rt.val)
229230
ir.stmts[idx][:inst] = quoted(rt.val)
230-
else
231-
ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE
232231
end
233232
end
234233
elseif head === :invoke
235234
mi′ = inst.args[1]::MethodInstance
236235
if mi′ !== irsv.mi # prevent infinite loop
237-
rt = concrete_eval_invoke(interp, inst, mi′, irsv)
236+
rt, nothrow = concrete_eval_invoke(interp, inst, mi′, irsv)
237+
if nothrow
238+
ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
239+
if isa(rt, Const) && is_inlineable_constant(rt.val)
240+
ir.stmts[idx][:inst] = quoted(rt.val)
241+
end
242+
end
238243
end
239244
elseif head === :throw_undef_if_not || # TODO: Terminate interpretation early if known false?
240245
head === :gc_preserve_begin ||
@@ -416,7 +421,15 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, irsv::IR
416421
end
417422
end
418423

419-
return maybe_singleton_const(ultimate_rt)
424+
nothrow = true
425+
for i = 1:length(ir.stmts)
426+
if (ir.stmts[i][:flag] & IR_FLAG_NOTHROW) == 0
427+
nothrow = false
428+
break
429+
end
430+
end
431+
432+
return Pair{Any, Bool}(maybe_singleton_const(ultimate_rt), nothrow)
420433
end
421434

422435
function ir_abstract_constant_propagation(interp::AbstractInterpreter, irsv::IRInterpretationState)

base/compiler/ssair/slot2ssa.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, info::Vector{Call
203203
push!(ssavaluetypes, Union{})
204204
push!(codelocs, 0)
205205
push!(info, NoCallInfo())
206-
push!(ssaflags, IR_FLAG_NULL)
206+
push!(ssaflags, IR_FLAG_NOTHROW)
207207
end
208208
nothing
209209
end

0 commit comments

Comments
 (0)