diff options
| author | Keith Randall <khr@golang.org> | 2022-09-17 18:52:35 -0400 |
|---|---|---|
| committer | Keith Randall <khr@google.com> | 2022-09-19 18:21:06 +0000 |
| commit | e283473ebbebf4a80db166e7e852d03c5cff1a61 (patch) | |
| tree | a3426f4f0f1719f25d582cc36606db022aaa229b /test/fixedbugs | |
| parent | 0053ec452db5bd973c7ac9f4faa5041884e460e8 (diff) | |
| download | go-e283473ebbebf4a80db166e7e852d03c5cff1a61.tar.xz | |
cmd/compile: avoid using destination pointer base type in memmove optimization
The type of the source and destination of a memmove call isn't
always accurate. It will always be a pointer (or an unsafe.Pointer), but
the base type might not be accurate. This comes about because multiple
copies of a pointer with different base types are coalesced into a single value.
In the failing example, the IData selector of the input argument is a
*[32]byte in one branch of the type switch, and a *[]byte in the other branch.
During the expand_calls pass both IDatas become just copies of the input
register. Those copies are deduped and an arbitrary one wins (in this case,
*[]byte is the unfortunate winner).
Generally an op v can rely on v.Type during rewrite rules. But relying
on v.Args[i].Type is discouraged.
Fixes #55122
Change-Id: I348fd9accf2058a87cd191eec01d39cda612f120
Reviewed-on: https://go-review.googlesource.com/c/go/+/431496
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Diffstat (limited to 'test/fixedbugs')
| -rw-r--r-- | test/fixedbugs/issue55122.go | 42 | ||||
| -rw-r--r-- | test/fixedbugs/issue55122b.go | 43 |
2 files changed, 85 insertions, 0 deletions
diff --git a/test/fixedbugs/issue55122.go b/test/fixedbugs/issue55122.go new file mode 100644 index 0000000000..24da89dcb6 --- /dev/null +++ b/test/fixedbugs/issue55122.go @@ -0,0 +1,42 @@ +// run + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + for i := 0; i < 10000; i++ { + h(i) + sink = make([]byte, 1024) // generate some garbage + } +} + +func h(iter int) { + var x [32]byte + for i := 0; i < 32; i++ { + x[i] = 99 + } + g(&x) + if x == ([32]byte{}) { + return + } + for i := 0; i < 32; i++ { + println(x[i]) + } + panic(iter) +} + +//go:noinline +func g(x interface{}) { + switch e := x.(type) { + case *[32]byte: + var c [32]byte + *e = c + case *[]byte: + *e = nil + } +} + +var sink []byte diff --git a/test/fixedbugs/issue55122b.go b/test/fixedbugs/issue55122b.go new file mode 100644 index 0000000000..a911a9f1b6 --- /dev/null +++ b/test/fixedbugs/issue55122b.go @@ -0,0 +1,43 @@ +// run + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + for i := 0; i < 10000; i++ { + h(i) + sink = make([]byte, 1024) // generate some garbage + } +} + +func h(iter int) { + var x [32]byte + for i := 0; i < 32; i++ { + x[i] = 99 + } + g(&x) + if x == ([32]byte{}) { + return + } + for i := 0; i < 32; i++ { + println(x[i]) + } + panic(iter) +} + +//go:noinline +func g(x interface{}) { + switch e := x.(type) { + case *[32]byte: + var c [32]byte + *e = c + case *[3]*byte: + var c [3]*byte + *e = c + } +} + +var sink []byte |
