]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add special case for testing first field of struct variable
authorIan Lance Taylor <iant@golang.org>
Sat, 14 Nov 2015 23:42:49 +0000 (15:42 -0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 16 Nov 2015 18:39:40 +0000 (18:39 +0000)
The change to the write barrier in https://golang.org/cl/16899 means
that the compiler now emits tests of the first field of a struct.  That
was using a register that was not used before.  This change fixes that
for amd64 by adding a special case for the first field of a struct.

Update #12416.

Change-Id: Ia57baa62cd741592fbeb9be82f1e846be73d6edd
Reviewed-on: https://go-review.googlesource.com/16933
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/amd64/gsubr.go
src/cmd/compile/internal/gc/gsubr.go

index 4cc946f2b69c1f6f1c99029da6a7fe47408e539d..003b0ad0c9932e0792828c2230b53377ea4305e5 100644 (file)
@@ -108,7 +108,15 @@ func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
        }
        // General case.
        var r1, r2, g1, g2 gc.Node
-       if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+
+       // A special case to make write barriers more efficient.
+       // Comparing the first field of a named struct can be done directly.
+       base := n1
+       if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+               base = n1.Left
+       }
+
+       if base.Op == gc.ONAME && base.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
                r1 = *n1
        } else {
                gc.Regalloc(&r1, t, n1)
index ba2c601b7fa29ff8b859e1e9e5612e50e1c1df45..14d4d3da8f6faa90e2b2311d0dc97613e9801270 100644 (file)
@@ -404,6 +404,17 @@ func Naddr(a *obj.Addr, n *Node) {
 
                a.Sym = Linksym(s)
 
+       case ODOT:
+               // A special case to make write barriers more efficient.
+               // Taking the address of the first field of a named struct
+               // is the same as taking the address of the struct.
+               if n.Left.Type.Etype != TSTRUCT || n.Left.Type.Type.Sym != n.Right.Sym {
+                       Debug['h'] = 1
+                       Dump("naddr", n)
+                       Fatalf("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
+               }
+               Naddr(a, n.Left)
+
        case OLITERAL:
                if Thearch.Thechar == '8' {
                        a.Width = 0