aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2020-11-25 01:11:56 -0500
committerRuss Cox <rsc@golang.org>2020-11-25 17:30:43 +0000
commit41f3af9d04362a56c1af186af134c704a03fa97b (patch)
treee67e7c1b67dd5c48a4c18fdb2f973bf789c7b2d1 /src/cmd/compile/internal/ssa
parent4d0d9c2c5c35377b0662f2fd0995867919552251 (diff)
downloadgo-41f3af9d04362a56c1af186af134c704a03fa97b.tar.gz
go-41f3af9d04362a56c1af186af134c704a03fa97b.zip
[dev.regabi] cmd/compile: replace *Node type with an interface Node [generated]
The plan is to introduce a Node interface that replaces the old *Node pointer-to-struct. The previous CL defined an interface INode modeling a *Node. This CL: - Changes all references outside internal/ir to use INode, along with many references inside internal/ir as well. - Renames Node to node. - Renames INode to Node So now ir.Node is an interface implemented by *ir.node, which is otherwise inaccessible, and the code outside package ir is now (clearly) using only the interface. The usual rule is never to redefine an existing name with a new meaning, so that old code that hasn't been updated gets a "unknown name" error instead of more mysterious errors or silent misbehavior. That rule would caution against replacing Node-the-struct with Node-the-interface, as in this CL, because code that says *Node would now be using a pointer to an interface. But this CL is being landed at the same time as another that moves Node from gc to ir. So the net effect is to replace *gc.Node with ir.Node, which does follow the rule: any lingering references to gc.Node will be told it's gone, not silently start using pointers to interfaces. So the rule is followed by the CL sequence, just not this specific CL. Overall, the loss of inlining caused by using interfaces cuts the compiler speed by about 6%, a not insignificant amount. However, as we convert the representation to concrete structs that are not the giant Node over the next weeks, that speed should come back as more of the compiler starts operating directly on concrete types and the memory taken up by the graph of Nodes drops due to the more precise structs. Honestly, I was expecting worse. % benchstat bench.old bench.new name old time/op new time/op delta Template 168ms ± 4% 182ms ± 2% +8.34% (p=0.000 n=9+9) Unicode 72.2ms ±10% 82.5ms ± 6% +14.38% (p=0.000 n=9+9) GoTypes 563ms ± 8% 598ms ± 2% +6.14% (p=0.006 n=9+9) Compiler 2.89s ± 4% 3.04s ± 2% +5.37% (p=0.000 n=10+9) SSA 6.45s ± 4% 7.25s ± 5% +12.41% (p=0.000 n=9+10) Flate 105ms ± 2% 115ms ± 1% +9.66% (p=0.000 n=10+8) GoParser 144ms ±10% 152ms ± 2% +5.79% (p=0.011 n=9+8) Reflect 345ms ± 9% 370ms ± 4% +7.28% (p=0.001 n=10+9) Tar 149ms ± 9% 161ms ± 5% +8.05% (p=0.001 n=10+9) XML 190ms ± 3% 209ms ± 2% +9.54% (p=0.000 n=9+8) LinkCompiler 327ms ± 2% 325ms ± 2% ~ (p=0.382 n=8+8) ExternalLinkCompiler 1.77s ± 4% 1.73s ± 6% ~ (p=0.113 n=9+10) LinkWithoutDebugCompiler 214ms ± 4% 211ms ± 2% ~ (p=0.360 n=10+8) StdCmd 14.8s ± 3% 15.9s ± 1% +6.98% (p=0.000 n=10+9) [Geo mean] 480ms 510ms +6.31% name old user-time/op new user-time/op delta Template 223ms ± 3% 237ms ± 3% +6.16% (p=0.000 n=9+10) Unicode 103ms ± 6% 113ms ± 3% +9.53% (p=0.000 n=9+9) GoTypes 758ms ± 8% 800ms ± 2% +5.55% (p=0.003 n=10+9) Compiler 3.95s ± 2% 4.12s ± 2% +4.34% (p=0.000 n=10+9) SSA 9.43s ± 1% 9.74s ± 4% +3.25% (p=0.000 n=8+10) Flate 132ms ± 2% 141ms ± 2% +6.89% (p=0.000 n=9+9) GoParser 177ms ± 9% 183ms ± 4% ~ (p=0.050 n=9+9) Reflect 467ms ±10% 495ms ± 7% +6.17% (p=0.029 n=10+10) Tar 183ms ± 9% 197ms ± 5% +7.92% (p=0.001 n=10+10) XML 249ms ± 5% 268ms ± 4% +7.82% (p=0.000 n=10+9) LinkCompiler 544ms ± 5% 544ms ± 6% ~ (p=0.863 n=9+9) ExternalLinkCompiler 1.79s ± 4% 1.75s ± 6% ~ (p=0.075 n=10+10) LinkWithoutDebugCompiler 248ms ± 6% 246ms ± 2% ~ (p=0.965 n=10+8) [Geo mean] 483ms 504ms +4.41% [git-generate] cd src/cmd/compile/internal/ir : # We need to do the conversion in multiple steps, so we introduce : # a temporary type alias that will start out meaning the pointer-to-struct : # and then change to mean the interface. rf ' mv Node OldNode add node.go \ type Node = *OldNode ' : # It should work to do this ex in ir, but it misses test files, due to a bug in rf. : # Run the command in gc to handle gc's tests, and then again in ssa for ssa's tests. cd ../gc rf ' ex . ../arm ../riscv64 ../arm64 ../mips64 ../ppc64 ../mips ../wasm { import "cmd/compile/internal/ir" *ir.OldNode -> ir.Node } ' cd ../ssa rf ' ex { import "cmd/compile/internal/ir" *ir.OldNode -> ir.Node } ' : # Back in ir, finish conversion clumsily with sed, : # because type checking and circular aliases do not mix. cd ../ir sed -i '' ' /type Node = \*OldNode/d s/\*OldNode/Node/g s/^func (n Node)/func (n *OldNode)/ s/OldNode/node/g s/type INode interface/type Node interface/ s/var _ INode = (Node)(nil)/var _ Node = (*node)(nil)/ ' *.go gofmt -w *.go sed -i '' ' s/{Func{}, 136, 248}/{Func{}, 152, 280}/ s/{Name{}, 32, 56}/{Name{}, 44, 80}/ s/{Param{}, 24, 48}/{Param{}, 44, 88}/ s/{node{}, 76, 128}/{node{}, 88, 152}/ ' sizeof_test.go cd ../ssa sed -i '' ' s/{LocalSlot{}, 28, 40}/{LocalSlot{}, 32, 48}/ ' sizeof_test.go cd ../gc sed -i '' 's/\*ir.Node/ir.Node/' mkbuiltin.go cd ../../../.. go install std cmd cd cmd/compile go test -u || go test -u Change-Id: I196bbe3b648e4701662e4a2bada40bf155e2a553 Reviewed-on: https://go-review.googlesource.com/c/go/+/272935 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa')
-rw-r--r--src/cmd/compile/internal/ssa/config.go2
-rw-r--r--src/cmd/compile/internal/ssa/deadstore.go20
-rw-r--r--src/cmd/compile/internal/ssa/debug.go12
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go2
-rw-r--r--src/cmd/compile/internal/ssa/location.go2
-rw-r--r--src/cmd/compile/internal/ssa/nilcheck.go2
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go2
-rw-r--r--src/cmd/compile/internal/ssa/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/ssa/stackalloc.go2
9 files changed, 23 insertions, 23 deletions
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
index 62abbdc223..eeabd81d03 100644
--- a/src/cmd/compile/internal/ssa/config.go
+++ b/src/cmd/compile/internal/ssa/config.go
@@ -139,7 +139,7 @@ type Frontend interface {
// Auto returns a Node for an auto variable of the given type.
// The SSA compiler uses this function to allocate space for spills.
- Auto(src.XPos, *types.Type) *ir.Node
+ Auto(src.XPos, *types.Type) ir.Node
// Given the name for a compound type, returns the name we should use
// for the parts of that compound type.
diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go
index 0f1cd4bc9f..f3ef33d670 100644
--- a/src/cmd/compile/internal/ssa/deadstore.go
+++ b/src/cmd/compile/internal/ssa/deadstore.go
@@ -137,9 +137,9 @@ func dse(f *Func) {
// reaches stores then we delete all the stores. The other operations will then
// be eliminated by the dead code elimination pass.
func elimDeadAutosGeneric(f *Func) {
- addr := make(map[*Value]*ir.Node) // values that the address of the auto reaches
- elim := make(map[*Value]*ir.Node) // values that could be eliminated if the auto is
- used := make(map[*ir.Node]bool) // used autos that must be kept
+ addr := make(map[*Value]ir.Node) // values that the address of the auto reaches
+ elim := make(map[*Value]ir.Node) // values that could be eliminated if the auto is
+ used := make(map[ir.Node]bool) // used autos that must be kept
// visit the value and report whether any of the maps are updated
visit := func(v *Value) (changed bool) {
@@ -147,7 +147,7 @@ func elimDeadAutosGeneric(f *Func) {
switch v.Op {
case OpAddr, OpLocalAddr:
// Propagate the address if it points to an auto.
- n, ok := v.Aux.(*ir.Node)
+ n, ok := v.Aux.(ir.Node)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -158,7 +158,7 @@ func elimDeadAutosGeneric(f *Func) {
return
case OpVarDef, OpVarKill:
// v should be eliminated if we eliminate the auto.
- n, ok := v.Aux.(*ir.Node)
+ n, ok := v.Aux.(ir.Node)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -174,7 +174,7 @@ func elimDeadAutosGeneric(f *Func) {
// for open-coded defers from being removed (since they
// may not be used by the inline code, but will be used by
// panic processing).
- n, ok := v.Aux.(*ir.Node)
+ n, ok := v.Aux.(ir.Node)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -222,7 +222,7 @@ func elimDeadAutosGeneric(f *Func) {
}
// Propagate any auto addresses through v.
- var node *ir.Node
+ var node ir.Node
for _, a := range args {
if n, ok := addr[a]; ok && !used[n] {
if node == nil {
@@ -299,11 +299,11 @@ func elimUnreadAutos(f *Func) {
// Loop over all ops that affect autos taking note of which
// autos we need and also stores that we might be able to
// eliminate.
- seen := make(map[*ir.Node]bool)
+ seen := make(map[ir.Node]bool)
var stores []*Value
for _, b := range f.Blocks {
for _, v := range b.Values {
- n, ok := v.Aux.(*ir.Node)
+ n, ok := v.Aux.(ir.Node)
if !ok {
continue
}
@@ -335,7 +335,7 @@ func elimUnreadAutos(f *Func) {
// Eliminate stores to unread autos.
for _, store := range stores {
- n, _ := store.Aux.(*ir.Node)
+ n, _ := store.Aux.(ir.Node)
if seen[n] {
continue
}
diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go
index 9de5f427c0..0d660361b1 100644
--- a/src/cmd/compile/internal/ssa/debug.go
+++ b/src/cmd/compile/internal/ssa/debug.go
@@ -25,7 +25,7 @@ type FuncDebug struct {
// Slots is all the slots used in the debug info, indexed by their SlotID.
Slots []LocalSlot
// The user variables, indexed by VarID.
- Vars []*ir.Node
+ Vars []ir.Node
// The slots that make up each variable, indexed by VarID.
VarSlots [][]SlotID
// The location list data, indexed by VarID. Must be processed by PutLocationList.
@@ -166,7 +166,7 @@ func (s *debugState) logf(msg string, args ...interface{}) {
type debugState struct {
// See FuncDebug.
slots []LocalSlot
- vars []*ir.Node
+ vars []ir.Node
varSlots [][]SlotID
lists [][]byte
@@ -190,7 +190,7 @@ type debugState struct {
// The pending location list entry for each user variable, indexed by VarID.
pendingEntries []pendingEntry
- varParts map[*ir.Node][]SlotID
+ varParts map[ir.Node][]SlotID
blockDebug []BlockDebug
pendingSlotLocs []VarLoc
liveSlots []liveSlot
@@ -347,7 +347,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
}
if state.varParts == nil {
- state.varParts = make(map[*ir.Node][]SlotID)
+ state.varParts = make(map[ir.Node][]SlotID)
} else {
for n := range state.varParts {
delete(state.varParts, n)
@@ -380,7 +380,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
for _, b := range f.Blocks {
for _, v := range b.Values {
if v.Op == OpVarDef || v.Op == OpVarKill {
- n := v.Aux.(*ir.Node)
+ n := v.Aux.(ir.Node)
if ir.IsSynthetic(n) {
continue
}
@@ -718,7 +718,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register)
switch {
case v.Op == OpVarDef, v.Op == OpVarKill:
- n := v.Aux.(*ir.Node)
+ n := v.Aux.(ir.Node)
if ir.IsSynthetic(n) {
break
}
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index 3d142a2272..df83383308 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -69,7 +69,7 @@ type TestFrontend struct {
func (TestFrontend) StringData(s string) *obj.LSym {
return nil
}
-func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Node {
+func (TestFrontend) Auto(pos src.XPos, t *types.Type) ir.Node {
n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"})
n.SetClass(ir.PAUTO)
return n
diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go
index 2f456c9f89..3dc3a81703 100644
--- a/src/cmd/compile/internal/ssa/location.go
+++ b/src/cmd/compile/internal/ssa/location.go
@@ -60,7 +60,7 @@ func (r *Register) GCNum() int16 {
// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
// parent = &{N: s, Type: string}
type LocalSlot struct {
- N *ir.Node // an ONAME *gc.Node representing a stack location.
+ N ir.Node // an ONAME *gc.Node representing a stack location.
Type *types.Type // type of slot
Off int64 // offset of slot in N
diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go
index 3c1fa600a3..b36f6b97e1 100644
--- a/src/cmd/compile/internal/ssa/nilcheck.go
+++ b/src/cmd/compile/internal/ssa/nilcheck.go
@@ -236,7 +236,7 @@ func nilcheckelim2(f *Func) {
continue
}
if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
- if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(*ir.Node).Type().HasPointers()) {
+ if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(ir.Node).Type().HasPointers()) {
// These ops don't really change memory.
continue
// Note: OpVarDef requires that the defined variable not have pointers.
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 9841883939..459a9923f7 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -1249,7 +1249,7 @@ func (s *regAllocState) regalloc(f *Func) {
// This forces later liveness analysis to make the
// value live at this point.
v.SetArg(0, s.makeSpill(a, b))
- } else if _, ok := a.Aux.(*ir.Node); ok && vi.rematerializeable {
+ } else if _, ok := a.Aux.(ir.Node); ok && vi.rematerializeable {
// Rematerializeable value with a gc.Node. This is the address of
// a stack object (e.g. an LEAQ). Keep the object live.
// Change it to VarLive, which is what plive expects for locals.
diff --git a/src/cmd/compile/internal/ssa/sizeof_test.go b/src/cmd/compile/internal/ssa/sizeof_test.go
index a27002ee3a..60ada011e3 100644
--- a/src/cmd/compile/internal/ssa/sizeof_test.go
+++ b/src/cmd/compile/internal/ssa/sizeof_test.go
@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
}{
{Value{}, 72, 112},
{Block{}, 164, 304},
- {LocalSlot{}, 28, 40},
+ {LocalSlot{}, 32, 48},
{valState{}, 28, 40},
}
diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go
index eee0a21a66..5257d44cfe 100644
--- a/src/cmd/compile/internal/ssa/stackalloc.go
+++ b/src/cmd/compile/internal/ssa/stackalloc.go
@@ -157,7 +157,7 @@ func (s *stackAllocState) stackalloc() {
if v.Aux == nil {
f.Fatalf("%s has nil Aux\n", v.LongString())
}
- loc := LocalSlot{N: v.Aux.(*ir.Node), Type: v.Type, Off: v.AuxInt}
+ loc := LocalSlot{N: v.Aux.(ir.Node), Type: v.Type, Off: v.AuxInt}
if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, loc)
}