mirror of https://github.com/golang/go.git
cmd/compile: avoid dynamic type when possible
If the expression type is a single compile-time known type, use that type instead of the dynamic one, so the later passes of the compiler could skip un-necessary runtime calls. Thanks Youlin Feng for writing the original test case. Change-Id: I3f65ab90f041474a9731338a82136c1d394c1773 Reviewed-on: https://go-review.googlesource.com/c/go/+/616975 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
6a3f39a9b8
commit
7e2487cf65
|
|
@ -67,3 +67,23 @@ func NewDynamicType(pos src.XPos, rtype Node) *DynamicType {
|
||||||
n.op = ODYNAMICTYPE
|
n.op = ODYNAMICTYPE
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToStatic returns static type of dt if it is actually static.
|
||||||
|
func (dt *DynamicType) ToStatic() Node {
|
||||||
|
if dt.Typecheck() == 0 {
|
||||||
|
base.Fatalf("missing typecheck: %v", dt)
|
||||||
|
}
|
||||||
|
if dt.RType != nil && dt.RType.Op() == OADDR {
|
||||||
|
addr := dt.RType.(*AddrExpr)
|
||||||
|
if addr.X.Op() == OLINKSYMOFFSET {
|
||||||
|
return TypeNode(dt.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dt.ITab != nil && dt.ITab.Op() == OADDR {
|
||||||
|
addr := dt.ITab.(*AddrExpr)
|
||||||
|
if addr.X.Op() == OLINKSYMOFFSET {
|
||||||
|
return TypeNode(dt.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3242,7 +3242,11 @@ func (r *reader) exprType() ir.Node {
|
||||||
|
|
||||||
dt := ir.NewDynamicType(pos, rtype)
|
dt := ir.NewDynamicType(pos, rtype)
|
||||||
dt.ITab = itab
|
dt.ITab = itab
|
||||||
return typed(typ, dt)
|
dt = typed(typ, dt).(*ir.DynamicType)
|
||||||
|
if st := dt.ToStatic(); st != nil {
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
return dt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reader) op() ir.Op {
|
func (r *reader) op() ir.Op {
|
||||||
|
|
|
||||||
|
|
@ -459,23 +459,6 @@ func walkSwitchType(sw *ir.SwitchStmt) {
|
||||||
nilGoto = jmp
|
nilGoto = jmp
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if n1.Op() == ir.ODYNAMICTYPE {
|
|
||||||
// Convert dynamic to static, if the dynamic is actually static.
|
|
||||||
// TODO: why isn't this OTYPE to begin with?
|
|
||||||
dt := n1.(*ir.DynamicType)
|
|
||||||
if dt.RType != nil && dt.RType.Op() == ir.OADDR {
|
|
||||||
addr := dt.RType.(*ir.AddrExpr)
|
|
||||||
if addr.X.Op() == ir.OLINKSYMOFFSET {
|
|
||||||
n1 = ir.TypeNode(n1.Type())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dt.ITab != nil && dt.ITab.Op() == ir.OADDR {
|
|
||||||
addr := dt.ITab.(*ir.AddrExpr)
|
|
||||||
if addr.X.Op() == ir.OLINKSYMOFFSET {
|
|
||||||
n1 = ir.TypeNode(n1.Type())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cases = append(cases, oneCase{
|
cases = append(cases, oneCase{
|
||||||
pos: ncase.Pos(),
|
pos: ncase.Pos(),
|
||||||
typ: n1,
|
typ: n1,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// asmcheck
|
||||||
|
|
||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package codegen
|
||||||
|
|
||||||
|
type Ix interface {
|
||||||
|
X()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Iy interface {
|
||||||
|
Y()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Iz interface {
|
||||||
|
Z()
|
||||||
|
}
|
||||||
|
|
||||||
|
func swXYZ(a Ix) {
|
||||||
|
switch t := a.(type) {
|
||||||
|
case Iy: // amd64:-".*typeAssert"
|
||||||
|
t.Y()
|
||||||
|
case Iz: // amd64:-".*typeAssert"
|
||||||
|
t.Z()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ig[T any] interface {
|
||||||
|
G() T
|
||||||
|
}
|
||||||
|
|
||||||
|
func swGYZ[T any](a Ig[T]) {
|
||||||
|
switch t := a.(type) {
|
||||||
|
case Iy: // amd64:-".*typeAssert"
|
||||||
|
t.Y()
|
||||||
|
case Iz: // amd64:-".*typeAssert"
|
||||||
|
t.Z()
|
||||||
|
case interface{ G() T }: // amd64:-".*typeAssert",".*assertE2I"
|
||||||
|
t.G()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func swCaller() {
|
||||||
|
swGYZ[int]((Ig[int])(nil))
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue