From: Cuong Manh Le Date: Wed, 23 Jul 2025 16:51:16 +0000 (+0700) Subject: cmd/compile: use unsigned power-of-two detector for unsigned mod X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=bd94ae8903e6256d9777a28bf86f425116fca316;p=gostls13.git cmd/compile: use unsigned power-of-two detector for unsigned mod Same as CL 689815, but for modulus instead of division. Updates #74485 Change-Id: I73000231c886a987a1093669ff207fd9117a8160 Reviewed-on: https://go-review.googlesource.com/c/go/+/689895 LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Auto-Submit: Cuong Manh Le Reviewed-by: Keith Randall Reviewed-by: Keith Randall --- diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 533dd96d8b..7ac36c3b3c 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -1293,11 +1293,10 @@ (Const64 [63]))) // Unsigned mod by power of 2 constant. -(Mod8u n (Const8 [c])) && isPowerOfTwo(c) => (And8 n (Const8 [c-1])) -(Mod16u n (Const16 [c])) && isPowerOfTwo(c) => (And16 n (Const16 [c-1])) -(Mod32u n (Const32 [c])) && isPowerOfTwo(c) => (And32 n (Const32 [c-1])) -(Mod64u n (Const64 [c])) && isPowerOfTwo(c) => (And64 n (Const64 [c-1])) -(Mod64u n (Const64 [-1<<63])) => (And64 n (Const64 [1<<63-1])) +(Mod8u n (Const8 [c])) && isUnsignedPowerOfTwo(uint8(c)) => (And8 n (Const8 [c-1])) +(Mod16u n (Const16 [c])) && isUnsignedPowerOfTwo(uint16(c)) => (And16 n (Const16 [c-1])) +(Mod32u n (Const32 [c])) && isUnsignedPowerOfTwo(uint32(c)) => (And32 n (Const32 [c-1])) +(Mod64u n (Const64 [c])) && isUnsignedPowerOfTwo(uint64(c)) => (And64 n (Const64 [c-1])) // Signed non-negative mod by power of 2 constant. (Mod8 n (Const8 [c])) && isNonNegative(n) && isPowerOfTwo(c) => (And8 n (Const8 [c-1])) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 9303b96822..3af7f40e68 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -16906,7 +16906,7 @@ func rewriteValuegeneric_OpMod16u(v *Value) bool { return true } // match: (Mod16u n (Const16 [c])) - // cond: isPowerOfTwo(c) + // cond: isUnsignedPowerOfTwo(uint16(c)) // result: (And16 n (Const16 [c-1])) for { t := v.Type @@ -16915,7 +16915,7 @@ func rewriteValuegeneric_OpMod16u(v *Value) bool { break } c := auxIntToInt16(v_1.AuxInt) - if !(isPowerOfTwo(c)) { + if !(isUnsignedPowerOfTwo(uint16(c))) { break } v.reset(OpAnd16) @@ -17060,7 +17060,7 @@ func rewriteValuegeneric_OpMod32u(v *Value) bool { return true } // match: (Mod32u n (Const32 [c])) - // cond: isPowerOfTwo(c) + // cond: isUnsignedPowerOfTwo(uint32(c)) // result: (And32 n (Const32 [c-1])) for { t := v.Type @@ -17069,7 +17069,7 @@ func rewriteValuegeneric_OpMod32u(v *Value) bool { break } c := auxIntToInt32(v_1.AuxInt) - if !(isPowerOfTwo(c)) { + if !(isUnsignedPowerOfTwo(uint32(c))) { break } v.reset(OpAnd32) @@ -17225,7 +17225,7 @@ func rewriteValuegeneric_OpMod64u(v *Value) bool { return true } // match: (Mod64u n (Const64 [c])) - // cond: isPowerOfTwo(c) + // cond: isUnsignedPowerOfTwo(uint64(c)) // result: (And64 n (Const64 [c-1])) for { t := v.Type @@ -17234,7 +17234,7 @@ func rewriteValuegeneric_OpMod64u(v *Value) bool { break } c := auxIntToInt64(v_1.AuxInt) - if !(isPowerOfTwo(c)) { + if !(isUnsignedPowerOfTwo(uint64(c))) { break } v.reset(OpAnd64) @@ -17243,20 +17243,6 @@ func rewriteValuegeneric_OpMod64u(v *Value) bool { v.AddArg2(n, v0) return true } - // match: (Mod64u n (Const64 [-1<<63])) - // result: (And64 n (Const64 [1<<63-1])) - for { - t := v.Type - n := v_0 - if v_1.Op != OpConst64 || auxIntToInt64(v_1.AuxInt) != -1<<63 { - break - } - v.reset(OpAnd64) - v0 := b.NewValue0(v.Pos, OpConst64, t) - v0.AuxInt = int64ToAuxInt(1<<63 - 1) - v.AddArg2(n, v0) - return true - } // match: (Mod64u x (Const64 [c])) // cond: x.Op != OpConst64 && c > 0 && umagicOK64(c) // result: (Sub64 x (Mul64 (Div64u x (Const64 [c])) (Const64 [c]))) @@ -17393,7 +17379,7 @@ func rewriteValuegeneric_OpMod8u(v *Value) bool { return true } // match: (Mod8u n (Const8 [c])) - // cond: isPowerOfTwo(c) + // cond: isUnsignedPowerOfTwo(uint8(c)) // result: (And8 n (Const8 [c-1])) for { t := v.Type @@ -17402,7 +17388,7 @@ func rewriteValuegeneric_OpMod8u(v *Value) bool { break } c := auxIntToInt8(v_1.AuxInt) - if !(isPowerOfTwo(c)) { + if !(isUnsignedPowerOfTwo(uint8(c))) { break } v.reset(OpAnd8) diff --git a/test/codegen/issue74485.go b/test/codegen/issue74485.go index 570707509b..b5aba9568c 100644 --- a/test/codegen/issue74485.go +++ b/test/codegen/issue74485.go @@ -25,3 +25,23 @@ func divUint8(b uint8) uint8 { // amd64:"SHRB [$]7, AL" return b / 128 } + +func modUint64(b uint64) uint64 { + // amd64:"BTRQ [$]63, AX" + return b % 9223372036854775808 +} + +func modUint32(b uint32) uint32 { + // amd64:"ANDL [$]2147483647, AX" + return b % 2147483648 +} + +func modUint16(b uint16) uint16 { + // amd64:"ANDL [$]32767, AX" + return b % 32768 +} + +func modUint8(b uint8) uint8 { + // amd64:"ANDL [$]127, AX" + return b % 128 +}