Commit 8d31df18 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

[dev.ssa] cmd/compile: use string contents instead of offset from string header

This generates more efficient code.

Before:

	0x003a 00058 (rr.go:7)	LEAQ	go.string.hdr."="(SB), BX
	0x0041 00065 (rr.go:7)	LEAQ	16(BX), BP
	0x0045 00069 (rr.go:7)	MOVQ	BP, 16(SP)

After:

	0x003a 00058 (rr.go:7)	LEAQ	go.string."="(SB), BX
	0x0041 00065 (rr.go:7)	MOVQ	BX, 16(SP)

It also matches the existing backend
and is more robust to other changes,
such as CL 11698, which I believe broke
the current code.

This CL fixes the encoding/base64 tests, as run with:

	GOGC=off GOSSAPKG=base64 go test -a encoding/base64

Change-Id: I3c475bed1dd3335cc14e13309e11d23f0ed32c17
Reviewed-on: https://go-review.googlesource.com/12654Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent d90e0481
...@@ -1922,12 +1922,12 @@ type ssaExport struct { ...@@ -1922,12 +1922,12 @@ type ssaExport struct {
mustImplement bool mustImplement bool
} }
// StringSym returns a symbol (a *Sym wrapped in an interface) which // StringData returns a symbol (a *Sym wrapped in an interface) which
// is a global string constant containing s. // is the data component of a global string constant containing s.
func (*ssaExport) StringSym(s string) interface{} { func (*ssaExport) StringData(s string) interface{} {
// TODO: is idealstring correct? It might not matter... // TODO: is idealstring correct? It might not matter...
hdr, _ := stringsym(s) _, data := stringsym(s)
return &ssa.ExternSymbol{Typ: idealstring, Sym: hdr} return &ssa.ExternSymbol{Typ: idealstring, Sym: data}
} }
// Log logs a message from the compiler. // Log logs a message from the compiler.
......
...@@ -17,10 +17,8 @@ type Config struct { ...@@ -17,10 +17,8 @@ type Config struct {
} }
type Frontend interface { type Frontend interface {
// StringSym returns a symbol pointing to the given string. // StringData returns a symbol pointing to the given string's contents.
// Strings are laid out in read-only memory with one word of pointer, StringData(string) interface{} // returns *gc.Sym
// one word of length, then the contents of the string.
StringSym(string) interface{} // returns *gc.Sym
// Log logs a message from the compiler. // Log logs a message from the compiler.
Logf(string, ...interface{}) Logf(string, ...interface{})
......
...@@ -15,7 +15,7 @@ type DummyFrontend struct { ...@@ -15,7 +15,7 @@ type DummyFrontend struct {
t testing.TB t testing.TB
} }
func (DummyFrontend) StringSym(s string) interface{} { func (DummyFrontend) StringData(s string) interface{} {
return nil return nil
} }
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
(Store dst (Load <t> src mem) mem) && t.Size() > 8 -> (Move [t.Size()] dst src mem) (Store dst (Load <t> src mem) mem) && t.Size() > 8 -> (Move [t.Size()] dst src mem)
// string ops // string ops
(Const <t> {s}) && t.IsString() -> (StringMake (OffPtr <TypeBytePtr> [2*config.PtrSize] (Addr <TypeBytePtr> {config.fe.StringSym(s.(string))} (SB <config.Uintptr>))) (Const <config.Uintptr> [int64(len(s.(string)))])) // TODO: ptr (Const <t> {s}) && t.IsString() -> (StringMake (Addr <TypeBytePtr> {config.fe.StringData(s.(string))} (SB <config.Uintptr>)) (Const <config.Uintptr> [int64(len(s.(string)))]))
(Load <t> ptr mem) && t.IsString() -> (StringMake (Load <TypeBytePtr> ptr mem) (Load <config.Uintptr> (OffPtr <TypeBytePtr> [config.PtrSize] ptr) mem)) (Load <t> ptr mem) && t.IsString() -> (StringMake (Load <TypeBytePtr> ptr mem) (Load <config.Uintptr> (OffPtr <TypeBytePtr> [config.PtrSize] ptr) mem))
(StringPtr (StringMake ptr _)) -> ptr (StringPtr (StringMake ptr _)) -> ptr
(StringLen (StringMake _ len)) -> len (StringLen (StringMake _ len)) -> len
......
...@@ -102,36 +102,32 @@ func rewriteValuegeneric(v *Value, config *Config) bool { ...@@ -102,36 +102,32 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
case OpConst: case OpConst:
// match: (Const <t> {s}) // match: (Const <t> {s})
// cond: t.IsString() // cond: t.IsString()
// result: (StringMake (OffPtr <TypeBytePtr> [2*config.PtrSize] (Addr <TypeBytePtr> {config.fe.StringSym(s.(string))} (SB <config.Uintptr>))) (Const <config.Uintptr> [int64(len(s.(string)))])) // result: (StringMake (Addr <TypeBytePtr> {config.fe.StringData(s.(string))} (SB <config.Uintptr>)) (Const <config.Uintptr> [int64(len(s.(string)))]))
{ {
t := v.Type t := v.Type
s := v.Aux s := v.Aux
if !(t.IsString()) { if !(t.IsString()) {
goto endedcb8bd24122d6a47bdc9b752460c344 goto enda6f250a3c775ae5a239ece8074b46cea
} }
v.Op = OpStringMake v.Op = OpStringMake
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
v.resetArgs() v.resetArgs()
v0 := v.Block.NewValue0(v.Line, OpOffPtr, TypeInvalid) v0 := v.Block.NewValue0(v.Line, OpAddr, TypeInvalid)
v0.Type = TypeBytePtr v0.Type = TypeBytePtr
v0.AuxInt = 2 * config.PtrSize v0.Aux = config.fe.StringData(s.(string))
v1 := v.Block.NewValue0(v.Line, OpAddr, TypeInvalid) v1 := v.Block.NewValue0(v.Line, OpSB, TypeInvalid)
v1.Type = TypeBytePtr v1.Type = config.Uintptr
v1.Aux = config.fe.StringSym(s.(string))
v2 := v.Block.NewValue0(v.Line, OpSB, TypeInvalid)
v2.Type = config.Uintptr
v1.AddArg(v2)
v0.AddArg(v1) v0.AddArg(v1)
v.AddArg(v0) v.AddArg(v0)
v3 := v.Block.NewValue0(v.Line, OpConst, TypeInvalid) v2 := v.Block.NewValue0(v.Line, OpConst, TypeInvalid)
v3.Type = config.Uintptr v2.Type = config.Uintptr
v3.AuxInt = int64(len(s.(string))) v2.AuxInt = int64(len(s.(string)))
v.AddArg(v3) v.AddArg(v2)
return true return true
} }
goto endedcb8bd24122d6a47bdc9b752460c344 goto enda6f250a3c775ae5a239ece8074b46cea
endedcb8bd24122d6a47bdc9b752460c344: enda6f250a3c775ae5a239ece8074b46cea:
; ;
case OpIsInBounds: case OpIsInBounds:
// match: (IsInBounds (Const [c]) (Const [d])) // match: (IsInBounds (Const [c]) (Const [d]))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment