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: OpAMD64CMOV*EQF clobbers AX, doesn't tell regalloc #26097

Closed
heschik opened this issue Jun 27, 2018 · 3 comments

Comments

Projects
None yet
4 participants
@heschik
Copy link
Contributor

commented Jun 27, 2018

CL 98695 (commit 080187f) adds OpAMD64CMOV{Q,L,W}EQF. The generated assembly looks like:

// MOV SRC,AX
// CMOV*NE DST,AX
// CMOV*PC AX,DST

That is, it uses AX as a scratch register so that it can check both equality and NAN-ness. (I think.) The problem is, regalloc doesn't know about this:
{name: "CMOVLEQF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},

gp21 doesn't have clobbers:ax.

I don't have a public repro, but given the below assembly I'm pretty sure I'm in the neighborhood of the problem. The three MOVLs clearly don't make sense.

 v677  	00341 (287)	UCOMISD	X1, X0
 v292  	00342 (287)	MOVL	$2, AX
 v287  	00343 (287)	MOVL	$1, CX
 v456  	00344 (287)	MOVL	CX, AX
 v456  	00345 (287)	CMOVLNE	AX, AX
 v456  	00346 (287)	CMOVLPC	AX, AX
 v460  	00347 (287)	MOVL	AX, "".~r2+24(SP)
 b196  	00348 (35)	RET

cc @randall77 @TocarIP @rasky

This is Google-internal b/110810807.

@heschik heschik added this to the Go1.11 milestone Jun 27, 2018

@TocarIP

This comment has been minimized.

Copy link
Contributor

commented Jun 27, 2018

Looks like we clobber AX for "ssa.OpAMD64CMOVQEQF, ssa.OpAMD64CMOVLEQF, ssa.OpAMD64CMOVWEQF", but only CMOVQEQF uses gp21pax regspec (which marks ax as clobbered)

@TocarIP

This comment has been minimized.

Copy link
Contributor

commented Jun 27, 2018

Here is a simple reproducer:

package main

//go:noinline
func foo1(v1, v2 int64, x1, x2 float64) int64 {
        r := v1
        if x1 == x2 {
                r = v2
        }
        return r
}

//go:noinline
func foo3(v1, v2 int16, x1, x2 float64) int16 {
        r := v1
        if x1 == x2 {
                r = v2
        }
        return r
}

//go:noinline
func foo2(v1, v2 int32, x1, x2 float64) int32 {
        r := v1
        if x1 == x2 {
                r = v2
        }
        return r
}

func main() {
//should print 1 1 1
        println(foo1(1, 2, 4.0, 5.0))
        println(foo2(1, 2, 4.0, 5.0))
        println(foo3(1, 2, 4.0, 5.0))
// prints 1 2 2
}
@gopherbot

This comment has been minimized.

Copy link

commented Jun 27, 2018

Change https://golang.org/cl/121336 mentions this issue: cmd/compile: mark CMOVLEQF, CMOVWEQF as cloberring AX

@bradfitz bradfitz added the NeedsFix label Jun 27, 2018

@gopherbot gopherbot closed this in b71ea0b Jun 28, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.