go/test/fixedbugs/issue7921.go
Than McIntosh 0b07bbd2be cmd/compile/internal/inl: inline based on scoring when GOEXPERIMENT=newinliner
This patch changes the inliner to use callsite scores when deciding to
inline as opposed to looking only at callee cost/hairyness.

For this to work, we have to relax the inline budget cutoff as part of
CanInline to allow for the possibility that a given function might
start off with a cost of N where N > 80, but then be called from a
callsites whose score is less than 80. Once a given function F in
package P has been approved by CanInline (based on the relaxed budget)
it will then be emitted as part of the export data, meaning that other
packages importing P will need to also need to compute callsite scores
appropriately.

For a function F that calls function G, if G is marked as potentially
inlinable then the hairyness computation for F will use G's cost for
the call to G as opposed to the default call cost; for this to work
with the new scheme (given relaxed cost change described above) we
use G's cost only if it falls below inlineExtraCallCost, otherwise
just use inlineExtraCallCost.

Included in this patch are a bunch of skips and workarounds to
selected 'errorcheck' tests in the <GOROOT>/test directory to deal
with the additional "can inline" messages emitted when the new inliner
is turned on.

Change-Id: I9be5f8cd0cd8676beb4296faf80d2f6be7246335
Reviewed-on: https://go-review.googlesource.com/c/go/+/519197
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2023-09-14 19:43:26 +00:00

59 lines
2.2 KiB
Go

// errorcheck -0 -m
//go:build !gcflags_noopt && !goexperiment.newinliner
// Copyright 2018 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 foo
import "bytes"
// In order to get desired results, we need a combination of
// both escape analysis and inlining.
func bufferNotEscape() string {
// b itself does not escape, only its buf field will be
// copied during String() call, but object "handle" itself
// can be stack-allocated.
var b bytes.Buffer
b.WriteString("123")
b.Write([]byte{'4'}) // ERROR "\[\]byte{...} does not escape$"
return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
}
func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape$"
b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
for _, x := range xs {
b.WriteString(x)
}
return b.Len() // ERROR "inlining call to bytes.\(\*Buffer\).Len$"
}
func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$"
b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
for _, x := range xs {
b.WriteString(x)
b.WriteByte(',')
}
return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
}
func bufferNoEscape4() []byte {
var b bytes.Buffer
b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m\]$" "inlining call to bytes.\(\*Buffer\).Grow$" `".+" escapes to heap`
useBuffer(&b)
return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$"
}
func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$"
b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$"
useBuffer(b)
}
//go:noinline
func useBuffer(b *bytes.Buffer) { // ERROR "b does not escape$"
b.WriteString("1234")
}