-
Notifications
You must be signed in to change notification settings - Fork 453
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
Fix bug where a ref assignment is moved ouside a conditional #7176
Conversation
Fixes #7170 Assignment of a ref, or other record with a single mutable field, is compiled to simple variable assignment. This triggers an incorrect optimisation that moves identical assignments in the true and false branches of a conditional above if they are identical and the guard has no side effects. Added a check that if the assigments to be moved are to variable, that variable must not occur free in the guard of the conditional.
7069899
to
0b80486
Compare
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.
Nice work! You'll probably need to rebase though as I just merged #7174, sorry!
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.
Nicely tracked down!
The optimisation is still incorrect. In fact it would be only sound under very unlikely circumstances. |
if (x.TAG === "A") { | ||
v = 1; |
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.
This is the only case where the optimisation was kicking.
It's pretty unlikely to fire to begin with, and when it fires the cases where one can legitimately move the common instruction up are pretty rare.
In this case, it would be OK because assigning to v
does not change the value of x.TAG
, because the two values cannot be aliases.
Fixes #7170
There is an optimisation of this form:
is transformed to:
The current check is that
guard
does not have side effects. (Also, this same optimisation does not apply toguard ? {c; c1} : {c; c2}
which is what the vast majority of cases of this form are compiled to -- that's why the original issue is not so easy to repro.However, the check for side effects is not enough. What you want to know is: executing
c
does not change the truth value ofguard
, which is a form of non-interference, much harder to establish.