-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
reflect: sort.SliceStable sorts incorrectly on arm64 with less
function created with reflect.MakeFunc
and slice of sufficient length
#57184
Comments
I can repro this using go v1.19.4 on an rk3588 (Rock 5B); the above works on x64 but fails on arm64 with the following:
Running it multiple times doesn't change the output; 260 is always after 239. |
This isn't right. You're comparing |
@randall77 you're absolutely right. that bug slipped in with my minimal example, but it reproduces with a comparison between |
Ok, I can reproduce now. |
I think I see the issue.
I think what is happening is that I can fix this by changing reflect to zero the target register before writing a "thinner" value to it.
Not really a full fix, but demonstrates that the upper bytes of registers are the problem. Really we need to decide whether booleans are full-reg or low-byte-only and enforce that rule throughout. @golang/arm |
I take back the claim that the rewrite rule I showed above is broken. It isn't, it only depends on the low bit. |
I thought I fixed some rules in the past to do the proper extension before comparison, maybe there are still places I missed. I think the compiler generally assume values only have low bits meaningful, so is the register ABI. So I think we want to fix the compiler. The TBNZ shouldn't be a problem, though. TBNZ only checks the zeroth bit, not the hight bits. I'll take a look. |
Something in the lower pass is to blame, on the return value of functions.
after lowering:
Those |
This is probably the bad one:
I think we just need to use some sort of TEST of the low bit instead of CMPW. |
Do we know whether this problem occurs on earlier releases? If so, we should backport. Thanks. |
I believe so, this rule is old. I will double-check. |
Change https://go.dev/cl/456556 mentions this issue: |
Yes, this bug was introduced in 1.18. @gopherbot please open backport issues. This bug causes miscompilation of conditional move instructions. In rare cases (involving reflection, but maybe others) the boolean expression triggering the conditional move is wrong. |
Backport issue(s) opened: #57211 (for 1.18), #57212 (for 1.19). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Change https://go.dev/cl/456437 mentions this issue: |
Similar to CL 456556 but for ppc64 instead of arm64. Change docs about how booleans are stored in registers for ppc64. We now don't promise to keep the upper bits zeroed; they might be junk. To test, I changed the boolean generation instructions (MOVBZload* and ISEL* with boolean type) to OR in 0x100 to the result. all.bash still passed, so I think nothing else is depending on the upper bits of booleans. Update #57184 Change-Id: Ie66f8934a0dafa34d0a8c2a37324868d959a852c Reviewed-on: https://go-review.googlesource.com/c/go/+/456437 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: KAMPANAT THUMWONG (KONG PC) <1992kongpc.kth@gmail.com> Run-TryBot: Archana Ravindar <aravind5@in.ibm.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes (with
gotip
)What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
The sort.SliceStable function fails to sort a slice correctly when using a comparison function created using reflect.MakeFunc. I've only reproduced the issue on Apple silicon and only when the length of the slice being sorted is greater than or equal to 261. The same program produced the correct result on amd64.
Go Playground Link: https://go.dev/play/p/HSez0_sewXy?v=gotip
Note that the bug does not reproduce in the playground, presumably because it runs on amd64, not arm64.
What did you expect to see?
(i.e. no output)
What did you see instead?
(the greatest value, 260, is moved to the wrong index)
The text was updated successfully, but these errors were encountered: