From: Chad Rosier Date: Wed, 7 Feb 2018 20:37:33 +0000 (-0500) Subject: cmd/compile: generate tbz/tbnz when comparing against zero on arm64 X-Git-Tag: go1.11beta1~1650 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cdd961630cd26c5e42a537aaa52c669cf667d0be;p=gostls13.git 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 Reviewed-by: Brad Fitzpatrick Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 73c55018f9..9b62d9f6b1 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -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{ diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 888f5f8556..48ca634438 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -534,6 +534,12 @@ (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) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 05974dab4c..4e91217517 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -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)