-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: OpInlMark can get removed by SSA dead code elimination, resulting in invalid inlining trees #54625
Comments
Note the The consequence of this is that when unwinding the stack at the MOVQ instruction, we'll find the |
Interestingly, that's the only function that ends up with a corrupt inline tree with GOEXPERIMENT=nounified that I could find. |
Here's a minimized, standalone repro of the nounified failure:
Compiled with
Again, note the bad |
Notably, the minimized test case repros with unified IR too, whereas the original net/http code did not. |
Change https://go.dev/cl/425395 mentions this issue: |
Looking at GOSSAFUNC=readTransfer output, the issue with the corrupt inline tree above is that the OpInlMark for the inlined This seems to be an issue with the "expand calls" phase. The inserted OpArgIntReg value seems to be taking the position of its first use, rather than the position of the original OpArg. /cc @dr2chase |
@mdempsky seems related to https://go-review.googlesource.com/c/go/+/309649 |
@cuonglm Thanks, that seems plausible. Further minimized repro:
|
Change https://go.dev/cl/425415 mentions this issue: |
CL 425415 adds a hacky check that we find valid PC offsets for all of the inline tree entries we emit. In particular, it reports the miscompilation of the test case above. |
With this patch, above test case pass,
But still fails for some tests:
Sounds like we still mess the pos somewhere else. |
When inlining function calls, we rewrite the position information on all of the nodes to keep track of the inlining context. This is necessary so that at runtime, we can synthesize additional stack frames so that the inlining is transparent to the user. However, for function literals, we *don't* want to apply this rewriting to the underlying function. Because within the function literal (when it's not itself inlined), the inlining context (if any) will have already be available at the caller PC instead. Unified IR was already getting this right in the case of user-written statements within the function literal, which is what the unit test for #46234 tested. However, it was still using inline-adjusted positions for the function declaration and its parameters, which occasionally end up getting used for generated code (e.g., loading captured values from the closure record). I've manually verified that this fixes the hang in https://go.dev/play/p/avQ0qgRzOgt, and spot-checked the -d=pctab=pctoinline output for kube-apiserver and kubelet and they seem better. However, I'm still working on a more robust test for this (hence "Updates" not "Fixes") and internal assertions to verify that we're emitting correct inline trees. In particular, there are still other cases (even in the non-unified frontend) where we're producing corrupt (but at least acyclic) inline trees. Updates #54625. Change-Id: Iacfd2e1eb06ae8dc299c0679f377461d3d46c15a Reviewed-on: https://go-review.googlesource.com/c/go/+/425395 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Change https://go.dev/cl/425785 mentions this issue: |
When spilling arg to stack or register, if it's a newly created value, the arg position should be preserved. Otherwise, we may end up using position information from deadcode lines. This fixes the minimized test case in #54625 by mdempsky@, and make building std successfully. However, the inline trees for these tests still be corrupted: - fixedbugs/issue53982.go - typeparam/issue47775.go - typeparam/issue47775b.go - typeparam/issue49432.go We probably still mess up the inline position somewhere else. Updates #54625 Change-Id: I0d87e26b9ab451b85b6e79787da74a2b79a16209 Reviewed-on: https://go-review.googlesource.com/c/go/+/425785 Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
When inlining function calls, we rewrite the position information on all of the nodes to keep track of the inlining context. This is necessary so that at runtime, we can synthesize additional stack frames so that the inlining is transparent to the user. However, for function literals, we *don't* want to apply this rewriting to the underlying function. Because within the function literal (when it's not itself inlined), the inlining context (if any) will have already be available at the caller PC instead. Unified IR was already getting this right in the case of user-written statements within the function literal, which is what the unit test for golang#46234 tested. However, it was still using inline-adjusted positions for the function declaration and its parameters, which occasionally end up getting used for generated code (e.g., loading captured values from the closure record). I've manually verified that this fixes the hang in https://go.dev/play/p/avQ0qgRzOgt, and spot-checked the -d=pctab=pctoinline output for kube-apiserver and kubelet and they seem better. However, I'm still working on a more robust test for this (hence "Updates" not "Fixes") and internal assertions to verify that we're emitting correct inline trees. In particular, there are still other cases (even in the non-unified frontend) where we're producing corrupt (but at least acyclic) inline trees. Updates golang#54625. Change-Id: Iacfd2e1eb06ae8dc299c0679f377461d3d46c15a Reviewed-on: https://go-review.googlesource.com/c/go/+/425395 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
What's the status of this? I see the CL was merged. Should we rebase and re-trybot CL 425415 to see if it reports any other failures? |
See my comment in #54625 (comment) Those tests still failed with current tip. |
Done. Still reporting failures: https://storage.googleapis.com/go-build-log/eeb08b68/linux-amd64_bc78596a.log Retitled to better reflect the current understanding of the issue, and bumping to 1.21. |
Change https://go.dev/cl/468415 mentions this issue: |
@cuonglm points out that CL 468415 addresses the failures reported by CL 425415. So I'll look into polishing that CL up to mail out for inclusion, at least during the dev cycle to help smoke out more failure cases. I think the underlying issue around ssa's deadcode elimination pass and OpInlMarks is still applicable though. |
When inlining functions that contain function literals, we need to be careful about position information. The OCLOSURE node should use the inline-adjusted position, but the ODCLFUNC and its body should use the original positions. However, the same problem can arise with certain generic constructs, which require the compiler to synthesize function literals to insert dictionary arguments. go.dev/cl/425395 fixed the issue with user-written function literals in a somewhat kludgy way; this CL extends the same solution to synthetic function literals. This is all quite subtle and the solutions aren't terribly robust, so longer term it's probably desirable to revisit how we track inlining context for positions. But for now, this seems to be the least bad solution, esp. for backporting to 1.20. Updates #54625. Fixes #58513. Change-Id: Icc43a70dbb11a0e665cbc9e6a64ef274ad8253d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/468415 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Than McIntosh <thanm@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Change https://go.dev/cl/471677 mentions this issue: |
… for synthetic closures When inlining functions that contain function literals, we need to be careful about position information. The OCLOSURE node should use the inline-adjusted position, but the ODCLFUNC and its body should use the original positions. However, the same problem can arise with certain generic constructs, which require the compiler to synthesize function literals to insert dictionary arguments. go.dev/cl/425395 fixed the issue with user-written function literals in a somewhat kludgy way; this CL extends the same solution to synthetic function literals. This is all quite subtle and the solutions aren't terribly robust, so longer term it's probably desirable to revisit how we track inlining context for positions. But for now, this seems to be the least bad solution, esp. for backporting to 1.20. Updates #54625. Fixes #58531. Change-Id: Icc43a70dbb11a0e665cbc9e6a64ef274ad8253d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/468415 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Than McIntosh <thanm@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> (cherry picked from commit 873c14cec730ee278848f7cc58d2b4d89ab52288) Reviewed-on: https://go-review.googlesource.com/c/go/+/471677 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
… for synthetic closures When inlining functions that contain function literals, we need to be careful about position information. The OCLOSURE node should use the inline-adjusted position, but the ODCLFUNC and its body should use the original positions. However, the same problem can arise with certain generic constructs, which require the compiler to synthesize function literals to insert dictionary arguments. go.dev/cl/425395 fixed the issue with user-written function literals in a somewhat kludgy way; this CL extends the same solution to synthetic function literals. This is all quite subtle and the solutions aren't terribly robust, so longer term it's probably desirable to revisit how we track inlining context for positions. But for now, this seems to be the least bad solution, esp. for backporting to 1.20. Updates golang#54625. Fixes golang#58531. Change-Id: Icc43a70dbb11a0e665cbc9e6a64ef274ad8253d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/468415 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Than McIntosh <thanm@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> (cherry picked from commit 873c14cec730ee278848f7cc58d2b4d89ab52288) Reviewed-on: https://go-review.googlesource.com/c/go/+/471677 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Hey @mdempsky, doing a sweep of the Go 1.21 milestone. Any updates here? Pushing to Backlog for now, feel free to move it to the Go 1.22 milestone if you plan to work on it. Thanks! |
See discussion at #46234.
The immediate issue is that https://go.dev/play/p/OikFLBmKguY?v=gotip causes the loop at
go/src/runtime/traceback.go
Line 362 in 7f632f7
The bigger issue is that we're generating trees like this for kube-apiserver, and this is presumably the root cause of #54593.
The text was updated successfully, but these errors were encountered: