From 9916feeddf30f8e4d159e92f49a090e01f4fa353 Mon Sep 17 00:00:00 2001 From: Ilya Tocar Date: Mon, 4 Dec 2017 14:24:16 -0600 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 4 ++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 14 ++++++++++++++ 2 files changed, 18 insertions(+) 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 (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) (MOVQi2f (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) (MOVLi2f (Arg [off] {sym})) -> @b.Func.Entry (Arg [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 {