diff options
| author | Jorropo <jorropo.pgm@gmail.com> | 2026-03-29 05:19:58 +0200 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-04-03 13:21:37 -0700 |
| commit | 0a36b58888cc41b276362673f70be87efd7e55ad (patch) | |
| tree | 4e23a040eca0b800599113ffdd20d9c5f641c637 /src/cmd/compile/internal/ssa/_gen/generic.rules | |
| parent | 142f2376017887a3ed02dc1bc91542d39cfe2ecd (diff) | |
| download | go-0a36b58888cc41b276362673f70be87efd7e55ad.tar.xz | |
cmd/compile: extend all the cmov into math generic rules with their contrary
If the bool comes from a local operation this is foldable into the comparison.
if a == b {
} else {
x++
}
becomes:
x += !(a == b)
becomes:
x += a != b
If the bool is passed in or loaded rather than being locally computed
this adds an extra XOR ^1 to invert it.
But at worst it should make the math equal to the compute + CMP + CMOV
which is a tie on modern CPUs which can execute CMOV on all int ALUs
and a win on the cheaper or older ones which can't.
Change-Id: Idd2566c7a3826ec432ebfbba7b3898aa0db4b812
Reviewed-on: https://go-review.googlesource.com/c/go/+/760922
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/_gen/generic.rules')
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/generic.rules | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 7dcf818976..e75f371790 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -2300,25 +2300,42 @@ // if b { x++ } => x += b // but not on arm64 because it has CSINC (CondSelect (Add8 <t> x (Const8 [1])) x bool) && config.arch != "arm64" => (Add8 x (CvtBoolToUint8 <t> bool)) (CondSelect (Add(64|32|16) <t> x (Const(64|32|16) [1])) x bool) && config.arch != "arm64" => (Add(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> bool))) +// if !b { x++ } => x += !b // but not on arm64 because it has CSINC +(CondSelect x (Add8 <t> x (Const8 [1])) bool) && config.arch != "arm64" => (Add8 x (CvtBoolToUint8 <t> (Not <bool.Type> bool))) +(CondSelect x (Add(64|32|16) <t> x (Const(64|32|16) [1])) bool) && config.arch != "arm64" => (Add(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool)))) // if b { x-- } => x -= b (CondSelect (Add8 <t> x (Const8 [-1])) x bool) => (Sub8 x (CvtBoolToUint8 <t> bool)) (CondSelect (Add(64|32|16) <t> x (Const(64|32|16) [-1])) x bool) => (Sub(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> bool))) +// if !b { x-- } => x -= !b +(CondSelect x (Add8 <t> x (Const8 [-1])) bool) => (Sub8 x (CvtBoolToUint8 <t> (Not <bool.Type> bool))) +(CondSelect x (Add(64|32|16) <t> x (Const(64|32|16) [-1])) bool) => (Sub(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool)))) // if b { x <<= 1 } => x <<= b (CondSelect (Lsh(64|32|16|8)x64 x (Const64 [1])) x bool) => (Lsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) +// if !b { x <<= 1 } => x <<= !b +(CondSelect x (Lsh(64|32|16|8)x64 x (Const64 [1])) bool) => (Lsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool))) // if b { x >>= 1 } => x >>= b (CondSelect (Rsh(64|32|16|8)x64 x (Const64 [1])) x bool) => (Rsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) (CondSelect (Rsh(64|32|16|8)Ux64 x (Const64 [1])) x bool) => (Rsh(64|32|16|8)Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) +// if !b { x >>= 1 } => x >>= !b +(CondSelect x (Rsh(64|32|16|8)x64 x (Const64 [1])) bool) => (Rsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool))) +(CondSelect x (Rsh(64|32|16|8)Ux64 x (Const64 [1])) bool) => (Rsh(64|32|16|8)Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool))) // if b { x |= 1 } => x |= b (CondSelect (Or8 <t> x (Const8 [1])) x bool) => (Or8 x (CvtBoolToUint8 <t> bool)) (CondSelect (Or(64|32|16) <t> x (Const(64|32|16) [1])) x bool) => (Or(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> bool))) +// if !b { x |= 1 } => x |= !b +(CondSelect x (Or8 <t> x (Const8 [1])) bool) => (Or8 x (CvtBoolToUint8 <t> (Not <bool.Type> bool))) +(CondSelect x (Or(64|32|16) <t> x (Const(64|32|16) [1])) bool) => (Or(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool)))) // if b { x ^= 1 } => x ^= b (CondSelect (Xor8 <t> x (Const8 [1])) x bool) => (Xor8 x (CvtBoolToUint8 <t> bool)) (CondSelect (Xor(64|32|16) <t> x (Const(64|32|16) [1])) x bool) => (Xor(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> bool))) +// if !b { x ^= 1 } => x ^= !b +(CondSelect x (Xor8 <t> x (Const8 [1])) bool) => (Xor8 x (CvtBoolToUint8 <t> (Not <bool.Type> bool))) +(CondSelect x (Xor(64|32|16) <t> x (Const(64|32|16) [1])) bool) => (Xor(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> (Not <bool.Type> bool)))) // bool(int(x)) => x (Neq8 (CvtBoolToUint8 x) (Const8 [0])) => x |
