mirror of
https://github.com/golang/go
synced 2024-11-18 11:44:45 -07:00
cmd/compile: convert constant divide strength reduction rules to typed aux
Passes toolstash-check. Change-Id: Ia5d11c099b8c6c0ed670960b2af808200e3b1ca1 Reviewed-on: https://go-review.googlesource.com/c/go/+/230739 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
56933fb838
commit
3d34c77829
@ -946,118 +946,118 @@
|
||||
|
||||
// Unsigned divide, not a power of 2. Strength reduce to a multiply.
|
||||
// For 8-bit divides, we just do a direct 9-bit by 8-bit multiply.
|
||||
(Div8u x (Const8 [c])) && umagicOK(8, c) ->
|
||||
(Div8u x (Const8 [c])) && umagicOK8(c) =>
|
||||
(Trunc32to8
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(1<<8+umagic(8,c).m)])
|
||||
(Const32 <typ.UInt32> [int32(1<<8+umagic8(c).m)])
|
||||
(ZeroExt8to32 x))
|
||||
(Const64 <typ.UInt64> [8+umagic(8,c).s])))
|
||||
(Const64 <typ.UInt64> [8+umagic8(c).s])))
|
||||
|
||||
// For 16-bit divides on 64-bit machines, we do a direct 17-bit by 16-bit multiply.
|
||||
(Div16u x (Const16 [c])) && umagicOK(16, c) && config.RegSize == 8 ->
|
||||
(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 8 =>
|
||||
(Trunc64to16
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(1<<16+umagic(16,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(1<<16+umagic16(c).m)])
|
||||
(ZeroExt16to64 x))
|
||||
(Const64 <typ.UInt64> [16+umagic(16,c).s])))
|
||||
(Const64 <typ.UInt64> [16+umagic16(c).s])))
|
||||
|
||||
// For 16-bit divides on 32-bit machines
|
||||
(Div16u x (Const16 [c])) && umagicOK(16, c) && config.RegSize == 4 && umagic(16,c).m&1 == 0 ->
|
||||
(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && umagic16(c).m&1 == 0 =>
|
||||
(Trunc32to16
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(1<<15+umagic(16,c).m/2)])
|
||||
(Const32 <typ.UInt32> [int32(1<<15+umagic16(c).m/2)])
|
||||
(ZeroExt16to32 x))
|
||||
(Const64 <typ.UInt64> [16+umagic(16,c).s-1])))
|
||||
(Div16u x (Const16 [c])) && umagicOK(16, c) && config.RegSize == 4 && c&1 == 0 ->
|
||||
(Const64 <typ.UInt64> [16+umagic16(c).s-1])))
|
||||
(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && c&1 == 0 =>
|
||||
(Trunc32to16
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(1<<15+(umagic(16,c).m+1)/2)])
|
||||
(Const32 <typ.UInt32> [int32(1<<15+(umagic16(c).m+1)/2)])
|
||||
(Rsh32Ux64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [1])))
|
||||
(Const64 <typ.UInt64> [16+umagic(16,c).s-2])))
|
||||
(Div16u x (Const16 [c])) && umagicOK(16, c) && config.RegSize == 4 && config.useAvg ->
|
||||
(Const64 <typ.UInt64> [16+umagic16(c).s-2])))
|
||||
(Div16u x (Const16 [c])) && umagicOK16(c) && config.RegSize == 4 && config.useAvg =>
|
||||
(Trunc32to16
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Avg32u
|
||||
(Lsh32x64 <typ.UInt32> (ZeroExt16to32 x) (Const64 <typ.UInt64> [16]))
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(umagic(16,c).m)])
|
||||
(Const32 <typ.UInt32> [int32(umagic16(c).m)])
|
||||
(ZeroExt16to32 x)))
|
||||
(Const64 <typ.UInt64> [16+umagic(16,c).s-1])))
|
||||
(Const64 <typ.UInt64> [16+umagic16(c).s-1])))
|
||||
|
||||
// For 32-bit divides on 32-bit machines
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 4 && umagic(32,c).m&1 == 0 && config.useHmul ->
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && umagic32(c).m&1 == 0 && config.useHmul =>
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Hmul32u <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(1<<31+umagic(32,c).m/2))])
|
||||
(Const32 <typ.UInt32> [int32(1<<31+umagic32(c).m/2)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [umagic(32,c).s-1]))
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 4 && c&1 == 0 && config.useHmul ->
|
||||
(Const64 <typ.UInt64> [umagic32(c).s-1]))
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && c&1 == 0 && config.useHmul =>
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Hmul32u <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(1<<31+(umagic(32,c).m+1)/2))])
|
||||
(Const32 <typ.UInt32> [int32(1<<31+(umagic32(c).m+1)/2)])
|
||||
(Rsh32Ux64 <typ.UInt32> x (Const64 <typ.UInt64> [1])))
|
||||
(Const64 <typ.UInt64> [umagic(32,c).s-2]))
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 4 && config.useAvg && config.useHmul ->
|
||||
(Const64 <typ.UInt64> [umagic32(c).s-2]))
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 4 && config.useAvg && config.useHmul =>
|
||||
(Rsh32Ux64 <typ.UInt32>
|
||||
(Avg32u
|
||||
x
|
||||
(Hmul32u <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(umagic(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(umagic32(c).m)])
|
||||
x))
|
||||
(Const64 <typ.UInt64> [umagic(32,c).s-1]))
|
||||
(Const64 <typ.UInt64> [umagic32(c).s-1]))
|
||||
|
||||
// For 32-bit divides on 64-bit machines
|
||||
// We'll use a regular (non-hi) multiply for this case.
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 8 && umagic(32,c).m&1 == 0 ->
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && umagic32(c).m&1 == 0 =>
|
||||
(Trunc64to32
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(1<<31+umagic(32,c).m/2)])
|
||||
(Const64 <typ.UInt64> [int64(1<<31+umagic32(c).m/2)])
|
||||
(ZeroExt32to64 x))
|
||||
(Const64 <typ.UInt64> [32+umagic(32,c).s-1])))
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 8 && c&1 == 0 ->
|
||||
(Const64 <typ.UInt64> [32+umagic32(c).s-1])))
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && c&1 == 0 =>
|
||||
(Trunc64to32
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(1<<31+(umagic(32,c).m+1)/2)])
|
||||
(Const64 <typ.UInt64> [int64(1<<31+(umagic32(c).m+1)/2)])
|
||||
(Rsh64Ux64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [1])))
|
||||
(Const64 <typ.UInt64> [32+umagic(32,c).s-2])))
|
||||
(Div32u x (Const32 [c])) && umagicOK(32, c) && config.RegSize == 8 && config.useAvg ->
|
||||
(Const64 <typ.UInt64> [32+umagic32(c).s-2])))
|
||||
(Div32u x (Const32 [c])) && umagicOK32(c) && config.RegSize == 8 && config.useAvg =>
|
||||
(Trunc64to32
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Avg64u
|
||||
(Lsh64x64 <typ.UInt64> (ZeroExt32to64 x) (Const64 <typ.UInt64> [32]))
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt32> [int64(umagic(32,c).m)])
|
||||
(Const64 <typ.UInt32> [int64(umagic32(c).m)])
|
||||
(ZeroExt32to64 x)))
|
||||
(Const64 <typ.UInt64> [32+umagic(32,c).s-1])))
|
||||
(Const64 <typ.UInt64> [32+umagic32(c).s-1])))
|
||||
|
||||
// For 64-bit divides on 64-bit machines
|
||||
// (64-bit divides on 32-bit machines are lowered to a runtime call by the walk pass.)
|
||||
(Div64u x (Const64 [c])) && umagicOK(64, c) && config.RegSize == 8 && umagic(64,c).m&1 == 0 && config.useHmul ->
|
||||
(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && umagic64(c).m&1 == 0 && config.useHmul =>
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Hmul64u <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(1<<63+umagic(64,c).m/2)])
|
||||
(Const64 <typ.UInt64> [int64(1<<63+umagic64(c).m/2)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [umagic(64,c).s-1]))
|
||||
(Div64u x (Const64 [c])) && umagicOK(64, c) && config.RegSize == 8 && c&1 == 0 && config.useHmul ->
|
||||
(Const64 <typ.UInt64> [umagic64(c).s-1]))
|
||||
(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && c&1 == 0 && config.useHmul =>
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Hmul64u <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(1<<63+(umagic(64,c).m+1)/2)])
|
||||
(Const64 <typ.UInt64> [int64(1<<63+(umagic64(c).m+1)/2)])
|
||||
(Rsh64Ux64 <typ.UInt64> x (Const64 <typ.UInt64> [1])))
|
||||
(Const64 <typ.UInt64> [umagic(64,c).s-2]))
|
||||
(Div64u x (Const64 [c])) && umagicOK(64, c) && config.RegSize == 8 && config.useAvg && config.useHmul ->
|
||||
(Const64 <typ.UInt64> [umagic64(c).s-2]))
|
||||
(Div64u x (Const64 [c])) && umagicOK64(c) && config.RegSize == 8 && config.useAvg && config.useHmul =>
|
||||
(Rsh64Ux64 <typ.UInt64>
|
||||
(Avg64u
|
||||
x
|
||||
(Hmul64u <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(umagic(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(umagic64(c).m)])
|
||||
x))
|
||||
(Const64 <typ.UInt64> [umagic(64,c).s-1]))
|
||||
(Const64 <typ.UInt64> [umagic64(c).s-1]))
|
||||
|
||||
// Signed divide by a negative constant. Rewrite to divide by a positive constant.
|
||||
(Div8 <t> n (Const8 [c])) && c < 0 && c != -1<<7 => (Neg8 (Div8 <t> n (Const8 <t> [-c])))
|
||||
@ -1095,77 +1095,77 @@
|
||||
(Const64 <typ.UInt64> [int64(log64(c))]))
|
||||
|
||||
// Signed divide, not a power of 2. Strength reduce to a multiply.
|
||||
(Div8 <t> x (Const8 [c])) && smagicOK(8,c) ->
|
||||
(Div8 <t> x (Const8 [c])) && smagicOK8(c) =>
|
||||
(Sub8 <t>
|
||||
(Rsh32x64 <t>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(smagic(8,c).m)])
|
||||
(Const32 <typ.UInt32> [int32(smagic8(c).m)])
|
||||
(SignExt8to32 x))
|
||||
(Const64 <typ.UInt64> [8+smagic(8,c).s]))
|
||||
(Const64 <typ.UInt64> [8+smagic8(c).s]))
|
||||
(Rsh32x64 <t>
|
||||
(SignExt8to32 x)
|
||||
(Const64 <typ.UInt64> [31])))
|
||||
(Div16 <t> x (Const16 [c])) && smagicOK(16,c) ->
|
||||
(Div16 <t> x (Const16 [c])) && smagicOK16(c) =>
|
||||
(Sub16 <t>
|
||||
(Rsh32x64 <t>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(smagic(16,c).m)])
|
||||
(Const32 <typ.UInt32> [int32(smagic16(c).m)])
|
||||
(SignExt16to32 x))
|
||||
(Const64 <typ.UInt64> [16+smagic(16,c).s]))
|
||||
(Const64 <typ.UInt64> [16+smagic16(c).s]))
|
||||
(Rsh32x64 <t>
|
||||
(SignExt16to32 x)
|
||||
(Const64 <typ.UInt64> [31])))
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK(32,c) && config.RegSize == 8 ->
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 8 =>
|
||||
(Sub32 <t>
|
||||
(Rsh64x64 <t>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(smagic(32,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(smagic32(c).m)])
|
||||
(SignExt32to64 x))
|
||||
(Const64 <typ.UInt64> [32+smagic(32,c).s]))
|
||||
(Const64 <typ.UInt64> [32+smagic32(c).s]))
|
||||
(Rsh64x64 <t>
|
||||
(SignExt32to64 x)
|
||||
(Const64 <typ.UInt64> [63])))
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK(32,c) && config.RegSize == 4 && smagic(32,c).m&1 == 0 && config.useHmul ->
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 == 0 && config.useHmul =>
|
||||
(Sub32 <t>
|
||||
(Rsh32x64 <t>
|
||||
(Hmul32 <t>
|
||||
(Const32 <typ.UInt32> [int64(int32(smagic(32,c).m/2))])
|
||||
(Const32 <typ.UInt32> [int32(smagic32(c).m/2)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [smagic(32,c).s-1]))
|
||||
(Const64 <typ.UInt64> [smagic32(c).s-1]))
|
||||
(Rsh32x64 <t>
|
||||
x
|
||||
(Const64 <typ.UInt64> [31])))
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK(32,c) && config.RegSize == 4 && smagic(32,c).m&1 != 0 && config.useHmul ->
|
||||
(Div32 <t> x (Const32 [c])) && smagicOK32(c) && config.RegSize == 4 && smagic32(c).m&1 != 0 && config.useHmul =>
|
||||
(Sub32 <t>
|
||||
(Rsh32x64 <t>
|
||||
(Add32 <t>
|
||||
(Hmul32 <t>
|
||||
(Const32 <typ.UInt32> [int64(int32(smagic(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(smagic32(c).m)])
|
||||
x)
|
||||
x)
|
||||
(Const64 <typ.UInt64> [smagic(32,c).s]))
|
||||
(Const64 <typ.UInt64> [smagic32(c).s]))
|
||||
(Rsh32x64 <t>
|
||||
x
|
||||
(Const64 <typ.UInt64> [31])))
|
||||
(Div64 <t> x (Const64 [c])) && smagicOK(64,c) && smagic(64,c).m&1 == 0 && config.useHmul ->
|
||||
(Div64 <t> x (Const64 [c])) && smagicOK64(c) && smagic64(c).m&1 == 0 && config.useHmul =>
|
||||
(Sub64 <t>
|
||||
(Rsh64x64 <t>
|
||||
(Hmul64 <t>
|
||||
(Const64 <typ.UInt64> [int64(smagic(64,c).m/2)])
|
||||
(Const64 <typ.UInt64> [int64(smagic64(c).m/2)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [smagic(64,c).s-1]))
|
||||
(Const64 <typ.UInt64> [smagic64(c).s-1]))
|
||||
(Rsh64x64 <t>
|
||||
x
|
||||
(Const64 <typ.UInt64> [63])))
|
||||
(Div64 <t> x (Const64 [c])) && smagicOK(64,c) && smagic(64,c).m&1 != 0 && config.useHmul ->
|
||||
(Div64 <t> x (Const64 [c])) && smagicOK64(c) && smagic64(c).m&1 != 0 && config.useHmul =>
|
||||
(Sub64 <t>
|
||||
(Rsh64x64 <t>
|
||||
(Add64 <t>
|
||||
(Hmul64 <t>
|
||||
(Const64 <typ.UInt64> [int64(smagic(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(smagic64(c).m)])
|
||||
x)
|
||||
x)
|
||||
(Const64 <typ.UInt64> [smagic(64,c).s]))
|
||||
(Const64 <typ.UInt64> [smagic64(c).s]))
|
||||
(Rsh64x64 <t>
|
||||
x
|
||||
(Const64 <typ.UInt64> [63])))
|
||||
@ -1211,14 +1211,14 @@
|
||||
=> (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))
|
||||
|
||||
// For architectures without rotates on less than 32-bits, promote these checks to 32-bit.
|
||||
(Eq8 (Mod8u x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && udivisibleOK(8,c) && !hasSmallRotate(config) ->
|
||||
(Eq32 (Mod32u <typ.UInt32> (ZeroExt8to32 <typ.UInt32> x) (Const32 <typ.UInt32> [c&0xff])) (Const32 <typ.UInt32> [0]))
|
||||
(Eq16 (Mod16u x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && udivisibleOK(16,c) && !hasSmallRotate(config) ->
|
||||
(Eq32 (Mod32u <typ.UInt32> (ZeroExt16to32 <typ.UInt32> x) (Const32 <typ.UInt32> [c&0xffff])) (Const32 <typ.UInt32> [0]))
|
||||
(Eq8 (Mod8 x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && sdivisibleOK(8,c) && !hasSmallRotate(config) ->
|
||||
(Eq32 (Mod32 <typ.Int32> (SignExt8to32 <typ.Int32> x) (Const32 <typ.Int32> [c])) (Const32 <typ.Int32> [0]))
|
||||
(Eq16 (Mod16 x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && sdivisibleOK(16,c) && !hasSmallRotate(config) ->
|
||||
(Eq32 (Mod32 <typ.Int32> (SignExt16to32 <typ.Int32> x) (Const32 <typ.Int32> [c])) (Const32 <typ.Int32> [0]))
|
||||
(Eq8 (Mod8u x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && udivisibleOK8(c) && !hasSmallRotate(config) =>
|
||||
(Eq32 (Mod32u <typ.UInt32> (ZeroExt8to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint8(c))])) (Const32 <typ.UInt32> [0]))
|
||||
(Eq16 (Mod16u x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && udivisibleOK16(c) && !hasSmallRotate(config) =>
|
||||
(Eq32 (Mod32u <typ.UInt32> (ZeroExt16to32 <typ.UInt32> x) (Const32 <typ.UInt32> [int32(uint16(c))])) (Const32 <typ.UInt32> [0]))
|
||||
(Eq8 (Mod8 x (Const8 [c])) (Const8 [0])) && x.Op != OpConst8 && sdivisibleOK8(c) && !hasSmallRotate(config) =>
|
||||
(Eq32 (Mod32 <typ.Int32> (SignExt8to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
|
||||
(Eq16 (Mod16 x (Const16 [c])) (Const16 [0])) && x.Op != OpConst16 && sdivisibleOK16(c) && !hasSmallRotate(config) =>
|
||||
(Eq32 (Mod32 <typ.Int32> (SignExt16to32 <typ.Int32> x) (Const32 <typ.Int32> [int32(c)])) (Const32 <typ.Int32> [0]))
|
||||
|
||||
// Divisibility checks x%c == 0 convert to multiply and rotate.
|
||||
// Note, x%c == 0 is rewritten as x == c*(x/c) during the opt pass
|
||||
@ -1240,16 +1240,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<8+umagic(8,c).m) && s == 8+umagic(8,c).s
|
||||
&& x.Op != OpConst8 && udivisibleOK(8,c)
|
||||
-> (Leq8U
|
||||
&& m == int32(1<<8+umagic8(c).m) && s == 8+umagic8(c).s
|
||||
&& x.Op != OpConst8 && udivisibleOK8(c)
|
||||
=> (Leq8U
|
||||
(RotateLeft8 <typ.UInt8>
|
||||
(Mul8 <typ.UInt8>
|
||||
(Const8 <typ.UInt8> [int64(int8(udivisible(8,c).m))])
|
||||
(Const8 <typ.UInt8> [int8(udivisible8(c).m)])
|
||||
x)
|
||||
(Const8 <typ.UInt8> [int64(8-udivisible(8,c).k)])
|
||||
(Const8 <typ.UInt8> [int8(8-udivisible8(c).k)])
|
||||
)
|
||||
(Const8 <typ.UInt8> [int64(int8(udivisible(8,c).max))])
|
||||
(Const8 <typ.UInt8> [int8(udivisible8(c).max)])
|
||||
)
|
||||
|
||||
(Eq16 x (Mul16 (Const16 [c])
|
||||
@ -1262,16 +1262,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<16+umagic(16,c).m) && s == 16+umagic(16,c).s
|
||||
&& x.Op != OpConst16 && udivisibleOK(16,c)
|
||||
-> (Leq16U
|
||||
&& m == int64(1<<16+umagic16(c).m) && s == 16+umagic16(c).s
|
||||
&& x.Op != OpConst16 && udivisibleOK16(c)
|
||||
=> (Leq16U
|
||||
(RotateLeft16 <typ.UInt16>
|
||||
(Mul16 <typ.UInt16>
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).m))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).m)])
|
||||
x)
|
||||
(Const16 <typ.UInt16> [int64(16-udivisible(16,c).k)])
|
||||
(Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).max))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).max)])
|
||||
)
|
||||
|
||||
(Eq16 x (Mul16 (Const16 [c])
|
||||
@ -1284,16 +1284,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<15+umagic(16,c).m/2) && s == 16+umagic(16,c).s-1
|
||||
&& x.Op != OpConst16 && udivisibleOK(16,c)
|
||||
-> (Leq16U
|
||||
&& m == int32(1<<15+umagic16(c).m/2) && s == 16+umagic16(c).s-1
|
||||
&& x.Op != OpConst16 && udivisibleOK16(c)
|
||||
=> (Leq16U
|
||||
(RotateLeft16 <typ.UInt16>
|
||||
(Mul16 <typ.UInt16>
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).m))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).m)])
|
||||
x)
|
||||
(Const16 <typ.UInt16> [int64(16-udivisible(16,c).k)])
|
||||
(Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).max))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).max)])
|
||||
)
|
||||
|
||||
(Eq16 x (Mul16 (Const16 [c])
|
||||
@ -1306,16 +1306,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<15+(umagic(16,c).m+1)/2) && s == 16+umagic(16,c).s-2
|
||||
&& x.Op != OpConst16 && udivisibleOK(16,c)
|
||||
-> (Leq16U
|
||||
&& m == int32(1<<15+(umagic16(c).m+1)/2) && s == 16+umagic16(c).s-2
|
||||
&& x.Op != OpConst16 && udivisibleOK16(c)
|
||||
=> (Leq16U
|
||||
(RotateLeft16 <typ.UInt16>
|
||||
(Mul16 <typ.UInt16>
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).m))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).m)])
|
||||
x)
|
||||
(Const16 <typ.UInt16> [int64(16-udivisible(16,c).k)])
|
||||
(Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).max))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).max)])
|
||||
)
|
||||
|
||||
(Eq16 x (Mul16 (Const16 [c])
|
||||
@ -1330,16 +1330,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(umagic(16,c).m) && s == 16+umagic(16,c).s-1
|
||||
&& x.Op != OpConst16 && udivisibleOK(16,c)
|
||||
-> (Leq16U
|
||||
&& m == int32(umagic16(c).m) && s == 16+umagic16(c).s-1
|
||||
&& x.Op != OpConst16 && udivisibleOK16(c)
|
||||
=> (Leq16U
|
||||
(RotateLeft16 <typ.UInt16>
|
||||
(Mul16 <typ.UInt16>
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).m))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).m)])
|
||||
x)
|
||||
(Const16 <typ.UInt16> [int64(16-udivisible(16,c).k)])
|
||||
(Const16 <typ.UInt16> [int16(16-udivisible16(c).k)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(int16(udivisible(16,c).max))])
|
||||
(Const16 <typ.UInt16> [int16(udivisible16(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1351,16 +1351,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(int32(1<<31+umagic(32,c).m/2)) && s == umagic(32,c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int32(1<<31+umagic32(c).m/2) && s == umagic32(c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1372,16 +1372,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(int32(1<<31+(umagic(32,c).m+1)/2)) && s == umagic(32,c).s-2
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int32(1<<31+(umagic32(c).m+1)/2) && s == umagic32(c).s-2
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1395,16 +1395,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(int32(umagic(32,c).m)) && s == umagic(32,c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int32(umagic32(c).m) && s == umagic32(c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1417,16 +1417,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<31+umagic(32,c).m/2) && s == 32+umagic(32,c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int64(1<<31+umagic32(c).m/2) && s == 32+umagic32(c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1439,16 +1439,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<31+(umagic(32,c).m+1)/2) && s == 32+umagic(32,c).s-2
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int64(1<<31+(umagic32(c).m+1)/2) && s == 32+umagic32(c).s-2
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1463,16 +1463,16 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(umagic(32,c).m) && s == 32+umagic(32,c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int64(umagic32(c).m) && s == 32+umagic32(c).s-1
|
||||
&& x.Op != OpConst32 && udivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(32-udivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-udivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(udivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(udivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq64 x (Mul64 (Const64 [c])
|
||||
@ -1483,16 +1483,16 @@
|
||||
(Const64 [s]))
|
||||
)
|
||||
) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<63+umagic(64,c).m/2) && s == umagic(64,c).s-1
|
||||
&& x.Op != OpConst64 && udivisibleOK(64,c)
|
||||
-> (Leq64U
|
||||
&& m == int64(1<<63+umagic64(c).m/2) && s == umagic64(c).s-1
|
||||
&& x.Op != OpConst64 && udivisibleOK64(c)
|
||||
=> (Leq64U
|
||||
(RotateLeft64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).m)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [int64(64-udivisible(64,c).k)])
|
||||
(Const64 <typ.UInt64> [64-udivisible64(c).k])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).max)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).max)])
|
||||
)
|
||||
(Eq64 x (Mul64 (Const64 [c])
|
||||
(Rsh64Ux64
|
||||
@ -1502,16 +1502,16 @@
|
||||
(Const64 [s]))
|
||||
)
|
||||
) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(1<<63+(umagic(64,c).m+1)/2) && s == umagic(64,c).s-2
|
||||
&& x.Op != OpConst64 && udivisibleOK(64,c)
|
||||
-> (Leq64U
|
||||
&& m == int64(1<<63+(umagic64(c).m+1)/2) && s == umagic64(c).s-2
|
||||
&& x.Op != OpConst64 && udivisibleOK64(c)
|
||||
=> (Leq64U
|
||||
(RotateLeft64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).m)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [int64(64-udivisible(64,c).k)])
|
||||
(Const64 <typ.UInt64> [64-udivisible64(c).k])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).max)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).max)])
|
||||
)
|
||||
(Eq64 x (Mul64 (Const64 [c])
|
||||
(Rsh64Ux64
|
||||
@ -1523,16 +1523,16 @@
|
||||
(Const64 [s]))
|
||||
)
|
||||
) && v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(umagic(64,c).m) && s == umagic(64,c).s-1
|
||||
&& x.Op != OpConst64 && udivisibleOK(64,c)
|
||||
-> (Leq64U
|
||||
&& m == int64(umagic64(c).m) && s == umagic64(c).s-1
|
||||
&& x.Op != OpConst64 && udivisibleOK64(c)
|
||||
=> (Leq64U
|
||||
(RotateLeft64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).m)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [int64(64-udivisible(64,c).k)])
|
||||
(Const64 <typ.UInt64> [64-udivisible64(c).k])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(udivisible(64,c).max)])
|
||||
(Const64 <typ.UInt64> [int64(udivisible64(c).max)])
|
||||
)
|
||||
|
||||
// Signed divisibility checks convert to multiply, add and rotate.
|
||||
@ -1549,19 +1549,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(smagic(8,c).m) && s == 8+smagic(8,c).s
|
||||
&& x.Op != OpConst8 && sdivisibleOK(8,c)
|
||||
-> (Leq8U
|
||||
&& m == int32(smagic8(c).m) && s == 8+smagic8(c).s
|
||||
&& x.Op != OpConst8 && sdivisibleOK8(c)
|
||||
=> (Leq8U
|
||||
(RotateLeft8 <typ.UInt8>
|
||||
(Add8 <typ.UInt8>
|
||||
(Mul8 <typ.UInt8>
|
||||
(Const8 <typ.UInt8> [int64(int8(sdivisible(8,c).m))])
|
||||
(Const8 <typ.UInt8> [int8(sdivisible8(c).m)])
|
||||
x)
|
||||
(Const8 <typ.UInt8> [int64(int8(sdivisible(8,c).a))])
|
||||
(Const8 <typ.UInt8> [int8(sdivisible8(c).a)])
|
||||
)
|
||||
(Const8 <typ.UInt8> [int64(8-sdivisible(8,c).k)])
|
||||
(Const8 <typ.UInt8> [int8(8-sdivisible8(c).k)])
|
||||
)
|
||||
(Const8 <typ.UInt8> [int64(int8(sdivisible(8,c).max))])
|
||||
(Const8 <typ.UInt8> [int8(sdivisible8(c).max)])
|
||||
)
|
||||
|
||||
(Eq16 x (Mul16 (Const16 [c])
|
||||
@ -1577,19 +1577,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(smagic(16,c).m) && s == 16+smagic(16,c).s
|
||||
&& x.Op != OpConst16 && sdivisibleOK(16,c)
|
||||
-> (Leq16U
|
||||
&& m == int32(smagic16(c).m) && s == 16+smagic16(c).s
|
||||
&& x.Op != OpConst16 && sdivisibleOK16(c)
|
||||
=> (Leq16U
|
||||
(RotateLeft16 <typ.UInt16>
|
||||
(Add16 <typ.UInt16>
|
||||
(Mul16 <typ.UInt16>
|
||||
(Const16 <typ.UInt16> [int64(int16(sdivisible(16,c).m))])
|
||||
(Const16 <typ.UInt16> [int16(sdivisible16(c).m)])
|
||||
x)
|
||||
(Const16 <typ.UInt16> [int64(int16(sdivisible(16,c).a))])
|
||||
(Const16 <typ.UInt16> [int16(sdivisible16(c).a)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(16-sdivisible(16,c).k)])
|
||||
(Const16 <typ.UInt16> [int16(16-sdivisible16(c).k)])
|
||||
)
|
||||
(Const16 <typ.UInt16> [int64(int16(sdivisible(16,c).max))])
|
||||
(Const16 <typ.UInt16> [int16(sdivisible16(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1605,19 +1605,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(smagic(32,c).m) && s == 32+smagic(32,c).s
|
||||
&& x.Op != OpConst32 && sdivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int64(smagic32(c).m) && s == 32+smagic32(c).s
|
||||
&& x.Op != OpConst32 && sdivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Add32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).a))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(32-sdivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1633,19 +1633,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(int32(smagic(32,c).m/2)) && s == smagic(32,c).s-1
|
||||
&& x.Op != OpConst32 && sdivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int32(smagic32(c).m/2) && s == smagic32(c).s-1
|
||||
&& x.Op != OpConst32 && sdivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Add32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).a))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(32-sdivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq32 x (Mul32 (Const32 [c])
|
||||
@ -1663,19 +1663,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(int32(smagic(32,c).m)) && s == smagic(32,c).s
|
||||
&& x.Op != OpConst32 && sdivisibleOK(32,c)
|
||||
-> (Leq32U
|
||||
&& m == int32(smagic32(c).m) && s == smagic32(c).s
|
||||
&& x.Op != OpConst32 && sdivisibleOK32(c)
|
||||
=> (Leq32U
|
||||
(RotateLeft32 <typ.UInt32>
|
||||
(Add32 <typ.UInt32>
|
||||
(Mul32 <typ.UInt32>
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).m))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).m)])
|
||||
x)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).a))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).a)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(32-sdivisible(32,c).k)])
|
||||
(Const32 <typ.UInt32> [int32(32-sdivisible32(c).k)])
|
||||
)
|
||||
(Const32 <typ.UInt32> [int64(int32(sdivisible(32,c).max))])
|
||||
(Const32 <typ.UInt32> [int32(sdivisible32(c).max)])
|
||||
)
|
||||
|
||||
(Eq64 x (Mul64 (Const64 [c])
|
||||
@ -1691,19 +1691,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(smagic(64,c).m/2) && s == smagic(64,c).s-1
|
||||
&& x.Op != OpConst64 && sdivisibleOK(64,c)
|
||||
-> (Leq64U
|
||||
&& m == int64(smagic64(c).m/2) && s == smagic64(c).s-1
|
||||
&& x.Op != OpConst64 && sdivisibleOK64(c)
|
||||
=> (Leq64U
|
||||
(RotateLeft64 <typ.UInt64>
|
||||
(Add64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).m)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).a)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).a)])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(64-sdivisible(64,c).k)])
|
||||
(Const64 <typ.UInt64> [64-sdivisible64(c).k])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).max)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).max)])
|
||||
)
|
||||
|
||||
(Eq64 x (Mul64 (Const64 [c])
|
||||
@ -1721,19 +1721,19 @@
|
||||
)
|
||||
)
|
||||
&& v.Block.Func.pass.name != "opt" && mul.Uses == 1
|
||||
&& m == int64(smagic(64,c).m) && s == smagic(64,c).s
|
||||
&& x.Op != OpConst64 && sdivisibleOK(64,c)
|
||||
-> (Leq64U
|
||||
&& m == int64(smagic64(c).m) && s == smagic64(c).s
|
||||
&& x.Op != OpConst64 && sdivisibleOK64(c)
|
||||
=> (Leq64U
|
||||
(RotateLeft64 <typ.UInt64>
|
||||
(Add64 <typ.UInt64>
|
||||
(Mul64 <typ.UInt64>
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).m)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).m)])
|
||||
x)
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).a)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).a)])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(64-sdivisible(64,c).k)])
|
||||
(Const64 <typ.UInt64> [64-sdivisible64(c).k])
|
||||
)
|
||||
(Const64 <typ.UInt64> [int64(sdivisible(64,c).max)])
|
||||
(Const64 <typ.UInt64> [int64(sdivisible64(c).max)])
|
||||
)
|
||||
|
||||
// Divisibility check for signed integers for power of two constant are simple mask.
|
||||
|
@ -96,7 +96,7 @@ func umagicOK(n uint, c int64) bool {
|
||||
return d&(d-1) != 0
|
||||
}
|
||||
|
||||
// umagicOKn reports whether we should strength reduce an n-bit divide by c.
|
||||
// umagicOKn reports whether we should strength reduce an unsigned n-bit divide by c.
|
||||
// We can strength reduce when c != 0 and c is not a power of two.
|
||||
func umagicOK8(c int8) bool { return c&(c-1) != 0 }
|
||||
func umagicOK16(c int16) bool { return c&(c-1) != 0 }
|
||||
@ -130,6 +130,11 @@ func umagic(n uint, c int64) umagicData {
|
||||
return umagicData{s: int64(s), m: m}
|
||||
}
|
||||
|
||||
func umagic8(c int8) umagicData { return umagic(8, int64(c)) }
|
||||
func umagic16(c int16) umagicData { return umagic(16, int64(c)) }
|
||||
func umagic32(c int32) umagicData { return umagic(32, int64(c)) }
|
||||
func umagic64(c int64) umagicData { return umagic(64, c) }
|
||||
|
||||
// For signed division, we use a similar strategy.
|
||||
// First, we enforce a positive c.
|
||||
// x / c = -(x / (-c))
|
||||
@ -164,6 +169,12 @@ func smagicOK(n uint, c int64) bool {
|
||||
return c&(c-1) != 0
|
||||
}
|
||||
|
||||
// smagicOKn reports whether we should strength reduce an signed n-bit divide by c.
|
||||
func smagicOK8(c int8) bool { return smagicOK(8, int64(c)) }
|
||||
func smagicOK16(c int16) bool { return smagicOK(16, int64(c)) }
|
||||
func smagicOK32(c int32) bool { return smagicOK(32, int64(c)) }
|
||||
func smagicOK64(c int64) bool { return smagicOK(64, c) }
|
||||
|
||||
type smagicData struct {
|
||||
s int64 // ⎡log2(c)⎤-1
|
||||
m uint64 // ⎡2^(n+s)/c⎤
|
||||
@ -191,6 +202,11 @@ func smagic(n uint, c int64) smagicData {
|
||||
return smagicData{s: int64(s), m: m}
|
||||
}
|
||||
|
||||
func smagic8(c int8) smagicData { return smagic(8, int64(c)) }
|
||||
func smagic16(c int16) smagicData { return smagic(16, int64(c)) }
|
||||
func smagic32(c int32) smagicData { return smagic(32, int64(c)) }
|
||||
func smagic64(c int64) smagicData { return smagic(64, c) }
|
||||
|
||||
// Divisibility x%c == 0 can be checked more efficiently than directly computing
|
||||
// the modulus x%c and comparing against 0.
|
||||
//
|
||||
@ -249,7 +265,7 @@ func smagic(n uint, c int64) smagicData {
|
||||
//
|
||||
// Where d0*2^k was replaced by c on the right hand side.
|
||||
|
||||
// uivisibleOK reports whether we should strength reduce a n-bit dividisibilty check by c.
|
||||
// udivisibleOK reports whether we should strength reduce an unsigned n-bit divisibilty check by c.
|
||||
func udivisibleOK(n uint, c int64) bool {
|
||||
// Convert from ConstX auxint values to the real uint64 constant they represent.
|
||||
d := uint64(c) << (64 - n) >> (64 - n)
|
||||
@ -259,6 +275,11 @@ func udivisibleOK(n uint, c int64) bool {
|
||||
return d&(d-1) != 0
|
||||
}
|
||||
|
||||
func udivisibleOK8(c int8) bool { return udivisibleOK(8, int64(c)) }
|
||||
func udivisibleOK16(c int16) bool { return udivisibleOK(16, int64(c)) }
|
||||
func udivisibleOK32(c int32) bool { return udivisibleOK(32, int64(c)) }
|
||||
func udivisibleOK64(c int64) bool { return udivisibleOK(64, c) }
|
||||
|
||||
type udivisibleData struct {
|
||||
k int64 // trailingZeros(c)
|
||||
m uint64 // m * (c>>k) mod 2^n == 1 multiplicative inverse of odd portion modulo 2^n
|
||||
@ -293,6 +314,11 @@ func udivisible(n uint, c int64) udivisibleData {
|
||||
}
|
||||
}
|
||||
|
||||
func udivisible8(c int8) udivisibleData { return udivisible(8, int64(c)) }
|
||||
func udivisible16(c int16) udivisibleData { return udivisible(16, int64(c)) }
|
||||
func udivisible32(c int32) udivisibleData { return udivisible(32, int64(c)) }
|
||||
func udivisible64(c int64) udivisibleData { return udivisible(64, c) }
|
||||
|
||||
// For signed integers, a similar method follows.
|
||||
//
|
||||
// Given c > 1 and odd, compute m such that (c * m) mod 2^n == 1
|
||||
@ -341,7 +367,7 @@ func udivisible(n uint, c int64) udivisibleData {
|
||||
// Note that the calculation is performed using unsigned integers.
|
||||
// Since a' can have n-1 bits, 2a' may have n bits and there is no risk of overflow.
|
||||
|
||||
// sdivisibleOK reports whether we should strength reduce a n-bit dividisibilty check by c.
|
||||
// sdivisibleOK reports whether we should strength reduce a signed n-bit divisibilty check by c.
|
||||
func sdivisibleOK(n uint, c int64) bool {
|
||||
if c < 0 {
|
||||
// Doesn't work for negative c.
|
||||
@ -352,6 +378,11 @@ func sdivisibleOK(n uint, c int64) bool {
|
||||
return c&(c-1) != 0
|
||||
}
|
||||
|
||||
func sdivisibleOK8(c int8) bool { return sdivisibleOK(8, int64(c)) }
|
||||
func sdivisibleOK16(c int16) bool { return sdivisibleOK(16, int64(c)) }
|
||||
func sdivisibleOK32(c int32) bool { return sdivisibleOK(32, int64(c)) }
|
||||
func sdivisibleOK64(c int64) bool { return sdivisibleOK(64, c) }
|
||||
|
||||
type sdivisibleData struct {
|
||||
k int64 // trailingZeros(c)
|
||||
m uint64 // m * (c>>k) mod 2^n == 1 multiplicative inverse of odd portion modulo 2^n
|
||||
@ -386,3 +417,8 @@ func sdivisible(n uint, c int64) sdivisibleData {
|
||||
max: max,
|
||||
}
|
||||
}
|
||||
|
||||
func sdivisible8(c int8) sdivisibleData { return sdivisible(8, int64(c)) }
|
||||
func sdivisible16(c int16) sdivisibleData { return sdivisible(16, int64(c)) }
|
||||
func sdivisible32(c int32) sdivisibleData { return sdivisible(32, int64(c)) }
|
||||
func sdivisible64(c int64) sdivisibleData { return sdivisible(64, c) }
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user