Skip to content

Commit

Permalink
Revert "cmd/compile: add signed divisibility by power of 2 rules"
Browse files Browse the repository at this point in the history
This reverts CL 168038 (git 68819fb)

Reason for revert: Doesn't work on 32 bit archs.

Change-Id: Idec9098060dc65bc2f774c5383f0477f8eb63a3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/173442
Reviewed-by: Brad Fitzpatrick <[email protected]>
  • Loading branch information
randall77 committed Apr 23, 2019
1 parent 58de7c6 commit 1761596
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 679 deletions.
291 changes: 0 additions & 291 deletions src/cmd/compile/internal/gc/testdata/arith_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package main

import (
"math"
"runtime"
"testing"
)
Expand Down Expand Up @@ -925,7 +924,6 @@ func TestArithmetic(t *testing.T) {
testShiftRemoval(t)
testShiftedOps(t)
testDivFixUp(t)
testDivisibleSignedPow2(t)
}

// testDivFixUp ensures that signed division fix-ups are being generated.
Expand Down Expand Up @@ -954,292 +952,3 @@ func testDivFixUp(t *testing.T) {
g64 = z % int64(i)
}
}

//go:noinline
func divisible_int8_2to1(x int8) bool {
return x%(1<<1) == 0
}

//go:noinline
func divisible_int8_2to2(x int8) bool {
return x%(1<<2) == 0
}

//go:noinline
func divisible_int8_2to3(x int8) bool {
return x%(1<<3) == 0
}

//go:noinline
func divisible_int8_2to4(x int8) bool {
return x%(1<<4) == 0
}

//go:noinline
func divisible_int8_2to5(x int8) bool {
return x%(1<<5) == 0
}

//go:noinline
func divisible_int8_2to6(x int8) bool {
return x%(1<<6) == 0
}

//go:noinline
func divisible_int16_2to1(x int16) bool {
return x%(1<<1) == 0
}

//go:noinline
func divisible_int16_2to2(x int16) bool {
return x%(1<<2) == 0
}

//go:noinline
func divisible_int16_2to3(x int16) bool {
return x%(1<<3) == 0
}

//go:noinline
func divisible_int16_2to4(x int16) bool {
return x%(1<<4) == 0
}

//go:noinline
func divisible_int16_2to5(x int16) bool {
return x%(1<<5) == 0
}

//go:noinline
func divisible_int16_2to6(x int16) bool {
return x%(1<<6) == 0
}

//go:noinline
func divisible_int16_2to7(x int16) bool {
return x%(1<<7) == 0
}

//go:noinline
func divisible_int16_2to8(x int16) bool {
return x%(1<<8) == 0
}

//go:noinline
func divisible_int16_2to9(x int16) bool {
return x%(1<<9) == 0
}

//go:noinline
func divisible_int16_2to10(x int16) bool {
return x%(1<<10) == 0
}

//go:noinline
func divisible_int16_2to11(x int16) bool {
return x%(1<<11) == 0
}

//go:noinline
func divisible_int16_2to12(x int16) bool {
return x%(1<<12) == 0
}

//go:noinline
func divisible_int16_2to13(x int16) bool {
return x%(1<<13) == 0
}

//go:noinline
func divisible_int16_2to14(x int16) bool {
return x%(1<<14) == 0
}

//go:noinline
func divisible_int32_2to4(x int32) bool {
return x%(1<<4) == 0
}

//go:noinline
func divisible_int32_2to15(x int32) bool {
return x%(1<<15) == 0
}

//go:noinline
func divisible_int32_2to26(x int32) bool {
return x%(1<<26) == 0
}

//go:noinline
func divisible_int64_2to4(x int64) bool {
return x%(1<<4) == 0
}

//go:noinline
func divisible_int64_2to15(x int64) bool {
return x%(1<<15) == 0
}

//go:noinline
func divisible_int64_2to26(x int64) bool {
return x%(1<<26) == 0
}

//go:noinline
func divisible_int64_2to34(x int64) bool {
return x%(1<<34) == 0
}

//go:noinline
func divisible_int64_2to48(x int64) bool {
return x%(1<<48) == 0
}

//go:noinline
func divisible_int64_2to57(x int64) bool {
return x%(1<<57) == 0
}

// testDivisibleSignedPow2 confirms that x%(1<<k)==0 is rewritten correctly
func testDivisibleSignedPow2(t *testing.T) {
var i int64
var pow2 = []int64{
1,
1 << 1,
1 << 2,
1 << 3,
1 << 4,
1 << 5,
1 << 6,
1 << 7,
1 << 8,
1 << 9,
1 << 10,
1 << 11,
1 << 12,
1 << 13,
1 << 14,
}
// exhaustive test for int8
for i = math.MinInt8; i <= math.MaxInt8; i++ {
if want, got := int8(i)%int8(pow2[1]) == 0, divisible_int8_2to1(int8(i)); got != want {
t.Errorf("divisible_int8_2to1(%d) = %v want %v", i, got, want)
}
if want, got := int8(i)%int8(pow2[2]) == 0, divisible_int8_2to2(int8(i)); got != want {
t.Errorf("divisible_int8_2to2(%d) = %v want %v", i, got, want)
}
if want, got := int8(i)%int8(pow2[3]) == 0, divisible_int8_2to3(int8(i)); got != want {
t.Errorf("divisible_int8_2to3(%d) = %v want %v", i, got, want)
}
if want, got := int8(i)%int8(pow2[4]) == 0, divisible_int8_2to4(int8(i)); got != want {
t.Errorf("divisible_int8_2to4(%d) = %v want %v", i, got, want)
}
if want, got := int8(i)%int8(pow2[5]) == 0, divisible_int8_2to5(int8(i)); got != want {
t.Errorf("divisible_int8_2to5(%d) = %v want %v", i, got, want)
}
if want, got := int8(i)%int8(pow2[6]) == 0, divisible_int8_2to6(int8(i)); got != want {
t.Errorf("divisible_int8_2to6(%d) = %v want %v", i, got, want)
}
}
// exhaustive test for int16
for i = math.MinInt16; i <= math.MaxInt16; i++ {
if want, got := int16(i)%int16(pow2[1]) == 0, divisible_int16_2to1(int16(i)); got != want {
t.Errorf("divisible_int16_2to1(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[2]) == 0, divisible_int16_2to2(int16(i)); got != want {
t.Errorf("divisible_int16_2to2(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[3]) == 0, divisible_int16_2to3(int16(i)); got != want {
t.Errorf("divisible_int16_2to3(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[4]) == 0, divisible_int16_2to4(int16(i)); got != want {
t.Errorf("divisible_int16_2to4(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[5]) == 0, divisible_int16_2to5(int16(i)); got != want {
t.Errorf("divisible_int16_2to5(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[6]) == 0, divisible_int16_2to6(int16(i)); got != want {
t.Errorf("divisible_int16_2to6(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[7]) == 0, divisible_int16_2to7(int16(i)); got != want {
t.Errorf("divisible_int16_2to7(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[8]) == 0, divisible_int16_2to8(int16(i)); got != want {
t.Errorf("divisible_int16_2to8(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[9]) == 0, divisible_int16_2to9(int16(i)); got != want {
t.Errorf("divisible_int16_2to9(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[10]) == 0, divisible_int16_2to10(int16(i)); got != want {
t.Errorf("divisible_int16_2to10(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[11]) == 0, divisible_int16_2to11(int16(i)); got != want {
t.Errorf("divisible_int16_2to11(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[12]) == 0, divisible_int16_2to12(int16(i)); got != want {
t.Errorf("divisible_int16_2to12(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[13]) == 0, divisible_int16_2to13(int16(i)); got != want {
t.Errorf("divisible_int16_2to13(%d) = %v want %v", i, got, want)
}
if want, got := int16(i)%int16(pow2[14]) == 0, divisible_int16_2to14(int16(i)); got != want {
t.Errorf("divisible_int16_2to14(%d) = %v want %v", i, got, want)
}
}
// spot check for int32 and int64
var (
two4 int64 = 1 << 4
two15 int64 = 1 << 15
two26 int64 = 1 << 26
two34 int64 = 1 << 34
two48 int64 = 1 << 48
two57 int64 = 1 << 57
)
var xs = []int64{two4, two4 + 3, -3 * two4, -3*two4 + 1,
two15, two15 + 3, -3 * two15, -3*two15 + 1,
two26, two26 + 37, -5 * two26, -5*two26 + 2,
two34, two34 + 356, -7 * two34, -7*two34 + 13,
two48, two48 + 3000, -12 * two48, -12*two48 + 1111,
two57, two57 + 397654, -15 * two57, -15*two57 + 11234,
}
for _, x := range xs {
if int64(int32(x)) == x {
if want, got := int32(x)%int32(two4) == 0, divisible_int32_2to4(int32(x)); got != want {
t.Errorf("divisible_int32_2to4(%d) = %v want %v", x, got, want)
}

if want, got := int32(x)%int32(two15) == 0, divisible_int32_2to15(int32(x)); got != want {
t.Errorf("divisible_int32_2to15(%d) = %v want %v", x, got, want)
}

if want, got := int32(x)%int32(two26) == 0, divisible_int32_2to26(int32(x)); got != want {
t.Errorf("divisible_int32_2to26(%d) = %v want %v", x, got, want)
}
}
// spot check for int64
if want, got := x%two4 == 0, divisible_int64_2to4(x); got != want {
t.Errorf("divisible_int64_2to4(%d) = %v want %v", x, got, want)
}

if want, got := x%two15 == 0, divisible_int64_2to15(x); got != want {
t.Errorf("divisible_int64_2to15(%d) = %v want %v", x, got, want)
}

if want, got := x%two26 == 0, divisible_int64_2to26(x); got != want {
t.Errorf("divisible_int64_2to26(%d) = %v want %v", x, got, want)
}

if want, got := x%two34 == 0, divisible_int64_2to34(x); got != want {
t.Errorf("divisible_int64_2to34(%d) = %v want %v", x, got, want)
}

if want, got := x%two48 == 0, divisible_int64_2to48(x); got != want {
t.Errorf("divisible_int64_2to48(%d) = %v want %v", x, got, want)
}

if want, got := x%two57 == 0, divisible_int64_2to57(x); got != want {
t.Errorf("divisible_int64_2to57(%d) = %v want %v", x, got, want)
}

}
}
19 changes: 4 additions & 15 deletions src/cmd/compile/internal/ssa/gen/generic.rules
Original file line number Diff line number Diff line change
Expand Up @@ -1143,27 +1143,16 @@
(Mod32 <t> n (Const32 [c])) && c < 0 && c != -1<<31 -> (Mod32 <t> n (Const32 <t> [-c]))
(Mod64 <t> n (Const64 [c])) && c < 0 && c != -1<<63 -> (Mod64 <t> n (Const64 <t> [-c]))

// Divisibility check for signed integers for power of two constant are simple mask.
(Eq8 (Mod8 <t> n (Const8 [c])) (Const8 [0])) && n.Op != OpConst8 && isPowerOfTwo(c&0xff)
-> (Eq8 (And8 <t> n (Const8 <t> [(c&0xff)-1])) (Const8 <t> [0]))
(Eq16 (Mod16 <t> n (Const16 [c])) (Const16 [0])) && n.Op != OpConst16 && isPowerOfTwo(c&0xffff)
-> (Eq16 (And16 <t> n (Const16 <t> [(c&0xffff)-1])) (Const16 <t> [0]))
(Eq32 (Mod32 <t> n (Const32 [c])) (Const32 [0])) && n.Op != OpConst32 && isPowerOfTwo(c&0xffffffff)
-> (Eq32 (And32 <t> n (Const32 <t> [(c&0xffffffff)-1])) (Const32 <t> [0]))
(Eq64 (Mod64 <t> n (Const64 [c])) (Const64 [0])) && n.Op != OpConst64 && isPowerOfTwo(c)
-> (Eq64 (And64 <t> n (Const64 <t> [c-1])) (Const64 <t> [0]))


// All other mods by constants, do A%B = A-(A/B*B).
// This implements % with two * and a bunch of ancillary ops.
// One of the * is free if the user's code also computes A/B.
(Mod8 <t> x (Const8 [c])) && x.Op != OpConst8 && (c > 0 || c == -1<<7) && v.Block.Func.pass.name != "opt"
(Mod8 <t> x (Const8 [c])) && x.Op != OpConst8 && (c > 0 || c == -1<<7)
-> (Sub8 x (Mul8 <t> (Div8 <t> x (Const8 <t> [c])) (Const8 <t> [c])))
(Mod16 <t> x (Const16 [c])) && x.Op != OpConst16 && (c > 0 || c == -1<<15) && v.Block.Func.pass.name != "opt"
(Mod16 <t> x (Const16 [c])) && x.Op != OpConst16 && (c > 0 || c == -1<<15)
-> (Sub16 x (Mul16 <t> (Div16 <t> x (Const16 <t> [c])) (Const16 <t> [c])))
(Mod32 <t> x (Const32 [c])) && x.Op != OpConst32 && (c > 0 || c == -1<<31) && v.Block.Func.pass.name != "opt"
(Mod32 <t> x (Const32 [c])) && x.Op != OpConst32 && (c > 0 || c == -1<<31)
-> (Sub32 x (Mul32 <t> (Div32 <t> x (Const32 <t> [c])) (Const32 <t> [c])))
(Mod64 <t> x (Const64 [c])) && x.Op != OpConst64 && (c > 0 || c == -1<<63) && v.Block.Func.pass.name != "opt"
(Mod64 <t> x (Const64 [c])) && x.Op != OpConst64 && (c > 0 || c == -1<<63)
-> (Sub64 x (Mul64 <t> (Div64 <t> x (Const64 <t> [c])) (Const64 <t> [c])))
(Mod8u <t> x (Const8 [c])) && x.Op != OpConst8 && c > 0 && umagicOK(8 ,c)
-> (Sub8 x (Mul8 <t> (Div8u <t> x (Const8 <t> [c])) (Const8 <t> [c])))
Expand Down
Loading

0 comments on commit 1761596

Please sign in to comment.