mirror of https://github.com/golang/go.git
cmd/compile: handle sole component for 1-byte type interface conversion
For 1-byte type, we have a special case for converting to interface type. But we missed an optimization for sole component-ed types, this CL add that one. goos: linux goarch: amd64 cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz Benchmark_BoolField-8 1000000000 0.6473 ns/op Benchmark_ByteField-8 1000000000 0.6094 ns/op Benchmark_Uint8Field-8 1000000000 0.6385 ns/op Benchmark_Int16Field-8 785179434 1.481 ns/op Benchmark_Int32Field-8 796127782 1.539 ns/op Benchmark_Int64Field-8 718815478 1.657 ns/op Fixes #49879 Change-Id: Idc0e9d3ff738c8c8081b8e8d65093dacf2bcf392 Reviewed-on: https://go-review.googlesource.com/c/go/+/367755 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
8ab42a945a
commit
3fd8b8627f
|
|
@ -1628,6 +1628,7 @@ func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
|
|||
// SoleComponent returns the only primitive component in t,
|
||||
// if there is exactly one. Otherwise, it returns nil.
|
||||
// Components are counted as in NumComponents, including blank fields.
|
||||
// Keep in sync with cmd/compile/internal/walk/convert.go:soleComponent.
|
||||
func (t *Type) SoleComponent() *Type {
|
||||
switch t.kind {
|
||||
case TSTRUCT:
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@ func dataWord(pos src.XPos, n ir.Node, init *ir.Nodes, escapes bool) ir.Node {
|
|||
return n
|
||||
}
|
||||
|
||||
isInteger := fromType.IsInteger()
|
||||
isBool := fromType.IsBoolean()
|
||||
if sc := fromType.SoleComponent(); sc != nil {
|
||||
isInteger = sc.IsInteger()
|
||||
isBool = sc.IsBoolean()
|
||||
}
|
||||
// Try a bunch of cases to avoid an allocation.
|
||||
var value ir.Node
|
||||
switch {
|
||||
|
|
@ -125,10 +131,11 @@ func dataWord(pos src.XPos, n ir.Node, init *ir.Nodes, escapes bool) ir.Node {
|
|||
// n is zero-sized. Use zerobase.
|
||||
cheapExpr(n, init) // Evaluate n for side-effects. See issue 19246.
|
||||
value = ir.NewLinksymExpr(base.Pos, ir.Syms.Zerobase, types.Types[types.TUINTPTR])
|
||||
case fromType.IsBoolean() || (fromType.Size() == 1 && fromType.IsInteger()):
|
||||
case isBool || fromType.Size() == 1 && isInteger:
|
||||
// n is a bool/byte. Use staticuint64s[n * 8] on little-endian
|
||||
// and staticuint64s[n * 8 + 7] on big-endian.
|
||||
n = cheapExpr(n, init)
|
||||
n = soleComponent(init, n)
|
||||
// byteindex widens n so that the multiplication doesn't overflow.
|
||||
index := ir.NewBinaryExpr(base.Pos, ir.OLSH, byteindex(n), ir.NewInt(3))
|
||||
if ssagen.Arch.LinkArch.ByteOrder == binary.BigEndian {
|
||||
|
|
@ -392,6 +399,29 @@ func rtconvfn(src, dst *types.Type) (param, result types.Kind) {
|
|||
return types.Txxx, types.Txxx
|
||||
}
|
||||
|
||||
func soleComponent(init *ir.Nodes, n ir.Node) ir.Node {
|
||||
if n.Type().SoleComponent() == nil {
|
||||
return n
|
||||
}
|
||||
// Keep in sync with cmd/compile/internal/types/type.go:Type.SoleComponent.
|
||||
for {
|
||||
switch {
|
||||
case n.Type().IsStruct():
|
||||
if n.Type().Field(0).Sym.IsBlank() {
|
||||
// Treat blank fields as the zero value as the Go language requires.
|
||||
n = typecheck.Temp(n.Type().Field(0).Type)
|
||||
appendWalkStmt(init, ir.NewAssignStmt(base.Pos, n, nil))
|
||||
return n
|
||||
}
|
||||
n = typecheck.Expr(ir.NewSelectorExpr(n.Pos(), ir.OXDOT, n, n.Type().Field(0).Sym))
|
||||
case n.Type().IsArray():
|
||||
n = typecheck.Expr(ir.NewIndexExpr(n.Pos(), n, ir.NewInt(0)))
|
||||
default:
|
||||
return n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// byteindex converts n, which is byte-sized, to an int used to index into an array.
|
||||
// We cannot use conv, because we allow converting bool to int here,
|
||||
// which is forbidden in user code.
|
||||
|
|
|
|||
Loading…
Reference in New Issue