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

cmd/compile: investigate test/fixedbugs/issue20250.go with GOEXPERIMENT=unified #54402

Open
mdempsky opened this issue Aug 11, 2022 · 7 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@mdempsky
Copy link
Member

mdempsky commented Aug 11, 2022

test/fixedbugs/issue20250.go contains this ERROR expectation:

func() { // ERROR "live at entry to f.func1: a &e"

This works fine currently on all trybots. It also works fine currently with GOEXPERIMENT=unified on most trybots.

But with GOEXPERIMENT=unified and the linux-arm and js-wasm trybots, we instead report:

live at entry to f.func1: &e a

on that line. Note: &e a instead of a &e.

Semantically, this doesn't matter. But it's still odd.

Notably, unified IR is generating identical IR for linux-amd64, linux-arm, and js-wasm:

diff -u <(GOEXPERIMENT=unified GOOS=linux GOARCH=amd64 go tool compile -l -W=2 issue20250.go) <(GOEXPERIMENT=unified GOOS=linux GOARCH=arm go tool compile -l -W=2 issue20250.go)
diff -u <(GOEXPERIMENT=unified GOOS=linux GOARCH=amd64 go tool compile -l -W=2 issue20250.go) <(GOEXPERIMENT=unified GOOS=js GOARCH=wasm go tool compile -l -W=2 issue20250.go)

so it's odd linux-arm and js-wasm are different.

Compiling for all targets listed by go tool dist list, it looks like it's dependent upon GOARCH:

  • Team a &e: amd64, arm64, ppc64, ppc64le, riscv64
  • Team '&e a': 386, arm, loong64, mips64, mips64le, s390x, wasm

I thought maybe this is regabi vs no-regabi architectures, but adding noregabi to GOEXPERIMENT only causes riscv64 to switch sides. The distinction between (e.g.,) amd64 and arm remains.

I plan to just relax the test expectations to allow either a &e or &e a, because I don't think it's a real issue and its blocking enabling GOEXPERIMENT=unified by default. But filing an issue to remember to look into this further into the dev cycle.

@mdempsky mdempsky added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 11, 2022
@mdempsky mdempsky added this to the Go1.20 milestone Aug 11, 2022
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Aug 11, 2022
@mdempsky
Copy link
Member Author

mdempsky commented Aug 11, 2022

I thought maybe this is regabi vs no-regabi architectures, but adding noregabi to GOEXPERIMENT only causes riscv64 to switch sides. The distinction between (e.g.,) amd64 and arm remains.

Ohh, riscv64 is a regabi-supported architecture, but {amd64, arm64, ppc64, ppc64le} are regabi-always architectures:

// regabiSupported is set to true on platforms where register ABI is
// supported and enabled by default.
// regabiAlwaysOn is set to true on platforms where register ABI is
// always on.
var regabiSupported, regabiAlwaysOn bool
switch goarch {
case "amd64", "arm64", "ppc64le", "ppc64":
regabiAlwaysOn = true
regabiSupported = true
case "riscv64":
regabiSupported = true
}

So that explains why GOEXPERIMENT=noregabi only affects riscv64.

It's still a bit puzzling that the specific combination unified && !regabi changes the order, but it at least supports the hypothesis that this is just a backend optimization question.

Notably, the test does involve OCONVIFACE, and unified IR now adds explicit RTTI operands to these nodes upfront. So that plausibly influences backend code generation. And there's the generated call to runtime.convT, which could be affected by regabi.

@gopherbot
Copy link

gopherbot commented Aug 11, 2022

Change https://go.dev/cl/422975 mentions this issue: test: relax fixedbugs/issue20250.go expectations

@cuonglm
Copy link
Member

cuonglm commented Aug 11, 2022

@mdempsky The backend sort the stack variables for stable stack layout. When register ABI on, &e is passed via register, so it's after a in stack layout.

See cmd/compile/internal/ssagen/pgen.go:byStackVar.

@mdempsky
Copy link
Member Author

mdempsky commented Aug 11, 2022

@cuonglm Thanks. But why does that sorting only change the output for GOEXPERIMENT=unified? Why do we always print the variables in the same order for GOEXPERIMENT=nounified?

@cuonglm
Copy link
Member

cuonglm commented Aug 11, 2022

@cuonglm Thanks. But why does that sorting only change the output for GOEXPERIMENT=unified? Why do we always print the variables in the same order for GOEXPERIMENT=nounified?

Seems related to how we record fn.ClosureVars. For unified, we record them as [e a], but [a e] for non-unified. Thus in directClosureCall, those closure variables are populated to fn.Dcl as [&e a]/[a &e] for unified/non-unified.

@mdempsky
Copy link
Member Author

mdempsky commented Aug 11, 2022

Oh right, because we removed unified's quirks mode and then changed the order that we visit assignment statements (9e5c968), which in turn affects the order that we capture variables.

I remembered previously being careful that unified IR generated fn.ClosureVars in the same order. But it makes sense that it would sometimes be different now, including in this test case.

Okay, that explains GOEXPERIMENT=unified's involvement here. Thanks.

The last minor question then is why GOEXPERIMENT=nounified always prints in the same order, on both regabi and noregabi architectures?

gopherbot pushed a commit that referenced this issue Aug 11, 2022
With GOEXPERIMENT=unified, the order variables are printed in "live at
entry to f.func1" is sensitive to whether regabi is enabled for some
reason. The order shouldn't matter to correctness, but it is odd.

For now, this CL just relaxes the test expectation order to unblock
enabling GOEXPERIMENT=unified by default. I've filed #54402 to
investigate further to confirm this a concern.

Updates #54402.

Change-Id: Iddfbb12c6cf7cc17b2aec8102b33761abd5f93ad
Reviewed-on: https://go-review.googlesource.com/c/go/+/422975
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
@cuonglm
Copy link
Member

cuonglm commented Aug 12, 2022

The last minor question then is why GOEXPERIMENT=nounified always prints in the same order, on both regabi and noregabi architectures?

It's a direct closure call, so it isn't marked as need context register. Thus closure variables aren't passed via registers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
Status: All-But-Submitted
Development

No branches or pull requests

4 participants
@mdempsky @cuonglm @gopherbot and others