// 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 }