diff options
| author | Russ Cox <rsc@golang.org> | 2020-11-25 01:11:56 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2020-11-25 17:30:43 +0000 |
| commit | 41f3af9d04362a56c1af186af134c704a03fa97b (patch) | |
| tree | e67e7c1b67dd5c48a4c18fdb2f973bf789c7b2d1 /src/cmd/compile/internal/gc/sinit.go | |
| parent | 4d0d9c2c5c35377b0662f2fd0995867919552251 (diff) | |
| download | go-git-41f3af9d04362a56c1af186af134c704a03fa97b.tar.gz | |
[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/gc/sinit.go')
| -rw-r--r-- | src/cmd/compile/internal/gc/sinit.go | 78 |
1 files changed, 39 insertions, 39 deletions
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index c0f85a1e33..e30663cfbb 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -14,8 +14,8 @@ import ( ) type InitEntry struct { - Xoffset int64 // struct, array only - Expr *ir.Node // bytes of run-time computed expressions + Xoffset int64 // struct, array only + Expr ir.Node // bytes of run-time computed expressions } type InitPlan struct { @@ -29,18 +29,18 @@ type InitPlan struct { type InitSchedule struct { // out is the ordered list of dynamic initialization // statements. - out []*ir.Node + out []ir.Node - initplans map[*ir.Node]*InitPlan - inittemps map[*ir.Node]*ir.Node + initplans map[ir.Node]*InitPlan + inittemps map[ir.Node]ir.Node } -func (s *InitSchedule) append(n *ir.Node) { +func (s *InitSchedule) append(n ir.Node) { s.out = append(s.out, n) } // staticInit adds an initialization statement n to the schedule. -func (s *InitSchedule) staticInit(n *ir.Node) { +func (s *InitSchedule) staticInit(n ir.Node) { if !s.tryStaticInit(n) { if base.Flag.Percent != 0 { ir.Dump("nonstatic", n) @@ -51,7 +51,7 @@ func (s *InitSchedule) staticInit(n *ir.Node) { // tryStaticInit attempts to statically execute an initialization // statement and reports whether it succeeded. -func (s *InitSchedule) tryStaticInit(n *ir.Node) bool { +func (s *InitSchedule) tryStaticInit(n ir.Node) bool { // Only worry about simple "l = r" assignments. Multiple // variable/expression OAS2 assignments have already been // replaced by multiple simple OAS assignments, and the other @@ -70,7 +70,7 @@ func (s *InitSchedule) tryStaticInit(n *ir.Node) bool { // like staticassign but we are copying an already // initialized value r. -func (s *InitSchedule) staticcopy(l *ir.Node, r *ir.Node) bool { +func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool { if r.Op() != ir.ONAME && r.Op() != ir.OMETHEXPR { return false } @@ -168,7 +168,7 @@ func (s *InitSchedule) staticcopy(l *ir.Node, r *ir.Node) bool { return false } -func (s *InitSchedule) staticassign(l *ir.Node, r *ir.Node) bool { +func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool { for r.Op() == ir.OCONVNOP { r = r.Left() } @@ -289,7 +289,7 @@ func (s *InitSchedule) staticassign(l *ir.Node, r *ir.Node) bool { markTypeUsedInInterface(val.Type(), l.Sym().Linksym()) - var itab *ir.Node + var itab ir.Node if l.Type().IsEmptyInterface() { itab = typename(val.Type()) } else { @@ -367,7 +367,7 @@ var statuniqgen int // name generator for static temps // staticname returns a name backed by a (writable) static data symbol. // Use readonlystaticname for read-only node. -func staticname(t *types.Type) *ir.Node { +func staticname(t *types.Type) ir.Node { // Don't use lookupN; it interns the resulting string, but these are all unique. n := NewName(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen))) statuniqgen++ @@ -377,18 +377,18 @@ func staticname(t *types.Type) *ir.Node { } // readonlystaticname returns a name backed by a (writable) static data symbol. -func readonlystaticname(t *types.Type) *ir.Node { +func readonlystaticname(t *types.Type) ir.Node { n := staticname(t) n.MarkReadonly() n.Sym().Linksym().Set(obj.AttrContentAddressable, true) return n } -func isSimpleName(n *ir.Node) bool { +func isSimpleName(n ir.Node) bool { return (n.Op() == ir.ONAME || n.Op() == ir.OMETHEXPR) && n.Class() != ir.PAUTOHEAP && n.Class() != ir.PEXTERN } -func litas(l *ir.Node, r *ir.Node, init *ir.Nodes) { +func litas(l ir.Node, r ir.Node, init *ir.Nodes) { a := ir.Nod(ir.OAS, l, r) a = typecheck(a, ctxStmt) a = walkexpr(a, init) @@ -405,7 +405,7 @@ const ( // getdyn calculates the initGenType for n. // If top is false, getdyn is recursing. -func getdyn(n *ir.Node, top bool) initGenType { +func getdyn(n ir.Node, top bool) initGenType { switch n.Op() { default: if isGoConst(n) { @@ -447,7 +447,7 @@ func getdyn(n *ir.Node, top bool) initGenType { } // isStaticCompositeLiteral reports whether n is a compile-time constant. -func isStaticCompositeLiteral(n *ir.Node) bool { +func isStaticCompositeLiteral(n ir.Node) bool { switch n.Op() { case ir.OSLICELIT: return false @@ -509,13 +509,13 @@ const ( // fixedlit handles struct, array, and slice literals. // TODO: expand documentation. -func fixedlit(ctxt initContext, kind initKind, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { +func fixedlit(ctxt initContext, kind initKind, n ir.Node, var_ ir.Node, init *ir.Nodes) { isBlank := var_ == ir.BlankNode - var splitnode func(*ir.Node) (a *ir.Node, value *ir.Node) + var splitnode func(ir.Node) (a ir.Node, value ir.Node) switch n.Op() { case ir.OARRAYLIT, ir.OSLICELIT: var k int64 - splitnode = func(r *ir.Node) (*ir.Node, *ir.Node) { + splitnode = func(r ir.Node) (ir.Node, ir.Node) { if r.Op() == ir.OKEY { k = indexconst(r.Left()) if k < 0 { @@ -531,7 +531,7 @@ func fixedlit(ctxt initContext, kind initKind, n *ir.Node, var_ *ir.Node, init * return a, r } case ir.OSTRUCTLIT: - splitnode = func(r *ir.Node) (*ir.Node, *ir.Node) { + splitnode = func(r ir.Node) (ir.Node, ir.Node) { if r.Op() != ir.OSTRUCTKEY { base.Fatalf("fixedlit: rhs not OSTRUCTKEY: %v", r) } @@ -576,7 +576,7 @@ func fixedlit(ctxt initContext, kind initKind, n *ir.Node, var_ *ir.Node, init * case initKindStatic: genAsStatic(a) case initKindDynamic, initKindLocalCode: - a = orderStmtInPlace(a, map[string][]*ir.Node{}) + a = orderStmtInPlace(a, map[string][]ir.Node{}) a = walkstmt(a) init.Append(a) default: @@ -586,7 +586,7 @@ func fixedlit(ctxt initContext, kind initKind, n *ir.Node, var_ *ir.Node, init * } } -func isSmallSliceLit(n *ir.Node) bool { +func isSmallSliceLit(n ir.Node) bool { if n.Op() != ir.OSLICELIT { return false } @@ -596,7 +596,7 @@ func isSmallSliceLit(n *ir.Node) bool { return smallintconst(r) && (n.Type().Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type().Elem().Width) } -func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { +func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { // make an array type corresponding the number of elements we have t := types.NewArray(n.Type().Elem(), n.Right().Int64Val()) dowidth(t) @@ -639,7 +639,7 @@ func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { // if the literal contains constants, // make static initialized array (1),(2) - var vstat *ir.Node + var vstat ir.Node mode := getdyn(n, true) if mode&initConst != 0 && !isSmallSliceLit(n) { @@ -655,7 +655,7 @@ func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { vauto := temp(types.NewPtr(t)) // set auto to point at new temp or heap (3 assign) - var a *ir.Node + var a ir.Node if x := prealloc[n]; x != nil { // temp allocated during order.go for dddarg if !types.Identical(t, x.Type()) { @@ -745,7 +745,7 @@ func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OAS, a, value) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]*ir.Node{}) + a = orderStmtInPlace(a, map[string][]ir.Node{}) a = walkstmt(a) init.Append(a) } @@ -754,12 +754,12 @@ func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OAS, var_, ir.Nod(ir.OSLICE, vauto, nil)) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]*ir.Node{}) + a = orderStmtInPlace(a, map[string][]ir.Node{}) a = walkstmt(a) init.Append(a) } -func maplit(n *ir.Node, m *ir.Node, init *ir.Nodes) { +func maplit(n ir.Node, m ir.Node, init *ir.Nodes) { // make the map var a := ir.Nod(ir.OMAKE, nil, nil) a.SetEsc(n.Esc()) @@ -866,7 +866,7 @@ func maplit(n *ir.Node, m *ir.Node, init *ir.Nodes) { init.Append(a) } -func anylit(n *ir.Node, var_ *ir.Node, init *ir.Nodes) { +func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) { t := n.Type() switch n.Op() { default: @@ -882,7 +882,7 @@ func anylit(n *ir.Node, var_ *ir.Node, init *ir.Nodes) { base.Fatalf("anylit: not ptr") } - var r *ir.Node + var r ir.Node if n.Right() != nil { // n.Right is stack temporary used as backing store. init.Append(ir.Nod(ir.OAS, n.Right(), nil)) // zero backing store, just in case (#18410) @@ -959,7 +959,7 @@ func anylit(n *ir.Node, var_ *ir.Node, init *ir.Nodes) { } } -func oaslit(n *ir.Node, init *ir.Nodes) bool { +func oaslit(n ir.Node, init *ir.Nodes) bool { if n.Left() == nil || n.Right() == nil { // not a special composite literal assignment return false @@ -995,7 +995,7 @@ func oaslit(n *ir.Node, init *ir.Nodes) bool { return true } -func getlit(lit *ir.Node) int { +func getlit(lit ir.Node) int { if smallintconst(lit) { return int(lit.Int64Val()) } @@ -1003,7 +1003,7 @@ func getlit(lit *ir.Node) int { } // stataddr returns the static address of n, if n has one, or else nil. -func stataddr(n *ir.Node) *ir.Node { +func stataddr(n ir.Node) ir.Node { if n == nil { return nil } @@ -1046,7 +1046,7 @@ func stataddr(n *ir.Node) *ir.Node { return nil } -func (s *InitSchedule) initplan(n *ir.Node) { +func (s *InitSchedule) initplan(n ir.Node) { if s.initplans[n] != nil { return } @@ -1091,7 +1091,7 @@ func (s *InitSchedule) initplan(n *ir.Node) { } } -func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *ir.Node) { +func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n ir.Node) { // special case: zero can be dropped entirely if isZero(n) { return @@ -1113,7 +1113,7 @@ func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *ir.Node) { p.E = append(p.E, InitEntry{Xoffset: xoffset, Expr: n}) } -func isZero(n *ir.Node) bool { +func isZero(n ir.Node) bool { switch n.Op() { case ir.ONIL: return true @@ -1151,11 +1151,11 @@ func isZero(n *ir.Node) bool { return false } -func isvaluelit(n *ir.Node) bool { +func isvaluelit(n ir.Node) bool { return n.Op() == ir.OARRAYLIT || n.Op() == ir.OSTRUCTLIT } -func genAsStatic(as *ir.Node) { +func genAsStatic(as ir.Node) { if as.Left().Type() == nil { base.Fatalf("genAsStatic as.Left not typechecked") } |
