summaryrefslogtreecommitdiff
path: root/test/codegen/arithmetic.go
diff options
context:
space:
mode:
authorBrian Kessler <brian.m.kessler@gmail.com>2019-04-05 14:05:07 -0600
committerBrad Fitzpatrick <bradfitz@golang.org>2019-04-30 22:02:07 +0000
commit4d9dd3580624df413d65d83e467fcd6ad4a0168b (patch)
tree77039e19031baa68b796747b2a5bd4e2c9a6d145 /test/codegen/arithmetic.go
parente7d08b6fe68be30a4239a1f930f96974db35473a (diff)
downloadgo-git-4d9dd3580624df413d65d83e467fcd6ad4a0168b.tar.gz
cmd/compile: add signed divisibility rules
"Division by invariant integers using multiplication" paper by Granlund and Montgomery contains a method for directly computing divisibility (x%c == 0 for c constant) by means of the modular inverse. The method is further elaborated in "Hacker's Delight" by Warren Section 10-17 This general rule can compute divisibilty by one multiplication, and add and a compare for odd divisors and an additional rotate for even divisors. To apply the divisibility rule, we must take into account the rules to rewrite x%c = x-((x/c)*c) and (x/c) for c constant on the first optimization pass "opt". This complicates the matching as we want to match only in the cases where the result of (x/c) is not also needed. So, we must match on the expanded form of (x/c) in the expression x == c*(x/c) in the "late opt" pass after common subexpresion elimination. Note, that if there is an intermediate opt pass introduced in the future we could simplify these rules by delaying the magic division rewrite to "late opt" and matching directly on (x/c) in the intermediate opt pass. On amd64, the divisibility check is 30-45% faster. name old time/op new time/op delta` DivisiblePow2constI64-4 0.83ns ± 1% 0.82ns ± 0% ~ (p=0.079 n=5+4) DivisibleconstI64-4 2.68ns ± 1% 1.87ns ± 0% -30.33% (p=0.000 n=5+4) DivisibleWDivconstI64-4 2.69ns ± 1% 2.71ns ± 3% ~ (p=1.000 n=5+5) DivisiblePow2constI32-4 1.15ns ± 1% 1.15ns ± 0% ~ (p=0.238 n=5+4) DivisibleconstI32-4 2.24ns ± 1% 1.20ns ± 0% -46.48% (p=0.016 n=5+4) DivisibleWDivconstI32-4 2.27ns ± 1% 2.27ns ± 1% ~ (p=0.683 n=5+5) DivisiblePow2constI16-4 0.81ns ± 1% 0.82ns ± 1% ~ (p=0.135 n=5+5) DivisibleconstI16-4 2.11ns ± 2% 1.20ns ± 1% -42.99% (p=0.008 n=5+5) DivisibleWDivconstI16-4 2.23ns ± 0% 2.27ns ± 2% +1.79% (p=0.029 n=4+4) DivisiblePow2constI8-4 0.81ns ± 1% 0.81ns ± 1% ~ (p=0.286 n=5+5) DivisibleconstI8-4 2.13ns ± 3% 1.19ns ± 1% -43.84% (p=0.008 n=5+5) DivisibleWDivconstI8-4 2.23ns ± 1% 2.25ns ± 1% ~ (p=0.183 n=5+5) Fixes #30282 Fixes #15806 Change-Id: Id20d78263a4fdfe0509229ae4dfa2fede83fc1d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/173998 Run-TryBot: Brian Kessler <brian.m.kessler@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'test/codegen/arithmetic.go')
-rw-r--r--test/codegen/arithmetic.go25
1 files changed, 21 insertions, 4 deletions
diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go
index 16158b2f4b..dcbc6d3f97 100644
--- a/test/codegen/arithmetic.go
+++ b/test/codegen/arithmetic.go
@@ -216,14 +216,14 @@ func ConstMods(n1 uint, n2 int) (uint, int) {
}
// Check that divisibility checks x%c==0 are converted to MULs and rotates
-func Divisible(n uint) (even, odd bool) {
+func Divisible(n1 uint, n2 int) (bool, bool, bool, bool) {
// amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ"
// 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
// arm64:"MOVD\t[$]-6148914691236517205","MUL","ROR",-"DIV"
// arm:"MUL","CMP\t[$]715827882",-".*udiv"
// ppc64:"MULLD","ROTL\t[$]63"
// ppc64le:"MULLD","ROTL\t[$]63"
- even = n%6 == 0
+ evenU := n1%6 == 0
// amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ"
// 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ"
@@ -231,8 +231,25 @@ func Divisible(n uint) (even, odd bool) {
// arm:"MUL","CMP\t[$]226050910",-".*udiv"
// ppc64:"MULLD",-"ROTL"
// ppc64le:"MULLD",-"ROTL"
- odd = n%19 == 0
- return
+ oddU := n1%19 == 0
+
+ // amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ"
+ // 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ"
+ // arm64:"MUL","ADD\t[$]3074457345618258602","ROR",-"DIV"
+ // arm:"MUL","ADD\t[$]715827882",-".*udiv"
+ // ppc64:"MULLD","ADD","ROTL\t[$]63"
+ // ppc64le:"MULLD","ADD","ROTL\t[$]63"
+ evenS := n2%6 == 0
+
+ // amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ"
+ // 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ"
+ // arm64:"MUL","ADD\t[$]485440633518672410",-"ROR",-"DIV"
+ // arm:"MUL","ADD\t[$]113025455",-".*udiv"
+ // ppc64:"MULLD","ADD",-"ROTL"
+ // ppc64le:"MULLD","ADD",-"ROTL"
+ oddS := n2%19 == 0
+
+ return evenU, oddU, evenS, oddS
}
// Check that fix-up code is not generated for divisions where it has been proven that