]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: generate tbz/tbnz when comparing against zero on arm64
authorChad Rosier <mrosier.qdt@qualcommdatacenter.com>
Wed, 7 Feb 2018 20:37:33 +0000 (15:37 -0500)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 14 Feb 2018 15:52:41 +0000 (15:52 +0000)
The tbz/tbnz checks the sign bit to determine if the value is >= 0 or < 0.

go1 benchmark results:
name                   old speed      new speed      delta
JSONEncode             94.4MB/s ± 1%  95.7MB/s ± 0%  +1.36%  (p=0.000 n=10+9)
JSONDecode             19.7MB/s ± 1%  19.9MB/s ± 1%  +1.08%  (p=0.000 n=9+10)
Gzip                   45.5MB/s ± 0%  46.0MB/s ± 0%  +1.06%  (p=0.000 n=10+10)
Revcomp                 376MB/s ± 0%   379MB/s ± 0%  +0.69%  (p=0.000 n=10+10)
RegexpMatchHard_1K     12.6MB/s ± 0%  12.7MB/s ± 0%  +0.57%  (p=0.000 n=10+8)
RegexpMatchMedium_32   3.21MB/s ± 0%  3.22MB/s ± 0%  +0.31%  (p=0.000 n=9+10)
RegexpMatchEasy1_1K    1.27GB/s ± 0%  1.27GB/s ± 0%  +0.23%  (p=0.000 n=9+9)
RegexpMatchHard_32     11.4MB/s ± 0%  11.4MB/s ± 1%  +0.19%  (p=0.036 n=10+8)
RegexpMatchEasy0_1K    1.77GB/s ± 0%  1.77GB/s ± 0%  +0.13%  (p=0.000 n=9+10)
RegexpMatchMedium_1K   19.3MB/s ± 0%  19.3MB/s ± 0%  +0.04%  (p=0.008 n=10+8)
RegexpMatchEasy0_32     131MB/s ± 0%   131MB/s ± 0%    ~     (p=0.211 n=10+10)
GobDecode              57.5MB/s ± 1%  57.6MB/s ± 2%    ~     (p=0.469 n=10+10)
GobEncode              58.6MB/s ± 1%  58.5MB/s ± 2%    ~     (p=0.781 n=10+10)
GoParse                9.40MB/s ± 0%  9.39MB/s ± 0%  -0.19%  (p=0.005 n=10+9)
RegexpMatchEasy1_32     133MB/s ± 0%   133MB/s ± 0%  -0.48%  (p=0.000 n=10+10)
Template               20.9MB/s ± 0%  20.6MB/s ± 0%  -1.54%  (p=0.000 n=8+10)

Change-Id: I411efe44db35c3962445618d5a47c12e31b3925b
Reviewed-on: https://go-review.googlesource.com/92715
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/gc/asm_test.go
src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/rewriteARM64.go

index 73c55018f9bd39312f429fccecf25b3a3a04e1a0..9b62d9f6b172f26b87986089ba1dc68102edfde4 100644 (file)
@@ -2711,6 +2711,46 @@ var linuxARM64Tests = []*asmTest{
                pos: []string{"LSL\t\\$17"},
                neg: []string{"CMP"},
        },
+       {
+               fn: `
+               func $(a int32, ptr *int) {
+                       if a >= 0 {
+                               *ptr = 0
+                       }
+               }
+               `,
+               pos: []string{"TBNZ"},
+       },
+       {
+               fn: `
+               func $(a int64, ptr *int) {
+                       if a >= 0 {
+                               *ptr = 0
+                       }
+               }
+               `,
+               pos: []string{"TBNZ"},
+       },
+       {
+               fn: `
+               func $(a int32, ptr *int) {
+                       if a < 0 {
+                               *ptr = 0
+                       }
+               }
+               `,
+               pos: []string{"TBZ"},
+       },
+       {
+               fn: `
+               func $(a int64, ptr *int) {
+                       if a < 0 {
+                               *ptr = 0
+                       }
+               }
+               `,
+               pos: []string{"TBZ"},
+       },
 }
 
 var linuxMIPSTests = []*asmTest{
index 888f5f855643e6092ed2547346cc86a108610491..48ca634438ff8e3fb5115a5faaf59b5941f03b64 100644 (file)
 (ZW  (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBZ  {ntz(int64(uint32(c)))} x yes no)
 (NZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBNZ {ntz(int64(uint32(c)))} x yes no)
 
+// Test sign-bit for signed comparisons against zero
+(GE (CMPWconst [0] x) yes no) -> (TBZ  {int64(31)} x yes no)
+(GE (CMPconst [0] x) yes no) -> (TBZ  {int64(63)} x yes no)
+(LT (CMPWconst [0] x) yes no) -> (TBNZ  {int64(31)} x yes no)
+(LT (CMPconst [0] x) yes no) -> (TBNZ  {int64(63)} x yes no)
+
 // fold offset into address
 (ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr)
 
index 05974dab4c81171f850a7c71774f247223066889..4e91217517473851baa6b8a5ca01f349ae75b46a 100644 (file)
@@ -16802,6 +16802,40 @@ func rewriteBlockARM64(b *Block) bool {
                        return true
                }
        case BlockARM64GE:
+               // match: (GE (CMPWconst [0] x) yes no)
+               // cond:
+               // result: (TBZ  {int64(31)} x yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpARM64CMPWconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       x := v.Args[0]
+                       b.Kind = BlockARM64TBZ
+                       b.SetControl(x)
+                       b.Aux = int64(31)
+                       return true
+               }
+               // match: (GE (CMPconst [0] x) yes no)
+               // cond:
+               // result: (TBZ  {int64(63)} x yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpARM64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       x := v.Args[0]
+                       b.Kind = BlockARM64TBZ
+                       b.SetControl(x)
+                       b.Aux = int64(63)
+                       return true
+               }
                // match: (GE (FlagEQ) yes no)
                // cond:
                // result: (First nil yes no)
@@ -17202,6 +17236,40 @@ func rewriteBlockARM64(b *Block) bool {
                        return true
                }
        case BlockARM64LT:
+               // match: (LT (CMPWconst [0] x) yes no)
+               // cond:
+               // result: (TBNZ  {int64(31)} x yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpARM64CMPWconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       x := v.Args[0]
+                       b.Kind = BlockARM64TBNZ
+                       b.SetControl(x)
+                       b.Aux = int64(31)
+                       return true
+               }
+               // match: (LT (CMPconst [0] x) yes no)
+               // cond:
+               // result: (TBNZ  {int64(63)} x yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpARM64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       x := v.Args[0]
+                       b.Kind = BlockARM64TBNZ
+                       b.SetControl(x)
+                       b.Aux = int64(63)
+                       return true
+               }
                // match: (LT (FlagEQ) yes no)
                // cond:
                // result: (First nil no yes)