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: doesn't optimize float comparison to MINSD #72831

Open
dominikh opened this issue Mar 12, 2025 · 9 comments
Open

cmd/compile: doesn't optimize float comparison to MINSD #72831

dominikh opened this issue Mar 12, 2025 · 9 comments
Labels
BugReport Issues describing a possible bug in the Go implementation. compiler/runtime Issues related to the Go compiler and/or runtime.

Comments

@dominikh
Copy link
Member

dominikh commented Mar 12, 2025

Go version

go version go1.24.1 linux/amd64

Output of go env in your module/workspace:

-

What did you do?

go build -gcflags=-S

func mymin(a, b float64) float64 {
	if a < b {
		return a
	} else {
		return b
	}
}

What did you see happen?

0x0000 00000 (bar.go:4)      UCOMISD X0, X1
0x0004 00004 (bar.go:4)      JLS     7
0x0006 00006 (bar.go:5)      RET
0x0007 00007 (bar.go:7)      MOVUPS  X1, X0
0x000a 00010 (bar.go:7)      RET

What did you expect to see?

I think

MINSD X1, X0
RET

but maybe

MINSD X0, X1
MOVUPS X1, X0
RET

AT&T argument order has me thoroughly confused at times.

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Mar 12, 2025
@randall77
Copy link
Contributor

We have to be very careful about NaNs and +/-0. I don't think MINSD does the same thing that your code does for some of those cases.
It can be tricky, see

// Floating-point min is tricky, as the hardware op isn't right for various special

@dominikh
Copy link
Member Author

I forgot about negative zero. I think you're right. mymin(+0.0, -0.0) and mymin(-0.0, +0.0) both return +0.0, whereas MINSD is documented to

If the values being compared are both 0.0s (of either sign), the value in the second source operand is returned

Thanks!

@dominikh dominikh closed this as not planned Won't fix, can't repro, duplicate, stale Mar 13, 2025
@dominikh
Copy link
Member Author

.. Of course the literal -0.0 doesn't do what you might expect in Go. With

zero := 0.0
println(mymin(+0.0, -zero))
println(mymin(-zero, +0.0))

we get -0.0 and +0.0, matching MINSD.

@dominikh dominikh reopened this Mar 13, 2025
@randall77
Copy link
Contributor

I guess it is possible that would work. All the non-commutative cases hurt my brain...
I guess MINSD was designed for exactly this case, at least in C semantics.

@dominikh
Copy link
Member Author

This runs to completion:

-- baz.go --
package main

import (
	"fmt"
	"math"
)

func mymin(a, b float64) float64 {
	if a < b {
		return a
	} else {
		return b
	}
}

func minsd(a, b float64) float64

func main() {
	zero := 0.0
	negZero := -zero
	cases := []float64{zero, negZero, math.NaN(), 42, -42, math.Inf(-1), math.Inf(1)}

	for _, a := range cases {
		for _, b := range cases {
			if ret1, ret2 := mymin(a, b), minsd(a, b); ret1 != ret2 {
				if math.IsNaN(ret1) && math.IsNaN(ret2) {
					continue
				}
				panic(fmt.Sprintf("%v %v, %v %v", a, b, ret1, ret2))
			}
		}
	}
}
-- baz.s --
// Code generated by command: go run asm.go. DO NOT EDIT.

// func minsd(a float64, b float64) float64
// Requires: SSE2
TEXT ·minsd(SB), $0-24
	MOVSD a+0(FP), X0
	MOVSD b+8(FP), X1
	MINSD X1, X0
	MOVSD X0, ret+16(FP)
	RET

I do apologize for making us think about floats.

@randall77
Copy link
Contributor

I do apologize for making us think about floats.

You shall be punished by having to write tests about floats.

@dr2chase
Copy link
Contributor

Can this be closed? (This is making me think about floats and SIMD, ugh.)

@dominikh
Copy link
Member Author

As far as I understand, we've concluded that the suggested optimization is (probably) safe, so I don't think this issue should be closed yet, sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. compiler/runtime Issues related to the Go compiler and/or runtime.
Projects
None yet
Development

No branches or pull requests

5 participants