Go version

go version go1.22.4 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/ren/.cache/go-build'
GOENV='/home/ren/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ren/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ren/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.4'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/ren/dev/junk/bugXXX/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1837702511=/tmp/go-build -gno-record-gcc-switches'

What did you do?

func isIn(c byte, lo, hi uint64) bool {
    var m uint64
    if c < 128 {
        m = hi
        if c < 64 {
            m = lo
        }
    }
    return (1<<(c%64))&m != 0
}

https://go.godbolt.org/z/EMn16qvPY

What did you see happen?

On amd64, an unnecessary CMPB instruction is generated, immediately followed by another CMPB.

CMPB    AL, $-128
CMPB    AL, $64
CMOVQCS BX, CX
CMPB    AL, $-128
MOVL    $0, DX
CMOVQCS CX, DX
BTQ AX, DX
SETCS   AL
RET

Similarly on arm64, two CMPWs one after the other.

MOVBU   R0, R3
MOVD    $1, R4
LSL R0, R4, R4
CMPW    $128, R3
CMPW    $64, R3
CSEL    LO, R1, R2, R1
CMPW    $128, R3
CSEL    LO, R1, ZR, R1
TST R1, R4
CSET    NE, R0
RET (R30)

What did you expect to see?

No unnecessary compares.

Comment From: Jorropo

Thx for the bug report. Minimized example:

func isIn(c byte, lo, hi uint64) uint64 {
    var m uint64
    if c < 128 {
        m = hi
        if c < 64 {
            m = lo
        }
    }
    return m
}

This is probably fine, as in completely free, the compare are fast and this one does not havet have any dependencies. There is still cost in fetching and caching bytecodes and maybe sometime it makes loops unaligned but that chance.

Comment From: gabyhelp

Similar Issues

  • https://github.com/golang/go/issues/53599
  • https://github.com/golang/go/issues/14761
  • https://github.com/golang/go/issues/43357
  • https://github.com/golang/go/issues/50325
  • https://github.com/golang/go/issues/65039

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: Jorropo

Dup of #65039 Nice bot