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: incorrect left shift result on s390x #72018

Closed
RaduBerinde opened this issue Feb 28, 2025 · 15 comments
Closed

cmd/compile: incorrect left shift result on s390x #72018

RaduBerinde opened this issue Feb 28, 2025 · 15 comments
Labels
arch-s390x Issues solely affecting the s390x architecture. BugReport Issues describing a possible bug in the Go implementation. 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

@RaduBerinde
Copy link
Contributor

Go version

go1.23.6 linux/s390x

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='s390x'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='s390x'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_s390x'
GOVCS=''
GOVERSION='go1.23.6'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GCCGO='gccgo'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='0'
GOMOD='/swiss/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -march=z196 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build487227182=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Ran this code in a test:

	v := (uint32(1) << bits.Len32(capacity-1))
	fmt.Printf("capacity: %d  len32: %d  v: %d\n", capacity, bits.Len32(capacity-1), v)

I ran it on an amd64 linux machine using qemu (it is possible but unlikely that it is a qemu issue):

docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run --rm --privileged \
  -v "${{ github.workspace }}:/swiss" \
  multiarch/ubuntu-core:s390x-focal \
  bash -c "
      uname -a &&
      lscpu | grep Endian &&
      apt-get update &&
      apt-get install -y wget &&
      wget -q https://go.dev/dl/go1.23.6.linux-s390x.tar.gz &&
      tar xzf go1.23.6.linux-s390x.tar.gz -C /usr/local &&
      export PATH="$PATH:/usr/local/go/bin" &&
      cd /swiss &&
      go version &&
      go env &&
      go test -v ./...
  "

What did you see happen?

Prints out:

capacity: 4294967295  len32: 32  v: 1

What did you expect to see?

So (1 << 32) comes out to 1. I expected to see 0. The spec is clear about this: "Shifts behave as if the left operand is shifted n times by 1 for a shift count of n."

@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Feb 28, 2025
@seankhliao seankhliao changed the title compiler: incorrect left shift result on s390x cmd/compile: incorrect left shift result on s390x Feb 28, 2025
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Feb 28, 2025
@seankhliao seankhliao added the arch-s390x Issues solely affecting the s390x architecture. label Feb 28, 2025
@randall77
Copy link
Contributor

I think the bug is here:

// result = shift >= 64 ? 0 : arg << shift
(Lsh(64|32|16|8)x64 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
(Lsh(64|32|16|8)x32 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
(Lsh(64|32|16|8)x16 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
(Lsh(64|32|16|8)x8 <t> x y) => (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))

We're comparing against 64 all the time, instead of the width of the shift.

@RaduBerinde
Copy link
Contributor Author

Same result on go1.24.0.

@ianlancetaylor
Copy link
Member

CC @golang/s390x

@srinivas-pokala
Copy link
Contributor

@RaduBerinde thanks for reporting the issue. I tried reproducing the same on linux/s390x with go1.23.6 & go1.24.0 versions but I could not able to reproduce it.

root@t83lp35:~/go_compiler/dev/test/dev # cat main.go
package main

import (
        "fmt"
        "math/bits"
)

func main() {
        capacity := uint32(0xFFFFFFFF)
        v := (uint32(1) << bits.Len32(capacity-1))
        fmt.Printf("capacity: %d  len32: %d  v: %d\n", capacity, bits.Len32(capacity-1), v)
}

root@t83lp35:~/go_compiler/dev/test/dev # go1.23.6 run main.go
capacity: 4294967295  len32: 32  v: 0
root@t83lp35:~/go_compiler/dev/test/dev # go1.24.0 run main.go
capacity: 4294967295  len32: 32  v: 0

@RaduBerinde Could you please share exact test you ran?

@randall77
Copy link
Contributor

I think capacity needs to not constant fold. Pass the 0xffffffff into a //go:noescape function or read it from a global.

@RaduBerinde
Copy link
Contributor Author

Yes, it's probably because of constant folding. It was part of a bigger project, it would be unwieldy to reproduce the exact code. Just try this:

package main

import "fmt"

func shift(n int) uint32 {
	return uint32(1) << n
}

func main() {
	for i := 0; i < 40; i++ {
		fmt.Printf("%d: %d\n", i, shift(i))
	}
}
28: 268435456
29: 536870912
30: 1073741824
31: 2147483648
32: 1
33: 2
34: 4
35: 8
36: 16
37: 32
38: 64
39: 128

@RaduBerinde
Copy link
Contributor Author

BTW something like the above should be a basic test for shifts on all platforms.

@randall77
Copy link
Contributor

Yes, I am surprised we don't already have a test for this.

@prattmic prattmic added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 28, 2025
@prattmic prattmic added this to the Backlog milestone Feb 28, 2025
@RaduBerinde
Copy link
Contributor Author

I noticed this was added to Backlog. I'd like to make a kind appeal to consider prioritizing this as it can lead to failures that are hard to debug. From Keith's comment, it sounds like a simple fix.

@randall77
Copy link
Contributor

I'll let the s390x folks prioritize this.

@srinivas-pokala
Copy link
Contributor

@RaduBerinde multiarch/qemu-user-static is unfortunately very old and a lot has been fixed. This is qemu issue, fix for this issue is target/s390x: Fix shifting 32-bit values for more than 31 bits which already fixed in qemu v7.0.0 . multiarch/qemu-user-static is way little old, it needs to pick the latest qemu version. Can you try replicating the issue with latest qemu version available?

@RaduBerinde
Copy link
Contributor Author

@srinivas-pokala thank you so much for finding that! I will try to figure out how to use a more recent version. I will close the issue once I confirm.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/654316 mentions this issue: cmd/compile: add tests for too-large shift amounts

@RaduBerinde
Copy link
Contributor Author

I confirmed that it works fine with a more recent qemu:

s390x
0: 1
1: 2
2: 4
3: 8
4: 16
5: 32
6: 64
7: 128
8: 256
9: 512
10: 1024
11: 2048
12: 4096
13: 8192
14: 16384
15: 32768
16: 65536
17: 131072
18: 262144
19: 524288
20: 1048576
21: 2097152
22: 4194304
23: 8388608
24: 16777216
25: 33554432
26: 67108864
27: 134217728
28: 268435456
29: 536870912
30: 1073741824
31: 2147483648
32: 0
33: 0
34: 0
35: 0
36: 0
37: 0
38: 0
39: 0

gopherbot pushed a commit that referenced this issue Mar 5, 2025
Update #72018

Change-Id: I3188019658c37da3c31f06472023b39e13170ebf
Reviewed-on: https://go-review.googlesource.com/c/go/+/654316
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-s390x Issues solely affecting the s390x architecture. BugReport Issues describing a possible bug in the Go implementation. 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
None yet
Development

No branches or pull requests

8 participants