aboutsummaryrefslogtreecommitdiff
path: root/test/codegen
diff options
context:
space:
mode:
authorthepudds <thepudds1460@gmail.com>2025-02-13 23:49:50 -0500
committerDavid Chase <drchase@google.com>2025-05-21 12:23:26 -0700
commitf4de2ecffb9c107e6058c1ebb30c68de1157f5c6 (patch)
tree85625c56665e010090451c811ccc4d7dbfd5cbf5 /test/codegen
parentce46c9db867fb54a9c1f39b73ac8c2f339ca0587 (diff)
downloadgo-f4de2ecffb9c107e6058c1ebb30c68de1157f5c6.tar.xz
cmd/compile/internal/walk: convert composite literals to interfaces without allocating
Today, this interface conversion causes the struct literal to be heap allocated: var sink any func example1() { sink = S{1, 1} } For basic literals like integers that are directly used in an interface conversion that would otherwise allocate, the compiler is able to use read-only global storage (see #18704). This CL extends that to struct and array literals as well by creating read-only global storage that is able to represent for example S{1, 1}, and then using a pointer to that storage in the interface when the interface conversion happens. A more challenging example is: func example2() { v := S{1, 1} sink = v } In this case, the struct literal is not directly part of the interface conversion, but is instead assigned to a local variable. To still avoid heap allocation in cases like this, in walk we construct a cache that maps from expressions used in interface conversions to earlier expressions that can be used to represent the same value (via ir.ReassignOracle.StaticValue). This is somewhat analogous to how we avoided heap allocation for basic literals in CL 649077 earlier in our stack, though here we also need to do a little more work to create the read-only global. CL 649076 (also earlier in our stack) added most of the tests along with debug diagnostics in convert.go to make it easier to test this change. See the writeup in #71359 for details. Fixes #71359 Fixes #71323 Updates #62653 Updates #53465 Updates #8618 Change-Id: I8924f0c69ff738ea33439bd6af7b4066af493b90 Reviewed-on: https://go-review.googlesource.com/c/go/+/649555 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@google.com>
Diffstat (limited to 'test/codegen')
-rw-r--r--test/codegen/zerosize.go19
1 files changed, 19 insertions, 0 deletions
diff --git a/test/codegen/zerosize.go b/test/codegen/zerosize.go
index ecf3305461..86c4819400 100644
--- a/test/codegen/zerosize.go
+++ b/test/codegen/zerosize.go
@@ -18,8 +18,27 @@ func zeroSize() {
g(&s, 1, 2, 3, 4, 5)
// amd64:`LEAQ\tcommand-line-arguments\..*\+55\(SP\)`
+ c <- noliteral(struct{}{})
+}
+
+// Like zeroSize, but without hiding the zero-sized struct.
+func zeroSize2() {
+ c := make(chan struct{})
+ // amd64:`MOVQ\t\$0, command-line-arguments\.s\+48\(SP\)`
+ var s *int
+ // force s to be a stack object, also use some (fixed) stack space
+ g(&s, 1, 2, 3, 4, 5)
+
+ // amd64:`LEAQ\tcommand-line-arguments\..*stmp_\d+\(SB\)`
c <- struct{}{}
}
//go:noinline
func g(**int, int, int, int, int, int) {}
+
+// noliteral prevents the compiler from recognizing a literal value.
+//
+//go:noinline
+func noliteral[T any](t T) T {
+ return t
+}