cmd/compile: add signed divisibility by power of 2 rules

For powers of two (c=1<<k), the divisibility check x%c == 0 can be made
just by checking the trailing zeroes via a mask x&(c-1) == 0 even for signed
integers. This avoids division fix-ups when just divisibility check is needed.

To apply this rule, we match on the fixed-up version of the division. This is
neccessary because the mod and division rewrite rules are already applied
during the initial opt pass.

The speed up on amd64 due to elimination of unneccessary fix-up code is ~55%:

name                     old time/op  new time/op  delta
DivconstI64-4            2.08ns ± 0%  2.09ns ± 1%     ~     (p=0.730 n=5+5)
DivisiblePow2constI64-4  1.78ns ± 1%  0.81ns ± 1%  -54.66%  (p=0.008 n=5+5)
DivconstU64-4            2.08ns ± 0%  2.08ns ± 0%     ~     (p=0.683 n=5+5)
DivconstI32-4            1.53ns ± 0%  1.53ns ± 1%     ~     (p=0.968 n=4+5)
DivisiblePow2constI32-4  1.79ns ± 1%  0.81ns ± 1%  -54.97%  (p=0.008 n=5+5)
DivconstU32-4            1.78ns ± 1%  1.80ns ± 2%     ~     (p=0.206 n=5+5)
DivconstI16-4            1.54ns ± 2%  1.54ns ± 0%     ~     (p=0.238 n=5+4)
DivisiblePow2constI16-4  1.78ns ± 0%  0.81ns ± 1%  -54.72%  (p=0.000 n=4+5)
DivconstU16-4            1.00ns ± 5%  1.01ns ± 1%     ~     (p=0.119 n=5+5)
DivconstI8-4             1.54ns ± 0%  1.54ns ± 2%     ~     (p=0.571 n=4+5)
DivisiblePow2constI8-4   1.78ns ± 0%  0.82ns ± 8%  -53.71%  (p=0.008 n=5+5)
DivconstU8-4             0.93ns ± 1%  0.93ns ± 1%     ~     (p=0.643 n=5+5)

A follow-up CL will address the general case of x%c == 0 for signed integers.

Updates #15806

Change-Id: Iabadbbe369b6e0998c8ce85d038ebc236142e42a
Reviewed-on: https://go-review.googlesource.com/c/go/+/173557
Run-TryBot: Brian Kessler <brian.m.kessler@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Brian Kessler 2019-04-23 22:04:38 -06:00 committed by Brad Fitzpatrick
parent 2693b42466
commit 44343c777c
5 changed files with 1909 additions and 8 deletions

View file

@ -8,6 +8,8 @@ import (
"testing"
)
var boolres bool
var i64res int64
func BenchmarkDivconstI64(b *testing.B) {
@ -16,6 +18,12 @@ func BenchmarkDivconstI64(b *testing.B) {
}
}
func BenchmarkDivisiblePow2constI64(b *testing.B) {
for i := 0; i < b.N; i++ {
boolres = int64(i)%16 == 0
}
}
var u64res uint64
func BenchmarkDivconstU64(b *testing.B) {
@ -32,6 +40,12 @@ func BenchmarkDivconstI32(b *testing.B) {
}
}
func BenchmarkDivisiblePow2constI32(b *testing.B) {
for i := 0; i < b.N; i++ {
boolres = int32(i)%16 == 0
}
}
var u32res uint32
func BenchmarkDivconstU32(b *testing.B) {
@ -48,6 +62,12 @@ func BenchmarkDivconstI16(b *testing.B) {
}
}
func BenchmarkDivisiblePow2constI16(b *testing.B) {
for i := 0; i < b.N; i++ {
boolres = int16(i)%16 == 0
}
}
var u16res uint16
func BenchmarkDivconstU16(b *testing.B) {
@ -64,6 +84,12 @@ func BenchmarkDivconstI8(b *testing.B) {
}
}
func BenchmarkDivisiblePow2constI8(b *testing.B) {
for i := 0; i < b.N; i++ {
boolres = int8(i)%16 == 0
}
}
var u8res uint8
func BenchmarkDivconstU8(b *testing.B) {