Commit cdd96163 authored by Chad Rosier's avatar Chad Rosier Committed by Brad Fitzpatrick

cmd/compile: generate tbz/tbnz when comparing against zero on arm64

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: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarCherry Zhang <cherryyz@google.com>
parent eab06e65
...@@ -2711,6 +2711,46 @@ var linuxARM64Tests = []*asmTest{ ...@@ -2711,6 +2711,46 @@ var linuxARM64Tests = []*asmTest{
pos: []string{"LSL\t\\$17"}, pos: []string{"LSL\t\\$17"},
neg: []string{"CMP"}, 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{ var linuxMIPSTests = []*asmTest{
......
...@@ -534,6 +534,12 @@ ...@@ -534,6 +534,12 @@
(ZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBZ {ntz(int64(uint32(c)))} x yes no) (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) (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 // fold offset into address
(ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr) (ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr)
......
...@@ -16802,6 +16802,40 @@ func rewriteBlockARM64(b *Block) bool { ...@@ -16802,6 +16802,40 @@ func rewriteBlockARM64(b *Block) bool {
return true return true
} }
case BlockARM64GE: 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) // match: (GE (FlagEQ) yes no)
// cond: // cond:
// result: (First nil yes no) // result: (First nil yes no)
...@@ -17202,6 +17236,40 @@ func rewriteBlockARM64(b *Block) bool { ...@@ -17202,6 +17236,40 @@ func rewriteBlockARM64(b *Block) bool {
return true return true
} }
case BlockARM64LT: 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) // match: (LT (FlagEQ) yes no)
// cond: // cond:
// result: (First nil no yes) // result: (First nil no yes)
......
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