Files
go/test/codegen/issue20859.go
Jake Bailey dd8aa2845b cmd/compile: reuse result slot for partial local returns
Extend rewriteresults to handle functions where only some explicit
returns return a local. For example:

    func f(x uint64, c bool) [16]byte {
        var ret [16]byte
        use(ret[:8], x)
        if c {
            return ret
        }
        return [16]byte{1}
    }

The previous CL handles the case where every explicit return returns the
same local. This CL relaxes that to require only that every direct local
return for a given result slot returns the same local. Other return
expressions for that slot are left alone.

The post-escape placement introduced in the first CL is what keeps
this weaker pattern safe: the pass rejects locals that escape to the
heap. If a local's address escapes, another return path that
overwrites the result slot could otherwise change what the escaped
pointer observes.

The rewrite remains conservative: no defers, no naked returns, explicit
return counts must match the signature, result parameters must be
anonymous, the local must have a normal zeroing declaration, must not be
closure-captured, must not escape to the heap, and must not map to
multiple result slots.

compilecmp results (this CL vs parent, over std cmd):

    file       before    after     delta       %
    addr2line  3956269   3953365   -2904   -0.073%
    asm        7237685   7235373   -2312   -0.032%
    buildid    3826062   3823646   -2416   -0.063%
    cgo        6195346   6192738   -2608   -0.042%
    compile    37103491  37095195  -8296   -0.022%
    cover      7917704   7910176   -7528   -0.095%
    dist       5336503   5333223   -3280   -0.061%
    distpack   4040039   4038759   -1280   -0.032%
    fix        12721347  12716307  -5040   -0.040%
    link       10108535  10106679  -1856   -0.018%
    nm         3935967   3932927   -3040   -0.077%
    objdump    6581468   6578508   -2960   -0.045%
    pack       3266676   3265284   -1392   -0.043%
    pprof      20281781  20271101  -10680  -0.053%
    test2json  4575312   4572568   -2744   -0.060%
    trace      18689578  18675114  -14464  -0.077%
    vet        12307501  12302205  -5296   -0.043%
    total      176007153 175925057 -82096  -0.047%

Function text size changes over std cmd total -2550 bytes (-0.006%).
Representative changes include:

    internal/gover.Parse                                      1481 -> 1150 (-22.35%)
    vendor/golang.org/x/net/dns/dnsmessage.(*Parser).resource 968  -> 741  (-23.45%)
    vendor/golang.org/x/net/dns/dnsmessage.(*Parser).resourceHeader 634 -> 523 (-17.51%)
    time.tzsetRule                                           2458 -> 2298 (-6.51%)
    crypto/rsa.(*PrivateKey).precompute                      3113 -> 2591 (-16.77%)
    net.(*Resolver).lookup                                   1212 -> 1157 (-4.54%)

Overall compilecmp effect of this CL stack (vs master):

    file       before    after     delta       %
    addr2line  3957733   3953365   -4368   -0.110%
    asm        7239069   7235373   -3696   -0.051%
    buildid    3826382   3823646   -2736   -0.072%
    cgo        6197914   6192738   -5176   -0.084%
    compile    37100088  37095195  -4893   -0.013%
    cover      7920312   7910176   -10136  -0.128%
    dist       5338479   5333223   -5256   -0.098%
    distpack   4045463   4038759   -6704   -0.166%
    fix        12725363  12716307  -9056   -0.071%
    link       10112423  10106679  -5744   -0.057%
    nm         3937359   3932927   -4432   -0.113%
    objdump    6583348   6578508   -4840   -0.074%
    pack       3267644   3265284   -2360   -0.072%
    pprof      20295357  20271101  -24256  -0.120%
    test2json  4576784   4572568   -4216   -0.092%
    trace      18698274  18675114  -23160  -0.124%
    vet        12311989  12302205  -9784   -0.079%
    total      176062230 175925057 -137173 -0.078%

Updates #20859

Change-Id: Ia423f28edc2366f6e01001cb3d05380ee4da5af0
Reviewed-on: https://go-review.googlesource.com/c/go/+/779002
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2026-08-17 11:01:31 -07:00

64 lines
1.2 KiB
Go

// asmcheck
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package codegen
//go:noinline
func use16(b []byte, x uint64) {
b[0] = byte(x)
}
//go:noinline
func resultSlotArray(x uint64) [16]byte {
var ret [16]byte
// amd64:-`.*\.ret\+`
use16(ret[:8], x)
// amd64:-`.*\.ret\+`
use16(ret[8:], x)
// amd64:-`.*\.ret\+` -`.*MOVUPS.*~r0`
return ret
}
//go:noinline
func resultSlotArrayMultipleReturns(x uint64, c bool) [16]byte {
var ret [16]byte
// amd64:-`.*\.ret\+`
use16(ret[:8], x)
if c {
// amd64:-`.*\.ret\+` -`.*MOVUPS.*~r0`
return ret
}
// amd64:-`.*\.ret\+`
use16(ret[8:], x)
// amd64:-`.*\.ret\+` -`.*MOVUPS.*~r0`
return ret
}
//go:noinline
func resultSlotPartialReturn(x uint64, c bool) [16]byte {
var ret [16]byte
// amd64:-`.*\.ret\+`
use16(ret[:8], x)
if c {
// amd64:-`.*\.ret\+` -`.*MOVUPS.*~r0`
return ret
}
return [16]byte{1}
}
//go:noinline
func resultSlotPartialReturnLocal(x uint64, c bool) [16]byte {
var ret [16]byte
// amd64:-`.*\.ret\+`
use16(ret[:8], x)
if c {
// amd64:-`.*\.ret\+` -`.*MOVUPS.*~r0`
return ret
}
other := [16]byte{1}
return other
}