aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/test/testdata/pgo/devirtualize
diff options
context:
space:
mode:
authorJulia Lapenko <julia.lapenko@gmail.com>2025-03-06 17:54:17 +0300
committerKeith Randall <khr@golang.org>2025-04-02 16:39:13 -0700
commit13b1261175efde5aac7c4c7f6f66ae3b2c609a2d (patch)
tree039846d213ad5481596ec84055bd6396bdf226a6 /src/cmd/compile/internal/test/testdata/pgo/devirtualize
parent116b82354ce53dea7b139039adbda3231689b02d (diff)
downloadgo-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.go42
-rw-r--r--src/cmd/compile/internal/test/testdata/pgo/devirtualize/devirt_test.go16
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()
+}