]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: don't spill register offsets on amd64
authorIlya Tocar <ilya.tocar@intel.com>
Mon, 4 Dec 2017 20:24:16 +0000 (14:24 -0600)
committerIlya Tocar <ilya.tocar@intel.com>
Wed, 14 Feb 2018 20:08:43 +0000 (20:08 +0000)
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>
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/rewriteAMD64.go

index db7c1a447b247e05b6498adca71a5c060f0c9ba8..e43b61b7c72946d11bca2bb1869b911c645129d2 100644 (file)
 (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)
index 0b2b321d2566603215b22e78ca676f0820844737..be850041900c61c1d6f87fbf5a0776e26aa70ddf 100644 (file)
@@ -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 {