summaryrefslogtreecommitdiffstats
path: root/test/codegen/condmove.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/codegen/condmove.go')
-rw-r--r--test/codegen/condmove.go210
1 files changed, 210 insertions, 0 deletions
diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go
new file mode 100644
index 0000000..f86da34
--- /dev/null
+++ b/test/codegen/condmove.go
@@ -0,0 +1,210 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+func cmovint(c int) int {
+ x := c + 4
+ if x < 0 {
+ x = 182
+ }
+ // amd64:"CMOVQLT"
+ // arm64:"CSEL\tLT"
+ // wasm:"Select"
+ return x
+}
+
+func cmovchan(x, y chan int) chan int {
+ if x != y {
+ x = y
+ }
+ // amd64:"CMOVQNE"
+ // arm64:"CSEL\tNE"
+ // wasm:"Select"
+ return x
+}
+
+func cmovuintptr(x, y uintptr) uintptr {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVQCS"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
+ return x
+}
+
+func cmov32bit(x, y uint32) uint32 {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVLCS"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
+ return x
+}
+
+func cmov16bit(x, y uint16) uint16 {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVWCS"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
+ return x
+}
+
+// Floating point comparison. For EQ/NE, we must
+// generate special code to handle NaNs.
+func cmovfloateq(x, y float64) int {
+ a := 128
+ if x == y {
+ a = 256
+ }
+ // amd64:"CMOVQNE","CMOVQPC"
+ // arm64:"CSEL\tEQ"
+ // wasm:"Select"
+ return a
+}
+
+func cmovfloatne(x, y float64) int {
+ a := 128
+ if x != y {
+ a = 256
+ }
+ // amd64:"CMOVQNE","CMOVQPS"
+ // arm64:"CSEL\tNE"
+ // wasm:"Select"
+ return a
+}
+
+//go:noinline
+func frexp(f float64) (frac float64, exp int) {
+ return 1.0, 4
+}
+
+//go:noinline
+func ldexp(frac float64, exp int) float64 {
+ return 1.0
+}
+
+// Generate a CMOV with a floating comparison and integer move.
+func cmovfloatint2(x, y float64) float64 {
+ yfr, yexp := 4.0, 5
+
+ r := x
+ for r >= y {
+ rfr, rexp := frexp(r)
+ if rfr < yfr {
+ rexp = rexp - 1
+ }
+ // amd64:"CMOVQHI"
+ // arm64:"CSEL\tMI"
+ // wasm:"Select"
+ r = r - ldexp(y, rexp-yexp)
+ }
+ return r
+}
+
+func cmovloaded(x [4]int, y int) int {
+ if x[2] != 0 {
+ y = x[2]
+ } else {
+ y = y >> 2
+ }
+ // amd64:"CMOVQNE"
+ // arm64:"CSEL\tNE"
+ // wasm:"Select"
+ return y
+}
+
+func cmovuintptr2(x, y uintptr) uintptr {
+ a := x * 2
+ if a == 0 {
+ a = 256
+ }
+ // amd64:"CMOVQEQ"
+ // arm64:"CSEL\tEQ"
+ // wasm:"Select"
+ return a
+}
+
+// Floating point CMOVs are not supported by amd64/arm64
+func cmovfloatmove(x, y int) float64 {
+ a := 1.0
+ if x <= y {
+ a = 2.0
+ }
+ // amd64:-"CMOV"
+ // arm64:-"CSEL"
+ // wasm:-"Select"
+ return a
+}
+
+// On amd64, the following patterns trigger comparison inversion.
+// Test that we correctly invert the CMOV condition
+var gsink int64
+var gusink uint64
+
+func cmovinvert1(x, y int64) int64 {
+ if x < gsink {
+ y = -y
+ }
+ // amd64:"CMOVQGT"
+ return y
+}
+func cmovinvert2(x, y int64) int64 {
+ if x <= gsink {
+ y = -y
+ }
+ // amd64:"CMOVQGE"
+ return y
+}
+func cmovinvert3(x, y int64) int64 {
+ if x == gsink {
+ y = -y
+ }
+ // amd64:"CMOVQEQ"
+ return y
+}
+func cmovinvert4(x, y int64) int64 {
+ if x != gsink {
+ y = -y
+ }
+ // amd64:"CMOVQNE"
+ return y
+}
+func cmovinvert5(x, y uint64) uint64 {
+ if x > gusink {
+ y = -y
+ }
+ // amd64:"CMOVQCS"
+ return y
+}
+func cmovinvert6(x, y uint64) uint64 {
+ if x >= gusink {
+ y = -y
+ }
+ // amd64:"CMOVQLS"
+ return y
+}
+
+func cmovload(a []int, i int, b bool) int {
+ if b {
+ i++
+ }
+ // See issue 26306
+ // amd64:-"CMOVQNE"
+ return a[i]
+}
+
+func cmovstore(a []int, i int, b bool) {
+ if b {
+ i++
+ }
+ // amd64:"CMOVQNE"
+ a[i] = 7
+}