]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: make oneBit function generic
authorMichael Munday <mndygolang+git@gmail.com>
Tue, 26 Aug 2025 21:12:29 +0000 (22:12 +0100)
committerGopher Robot <gobot@golang.org>
Fri, 29 Aug 2025 17:02:33 +0000 (10:02 -0700)
Allows rewrite rules using oneBit to be made more compact.

Change-Id: I986715f77db5b548759d809fe668e1893048f25c
Reviewed-on: https://go-review.googlesource.com/c/go/+/699295
Reviewed-by: Youlin Feng <fengyoulin@live.com>
Commit-Queue: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritegeneric.go

index 7ac36c3b3cd3911ad07cf9a21d3737b562ae655f..da112abbf5677ede19ddceff457920f677bdd21d 100644 (file)
 (Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 => (Neq(8|16|32|64) x y)
 
 // Optimize bitsets
-(Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
-  => (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
-(Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
-  => (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
-(Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
-  => (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
-(Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
-  => (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
-(Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
-  => (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
-(Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
-  => (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
-(Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
-  => (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
-(Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
-  => (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
+(Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && oneBit(y)
+  => (Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
+(Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && oneBit(y)
+  => (Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
 
 // Reassociate expressions involving
 // constants such that constants come first,
index 236a3f885adb4bf72cf17d9806c6548883c67f7b..6704c7d6e0294a1bce275ef781a9e9157f580cab 100644 (file)
@@ -470,11 +470,10 @@ func ntz32(x int32) int { return bits.TrailingZeros32(uint32(x)) }
 func ntz16(x int16) int { return bits.TrailingZeros16(uint16(x)) }
 func ntz8(x int8) int   { return bits.TrailingZeros8(uint8(x)) }
 
-func oneBit(x int64) bool   { return x&(x-1) == 0 && x != 0 }
-func oneBit8(x int8) bool   { return x&(x-1) == 0 && x != 0 }
-func oneBit16(x int16) bool { return x&(x-1) == 0 && x != 0 }
-func oneBit32(x int32) bool { return x&(x-1) == 0 && x != 0 }
-func oneBit64(x int64) bool { return x&(x-1) == 0 && x != 0 }
+// oneBit reports whether x contains exactly one set bit.
+func oneBit[T int8 | int16 | int32 | int64](x T) bool {
+       return x&(x-1) == 0 && x != 0
+}
 
 // nto returns the number of trailing ones.
 func nto(x int64) int64 {
index 3af7f40e684f912f5a74a12173add3c5209a7f82..5394747ba577175f97748b54f5e06b804935818c 100644 (file)
@@ -8796,7 +8796,7 @@ func rewriteValuegeneric_OpEq16(v *Value) bool {
                break
        }
        // match: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
-       // cond: oneBit16(y)
+       // cond: oneBit(y)
        // result: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -8813,7 +8813,7 @@ func rewriteValuegeneric_OpEq16(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt16(v_0_1.AuxInt)
-                               if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
+                               if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpNeq16)
@@ -9660,7 +9660,7 @@ func rewriteValuegeneric_OpEq32(v *Value) bool {
                break
        }
        // match: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
-       // cond: oneBit32(y)
+       // cond: oneBit(y)
        // result: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -9677,7 +9677,7 @@ func rewriteValuegeneric_OpEq32(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt32(v_0_1.AuxInt)
-                               if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
+                               if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpNeq32)
@@ -10241,7 +10241,7 @@ func rewriteValuegeneric_OpEq64(v *Value) bool {
                break
        }
        // match: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
-       // cond: oneBit64(y)
+       // cond: oneBit(y)
        // result: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -10258,7 +10258,7 @@ func rewriteValuegeneric_OpEq64(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt64(v_0_1.AuxInt)
-                               if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
+                               if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpNeq64)
@@ -10663,7 +10663,7 @@ func rewriteValuegeneric_OpEq8(v *Value) bool {
                break
        }
        // match: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
-       // cond: oneBit8(y)
+       // cond: oneBit(y)
        // result: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -10680,7 +10680,7 @@ func rewriteValuegeneric_OpEq8(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt8(v_0_1.AuxInt)
-                               if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
+                               if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpNeq8)
@@ -20309,7 +20309,7 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool {
                break
        }
        // match: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
-       // cond: oneBit16(y)
+       // cond: oneBit(y)
        // result: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -20326,7 +20326,7 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt16(v_0_1.AuxInt)
-                               if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
+                               if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpEq16)
@@ -20496,7 +20496,7 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool {
                break
        }
        // match: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
-       // cond: oneBit32(y)
+       // cond: oneBit(y)
        // result: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -20513,7 +20513,7 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt32(v_0_1.AuxInt)
-                               if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
+                               if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpEq32)
@@ -20706,7 +20706,7 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool {
                break
        }
        // match: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
-       // cond: oneBit64(y)
+       // cond: oneBit(y)
        // result: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -20723,7 +20723,7 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt64(v_0_1.AuxInt)
-                               if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
+                               if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpEq64)
@@ -20916,7 +20916,7 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool {
                break
        }
        // match: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
-       // cond: oneBit8(y)
+       // cond: oneBit(y)
        // result: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -20933,7 +20933,7 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool {
                                        continue
                                }
                                y := auxIntToInt8(v_0_1.AuxInt)
-                               if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
+                               if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit(y)) {
                                        continue
                                }
                                v.reset(OpEq8)