From: Ian Lance Taylor Date: Sat, 14 Nov 2015 23:42:49 +0000 (-0800) Subject: cmd/compile: add special case for testing first field of struct variable X-Git-Tag: go1.6beta1~435 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9aed0b7e3d3c9cbd5877fcbcecfcdec9111f5a81;p=gostls13.git cmd/compile: add special case for testing first field of struct variable 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 Reviewed-by: Russ Cox --- diff --git a/src/cmd/compile/internal/amd64/gsubr.go b/src/cmd/compile/internal/amd64/gsubr.go index 4cc946f2b6..003b0ad0c9 100644 --- a/src/cmd/compile/internal/amd64/gsubr.go +++ b/src/cmd/compile/internal/amd64/gsubr.go @@ -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) diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index ba2c601b7f..14d4d3da8f 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -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