Skip to content

Commit a2058ba

Browse files
committed
[dev.regabi] cmd/compile: add ConstExpr
Currently, we represent constant-folded expressions with Name, which is suboptimal because Name has a lot of fields to support declared names (which are irrelevant to constant-folded expressions), while constant expressions are fairly common. This CL introduces a new lightweight ConstExpr type that simply wraps an existing expression and associates it with a value. Passes buildall w/ toolstash -cmp. name old time/op new time/op delta Template 252ms ± 3% 254ms ± 1% ~ (p=0.821 n=12+10) Unicode 120ms ± 2% 107ms ± 7% -11.09% (p=0.000 n=12+12) GoTypes 918ms ± 2% 918ms ± 1% ~ (p=0.974 n=12+10) Compiler 5.19s ± 1% 5.18s ± 0% ~ (p=0.190 n=12+11) SSA 12.4s ± 1% 12.3s ± 1% ~ (p=0.283 n=10+12) Flate 152ms ± 2% 148ms ± 4% -2.68% (p=0.007 n=10+12) GoParser 212ms ± 1% 211ms ± 2% ~ (p=0.674 n=10+12) Reflect 543ms ± 3% 542ms ± 3% ~ (p=0.799 n=12+12) Tar 224ms ± 2% 225ms ± 2% ~ (p=0.378 n=12+12) XML 292ms ± 1% 299ms ± 3% +2.18% (p=0.006 n=10+12) name old user-time/op new user-time/op delta Template 243ms ± 4% 244ms ± 5% ~ (p=0.887 n=12+12) Unicode 112ms ± 6% 100ms ±10% -10.76% (p=0.000 n=12+12) GoTypes 898ms ± 3% 895ms ± 3% ~ (p=0.671 n=12+12) Compiler 5.10s ± 1% 5.08s ± 1% ~ (p=0.104 n=12+11) SSA 12.2s ± 2% 12.1s ± 1% ~ (p=0.487 n=11+12) Flate 144ms ± 6% 145ms ± 5% ~ (p=0.695 n=12+11) GoParser 205ms ± 5% 204ms ± 3% ~ (p=0.514 n=12+12) Reflect 528ms ± 3% 531ms ± 4% ~ (p=0.630 n=12+12) Tar 218ms ± 4% 219ms ± 3% ~ (p=0.843 n=12+12) XML 284ms ± 5% 291ms ± 5% ~ (p=0.069 n=11+12) name old alloc/op new alloc/op delta Template 37.0MB ± 0% 36.7MB ± 0% -0.72% (p=0.000 n=12+12) Unicode 31.9MB ± 0% 29.5MB ± 0% -7.60% (p=0.000 n=12+12) GoTypes 119MB ± 0% 118MB ± 0% -0.40% (p=0.000 n=12+12) Compiler 629MB ± 0% 626MB ± 0% -0.36% (p=0.000 n=11+12) SSA 1.45GB ± 0% 1.43GB ± 0% -0.78% (p=0.000 n=12+12) Flate 22.2MB ± 0% 21.9MB ± 0% -1.12% (p=0.000 n=12+12) GoParser 29.4MB ± 0% 29.3MB ± 0% -0.36% (p=0.000 n=12+12) Reflect 76.1MB ± 0% 75.8MB ± 0% -0.38% (p=0.000 n=12+12) Tar 33.4MB ± 0% 33.2MB ± 0% -0.61% (p=0.000 n=12+12) XML 43.2MB ± 0% 42.8MB ± 0% -1.03% (p=0.000 n=11+12) name old allocs/op new allocs/op delta Template 375k ± 0% 375k ± 0% ~ (p=0.854 n=12+12) Unicode 300k ± 0% 300k ± 0% ~ (p=0.766 n=12+12) GoTypes 1.30M ± 0% 1.30M ± 0% ~ (p=0.272 n=12+12) Compiler 5.89M ± 0% 5.89M ± 0% ~ (p=0.478 n=12+12) SSA 14.0M ± 0% 14.0M ± 0% ~ (p=0.266 n=12+12) Flate 226k ± 0% 226k ± 0% ~ (p=0.898 n=12+12) GoParser 313k ± 0% 313k ± 0% -0.01% (p=0.042 n=12+11) Reflect 971k ± 0% 971k ± 0% ~ (p=0.080 n=12+12) Tar 342k ± 0% 342k ± 0% ~ (p=0.600 n=12+12) XML 416k ± 0% 416k ± 0% ~ (p=0.217 n=11+12) name old maxRSS/op new maxRSS/op delta Template 43.1M ± 5% 42.5M ± 5% ~ (p=0.086 n=12+12) Unicode 49.4M ± 2% 47.0M ± 2% -4.88% (p=0.000 n=12+12) GoTypes 85.3M ± 2% 84.6M ± 2% -0.84% (p=0.047 n=11+11) Compiler 394M ± 3% 386M ± 2% -1.97% (p=0.000 n=10+11) SSA 847M ± 4% 821M ± 2% -2.98% (p=0.000 n=11+12) Flate 36.0M ± 7% 35.2M ± 7% ~ (p=0.128 n=12+12) GoParser 39.4M ± 7% 39.5M ± 4% ~ (p=0.413 n=12+11) Reflect 64.0M ± 3% 63.6M ± 3% ~ (p=0.413 n=11+12) Tar 43.3M ± 5% 43.3M ± 5% ~ (p=0.503 n=12+12) XML 47.6M ± 4% 46.4M ± 2% -2.46% (p=0.013 n=11+12) Change-Id: If5781be346351c30b2228807211b5e57f777c506 Reviewed-on: https://go-review.googlesource.com/c/go/+/275033 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
1 parent beb5e05 commit a2058ba

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

src/cmd/compile/internal/gc/const.go

+7-20
Original file line numberDiff line numberDiff line change
@@ -115,22 +115,12 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
115115
return n
116116
}
117117

118-
if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL {
119-
// Can't always set n.Type directly on OLITERAL nodes.
120-
// See discussion on CL 20813.
121-
old := n
122-
n = ir.Copy(old)
123-
if old.Op() == ir.OLITERAL {
124-
// Keep untyped constants in their original untyped syntax for error messages.
125-
n.(ir.OrigNode).SetOrig(old)
126-
}
127-
}
128-
129118
// Nil is technically not a constant, so handle it specially.
130119
if n.Type().Kind() == types.TNIL {
131120
if n.Op() != ir.ONIL {
132121
base.Fatalf("unexpected op: %v (%v)", n, n.Op())
133122
}
123+
n = ir.Copy(n)
134124
if t == nil {
135125
base.Errorf("use of untyped nil")
136126
n.SetDiag(true)
@@ -158,10 +148,11 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
158148
case ir.OLITERAL:
159149
v := convertVal(n.Val(), t, explicit)
160150
if v.Kind() == constant.Unknown {
151+
n = ir.NewConstExpr(n.Val(), n)
161152
break
162153
}
154+
n = ir.NewConstExpr(v, n)
163155
n.SetType(t)
164-
n.SetVal(v)
165156
return n
166157

167158
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG:
@@ -541,8 +532,9 @@ func evalConst(n ir.Node) ir.Node {
541532
i2++
542533
}
543534

544-
nl := origConst(s[i], constant.MakeString(strings.Join(strs, "")))
545-
nl.(ir.OrigNode).SetOrig(nl) // it's bigger than just s[i]
535+
nl := ir.Copy(n)
536+
nl.PtrList().Set(s[i:i2])
537+
nl = origConst(nl, constant.MakeString(strings.Join(strs, "")))
546538
newList = append(newList, nl)
547539
i = i2 - 1
548540
} else {
@@ -645,12 +637,7 @@ func origConst(n ir.Node, v constant.Value) ir.Node {
645637
return n
646638
}
647639

648-
orig := n
649-
n = ir.NodAt(orig.Pos(), ir.OLITERAL, nil, nil)
650-
n.(ir.OrigNode).SetOrig(orig)
651-
n.SetType(orig.Type())
652-
n.SetVal(v)
653-
return n
640+
return ir.NewConstExpr(v, n)
654641
}
655642

656643
func origBoolConst(n ir.Node, v bool) ir.Node {

src/cmd/compile/internal/ir/expr.go

+25
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"cmd/compile/internal/types"
1010
"cmd/internal/src"
1111
"fmt"
12+
"go/constant"
1213
)
1314

1415
// A miniStmt is a miniNode with extra fields common to expressions.
@@ -300,6 +301,30 @@ func (n *CompLitExpr) SetOp(op Op) {
300301
}
301302
}
302303

304+
type ConstExpr struct {
305+
miniExpr
306+
val constant.Value
307+
orig Node
308+
}
309+
310+
func NewConstExpr(val constant.Value, orig Node) Node {
311+
n := &ConstExpr{orig: orig, val: val}
312+
n.op = OLITERAL
313+
n.pos = orig.Pos()
314+
n.SetType(orig.Type())
315+
n.SetTypecheck(orig.Typecheck())
316+
n.SetDiag(orig.Diag())
317+
return n
318+
}
319+
320+
func (n *ConstExpr) String() string { return fmt.Sprint(n) }
321+
func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
322+
func (n *ConstExpr) rawCopy() Node { c := *n; return &c }
323+
func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() }
324+
func (n *ConstExpr) Orig() Node { return n.orig }
325+
func (n *ConstExpr) SetOrig(orig Node) { n.orig = orig }
326+
func (n *ConstExpr) Val() constant.Value { return n.val }
327+
303328
// A ConvExpr is a conversion Type(X).
304329
// It may end up being a value or a type.
305330
type ConvExpr struct {

0 commit comments

Comments
 (0)