cmd/compile/internal/typecheck: push ONEW into go/defer wrappers

Currently, we rewrite:

	go f(new(T))

into:

	tmp := new(T)
	go func() { f(tmp) }()

However, we can both shrink the closure and improve escape analysis by
instead rewriting it into:

	go func() { f(new(T)) }()

This CL does that.

Change-Id: Iae16a476368da35123052ca9ff41c49159980458
Reviewed-on: https://go-review.googlesource.com/c/go/+/520340
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Matthew Dempsky 2023-08-16 22:37:42 -07:00 committed by Gopher Robot
parent 7e2e648a2d
commit 2c51ea11b0
2 changed files with 13 additions and 13 deletions

View File

@ -241,7 +241,7 @@ func tcGoDefer(n *ir.GoDeferStmt) {
// the wrapper, so we don't need to allocate space for them within
// the closure.
switch arg.Op() {
case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR:
case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR, ir.ONEW:
return
case ir.ONAME:
arg := arg.(*ir.Name)

View File

@ -19,31 +19,31 @@ func g() {
defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
go f()
go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
go f(nil...)
go f([]*int{}...) // ERROR "\[\]\*int{} does not escape$"
go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
for {
defer f()
defer f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
defer f(new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
defer f(nil...)
defer f([]*int{}...) // ERROR "\[\]\*int{} does not escape$"
defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
go f()
go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$"
go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
go f(nil...)
go f([]*int{}...) // ERROR "\[\]\*int{} does not escape$"
go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$"
go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
}
}