diff options
| author | Julia Lapenko <julia.lapenko@gmail.com> | 2025-03-06 17:54:17 +0300 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2025-04-02 16:39:13 -0700 |
| commit | 13b1261175efde5aac7c4c7f6f66ae3b2c609a2d (patch) | |
| tree | 039846d213ad5481596ec84055bd6396bdf226a6 /src/cmd/compile/internal/test/testdata/pgo/devirtualize | |
| parent | 116b82354ce53dea7b139039adbda3231689b02d (diff) | |
| download | go-13b1261175efde5aac7c4c7f6f66ae3b2c609a2d.tar.xz | |
cmd/compile/internal/devirtualize: do not select a zero-weight edge as the hottest one
When both a direct call and an interface call appear on the same line,
PGO devirtualization may make a suboptimal decision. In some cases,
the directly called function becomes a candidate for devirtualization
if no other relevant outgoing edges with non-zero weight exist for the
caller's IRNode in the WeightedCG. The edge to this candidate is
considered the hottest. Despite having zero weight, this edge still
causes the interface call to be devirtualized.
This CL prevents devirtualization when the weight of the hottest edge
is 0.
Fixes #72092
Change-Id: I06c0c5e080398d86f832e09244aceaa4aeb98721
Reviewed-on: https://go-review.googlesource.com/c/go/+/655475
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/compile/internal/test/testdata/pgo/devirtualize')
| -rw-r--r-- | src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt.go | 42 | ||||
| -rw-r--r-- | src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go | 16 |
2 files changed, 58 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt.go b/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt.go index ac238f6dea..129809e386 100644 --- a/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt.go +++ b/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt.go @@ -250,3 +250,45 @@ func ExerciseFuncClosure(iter int, a1, a2 AddFunc, m1, m2 mult.MultFunc) int { } return val } + +//go:noinline +func IfaceZeroWeight(a *Add, b Adder) bool { + return a.Add(1, 2) == b.Add(3, 4) // unwanted devirtualization +} + +// ExerciseIfaceZeroWeight never calls IfaceZeroWeight, so the callee +// is not expected to appear in the profile. +// +//go:noinline +func ExerciseIfaceZeroWeight() { + if false { + a := &Add{} + b := &Sub{} + // Unreachable call + IfaceZeroWeight(a, b) + } +} + +func DirectCall() bool { + return true +} + +func IndirectCall() bool { + return false +} + +//go:noinline +func IndirCallZeroWeight(indirectCall func() bool) bool { + return DirectCall() && indirectCall() // unwanted devirtualization +} + +// ExerciseIndirCallZeroWeight never calls IndirCallZeroWeight, so the +// callee is not expected to appear in the profile. +// +//go:noinline +func ExerciseIndirCallZeroWeight() { + if false { + // Unreachable call + IndirCallZeroWeight(IndirectCall) + } +} diff --git a/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go b/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go index 59b565d77f..2116e9b249 100644 --- a/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go +++ b/src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go @@ -71,3 +71,19 @@ func TestDevirtFuncClosure(t *testing.T) { t.Errorf("ExerciseFuncClosure(10) got %d want 1176", v) } } + +func BenchmarkDevirtIfaceZeroWeight(t *testing.B) { + ExerciseIfaceZeroWeight() +} + +func TestDevirtIfaceZeroWeight(t *testing.T) { + ExerciseIfaceZeroWeight() +} + +func BenchmarkDevirtIndirCallZeroWeight(t *testing.B) { + ExerciseIndirCallZeroWeight() +} + +func TestDevirtIndirCallZeroWeight(t *testing.T) { + ExerciseIndirCallZeroWeight() +} |
