-
-
Couldn't load subscription status.
- Fork 5.7k
[Compiler] fix some cycle_fix_limited usage #57545
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -195,7 +195,7 @@ function finish!(interp::AbstractInterpreter, mi::MethodInstance, ci::CodeInstan | |
| end | ||
|
|
||
| function finish_nocycle(::AbstractInterpreter, frame::InferenceState) | ||
| finishinfer!(frame, frame.interp) | ||
| finishinfer!(frame, frame.interp, frame.cycleid) | ||
| opt = frame.result.src | ||
| if opt isa OptimizationState # implies `may_optimize(caller.interp) === true` | ||
| optimize(frame.interp, opt, frame.result) | ||
|
|
@@ -232,7 +232,7 @@ function finish_cycle(::AbstractInterpreter, frames::Vector{AbsIntState}, cyclei | |
| for frameid = cycleid:length(frames) | ||
| caller = frames[frameid]::InferenceState | ||
| adjust_cycle_frame!(caller, cycle_valid_worlds, cycle_valid_effects) | ||
| finishinfer!(caller, caller.interp) | ||
| finishinfer!(caller, caller.interp, cycleid) | ||
| end | ||
| for frameid = cycleid:length(frames) | ||
| caller = frames[frameid]::InferenceState | ||
|
|
@@ -312,26 +312,21 @@ function cache_result!(interp::AbstractInterpreter, result::InferenceResult, ci: | |
| return true | ||
| end | ||
|
|
||
| function cycle_fix_limited(@nospecialize(typ), sv::InferenceState) | ||
| function cycle_fix_limited(@nospecialize(typ), sv::InferenceState, cycleid::Int) | ||
| if typ isa LimitedAccuracy | ||
| if sv.parentid === 0 | ||
| # we might have introduced a limit marker, but we should know it must be sv and other callers_in_cycle | ||
| #@assert !isempty(callers_in_cycle(sv)) | ||
| # FIXME: this assert fails, appearing to indicate there is a bug in filtering this list earlier. | ||
| # In particular (during doctests for example), during inference of | ||
| # show(Base.IOContext{Base.GenericIOBuffer{Memory{UInt8}}}, Base.Multimedia.MIME{:var"text/plain"}, LinearAlgebra.BunchKaufman{Float64, Array{Float64, 2}, Array{Int64, 1}}) | ||
| # we observed one of the ssavaluetypes here to be Core.Compiler.LimitedAccuracy(typ=Any, causes=Core.Compiler.IdSet(getproperty(LinearAlgebra.BunchKaufman{Float64, Array{Float64, 2}, Array{Int64, 1}}, Symbol))) | ||
| return typ.typ | ||
| end | ||
| causes = copy(typ.causes) | ||
| delete!(causes, sv) | ||
| for caller in callers_in_cycle(sv) | ||
| delete!(causes, caller) | ||
| end | ||
| if isempty(causes) | ||
| return typ.typ | ||
| frames = sv.callstack::Vector{AbsIntState} | ||
| causes = typ.causes | ||
| for frameid = cycleid:length(frames) | ||
| caller = frames[frameid]::InferenceState | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this throws |
||
| caller in causes || continue | ||
| causes === typ.causes && (causes = copy(causes)) | ||
| pop!(causes, caller) | ||
| if isempty(causes) | ||
| return typ.typ | ||
| end | ||
| end | ||
| if length(causes) != length(typ.causes) | ||
| @assert sv.parentid != 0 | ||
| if causes !== typ.causes | ||
| return LimitedAccuracy(typ.typ, causes) | ||
| end | ||
| end | ||
|
|
@@ -439,20 +434,23 @@ const empty_edges = Core.svec() | |
|
|
||
| # inference completed on `me` | ||
| # update the MethodInstance | ||
| function finishinfer!(me::InferenceState, interp::AbstractInterpreter) | ||
| function finishinfer!(me::InferenceState, interp::AbstractInterpreter, cycleid::Int) | ||
| # prepare to run optimization passes on fulltree | ||
| @assert isempty(me.ip) | ||
| # inspect whether our inference had a limited result accuracy, | ||
| # else it may be suitable to cache | ||
| bestguess = me.bestguess = cycle_fix_limited(me.bestguess, me) | ||
| exc_bestguess = me.exc_bestguess = cycle_fix_limited(me.exc_bestguess, me) | ||
| bestguess = me.bestguess = cycle_fix_limited(me.bestguess, me, cycleid) | ||
| exc_bestguess = me.exc_bestguess = cycle_fix_limited(me.exc_bestguess, me, cycleid) | ||
| limited_ret = bestguess isa LimitedAccuracy || exc_bestguess isa LimitedAccuracy | ||
| limited_src = false | ||
| if !limited_ret | ||
| if limited_ret | ||
| @assert me.parentid != 0 | ||
| else | ||
| gt = me.ssavaluetypes | ||
| for j = 1:length(gt) | ||
| gt[j] = gtj = cycle_fix_limited(gt[j], me) | ||
| if gtj isa LimitedAccuracy && me.parentid != 0 | ||
| gt[j] = gtj = cycle_fix_limited(gt[j], me, cycleid) | ||
| if gtj isa LimitedAccuracy | ||
| @assert me.parentid != 0 | ||
| limited_src = true | ||
| break | ||
| end | ||
|
|
@@ -474,6 +472,7 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter) | |
| # a parent may be cached still, but not this intermediate work: | ||
| # we can throw everything else away now | ||
| result.src = nothing | ||
| result.tombstone = true | ||
| me.cache_mode = CACHE_MODE_NULL | ||
| set_inlineable!(me.src, false) | ||
| elseif limited_src | ||
|
|
@@ -714,7 +713,7 @@ function merge_call_chain!(::AbstractInterpreter, parent::InferenceState, child: | |
| add_cycle_backedge!(parent, child) | ||
| parent.cycleid === ancestorid && break | ||
| child = parent | ||
| parent = frame_parent(child)::InferenceState | ||
| parent = cycle_parent(child)::InferenceState | ||
| end | ||
| # ensure that walking the callstack has the same cycleid (DAG) | ||
| for frameid = reverse(ancestorid:length(frames)) | ||
|
|
@@ -750,7 +749,7 @@ end | |
| # returned instead. | ||
| function resolve_call_cycle!(interp::AbstractInterpreter, mi::MethodInstance, parent::AbsIntState) | ||
| # TODO (#48913) implement a proper recursion handling for irinterp: | ||
| # This works currently just because the irinterp code doesn't get used much with | ||
| # This works most of the time currently just because the irinterp code doesn't get used much with | ||
| # `@assume_effects`, so it never sees a cycle normally, but that may not be a sustainable solution. | ||
| parent isa InferenceState || return false | ||
| frames = parent.callstack::Vector{AbsIntState} | ||
|
|
@@ -762,7 +761,7 @@ function resolve_call_cycle!(interp::AbstractInterpreter, mi::MethodInstance, pa | |
| if is_same_frame(interp, mi, frame) | ||
| if uncached | ||
| # our attempt to speculate into a constant call lead to an undesired self-cycle | ||
| # that cannot be converged: poison our call-stack (up to the discovered duplicate frame) | ||
| # that cannot be converged: if necessary, poison our call-stack (up to the discovered duplicate frame) | ||
| # with the limited flag and abort (set return type to Any) now | ||
| poison_callstack!(parent, frame) | ||
| return true | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW: this is the bugfix, the rest is various improvements of various sorts
n.b. the LimitedAccuracy object does not need to contain a Set anymore, since all of the nodes now have a
frameid::Int, which is reliable and strongly ordered, so we could now build the lattice over the frameid value instead, which may be much simpler.