diff options
author | Russ Cox <rsc@golang.org> | 2013-09-17 16:54:22 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2013-09-17 16:54:22 -0400 |
commit | aa0439ba65bfa762c26a3dbb3f0c0474267b5582 (patch) | |
tree | 8bf2670a6b2611ffc776d0c8a2ea3ed704fcc0c6 /test/nilptr3.go | |
parent | eef7035ec860a2a8eac39ed3f4c0cb2a384599a2 (diff) | |
download | go-aa0439ba65bfa762c26a3dbb3f0c0474267b5582.tar.gz go-aa0439ba65bfa762c26a3dbb3f0c0474267b5582.zip |
cmd/gc: eliminate redundant &x.Field nil checks
This eliminates ~75% of the nil checks being emitted,
on all architectures. We can do better, but we need
a bit more general support from the compiler, and
I don't want to do that so close to Go 1.2.
What's here is simple but effective and safe.
A few small code generation cleanups were required
to make the analysis consistent on all systems about
which nil checks are omitted, at least in the test.
Fixes #6019.
R=ken2
CC=golang-dev
https://golang.org/cl/13334052
Diffstat (limited to 'test/nilptr3.go')
-rw-r--r-- | test/nilptr3.go | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/test/nilptr3.go b/test/nilptr3.go new file mode 100644 index 0000000000..08597a02d9 --- /dev/null +++ b/test/nilptr3.go @@ -0,0 +1,191 @@ +// errorcheck -0 -d=nil + +// Copyright 2013 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. + +// Test that nil checks are removed. +// Optimization is enabled. + +package p + +type Struct struct { + X int + Y float64 +} + +type BigStruct struct { + X int + Y float64 + A [1<<20]int + Z string +} + +type Empty struct { +} + +type Empty1 struct { + Empty +} + +var ( + intp *int + arrayp *[10]int + array0p *[0]int + bigarrayp *[1<<26]int + structp *Struct + bigstructp *BigStruct + emptyp *Empty + empty1p *Empty1 +) + +func f1() { + _ = *intp // ERROR "generated nil check" + + // This one should be removed but the block copy needs + // to be turned into its own pseudo-op in order to see + // the indirect. + _ = *arrayp // ERROR "generated nil check" + + // 0-byte indirect doesn't suffice + _ = *array0p // ERROR "generated nil check" + _ = *array0p // ERROR "removed repeated nil check" 386 + + _ = *intp // ERROR "removed repeated nil check" + _ = *arrayp // ERROR "removed repeated nil check" + _ = *structp // ERROR "generated nil check" + _ = *emptyp // ERROR "generated nil check" + _ = *arrayp // ERROR "removed repeated nil check" +} + +func f2() { + var ( + intp *int + arrayp *[10]int + array0p *[0]int + bigarrayp *[1<<20]int + structp *Struct + bigstructp *BigStruct + emptyp *Empty + empty1p *Empty1 + ) + + _ = *intp // ERROR "generated nil check" + _ = *arrayp // ERROR "generated nil check" + _ = *array0p // ERROR "generated nil check" + _ = *array0p // ERROR "removed repeated nil check" + _ = *intp // ERROR "removed repeated nil check" + _ = *arrayp // ERROR "removed repeated nil check" + _ = *structp // ERROR "generated nil check" + _ = *emptyp // ERROR "generated nil check" + _ = *arrayp // ERROR "removed repeated nil check" + _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!! + _ = *bigstructp // ERROR "generated nil check" + _ = *empty1p // ERROR "generated nil check" +} + +func fx10k() *[10000]int +var b bool + + +func f3(x *[10000]int) { + // Using a huge type and huge offsets so the compiler + // does not expect the memory hardware to fault. + _ = x[9999] // ERROR "generated nil check" + + for { + if x[9999] != 0 { // ERROR "generated nil check" + break + } + } + + x = fx10k() + _ = x[9999] // ERROR "generated nil check" + if b { + _ = x[9999] // ERROR "removed repeated nil check" + } else { + _ = x[9999] // ERROR "removed repeated nil check" + } + _ = x[9999] // ERROR "generated nil check" + + x = fx10k() + if b { + _ = x[9999] // ERROR "generated nil check" + } else { + _ = x[9999] // ERROR "generated nil check" + } + _ = x[9999] // ERROR "generated nil check" + + fx10k() + // This one is a bit redundant, if we figured out that + // x wasn't going to change across the function call. + // But it's a little complex to do and in practice doesn't + // matter enough. + _ = x[9999] // ERROR "generated nil check" +} + +func f3a() { + x := fx10k() + y := fx10k() + z := fx10k() + _ = &x[9] // ERROR "generated nil check" + y = z + _ = &x[9] // ERROR "removed repeated nil check" + x = y + _ = &x[9] // ERROR "generated nil check" +} + +func f3b() { + x := fx10k() + y := fx10k() + _ = &x[9] // ERROR "generated nil check" + y = x + _ = &x[9] // ERROR "removed repeated nil check" + x = y + _ = &x[9] // ERROR "removed repeated nil check" +} + +func fx10() *[10]int + +func f4(x *[10]int) { + // Most of these have no checks because a real memory reference follows, + // and the offset is small enough that if x is nil, the address will still be + // in the first unmapped page of memory. + + _ = x[9] // ERROR "removed nil check before indirect" + + for { + if x[9] != 0 { // ERROR "removed nil check before indirect" + break + } + } + + x = fx10() + _ = x[9] // ERROR "removed nil check before indirect" + if b { + _ = x[9] // ERROR "removed nil check before indirect" + } else { + _ = x[9] // ERROR "removed nil check before indirect" + } + _ = x[9] // ERROR "removed nil check before indirect" + + x = fx10() + if b { + _ = x[9] // ERROR "removed nil check before indirect" + } else { + _ = &x[9] // ERROR "generated nil check" + } + _ = x[9] // ERROR "removed nil check before indirect" + + fx10() + _ = x[9] // ERROR "removed nil check before indirect" + + x = fx10() + y := fx10() + _ = &x[9] // ERROR "generated nil check" + y = x + _ = &x[9] // ERROR "removed repeated nil check" + x = y + _ = &x[9] // ERROR "removed repeated nil check" +} + |