Skip to content

cmd/compile: bad small array comparisons on amd64 since go1.9 #23719

Closed
@mjl-

Description

@mjl-

What version of Go are you using (go version)?

$ go1.10rc1 version
go version go1.10rc1 darwin/amd64
$ go1.9.3 version
go version go1.9.3 darwin/amd64
$ go1.9 version
go version go1.9 darwin/amd64
$ go1.8.6 version
go version go1.8.6 darwin/amd64

Does this issue reproduce with the latest release?

yes, and tip

What operating system and processor architecture are you using (go env)?

$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/mjl/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/c6/wjpsl76s11l9cn3rv7lzjvq00000gn/T/go-build257631275=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

https://play.golang.org/p/JSCb-q6cHiE

compare an [2]int32 array.
go for amd64 incorrectly says they are equal, even if the elements at indices 1 don't match.
longer/shorter arrays do compare properly.
[2]int64 does compare correctly.
this only seems broken on amd64, since go1.9.
compiling with GOARCH=386 gives correct behaviour, same for arm.

more elaborate program with more cases:

$ cat test.go
package main

import (
	"fmt"
)

func main() {
	// the first one seems wrong, should not be equal
	func() {
		v1 := [2]int32{-102,-102}
		v2 := [2]int32{-102,1126}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()

	func() {
		v1 := [2]int64{-102,-102}
		v2 := [2]int64{-102,1126}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()

	func() {
		v1 := [2]int32{-102, -102}
		v2 := [2]int32{1126, -102}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()

	func() {
		v1 := [3]int32{-102,-102, 1}
		v2 := [3]int32{-102,1126, 2}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()

	func() {
		v1 := [3]int32{-102,-102, 1}
		v2 := [3]int32{-102,-102, 2}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()

	func() {
		v1 := [1]int32{-102}
		v2 := [1]int32{-102}
		fmt.Printf("%#v == %#v is %v\n", v1, v2, v1 == v2)
	}()
}
$ go1.8.6 run test.go
[2]int32{-102, -102} == [2]int32{-102, 1126} is false

$ go1.9 run test.go 
[2]int32{-102, -102} == [2]int32{-102, 1126} is true

$ go1.9.3 run test.go
[2]int32{-102, -102} == [2]int32{-102, 1126} is true

$ go1.10rc1 run test.go
[2]int32{-102, -102} == [2]int32{-102, 1126} is true

$ /Users/mjl/src/go/bin/go version
go version devel +fd7331a821 Tue Feb 6 05:00:01 2018 +0000 darwin/amd64
$ /Users/mjl/src/go/bin/go run test.go 
[2]int32{-102, -102} == [2]int32{-102, 1126} is true


$ GOARCH=386 go1.10rc1 build
$ ./intarraybug 
[2]int32{-102, -102} == [2]int32{-102, 1126} is false

pi@raspberrypi$ go version
go version go1.9.2 linux/arm
pi@raspberrypi$ go run test.go 
[2]int32{-102, -102} == [2]int32{-102, 1126} is false

What did you expect to see?

[2]int32{-102, -102} == [2]int32{-102, 1126} is false

What did you see instead?

[2]int32{-102, -102} == [2]int32{-102, 1126} is true

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions