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 {
mustImplement bool
}
// StringSym returns a symbol (a *Sym wrapped in an interface) which
// is a global string constant containing s.
func (*ssaExport) StringSym(s string) interface{} {
// StringData returns a symbol (a *Sym wrapped in an interface) which
// is the data component of a global string constant containing s.
func (*ssaExport) StringData(s string) interface{} {
// TODO: is idealstring correct? It might not matter...
hdr, _ := stringsym(s)
return &ssa.ExternSymbol{Typ: idealstring, Sym: hdr}
_, data := stringsym(s)
return &ssa.ExternSymbol{Typ: idealstring, Sym: data}
}
// Log logs a message from the compiler.
......
......@@ -17,10 +17,8 @@ type Config struct {
}
type Frontend interface {
// StringSym returns a symbol pointing to the given string.
// Strings are laid out in read-only memory with one word of pointer,
// one word of length, then the contents of the string.
StringSym(string) interface{} // returns *gc.Sym
// StringData returns a symbol pointing to the given string's contents.
StringData(string) interface{} // returns *gc.Sym
// Log logs a message from the compiler.
Logf(string, ...interface{})
......
......@@ -15,7 +15,7 @@ type DummyFrontend struct {
t testing.TB
}
func (DummyFrontend) StringSym(s string) interface{} {
func (DummyFrontend) StringData(s string) interface{} {
return nil
}
......
......@@ -45,7 +45,7 @@
(Store dst (Load <t> src mem) mem) && t.Size() > 8 -> (Move [t.Size()] dst src mem)
// 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))
(StringPtr (StringMake ptr _)) -> ptr
(StringLen (StringMake _ len)) -> len
......
......@@ -102,36 +102,32 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
case OpConst:
// match: (Const <t> {s})
// 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
s := v.Aux
if !(t.IsString()) {
goto endedcb8bd24122d6a47bdc9b752460c344
goto enda6f250a3c775ae5a239ece8074b46cea
}
v.Op = OpStringMake
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v0 := v.Block.NewValue0(v.Line, OpOffPtr, TypeInvalid)
v0 := v.Block.NewValue0(v.Line, OpAddr, TypeInvalid)
v0.Type = TypeBytePtr
v0.AuxInt = 2 * config.PtrSize
v1 := v.Block.NewValue0(v.Line, OpAddr, TypeInvalid)
v1.Type = TypeBytePtr
v1.Aux = config.fe.StringSym(s.(string))
v2 := v.Block.NewValue0(v.Line, OpSB, TypeInvalid)
v2.Type = config.Uintptr
v1.AddArg(v2)
v0.Aux = config.fe.StringData(s.(string))
v1 := v.Block.NewValue0(v.Line, OpSB, TypeInvalid)
v1.Type = config.Uintptr
v0.AddArg(v1)
v.AddArg(v0)
v3 := v.Block.NewValue0(v.Line, OpConst, TypeInvalid)
v3.Type = config.Uintptr
v3.AuxInt = int64(len(s.(string)))
v.AddArg(v3)
v2 := v.Block.NewValue0(v.Line, OpConst, TypeInvalid)
v2.Type = config.Uintptr
v2.AuxInt = int64(len(s.(string)))
v.AddArg(v2)
return true
}
goto endedcb8bd24122d6a47bdc9b752460c344
endedcb8bd24122d6a47bdc9b752460c344:
goto enda6f250a3c775ae5a239ece8074b46cea
enda6f250a3c775ae5a239ece8074b46cea:
;
case OpIsInBounds:
// 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