Files
Cuong Manh Le 5391dd543a cmd/compile: don't move a non-escaping slice to the heap
The slice pass stack allocates append backing stores whose only escape
is a transition out of the slice variable's exclusive ownership,
inserting a move2heap at that transition. It looks for the transition
without checking escape analysis result, so an append that does not
escape gets a move2heap too, unnecessary copying the stack backing store
to the heap.

Fix this by skipping the optimization for non-escaping appends.

Fixes #82126

Change-Id: Iea23d237cae9f82ef79b539d89045671a3dee8b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/848666
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2026-10-22 19:09:42 -07:00

264 lines
4.3 KiB
Go

// asmcheck
//go:build !goexperiment.runtimefreegc
// Copyright 2025 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
func Append1(n int) []int {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append2(n int) (r []int) {
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return
}
func Append3(n int) (r []int) {
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append4(n int) []int {
var r []int
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
println(cap(r))
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append5(n int) []int {
var r []int
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
useSlice(r)
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append5b(n int) []int {
var r []int
useSlice(r)
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append6(n int) []*int {
var r []*int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, new(i))
}
// amd64:`.*moveSliceNoCap\b`
return r
}
func Append7(n int) []*int {
var r []*int
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, new(i))
}
println(cap(r))
// amd64:`.*moveSlice\b`
return r
}
func Append8(n int, p *[]int) {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
*p = r
}
func Append8b(n int, p *[]int) {
var r []int
// amd64:`.*moveSliceNoCapNoScan\b`
*p = r
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
}
func Append9(n int) []int {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
println(len(r))
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append10(n int) []int {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
println(r[3])
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append11(n int) []int {
var r []int
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
r = r[3:5]
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append12(n int) []int {
var r []int
r = nil
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append13(n int) []int {
var r []int
r, r = nil, nil
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append14(n int) []int {
var r []int
r = []int{3, 4, 5}
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append15(n int) []int {
r := []int{3, 4, 5}
for i := range n {
// amd64:`.*growsliceBuf\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoScan\b`
return r
}
func Append16(r []int, n int) []int {
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append17(n int) []int {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
for i, x := range r {
println(i, x)
}
// "range r" keeps pointer to backing store of r. Our analysis
// is not yet precise enough to know it is OK in this case, so
// currently no `moveSliceNoCapNoScan` here. See #79909.
// amd64:-`.*moveSlice`
return r
}
func Append18(n int, p *[]int) {
var r []int
for i := range n {
// amd64:-`.*moveSliceNoCapNoScan`
*p = r
// amd64:`.*growslice`
r = append(r, i)
}
}
func Append19(n int, p [][]int) {
for j := range p {
var r []int
for i := range n {
// amd64:`.*growslice`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan`
p[j] = r
}
}
func Append20(n int, p [][]int) {
for j := range p {
var r []int
// amd64:`.*growslice`
r = append(r, 0)
// amd64:-`.*moveSliceNoCapNoScan`
p[j] = r
}
}
func Append21(n int) []int {
var r []int
for i := range n {
// amd64:`.*growslice\b`
r = append(r, i)
}
// amd64:`.*moveSliceNoCapNoScan\b`
return r
}
func Append22(n int) int {
// amd64:-`.*moveSlice`
return Append21(n)[0]
}
//go:noinline
func useSlice(s []int) {
}