mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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>
This commit is contained in:
parent
4d0d9c2c5c
commit
41f3af9d04
62 changed files with 1273 additions and 1272 deletions
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// range
|
||||
func typecheckrange(n *ir.Node) {
|
||||
func typecheckrange(n ir.Node) {
|
||||
// Typechecking order is important here:
|
||||
// 0. first typecheck range expression (slice/map/chan),
|
||||
// it is evaluated only once and so logically it is not part of the loop.
|
||||
|
|
@ -39,7 +39,7 @@ func typecheckrange(n *ir.Node) {
|
|||
decldepth--
|
||||
}
|
||||
|
||||
func typecheckrangeExpr(n *ir.Node) {
|
||||
func typecheckrangeExpr(n ir.Node) {
|
||||
n.SetRight(typecheck(n.Right(), ctxExpr))
|
||||
|
||||
t := n.Right().Type()
|
||||
|
|
@ -95,7 +95,7 @@ func typecheckrangeExpr(n *ir.Node) {
|
|||
base.ErrorfAt(n.Pos(), "too many variables in range")
|
||||
}
|
||||
|
||||
var v1, v2 *ir.Node
|
||||
var v1, v2 ir.Node
|
||||
if n.List().Len() != 0 {
|
||||
v1 = n.List().First()
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ func cheapComputableIndex(width int64) bool {
|
|||
// simpler forms. The result must be assigned back to n.
|
||||
// Node n may also be modified in place, and may also be
|
||||
// the returned node.
|
||||
func walkrange(n *ir.Node) *ir.Node {
|
||||
func walkrange(n ir.Node) ir.Node {
|
||||
if isMapClear(n) {
|
||||
m := n.Right()
|
||||
lno := setlineno(m)
|
||||
|
|
@ -179,7 +179,7 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
lno := setlineno(a)
|
||||
n.SetRight(nil)
|
||||
|
||||
var v1, v2 *ir.Node
|
||||
var v1, v2 ir.Node
|
||||
l := n.List().Len()
|
||||
if l > 0 {
|
||||
v1 = n.List().First()
|
||||
|
|
@ -205,12 +205,12 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
// to avoid erroneous processing by racewalk.
|
||||
n.PtrList().Set(nil)
|
||||
|
||||
var ifGuard *ir.Node
|
||||
var ifGuard ir.Node
|
||||
|
||||
translatedLoopOp := ir.OFOR
|
||||
|
||||
var body []*ir.Node
|
||||
var init []*ir.Node
|
||||
var body []ir.Node
|
||||
var init []ir.Node
|
||||
switch t.Etype {
|
||||
default:
|
||||
base.Fatalf("walkrange")
|
||||
|
|
@ -240,7 +240,7 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
|
||||
// for v1 := range ha { body }
|
||||
if v2 == nil {
|
||||
body = []*ir.Node{ir.Nod(ir.OAS, v1, hv1)}
|
||||
body = []ir.Node{ir.Nod(ir.OAS, v1, hv1)}
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
a := ir.Nod(ir.OAS2, nil, nil)
|
||||
a.PtrList().Set2(v1, v2)
|
||||
a.PtrRlist().Set2(hv1, tmp)
|
||||
body = []*ir.Node{a}
|
||||
body = []ir.Node{a}
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -321,14 +321,14 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
if v1 == nil {
|
||||
body = nil
|
||||
} else if v2 == nil {
|
||||
body = []*ir.Node{ir.Nod(ir.OAS, v1, key)}
|
||||
body = []ir.Node{ir.Nod(ir.OAS, v1, key)}
|
||||
} else {
|
||||
elem := nodSym(ir.ODOT, hit, elemsym)
|
||||
elem = ir.Nod(ir.ODEREF, elem, nil)
|
||||
a := ir.Nod(ir.OAS2, nil, nil)
|
||||
a.PtrList().Set2(v1, v2)
|
||||
a.PtrRlist().Set2(key, elem)
|
||||
body = []*ir.Node{a}
|
||||
body = []ir.Node{a}
|
||||
}
|
||||
|
||||
case types.TCHAN:
|
||||
|
|
@ -353,7 +353,7 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
if v1 == nil {
|
||||
body = nil
|
||||
} else {
|
||||
body = []*ir.Node{ir.Nod(ir.OAS, v1, hv1)}
|
||||
body = []ir.Node{ir.Nod(ir.OAS, v1, hv1)}
|
||||
}
|
||||
// Zero hv1. This prevents hv1 from being the sole, inaccessible
|
||||
// reference to an otherwise GC-able value during the next channel receive.
|
||||
|
|
@ -467,7 +467,7 @@ func walkrange(n *ir.Node) *ir.Node {
|
|||
// }
|
||||
//
|
||||
// where == for keys of map m is reflexive.
|
||||
func isMapClear(n *ir.Node) bool {
|
||||
func isMapClear(n ir.Node) bool {
|
||||
if base.Flag.N != 0 || instrumenting {
|
||||
return false
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ func isMapClear(n *ir.Node) bool {
|
|||
}
|
||||
|
||||
// mapClear constructs a call to runtime.mapclear for the map m.
|
||||
func mapClear(m *ir.Node) *ir.Node {
|
||||
func mapClear(m ir.Node) ir.Node {
|
||||
t := m.Type()
|
||||
|
||||
// instantiate mapclear(typ *type, hmap map[any]any)
|
||||
|
|
@ -534,7 +534,7 @@ func mapClear(m *ir.Node) *ir.Node {
|
|||
// in which the evaluation of a is side-effect-free.
|
||||
//
|
||||
// Parameters are as in walkrange: "for v1, v2 = range a".
|
||||
func arrayClear(n, v1, v2, a *ir.Node) bool {
|
||||
func arrayClear(n, v1, v2, a ir.Node) bool {
|
||||
if base.Flag.N != 0 || instrumenting {
|
||||
return false
|
||||
}
|
||||
|
|
@ -590,7 +590,7 @@ func arrayClear(n, v1, v2, a *ir.Node) bool {
|
|||
tmp = conv(tmp, types.Types[types.TUINTPTR])
|
||||
n.PtrBody().Append(ir.Nod(ir.OAS, hn, tmp))
|
||||
|
||||
var fn *ir.Node
|
||||
var fn ir.Node
|
||||
if a.Type().Elem().HasPointers() {
|
||||
// memclrHasPointers(hp, hn)
|
||||
Curfn.Func().SetWBPos(stmt.Pos())
|
||||
|
|
@ -615,7 +615,7 @@ func arrayClear(n, v1, v2, a *ir.Node) bool {
|
|||
}
|
||||
|
||||
// addptr returns (*T)(uintptr(p) + n).
|
||||
func addptr(p *ir.Node, n int64) *ir.Node {
|
||||
func addptr(p ir.Node, n int64) ir.Node {
|
||||
t := p.Type()
|
||||
|
||||
p = ir.Nod(ir.OCONVNOP, p, nil)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue