blob: 390b6c350a4cd8ae8e93a8780fcb3918f851cdb7 [file] [log] [blame]
// Copyright 2023 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.
// WARNING: Please avoid updating this file. If this file needs to be updated,
// then a new devirt.pprof file should be generated:
//
// $ cd $GOROOT/src/cmd/compile/internal/test/testdata/pgo/devirtualize/
// $ go mod init example.com/pgo/devirtualize
// $ go test -bench=. -cpuprofile ./devirt.pprof
package devirt
import "example.com/pgo/devirtualize/mult"
var sink int
type Adder interface {
Add(a, b int) int
}
type Add struct{}
func (Add) Add(a, b int) int {
for i := 0; i < 1000; i++ {
sink++
}
return a + b
}
type Sub struct{}
func (Sub) Add(a, b int) int {
for i := 0; i < 1000; i++ {
sink++
}
return a - b
}
// Exercise calls mostly a1 and m1.
//
//go:noinline
func Exercise(iter int, a1, a2 Adder, m1, m2 mult.Multiplier) {
for i := 0; i < iter; i++ {
a := a1
m := m1
if i%10 == 0 {
a = a2
m = m2
}
// N.B. Profiles only distinguish calls on a per-line level,
// making the two calls ambiguous. However because the
// interfaces and implementations are mutually exclusive,
// devirtualization can still select the correct callee for
// each.
//
// If they were not mutually exclusive (for example, two Add
// calls), then we could not definitively select the correct
// callee.
sink += m.Multiply(42, a.Add(1, 2))
}
}
func init() {
// TODO: until https://golang.org/cl/497175 or similar lands,
// we need to create an explicit reference to callees
// in another package for devirtualization to work.
m := mult.Mult{}
m.Multiply(42, 0)
n := mult.NegMult{}
n.Multiply(42, 0)
}