]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: teach componentgen about string constants
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 8 Jan 2015 23:30:02 +0000 (15:30 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Wed, 1 Apr 2015 16:32:20 +0000 (16:32 +0000)
This makes it cheaper to copy string literals.
This happens just about anywhere that they are used.

Example:

func f() string {
return "f"
}

Using 6g, compiler output before:

"".f t=1 size=32 value=0 args=0x10 locals=0x0
0x0000 00000 (p.go:3) TEXT "".f+0(SB),4,$0-16
0x0000 00000 (p.go:3) FUNCDATA $0,gclocals·d64e51a4c4bfeaa840e480961ec6b0b3+0(SB)
0x0000 00000 (p.go:3) FUNCDATA $1,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0000 00000 (p.go:4) LEAQ go.string."f"+0(SB),BX
0x0007 00007 (p.go:4) MOVQ (BX),BP
0x000a 00010 (p.go:4) MOVQ BP,"".~r0+8(FP)
0x000f 00015 (p.go:4) MOVQ 8(BX),BP
0x0013 00019 (p.go:4) MOVQ BP,"".~r0+16(FP)
0x0018 00024 (p.go:4) RET ,

After:

"".f t=1 size=32 value=0 args=0x10 locals=0x0
0x0000 00000 (p.go:3) TEXT "".f+0(SB),4,$0-16
0x0000 00000 (p.go:3) FUNCDATA $0,gclocals·d64e51a4c4bfeaa840e480961ec6b0b3+0(SB)
0x0000 00000 (p.go:3) FUNCDATA $1,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0000 00000 (p.go:4) MOVQ $go.string."f"+16(SB),BX
0x0007 00007 (p.go:4) MOVQ BX,"".~r0+8(FP)
0x000c 00012 (p.go:4) MOVQ $1,"".~r0+16(FP)
0x0015 00021 (p.go:4) RET ,

The leading MOVQ here will be converted into a LEAQ by the linker,
but there is still a net reduction of two MOVQs.

Before:

TEXT main.f(SB)
        p.go:4  0x2000  488d1d49500500  LEAQ 0x55049(IP), BX
        p.go:4  0x2007  488b2b          MOVQ 0(BX), BP
        p.go:4  0x200a  48896c2408      MOVQ BP, 0x8(SP)
        p.go:4  0x200f  488b6b08        MOVQ 0x8(BX), BP
        p.go:4  0x2013  48896c2410      MOVQ BP, 0x10(SP)
        p.go:4  0x2018  c3              RET

After:

TEXT main.f(SB)
        p.go:4  0x2000  488d1dd94c0500          LEAQ 0x54cd9(IP), BX
        p.go:4  0x2007  48895c2408              MOVQ BX, 0x8(SP)
        p.go:4  0x200c  48c744241001000000      MOVQ $0x1, 0x10(SP)
        p.go:4  0x2015  c3                      RET

The performance improvement is small but widespread.

As a nice small example, net/url's sole benchmark using 6g:

benchmark           old ns/op     new ns/op     delta
BenchmarkString     16372         16118         -1.55%

And with 8g:

benchmark           old ns/op     new ns/op     delta
BenchmarkString     22034         21709         -1.47%

Change-Id: I4ce202ee7dbd4057be869e2faaaa638c28a1fff0
Reviewed-on: https://go-review.googlesource.com/2587
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>

src/cmd/internal/gc/gen.go

index 445efc9ad0e116378bc8e6b6a8be2cf67e629474..1a7f76fd0845928ddf9894ebbe82e0404851c7c8 100644 (file)
@@ -1135,6 +1135,8 @@ func Componentgen(nr *Node, nl *Node) bool {
        freel := 0
        freer := 0
 
+       var isConstString bool
+
        switch nl.Type.Etype {
        default:
                goto no
@@ -1178,9 +1180,10 @@ func Componentgen(nr *Node, nl *Node) bool {
                break
        }
 
+       isConstString = Isconst(nr, CTSTR)
        nodl = *nl
        if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
+               if nr != nil && !cadable(nr) && !isConstString {
                        goto no
                }
                Igen(nl, &nodl, nil)
@@ -1189,7 +1192,7 @@ func Componentgen(nr *Node, nl *Node) bool {
 
        if nr != nil {
                nodr = *nr
-               if !cadable(nr) {
+               if !cadable(nr) && !isConstString {
                        Igen(nr, &nodr, nil)
                        freer = 1
                }
@@ -1275,7 +1278,13 @@ func Componentgen(nr *Node, nl *Node) bool {
                nodl.Xoffset += int64(Array_array)
                nodl.Type = Ptrto(Types[TUINT8])
 
-               if nr != nil {
+               if isConstString {
+                       Regalloc(&nodr, Types[Tptr], nil)
+                       p := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &nodr)
+                       Datastring(nr.Val.U.Sval, &p.From)
+                       p.From.Type = obj.TYPE_ADDR
+                       Regfree(&nodr)
+               } else if nr != nil {
                        nodr.Xoffset += int64(Array_array)
                        nodr.Type = nodl.Type
                }
@@ -1285,7 +1294,9 @@ func Componentgen(nr *Node, nl *Node) bool {
                nodl.Xoffset += int64(Array_nel) - int64(Array_array)
                nodl.Type = Types[Simtype[TUINT]]
 
-               if nr != nil {
+               if isConstString {
+                       Nodconst(&nodr, nodl.Type, int64(len(nr.Val.U.Sval)))
+               } else if nr != nil {
                        nodr.Xoffset += int64(Array_nel) - int64(Array_array)
                        nodr.Type = nodl.Type
                }