]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile/internal/noder: allow OCONVNOP for identical iface conversions
authorMatthew Dempsky <mdempsky@google.com>
Thu, 1 Sep 2022 23:06:11 +0000 (16:06 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 2 Sep 2022 18:26:02 +0000 (18:26 +0000)
In go.dev/cl/421821, I included a hack to force OCONVNOP back to
OCONVIFACE for conversions involving shape types and non-empty
interfaces. The comment correctly noted that this was only needed for
conversions between non-identical types, but the code was conservative
and applied to even conversions between identical types.

This CL adds an extra bool to record whether the conversion is between
identical types, so we can keep OCONVNOP instead of forcing back to
OCONVIFACE. This has a small improvement to generated code, because we
no longer need a convI2I call (as demonstrated by codegen/ifaces.go).

But more usefully, this is relevant to pruning unnecessary itab slots
in runtime dictionaries (next CL).

Change-Id: I94f89e961cd26629b925037fea58d283140766ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/427678
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/compile/internal/noder/reader.go
src/cmd/compile/internal/noder/writer.go
test/codegen/ifaces.go [new file with mode: 0644]

index e69d8edc0b7b8fce5fe2ba0f53f0160cabab42a7..c37f49c1ea5e298ab284c1b3a8a4c5650d77f0b4 100644 (file)
@@ -2432,6 +2432,7 @@ func (r *reader) expr() (res ir.Node) {
                pos := r.pos()
                typeWord, srcRType := r.convRTTI(pos)
                dstTypeParam := r.Bool()
+               identical := r.Bool()
                x := r.expr()
 
                // TODO(mdempsky): Stop constructing expressions of untyped type.
@@ -2460,8 +2461,10 @@ func (r *reader) expr() (res ir.Node) {
                // Should this be moved down into typecheck.{Assign,Convert}op?
                // This would be a non-issue if itabs were unique for each
                // *underlying* interface type instead.
-               if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
-                       n.SetOp(ir.OCONVIFACE)
+               if !identical {
+                       if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
+                               n.SetOp(ir.OCONVIFACE)
+                       }
                }
 
                // spec: "If the type is a type parameter, the constant is converted
index c2ff639b00b0bc5fbbc4d5ce1cc4856c67b7d9b3..a03593e743d57febdec6c0a8c6232e9ea603b69d 100644 (file)
@@ -2085,6 +2085,7 @@ func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
        w.pos(expr)
        w.convRTTI(src, dst)
        w.Bool(isTypeParam(dst))
+       w.Bool(identical)
        w.expr(expr)
 }
 
diff --git a/test/codegen/ifaces.go b/test/codegen/ifaces.go
new file mode 100644 (file)
index 0000000..d773845
--- /dev/null
@@ -0,0 +1,21 @@
+// asmcheck
+
+// Copyright 2022 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 I interface { M() }
+
+func NopConvertIface(x I) I {
+        // amd64:-`.*runtime.convI2I`
+       return I(x)
+}
+
+func NopConvertGeneric[T any](x T) T {
+        // amd64:-`.*runtime.convI2I`
+        return T(x)
+}
+
+var NopConvertGenericIface = NopConvertGeneric[I]