aboutsummaryrefslogtreecommitdiff
path: root/test/codegen
diff options
context:
space:
mode:
authorJorropo <jorropo.pgm@gmail.com>2026-03-29 05:19:58 +0200
committerGopher Robot <gobot@golang.org>2026-04-03 13:21:37 -0700
commit0a36b58888cc41b276362673f70be87efd7e55ad (patch)
tree4e23a040eca0b800599113ffdd20d9c5f641c637 /test/codegen
parent142f2376017887a3ed02dc1bc91542d39cfe2ecd (diff)
downloadgo-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.go71
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 {