-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
cmd/compile: internal compiler error: 'F': func F, startMem[b1] has different values #61992
Comments
Change https://go.dev/cl/519115 mentions this issue: |
git bisect points to https://go-review.googlesource.com/c/go/+/492895 |
This looks like a bug in expand calls. It is confused about which memory to use and gets the memory chain in a bad state. The CL mentioned just notices that bug. |
This works fine in the cleaned-up expand calls. https://go.dev/cl/507295 |
That's good for tip, but what can we reasonably backport to 1.21? |
I've been poking at the old code, and it is horrible, and the expand calls cleanup cherry-picks cleanly onto 1.21. |
I'm wondering if it's more reasonable to backport a fix for the expand calls pass, because this check is correct and valuable, and it has also checked out another bug before, see #59973. |
The rough cause is that arguments are marshalled "blindly" in argument order, and those that must go on stack are stored, which affects memory. If args (or results) occur in a different blocks that constrains their order; so would a data flow between two of the arguments (e.g., "P" and "pointerToP"). I think a better "fix" is to (1) iterate in block order (2) do all the not-memory args first (3) record memory replacements in a map. I'm a little worried about complex control leading to calls (and Phi functions), but I think that data flow dependences are okay because pointers args require a load-then-store, and the loads will just float early (not be threaded onto the new mem). This would also require additional load-updating in mem uses in subsequent blocks. I think this will (usually?) be limited to the call. This should also cause problems with return values. The refactored code might still have this problem (potentially) or it may dodge it by handing the memory re-threading to the rewrite cleanup pass; if it does have this problem for other inputs, it is less complicated and easier to understand. |
Bonus fun, it's a closure call, by default the first parameter is ignored by expand calls but in this case it is a load and thus retains a pointer to the "old" memory. |
I'm not sure I understand why we need to put the arg marshaling anywhere but the block of the call itself. |
The extra block appears because of a check for an illegal shift value. The minimum-touch fixes moves the dereference rewrite to always in the block containing the dereference (in bug-world, it depends on the size of the dereference) and also does an update to the mem of the closure parameter. That is my current understanding, at least. |
I tried moving the arg marshalling into the call block (it was not there) and that seems to work, and that is probably the best fix. That also looks like what the rewritten expand_calls does. I am however now a little curious about one of the changes that I tried, which was to do all the memory args first, under the assumption that having more registers free to accomplish memory movement is a good thing. But that is not this bug. |
Change https://go.dev/cl/519276 mentions this issue: |
@gopherbot please open the backport tracking issues. This is a use-blocking compiler bug. |
Backport issue(s) opened: #62056 (for 1.20), #62057 (for 1.21). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
@Nasfame It is a good question whether we need a backport to 1.20. It is not needed for this issue, but we probably want to fix the store chain even if there's no subsequent pass that notices. Because maybe there is a pass that notices, silently generating incorrect code. |
Change https://go.dev/cl/520058 mentions this issue: |
Change https://go.dev/cl/520059 mentions this issue: |
@randall77 @dr2chase There are currently backport issues for both 1.20 and 1.21 which will be approved pending the decision on whether we need a backport for both 1.20 and 1.21. Do we need both backports or just a single backport? |
I think we need to backport to both 1.21 and 1.20, see my comment above. |
…shalling into call block For aggregate-typed arguments passed to a call, expandCalls decomposed them into parts in the same block where the value was created. This is not necessarily the call block, and in the case where stores are involved, can change the memory leaving that block, and getting that right is problematic. Instead, do all the expanding in the same block as the call, which avoids the problems of (1) not being able to reorder loads/stores across a block boundary to conform to memory order and (2) (incorrectly, not) exposing the new memory to consumers in other blocks. Putting it all in the same block as the call allows reordering, and the call creates its own new memory (which is already dealt with correctly). Fixes #62057. Updates #61992. Change-Id: Icc7918f0d2dd3c480cc7f496cdcd78edeca7f297 Reviewed-on: https://go-review.googlesource.com/c/go/+/519276 Reviewed-by: Keith Randall <khr@google.com> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> (cherry picked from commit e72ecc6) Reviewed-on: https://go-review.googlesource.com/c/go/+/520058
…shalling into call block For aggregate-typed arguments passed to a call, expandCalls decomposed them into parts in the same block where the value was created. This is not necessarily the call block, and in the case where stores are involved, can change the memory leaving that block, and getting that right is problematic. Instead, do all the expanding in the same block as the call, which avoids the problems of (1) not being able to reorder loads/stores across a block boundary to conform to memory order and (2) (incorrectly, not) exposing the new memory to consumers in other blocks. Putting it all in the same block as the call allows reordering, and the call creates its own new memory (which is already dealt with correctly). Fixes #62056. Updates #61992. Change-Id: Icc7918f0d2dd3c480cc7f496cdcd78edeca7f297 Reviewed-on: https://go-review.googlesource.com/c/go/+/519276 Reviewed-by: Keith Randall <khr@google.com> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> (cherry picked from commit e72ecc6) Reviewed-on: https://go-review.googlesource.com/c/go/+/520059
Doesn't crash on go1.20.7
cc @golang/compiler
The text was updated successfully, but these errors were encountered: