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

abstract_apply: Don't drop effects of iterate'd calls #47846

Merged
merged 2 commits into from
Dec 9, 2022
Merged

Conversation

Keno
Copy link
Member

@Keno Keno commented Dec 9, 2022

We were accidentally dropping the effects of calls from iterate calls performed during abstract_iteration. This allowed calls that were not actually eligible for (semi-)concrete evaluation to go through that path anyway. This could cause incorrect results (see test), though it was usually fine, since iterate call tend to not have side effects. It was noticed however in #47688, because it forced irinterp down a path that was not meant to be reachable (resulting in a TODO error message). For good measure, let's also address this todo (since it is reachable by external absint if they want), but the missing effect propagation was the more serious bug here.

We were accidentally dropping the effects of calls from
`iterate` calls performed during abstract_iteration. This
allowed calls that were not actually eligible for (semi-)concrete
evaluation to go through that path anyway. This could cause
incorrect results (see test), though it was usually fine, since
iterate call tend to not have side effects. It was noticed
however in #47688, because it forced irinterp down a path
that was not meant to be reachable (resulting in a TODO
error message). For good measure, let's also address this
todo (since it is reachable by external absint if they want),
but the missing effect propagation was the more serious bug
here.
@Keno Keno requested a review from aviatesk December 9, 2022 04:40
@@ -114,6 +114,7 @@ Each (abstract) call to `iterate`, corresponds to one entry in `ainfo.each::Vect
"""
struct AbstractIterationInfo
each::Vector{CallMeta}
complete::Bool
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change is necessary for this PR or it is a separate fix on the inlining algorithm?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds all the calls into the .each field (partly to look at the affects, but mostly for Cthulhu's benefit). Previously the inlining algorithm used the presence or absence of this info to determine whether or not we had the complete set of iteration items. Now we need to keep track of it separately.

@@ -1482,7 +1492,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
# ... but cannot terminate
if !may_have_terminated
# ... and cannot have terminated prior to this loop
return Any[Bottom], nothing
return AbstractIterationResult(Any[Bottom], AbstractIterationInfo(calls, false), EFFECTS_UNKNOWN′)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EFFECTS_THROWS seems to be more consistent with the change on L1465 above?

Suggested change
return AbstractIterationResult(Any[Bottom], AbstractIterationInfo(calls, false), EFFECTS_UNKNOWN′)
return AbstractIterationResult(Any[Bottom], AbstractIterationInfo(calls, false), EFFECTS_THROWS)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, we have proven that we cannot terminate, but I'm not sure we've proven that the state has fixpointed, meaning that our call effects cover the largest possible effect set the call could produce during its execution.

Comment on lines +1559 to +1560
effects = merge_effects(effects, ai_effects)
if info !== nothing
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
effects = merge_effects(effects, ai_effects)
if info !== nothing
# merge effects of the `iterate` call
effects = merge_effects(effects, ai_effects)
# merge effects of call(s) with the iterated arguments
if info !== nothing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really the effects of the iterate call. It's more the effects of imprecision of the iterate call. The info.each, are all methods of iterate.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I understand.

test/compiler/inference.jl Outdated Show resolved Hide resolved
Co-authored-by: Shuhei Kadowaki <[email protected]>
Comment on lines +1559 to +1560
effects = merge_effects(effects, ai_effects)
if info !== nothing
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I understand.

@aviatesk
Copy link
Sponsor Member

aviatesk commented Dec 9, 2022

@nanosoldier runbenchmarks("inference", vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - no performance regressions were detected. A full report can be found here.

@aviatesk aviatesk merged commit 2a0d58a into master Dec 9, 2022
@aviatesk aviatesk deleted the kf/47688 branch December 9, 2022 08:54
@KristofferC KristofferC added the backport 1.9 Change should be backported to release-1.9 label Mar 6, 2023
KristofferC pushed a commit that referenced this pull request Mar 7, 2023
We were accidentally dropping the effects of calls from
`iterate` calls performed during abstract_iteration. This
allowed calls that were not actually eligible for (semi-)concrete
evaluation to go through that path anyway. This could cause
incorrect results (see test), though it was usually fine, since
iterate call tend to not have side effects. It was noticed
however in #47688, because it forced irinterp down a path
that was not meant to be reachable (resulting in a TODO
error message). For good measure, let's also address this
todo (since it is reachable by external absint if they want),
but the missing effect propagation was the more serious bug
here.

(cherry picked from commit 2a0d58a)
@KristofferC KristofferC mentioned this pull request Mar 7, 2023
52 tasks
@KristofferC KristofferC removed the backport 1.9 Change should be backported to release-1.9 label Mar 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants