Skip to content

cmd/compile: Go round-trip fails float32->float64->float32 but C works with gcc 7.4.1 and 8.3.1 (-O0, ..., -O3, -Og, -Os) #36399

Closed
@x448

Description

@x448

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

$ go version
go version go1.13.5 linux/amd64

Does this issue reproduce with the latest release?

yes

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

linux/amd64

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/x448/.cache/go-build"
GOENV="/home/x448/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/x448/gocode1.13"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/x448/go1.13"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/x448/go1.13/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/x448/gocode1.13/mysrc/cbor-go/float16/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build276233946=/tmp/go-build -gno-record-gcc-switches"

What did you do?

  • Cast float64 to float32 with sNaN value (turns into qNaN).
  • Cast float32 to float64 with sNaN value (keeps sNaN).

More at fxamacker/cbor#93

Bug reproducer:
https://play.golang.org/p/kzLI9A07wRv

package main

import (
	"fmt"
	"math"
)

func main() {
	// init float32 with sNaN
	const u32 = uint32(0x7f800001) // IEEE 754 binary32 representation of sNaN
	f32 := math.Float32frombits(u32)

	// cast float32 to float64
	f64 := float64(f32)
	u64 := math.Float64bits(f64)

	// test passes
	sbit64 := uint64(0x8000000000000) // the signalling/quiet bit for IEEE 754 binary64
	if (u64 & sbit64) != 0 {
		fmt.Printf("Go/Golang lost bit when casting float32 to float64, forced sNaN to qNaN\n")
	}

	f32bis := float32(f64)
	u32bis := math.Float32bits(f32bis)
	diff := u32bis ^ u32

	// test fails
	if diff != 0 {
		fmt.Printf("Go/Golang lost bit when casting float64 to float32, forced sNaN to qNaN\n")
		fmt.Printf("u32=0x%08x, u32bis=0x%08x, diff=0x%08x\n", u32, u32bis, diff)
	}

}

What did you expect to see?

Consistent behavior when casting from float64 to float32 and vice versa regarding the NaN signalling bit (quiet bit).

What did you see instead?

Inconsistent behavior when casting float with NaN signalling bit.

Go/Golang lost bit when casting float64 to float32, forced sNaN to qNaN
u32=0x7f800001, u32bis=0x7fc00001, diff=0x00400000

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions