Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inference: override InterConditional result with Const carefully #44668

Merged
merged 2 commits into from
Mar 22, 2022
Merged
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
29 changes: 16 additions & 13 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,20 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
splitsigs = switchtupleunion(sig)
for sig_n in splitsigs
result = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv)
rt, edge = result.rt, result.edge
if edge !== nothing
push!(edges, edge)
end
rt = result.rt
edge = result.edge
edge !== nothing && push!(edges, edge)
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
this_arginfo = ArgInfo(fargs, this_argtypes)
const_call_result = abstract_call_method_with_const_args(interp, result,
f, this_arginfo, match, sv)
effects = result.edge_effects
const_result = nothing
if const_call_result !== nothing
if const_call_result.rt ⊑ rt
(; rt, effects, const_result) = const_call_result
const_rt = const_call_result.rt
if const_rt ⊑ rt
rt = const_rt
(; effects, const_result) = const_call_result
end
end
tristate_merge!(sv, effects)
Expand All @@ -143,6 +144,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
break
end
end
this_conditional = ignorelimited(this_rt)
this_rt = widenwrappedconditional(this_rt)
else
if infer_compilation_signature(interp)
# Also infer the compilation signature for this method, so it's available
Expand All @@ -159,10 +162,10 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
end

result = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv)
this_rt, edge = result.rt, result.edge
if edge !== nothing
push!(edges, edge)
end
this_conditional = ignorelimited(result.rt)
this_rt = widenwrappedconditional(result.rt)
edge = result.edge
edge !== nothing && push!(edges, edge)
# try constant propagation with argtypes for this match
# this is in preparation for inlining, or improving the return result
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
Expand All @@ -172,10 +175,12 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
effects = result.edge_effects
const_result = nothing
if const_call_result !== nothing
this_const_rt = const_call_result.rt
this_const_conditional = ignorelimited(const_call_result.rt)
this_const_rt = widenwrappedconditional(const_call_result.rt)
# return type of const-prop' inference can be wider than that of non const-prop' inference
# e.g. in cases when there are cycles but cached result is still accurate
if this_const_rt ⊑ this_rt
this_conditional = this_const_conditional
this_rt = this_const_rt
(; effects, const_result) = const_call_result
end
Expand All @@ -186,8 +191,6 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
any_const_result = true
end
end
this_conditional = ignorelimited(this_rt)
this_rt = widenwrappedconditional(this_rt)
@assert !(this_conditional isa Conditional) "invalid lattice element returned from inter-procedural context"
seen += 1
rettype = tmerge(rettype, this_rt)
Expand Down
7 changes: 7 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,13 @@ end
end
@test ts == Any[Any]
end

# a tricky case: if constant inference derives `Const` while non-constant inference has
# derived `InterConditional`, we should not discard that constant information
iszero_simple(x) = x === 0
@test Base.return_types() do
iszero_simple(0) ? nothing : missing
end |> only === Nothing
end

@testset "branching on conditional object" begin
Expand Down