Skip to content

cmd/compile: unnecessary temporary variable on stack #65495

Open
@katsusan

Description

@katsusan

Go version

go version go1.21.6 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://goproxy.cn'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.6'
GCCGO='/usr/local/bin/gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
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 -fdebug-prefix-map=/tmp/go-build734905149=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Use GOSSAFUNC=enc go build qmac.go or go tool compile -S qmac.go for its assembly results or see https://godbolt.org/z/9GxzbY4eP.

//qmac.go
package main

func main() {}

type desc struct {
        t int
        x int
        y int
        z int
        p int
}

func enc(d []byte) []byte {
        var buf = d
        t, a, b, c, pr := 0,  -1, 3, 1, 113
        for i := 0; i < len(buf); i++ {
                res := process(t, a, b, c, pr)
                buf[i] = byte(res.z)
        }

        return buf
}

//go:noinline
func process(t, a, b, c, pr int) desc {
        d :=  desc{
                t: t,
                x : a,
                y: b,
                z: c,
                p: pr,
        }
        //...
        return d
}

What did you see happen?

For every loop Go compiler stores the call result into onstack variable main.res, which is meaningless, as main.res is only an intermediate result for setting buf[i].

I also haven't figured out what autotmp_11 is used for here, why not doing a direct store MOVQ AX, main.res-xx(SP) instead of MOVQ AX, main..autotmp_11-40(SP), MOVQ main..autotmp_11-40(SP), DX, MOVQ DX, main.res-80(SP)

image

What did you expect to see?

Compiler can optimize the redundant store operations like following case.
(reduce process's parameters from 5 to 4)

image
//qmac2.go
package main

func main() {}

type desc struct {
        t int
        x int
        y int
        z int
}

func enc(d []byte) []byte {
        var buf = d
        t, a, b, c := 0,  -1, 3, 1
        for i := 0; i < len(buf); i++ {
                res := process(t, a, b, c)
                buf[i] = byte(res.z)
        }

        return buf
}

//go:noinline
func process(t, a, b, c int) desc {
        d :=  desc{
                t: t,
                x : a,
                y: b,
                z: c,
        }
        //...
        return d
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions