Skip to content

cmd/compile: b.Loop un-optimizer regression heap allocate objects passed to non-leaky functions it used to stack allocate #76482

@zigo101

Description

@zigo101

Go version

go version go1.26-devel_c048a9a11f Wed Nov 26 16:20:21 2025 -0800 linux/amd64

Output of go env in your module/workspace:

.

What did you do?

package main

import "testing"

type Data struct {
    v [1<<10]float32
}

func NonPointerReturn() Data {
    return Data{}
}

func ReturnAsInput(d *Data)  {
    *d = Data{}
}

func PointerReturn() *Data {
    return &Data{}
}

var x float32
var n = 123
func useData(d *Data) {
    x = d.v[n]
}

func Benchmark_NonPointerReturn(b *testing.B) {
	for b.Loop() {
		var d = NonPointerReturn()
		useData(&d)
	}
}

func Benchmark_NonPointerReturnB(b *testing.B) {
	for b.Loop() {
	    var d = new(Data)
		*d = NonPointerReturn()
		useData(d)
	}
}

func Benchmark_ReturnAsInput(b *testing.B) {
	for b.Loop() {
	    var d = new(Data)
		ReturnAsInput(d)
		useData(d)
	}
}

func Benchmark_PointerReturn(b *testing.B) {
	for b.Loop() {
		var d = PointerReturn()
		useData(d)
	}
}

What did you see happen?

Similar benchmark results between tip and 1.25 toolchain.

What did you expect to see?

The benchmark results look quite different.

$ gotv 1.25 test -bench=. -benchmem main_test.go 
[Run]: $HOME/.cache/gotv/tag_go1.25.4/bin/go test -bench=. -benchmem main_test.go
goos: linux
goarch: amd64
cpu: Intel(R) Core(TM) i5-4200M CPU @ 2.50GHz
Benchmark_NonPointerReturn-4    	10438954	       114.4 ns/op	       0 B/op	       0 allocs/op
Benchmark_NonPointerReturnB-4   	 5389276	       222.7 ns/op	       0 B/op	       0 allocs/op
Benchmark_ReturnAsInput-4       	10283925	       109.5 ns/op	       0 B/op	       0 allocs/op
Benchmark_PointerReturn-4       	 1522304	       779.8 ns/op	    4096 B/op	       1 allocs/op
PASS
ok  	command-line-arguments	4.713s

$ gotv :tip test -bench=. -benchmem main_test.go 
[Run]: $HOME/.cache/gotv/bra_master/bin/go test -bench=. -benchmem main_test.go
goos: linux
goarch: amd64
cpu: Intel(R) Core(TM) i5-4200M CPU @ 2.50GHz
Benchmark_NonPointerReturn-4    	  567326	      1982 ns/op	    8192 B/op	       2 allocs/op
Benchmark_NonPointerReturnB-4   	11456282	       103.7 ns/op	       0 B/op	       0 allocs/op
Benchmark_ReturnAsInput-4       	10468320	       107.6 ns/op	       0 B/op	       0 allocs/op
Benchmark_PointerReturn-4       	22553568	        52.91 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	command-line-arguments	4.639s

It looks Go 1.26 makes some improvements, but also makes some bad things.

BTW, I expect the four benchmarks are on par (whether the size of Data is smaller than 1<<15 or not). Still not on tip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.FixPendingIssues that have a fix which has not yet been reviewed or submitted.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions