Skip to content

cmd/compile: incorrect use of CMN on arm64  #50854

@rsc

Description

@rsc
% go version
go version devel go1.18-78d3202a14 Sun Jan 16 12:20:41 2022 -0500 darwin/arm64
% cat x.go
package main

//go:noinline
func f(p int64, x, y int64, b bool) bool { return -x <= p && b }

func main() { println(f(1, -1<<63, 1<<63-1, true)) }

% go run x.go
true
% go tool compile -S x.go
"".f STEXT size=32 args=0x20 locals=0x0 funcid=0x0 align=0x0 leaf
	0x0000 00000 (x.go:4)	TEXT	"".f(SB), LEAF|NOFRAME|ABIInternal, $0-32
	0x0000 00000 (x.go:4)	FUNCDATA	ZR, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$5, "".f.arginfo1(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$6, "".f.argliveinfo(SB)
	0x0000 00000 (x.go:4)	PCDATA	$3, $1
	0x0000 00000 (x.go:4)	NEG	R1, R1
	0x0004 00004 (x.go:4)	CMP	R1, R0
	0x0008 00008 (x.go:4)	CSET	GE, R1
	0x000c 00012 (x.go:4)	AND	R3, R1, R0
	0x0010 00016 (x.go:4)	RET	(R30)
	0x0000 e1 03 01 cb 1f 00 01 eb e1 b7 9f 9a 20 00 03 8a  ............ ...
	0x0010 c0 03 5f d6 00 00 00 00 00 00 00 00 00 00 00 00  .._.............

So far so good. Note that -x <= p is implemented as NEG, CMP.

Now let's change the body of f: s/b/p <= y/.

% cat x.go
package main

//go:noinline
func f(p int64, x, y int64, b bool) bool { return -x <= p && p <= y }

func main() { println(f(1, -1<<63, 1<<63-1, true)) }
% go run x.go
false
% go tool compile -S x.go
"".f STEXT size=32 args=0x20 locals=0x0 funcid=0x0 align=0x0 leaf
	0x0000 00000 (x.go:4)	TEXT	"".f(SB), LEAF|NOFRAME|ABIInternal, $0-32
	0x0000 00000 (x.go:4)	FUNCDATA	ZR, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$5, "".f.arginfo1(SB)
	0x0000 00000 (x.go:4)	FUNCDATA	$6, "".f.argliveinfo(SB)
	0x0000 00000 (x.go:4)	PCDATA	$3, $1
	0x0000 00000 (x.go:4)	CMN	R1, R0
	0x0004 00004 (x.go:4)	BLT	20
	0x0008 00008 (x.go:4)	CMP	R0, R2
	0x000c 00012 (x.go:4)	CSET	GE, R1
	0x0010 00016 (x.go:4)	JMP	24
	0x0014 00020 (x.go:4)	MOVD	ZR, R1
	0x0018 00024 (x.go:4)	MOVD	R1, R0
	0x001c 00028 (x.go:4)	RET	(R30)
	0x0000 1f 00 01 ab 8b 00 00 54 5f 00 00 eb e1 b7 9f 9a  .......T_.......
	0x0010 02 00 00 14 01 00 80 d2 e0 03 01 aa c0 03 5f d6  .............._.

Note that the NEG, CMP has changed to CMN. The CMN is wrong in the case where the comparison argument is -1<<63, since its negation is itself.

This optimization should not be applied when compiling -x <= p.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.okay-after-beta1Used by release team to mark a release-blocker issue as okay to resolve either before or after beta1release-blocker

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions