diff options
author | David Chase <drchase@google.com> | 2018-03-23 22:46:06 -0400 |
---|---|---|
committer | David Chase <drchase@google.com> | 2018-05-14 14:09:49 +0000 |
commit | c2c1822b12fa1c86dcf067c845e9cae0a9725c12 (patch) | |
tree | 95e0f8b0ec294ab6a029ea698301ef97d3b65eb2 /src/cmd/compile/internal/ssa/value.go | |
parent | c06f02752022c1421d4310f8c13deaa28cca17fb (diff) | |
download | go-c2c1822b12fa1c86dcf067c845e9cae0a9725c12.tar.gz go-c2c1822b12fa1c86dcf067c845e9cae0a9725c12.zip |
cmd/compile: assign and preserve statement boundaries.
A new pass run after ssa building (before any other
optimization) identifies the "first" ssa node for each
statement. Other "noise" nodes are tagged as being never
appropriate for a statement boundary (e.g., VarKill, VarDef,
Phi).
Rewrite, deadcode, cse, and nilcheck are modified to move
the statement boundaries forward whenever possible if a
boundary-tagged ssa value is removed; never-boundary nodes
are ignored in this search (some operations involving
constants are also tagged as never-boundary and also ignored
because they are likely to be moved or removed during
optimization).
Code generation treats all nodes except those explicitly
marked as statement boundaries as "not statement" nodes,
and floats statement boundaries to the beginning of each
same-line run of instructions found within a basic block.
Line number html conversion was modified to make statement
boundary nodes a bit more obvious by prepending a "+".
The code in fuse.go that glued together the value slices
of two blocks produced a result that depended on the
former capacities (not lengths) of the two slices. This
causes differences in the 386 bootstrap, and also can
sometimes put values into an order that does a worse job
of preserving statement boundaries when values are removed.
Portions of two delve tests that had caught problems were
incorporated into ssa/debug_test.go. There are some
opportunities to do better with optimized code, but the
next-ing is not lying or overly jumpy.
Over 4 CLs, compilebench geomean measured binary size
increase of 3.5% and compile user time increase of 3.8%
(this is after optimization to reuse a sparse map instead
of creating multiple maps.)
This CL worsens the optimized-debugging experience with
Delve; we need to work with the delve team so that
they can use the is_stmt marks that we're emitting now.
The reference output changes from time to time depending
on other changes in the compiler, sometimes better,
sometimes worse.
This CL now includes a test ensuring that 99+% of the lines
in the Go command itself (a handy optimized binary) include
is_stmt markers.
Change-Id: I359c94e06843f1eb41f9da437bd614885aa9644a
Reviewed-on: https://go-review.googlesource.com/102435
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/value.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/value.go | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 9a79a99f54..6d5fe9caed 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -130,16 +130,21 @@ func (v *Value) LongString() string { for _, a := range v.Args { s += fmt.Sprintf(" %v", a) } - r := v.Block.Func.RegAlloc + var r []Location + if v.Block != nil { + r = v.Block.Func.RegAlloc + } if int(v.ID) < len(r) && r[v.ID] != nil { s += " : " + r[v.ID].String() } var names []string - for name, values := range v.Block.Func.NamedValues { - for _, value := range values { - if value == v { - names = append(names, name.String()) - break // drop duplicates. + if v.Block != nil { + for name, values := range v.Block.Func.NamedValues { + for _, value := range values { + if value == v { + names = append(names, name.String()) + break // drop duplicates. + } } } } @@ -244,6 +249,10 @@ func (v *Value) resetArgs() { func (v *Value) reset(op Op) { v.Op = op + if op != OpCopy && notStmtBoundary(op) { + // Special case for OpCopy because of how it is used in rewrite + v.Pos = v.Pos.WithNotStmt() + } v.resetArgs() v.AuxInt = 0 v.Aux = nil @@ -251,7 +260,7 @@ func (v *Value) reset(op Op) { // copyInto makes a new value identical to v and adds it to the end of b. func (v *Value) copyInto(b *Block) *Value { - c := b.NewValue0(v.Pos, v.Op, v.Type) // Lose the position, this causes line number churn otherwise. + c := b.NewValue0(v.Pos.WithNotStmt(), v.Op, v.Type) // Lose the position, this causes line number churn otherwise. c.Aux = v.Aux c.AuxInt = v.AuxInt c.AddArgs(v.Args...) @@ -263,13 +272,6 @@ func (v *Value) copyInto(b *Block) *Value { return c } -// copyIntoNoXPos makes a new value identical to v and adds it to the end of b. -// The copied value receives no source code position to avoid confusing changes -// in debugger information (the intended user is the register allocator). -func (v *Value) copyIntoNoXPos(b *Block) *Value { - return v.copyIntoWithXPos(b, src.NoXPos) -} - // copyIntoWithXPos makes a new value identical to v and adds it to the end of b. // The supplied position is used as the position of the new value. func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value { |