From e22ba7f0fbd7a92418834dafbc1b539de1a85219 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 30 Aug 2016 19:11:19 -0700 Subject: [PATCH] cmd/compile: enable CSE of constant strings CL 27254 changed a constant string to a byte array in encoding/hex and got significant performance improvements. hex.Encode used the string twice in a single function. The rewrite rules lower constant strings into components. The pointer component requires an aux symbol. The existing implementation created a new aux symbol every time. As a result, constant string pointers were never CSE'd. Tighten then moved the pointer calculation next to the uses, i.e. into the loop. The re-use of aux syms enabled by this CL occurs 3691 times during make.bash. This CL should not go in without CL 38338 or something like it. Change-Id: Ibbf5b17283c0e31821d04c7e08d995c654de5663 Reviewed-on: https://go-review.googlesource.com/28219 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 960e14cc77..ee825acb0c 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3104,17 +3104,16 @@ func etypesign(e EType) int8 { func (s *state) lookupSymbol(n *Node, sym interface{}) interface{} { switch sym.(type) { default: - s.Fatalf("sym %v is of uknown type %T", sym, sym) + s.Fatalf("sym %v is of unknown type %T", sym, sym) case *ssa.ExternSymbol, *ssa.ArgSymbol, *ssa.AutoSymbol: // these are the only valid types } if lsym, ok := s.varsyms[n]; ok { return lsym - } else { - s.varsyms[n] = sym - return sym } + s.varsyms[n] = sym + return sym } // addr converts the address of the expression n to SSA, adds it to s and returns the SSA result. @@ -4692,17 +4691,25 @@ func fieldIdx(n *Node) int { // It also exports a bunch of compiler services for the ssa backend. type ssafn struct { curfn *Node - stksize int64 // stack size for current frame - stkptrsize int64 // prefix of stack containing pointers + strings map[string]interface{} // map from constant string to data symbols + stksize int64 // stack size for current frame + stkptrsize int64 // prefix of stack containing pointers log bool } // StringData returns a symbol (a *Sym wrapped in an interface) which // is the data component of a global string constant containing s. -func (*ssafn) StringData(s string) interface{} { - // TODO: is idealstring correct? It might not matter... +func (e *ssafn) StringData(s string) interface{} { + if aux, ok := e.strings[s]; ok { + return aux + } + if e.strings == nil { + e.strings = make(map[string]interface{}) + } data := stringsym(s) - return &ssa.ExternSymbol{Typ: idealstring, Sym: data} + aux := &ssa.ExternSymbol{Typ: idealstring, Sym: data} + e.strings[s] = aux + return aux } func (e *ssafn) Auto(t ssa.Type) ssa.GCNode {