aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzuojunwei.1024 <zuojunwei.1024@bytedance.com>2025-12-23 16:12:04 +0800
committerCherry Mui <cherryyz@google.com>2025-12-30 07:26:35 -0800
commitcd668d744f77da06ca9565f41c63c3a5251469ee (patch)
tree30077015dd0352f661f313d5b262ffd2bd801957
parent06eff0f7c3027a78088d45efdaec8ac3ed636481 (diff)
downloadgo-cd668d744f77da06ca9565f41c63c3a5251469ee.tar.xz
cmd/compile: disable inlining for functions using runtime.deferrangefunc
The rangefunc rewrite pass implements defer using deferrangefunc and deferproccat. The loop body is rewritten into a closure, it cannot be inlined due to defer call. But the outer function may still be inlined in certain scenarios (e.g., with PGO), leading to the defer executing at the wrong time. Fixes #77033 Change-Id: I4649fad5cd1b65891832523522002d9352711123 Reviewed-on: https://go-review.googlesource.com/c/go/+/732140 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
-rw-r--r--src/cmd/compile/internal/inline/inl.go3
-rw-r--r--src/cmd/compile/testdata/script/issue77033.txt40
2 files changed, 43 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go
index 33f9c325c3..4fa9cf07fb 100644
--- a/src/cmd/compile/internal/inline/inl.go
+++ b/src/cmd/compile/internal/inline/inl.go
@@ -516,6 +516,9 @@ opSwitch:
break opSwitch
case "panicrangestate":
cheap = true
+ case "deferrangefunc":
+ v.reason = "defer call in range func"
+ return true
}
}
}
diff --git a/src/cmd/compile/testdata/script/issue77033.txt b/src/cmd/compile/testdata/script/issue77033.txt
new file mode 100644
index 0000000000..3b977e5440
--- /dev/null
+++ b/src/cmd/compile/testdata/script/issue77033.txt
@@ -0,0 +1,40 @@
+go test -bench=Foo -cpuprofile=default.pgo
+go test -bench=Foo -pgo=default.pgo
+! stdout 'FAIL'
+
+-- main_test.go --
+package main
+
+import (
+ "testing"
+)
+
+var a int
+
+func save(x int) {
+ a = x
+}
+
+func foo() {
+ for i := range yield1 {
+ defer save(i)
+ }
+}
+
+func yield1(yield func(int) bool) {
+ yield(1)
+}
+
+func BenchmarkFoo(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ foo()
+ }
+ if a != 1 {
+ b.Fatalf("a = %d; want 1", a)
+ }
+}
+
+-- go.mod --
+module demo
+
+go 1.24