aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/value.go
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2018-03-23 22:46:06 -0400
committerDavid Chase <drchase@google.com>2018-05-14 14:09:49 +0000
commitc2c1822b12fa1c86dcf067c845e9cae0a9725c12 (patch)
tree95e0f8b0ec294ab6a029ea698301ef97d3b65eb2 /src/cmd/compile/internal/ssa/value.go
parentc06f02752022c1421d4310f8c13deaa28cca17fb (diff)
downloadgo-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.go30
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 {