1
0
mirror of https://github.com/golang/go synced 2024-07-05 09:50:19 +00:00

cmd/compile: fix x=x assignments

No point in doing anything for x=x assignments.
In addition, skipping these assignments prevents generating:
    VARDEF x
    COPY x -> x
which is bad because x is incorrectly considered
dead before the vardef.

Fixes #14904

Change-Id: I6817055ec20bcc34a9648617e0439505ee355f82
Reviewed-on: https://go-review.googlesource.com/21470
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Dave Cheney <dave@cheney.net>
This commit is contained in:
Keith Randall 2016-04-01 11:05:30 -07:00
parent 5c7ae10f66
commit 309144b7f1
4 changed files with 120 additions and 7 deletions

View File

@ -661,6 +661,17 @@ func (s *state) stmt(n *Node) {
return
}
if n.Left == n.Right && n.Left.Op == ONAME {
// An x=x assignment. No point in doing anything
// here. In addition, skipping this assignment
// prevents generating:
// VARDEF x
// COPY x -> x
// which is bad because x is incorrectly considered
// dead before the vardef. See issue #14904.
return
}
var t *Type
if n.Right != nil {
t = n.Right.Type

View File

@ -99,3 +99,5 @@ func TestUnsafe(t *testing.T) { runTest(t, "unsafe_ssa.go") }
func TestPhi(t *testing.T) { runTest(t, "phi_ssa.go") }
func TestSlice(t *testing.T) { runTest(t, "slice.go") }
func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") }

View File

@ -0,0 +1,101 @@
// run
// This test makes sure that naming named
// return variables in a return statement works.
// See issue #14904.
package main
import (
"fmt"
"runtime"
)
// Our heap-allocated object that will be GC'd incorrectly.
// Note that we always check the second word because that's
// where 0xdeaddeaddeaddead is written.
type B [4]int
// small (SSAable) array
type T1 [3]*B
//go:noinline
func f1() (t T1) {
t[0] = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// large (non-SSAable) array
type T2 [8]*B
//go:noinline
func f2() (t T2) {
t[0] = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// small (SSAable) struct
type T3 struct {
a, b, c *B
}
//go:noinline
func f3() (t T3) {
t.a = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// large (non-SSAable) struct
type T4 struct {
a, b, c, d, e, f *B
}
//go:noinline
func f4() (t T4) {
t.a = &B{91, 92, 93, 94}
runtime.GC()
return t
}
var sink *B
func f5() int {
b := &B{91, 92, 93, 94}
t := T4{b, nil, nil, nil, nil, nil}
sink = b // make sure b is heap allocated ...
sink = nil // ... but not live
runtime.GC()
t = t
return t.a[1]
}
func main() {
failed := false
if v := f1()[0][1]; v != 92 {
fmt.Printf("f1()[0][1]=%d, want 92\n", v)
failed = true
}
if v := f2()[0][1]; v != 92 {
fmt.Printf("f2()[0][1]=%d, want 92\n", v)
failed = true
}
if v := f3().a[1]; v != 92 {
fmt.Printf("f3().a[1]=%d, want 92\n", v)
failed = true
}
if v := f4().a[1]; v != 92 {
fmt.Printf("f4().a[1]=%d, want 92\n", v)
failed = true
}
if v := f5(); v != 92 {
fmt.Printf("f5()=%d, want 92\n", v)
failed = true
}
if failed {
panic("bad")
}
}

View File

@ -606,13 +606,12 @@ func f39a() (x []int) {
return
}
// TODO: Reenable after #14904 is fixed.
//func f39b() (x [10]*int) {
// x = [10]*int{}
// x[0] = new(int) // E.R.R.O.R. "live at call to newobject: x$"
// printnl() // E.R.R.O.R. "live at call to printnl: x$"
// return x
//}
func f39b() (x [10]*int) {
x = [10]*int{}
x[0] = new(int) // ERROR "live at call to newobject: x$"
printnl() // ERROR "live at call to printnl: x$"
return x
}
func f39c() (x [10]*int) {
x = [10]*int{}