diff options
| author | Ilya Tocar <ilya.tocar@intel.com> | 2017-12-04 14:24:16 -0600 |
|---|---|---|
| committer | Ilya Tocar <ilya.tocar@intel.com> | 2018-02-14 20:08:43 +0000 |
| commit | 9916feeddf30f8e4d159e92f49a090e01f4fa353 (patch) | |
| tree | f532646bc0304e36dfb9390ac9a877a25cc23921 /src | |
| parent | de4edf3de7acda2cc7da8764ecdb3ff2e85c7a2d (diff) | |
| download | go-9916feeddf30f8e4d159e92f49a090e01f4fa353.tar.xz | |
cmd/compile/internal/ssa: don't spill register offsets on amd64
Transform (ADDQconst SP) into (LEA SP), because lea is rematerializeable,
so this avoids register spill. We can't mark ADDQconst as rematerializeable,
because it clobbers flags. This makes go binary ~2kb smaller.
For reference here is generated code for function from bug report.
Before:
CALL "".g(SB)
MOVBLZX (SP), AX
LEAQ 8(SP), DI
TESTB AX, AX
JEQ 15
MOVQ "".p(SP), SI
DUFFCOPY $196
MOVQ $0, (SP)
PCDATA $0, $1
CALL "".h(SB)
RET
MOVQ DI, ""..autotmp_2-8(SP) // extra spill
PCDATA $0, $2
CALL "".g(SB)
MOVQ ""..autotmp_2-8(SP), DI // extra register fill
MOVQ "".p(SP), SI
DUFFCOPY $196
MOVQ $1, (SP)
PCDATA $0, $1
CALL "".h(SB)
JMP 14
END
After:
CALL "".g(SB)
MOVBLZX (SP), AX
TESTB AX, AX
JEQ 15
LEAQ 8(SP), DI
MOVQ "".p(SP), SI
DUFFCOPY $196
MOVQ $0, (SP)
PCDATA $0, $1
CALL "".h(SB)
RET
PCDATA $0, $0 // no spill
CALL "".g(SB)
LEAQ 8(SP), DI // rematerialized instead
MOVQ "".p(SP), SI
DUFFCOPY $196
MOVQ $1, (SP)
PCDATA $0, $1
CALL "".h(SB)
JMP 14
END
Fixes #22947
Change-Id: I8f33b860dc6c8828373477171b172ca2ce30074f
Reviewed-on: https://go-review.googlesource.com/81815
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/ssa/gen/AMD64.rules | 4 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/rewriteAMD64.go | 14 |
2 files changed, 18 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index db7c1a447b..e43b61b7c7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2662,3 +2662,7 @@ (MOVLf2i <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) (MOVQi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) (MOVLi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) + +// LEAQ is rematerializeable, so this helps to avoid register spill. +// See isuue 22947 for details +(ADDQconst [off] x:(SP)) -> (LEAQ [off] x) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 0b2b321d25..be85004190 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2054,6 +2054,20 @@ func rewriteValueAMD64_OpAMD64ADDQconst_0(v *Value) bool { v.AddArg(x) return true } + // match: (ADDQconst [off] x:(SP)) + // cond: + // result: (LEAQ [off] x) + for { + off := v.AuxInt + x := v.Args[0] + if x.Op != OpSP { + break + } + v.reset(OpAMD64LEAQ) + v.AuxInt = off + v.AddArg(x) + return true + } return false } func rewriteValueAMD64_OpAMD64ADDQconstmem_0(v *Value) bool { |
