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 /test/codegen | |
| 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 'test/codegen')
| -rw-r--r-- | test/codegen/condmove.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go index 6d1bba4c70..ec1b971ed7 100644 --- a/test/codegen/condmove.go +++ b/test/codegen/condmove.go @@ -464,6 +464,16 @@ func cmovmathadd(a uint, b bool) uint { // wasm:"I64Add" -"Select" return a } +func cmovmathaddelse(a uint, b bool) uint { + if !b { + a++ + } + // amd64:"ADDQ" -"CMOV" + // arm64:"CSINC" -"CSEL" + // ppc64x:"ADD" -"ISEL" + // wasm:"I64Add" -"Select" + return a +} func cmovmathsub(a uint, b bool) uint { if b { @@ -475,6 +485,16 @@ func cmovmathsub(a uint, b bool) uint { // wasm:"I64Sub" -"Select" return a } +func cmovmathsubelse(a uint, b bool) uint { + if !b { + a-- + } + // amd64:"SUBQ" -"CMOV" + // arm64:"SUB" -"CSEL" + // ppc64x:"SUB" -"ISEL" + // wasm:"I64Sub" -"Select" + return a +} func cmovmathdouble(a uint, b bool) uint { if b { @@ -486,6 +506,16 @@ func cmovmathdouble(a uint, b bool) uint { // wasm:"I64Shl" -"Select" return a } +func cmovmathdoubleelse(a uint, b bool) uint { + if !b { + a *= 2 + } + // amd64:"SHL" -"CMOV" + // amd64/v3:"SHL" -"CMOV" -"MOV" + // arm64:"LSL" -"CSEL" + // wasm:"I64Shl" -"Select" + return a +} func cmovmathhalvei(a int, b bool) int { if b { @@ -498,6 +528,17 @@ func cmovmathhalvei(a int, b bool) int { // wasm:-"Select" return a } +func cmovmathhalveielse(a int, b bool) int { + if !b { + // For some reason the compiler attributes the shift to inside this block rather than where the Phi node is. + // arm64:"ASR" -"CSEL" + // wasm:"I64ShrS" -"Select" + a /= 2 + } + // arm64:-"CSEL" + // wasm:-"Select" + return a +} func cmovmathhalveu(a uint, b bool) uint { if b { @@ -509,6 +550,16 @@ func cmovmathhalveu(a uint, b bool) uint { // wasm:"I64ShrU" -"Select" return a } +func cmovmathhalveuelse(a uint, b bool) uint { + if !b { + a /= 2 + } + // amd64:"SHR" -"CMOV" + // amd64/v3:"SHR" -"CMOV" -"MOV" + // arm64:"LSR" -"CSEL" + // wasm:"I64ShrU" -"Select" + return a +} func cmovmathor(a uint, b bool) uint { if b { @@ -520,6 +571,16 @@ func cmovmathor(a uint, b bool) uint { // wasm:"I64Or" -"Select" return a } +func cmovmathorelse(a uint, b bool) uint { + if !b { + a |= 1 + } + // amd64:"ORQ" -"CMOV" + // arm64:"ORR" -"CSEL" + // ppc64x:"OR" -"ISEL" + // wasm:"I64Or" -"Select" + return a +} func cmovmathxor(a uint, b bool) uint { if b { @@ -531,6 +592,16 @@ func cmovmathxor(a uint, b bool) uint { // wasm:"I64Xor" -"Select" return a } +func cmovmathxorelse(a uint, b bool) uint { + if !b { + a ^= 1 + } + // amd64:"XORQ" -"CMOV" + // arm64:"EOR" -"CSEL" + // ppc64x:"XOR" -"ISEL" + // wasm:"I64Xor" -"Select" + return a +} func branchlessBoolToUint8(b bool) (r uint8) { if b { |
