diff options
| author | Josh Bleecher Snyder <josharian@gmail.com> | 2017-03-09 13:30:20 -0800 |
|---|---|---|
| committer | David Chase <drchase@google.com> | 2017-03-13 18:38:28 +0000 |
| commit | c694f6f3a80bcb42960e021b279eb6d23baf2c50 (patch) | |
| tree | 07cdf32814ddc1f978a5cf49afc6dcfd4f58489a /src | |
| parent | 4e0c7c3f61475116c4ae8d11ef796819d9c404f0 (diff) | |
| download | go-c694f6f3a80bcb42960e021b279eb6d23baf2c50.tar.xz | |
cmd/compile: eliminate more nil checks of phis
The existing implementation started by eliminating
nil checks for OpAddr, OpAddPtr, and OpPhis with
all non-nil args.
However, some OpPhis had all non-nil args,
but their args had not been processed yet.
Pull the OpPhi checks into their own loop,
and repeat until stabilization.
Eliminates a dozen additional nilchecks during make.bash.
Negligible compiler performance impact.
Change-Id: If7b803c3ad7582af7d9867d05ca13e03e109d864
Reviewed-on: https://go-review.googlesource.com/37999
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/ssa/nilcheck.go | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index ea6523d24c..c63b7d2200 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -39,23 +39,36 @@ func nilcheckelim(f *Func) { // make an initial pass identifying any non-nil values for _, b := range f.Blocks { - // a value resulting from taking the address of a - // value, or a value constructed from an offset of a - // non-nil ptr (OpAddPtr) implies it is non-nil for _, v := range b.Values { + // a value resulting from taking the address of a + // value, or a value constructed from an offset of a + // non-nil ptr (OpAddPtr) implies it is non-nil if v.Op == OpAddr || v.Op == OpAddPtr { nonNilValues[v.ID] = true - } else if v.Op == OpPhi { + } + } + } + + for changed := true; changed; { + changed = false + for _, b := range f.Blocks { + for _, v := range b.Values { // phis whose arguments are all non-nil // are non-nil - argsNonNil := true - for _, a := range v.Args { - if !nonNilValues[a.ID] { - argsNonNil = false + if v.Op == OpPhi { + argsNonNil := true + for _, a := range v.Args { + if !nonNilValues[a.ID] { + argsNonNil = false + break + } + } + if argsNonNil { + if !nonNilValues[v.ID] { + changed = true + } + nonNilValues[v.ID] = true } - } - if argsNonNil { - nonNilValues[v.ID] = true } } } |
