]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add rewrite rules for conditional instructions on arm64
authorfanzha02 <fannie.zhang@arm.com>
Mon, 18 Jan 2021 06:32:49 +0000 (14:32 +0800)
committerfannie zhang <Fannie.Zhang@arm.com>
Thu, 18 Mar 2021 01:46:58 +0000 (01:46 +0000)
This CL adds rewrite rules for CSETM, CSINC, CSINV, and CSNEG. By adding
these rules, we can save one instruction.

For example,

  func test(cond bool, a int) int {
    if cond {
      a++
    }
    return a
  }

Before:

  MOVD "".a+8(RSP), R0
  ADD $1, R0, R1
  MOVBU "".cond(RSP), R2
  CMPW $0, R2
  CSEL NE, R1, R0, R0

After:

  MOVBU "".cond(RSP), R0
  CMPW $0, R0
  MOVD "".a+8(RSP), R0
  CSINC EQ, R0, R0, R0

This patch is a copy of CL 285694. Co-authored-by: JunchenLi
<junchen.li@arm.com>

Change-Id: Ic1a79e8b8ece409b533becfcb7950f11e7b76f24
Reviewed-on: https://go-review.googlesource.com/c/go/+/302231
Trust: fannie zhang <Fannie.Zhang@arm.com>
Run-TryBot: fannie zhang <Fannie.Zhang@arm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/arm64/ssa.go
src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/gen/ARM64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteARM64.go
test/codegen/condmove.go

index 056a6eb62da8fc8151b03bd05a9f418dbd088431..3250b49c92f2b6fd75eecd167eaa3212d61f5a69 100644 (file)
@@ -956,6 +956,20 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                p.SetFrom3Reg(r1)
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
+       case ssa.OpARM64CSINC, ssa.OpARM64CSINV, ssa.OpARM64CSNEG:
+               p := s.Prog(v.Op.Asm())
+               p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
+               p.From.Reg = condBits[ssa.Op(v.AuxInt)]
+               p.Reg = v.Args[0].Reg()
+               p.SetFrom3Reg(v.Args[1].Reg())
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = v.Reg()
+       case ssa.OpARM64CSETM:
+               p := s.Prog(arm64.ACSETM)
+               p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
+               p.From.Reg = condBits[ssa.Op(v.AuxInt)]
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = v.Reg()
        case ssa.OpARM64DUFFZERO:
                // runtime.duffzero expects start address in R20
                p := s.Prog(obj.ADUFFZERO)
index ea912f9f97567eeeabc84e0ba7e4e920fcf88f18..6f30c11bd1b7a2d1d53545a880f148d7193c60e5 100644 (file)
 (XOR x (MVN y)) => (EON x y)
 (OR  x (MVN y)) => (ORN x y)
 (MVN (XOR x y)) => (EON x y)
+
+(CSEL [cc] (MOVDconst [-1]) (MOVDconst [0]) flag) => (CSETM [cc] flag)
+(CSEL [cc] (MOVDconst [0]) (MOVDconst [-1]) flag) => (CSETM [arm64Negate(cc)] flag)
 (CSEL [cc] x (MOVDconst [0]) flag) => (CSEL0 [cc] x flag)
 (CSEL [cc] (MOVDconst [0]) y flag) => (CSEL0 [arm64Negate(cc)] y flag)
+(CSEL [cc] x (ADDconst [1] a) flag) => (CSINC [cc] x a flag)
+(CSEL [cc] (ADDconst [1] a) x flag) => (CSINC [arm64Negate(cc)] x a flag)
+(CSEL [cc] x (MVN a) flag) => (CSINV [cc] x a flag)
+(CSEL [cc] (MVN a) x flag) => (CSINV [arm64Negate(cc)] x a flag)
+(CSEL [cc] x (NEG a) flag) => (CSNEG [cc] x a flag)
+(CSEL [cc] (NEG a) x flag) => (CSNEG [arm64Negate(cc)] x a flag)
+
 (SUB x (SUB y z)) => (SUB (ADD <v.Type> x z) y)
 (SUB (SUB x y) z) => (SUB x (ADD <y.Type> y z))
 
 (LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
 (GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
 
-// absorb InvertFlags into CSEL(0)
+// absorb InvertFlags into conditional instructions
 (CSEL [cc] x y (InvertFlags cmp)) => (CSEL [arm64Invert(cc)] x y cmp)
 (CSEL0 [cc] x (InvertFlags cmp)) => (CSEL0 [arm64Invert(cc)] x cmp)
+(CSETM [cc] (InvertFlags cmp)) => (CSETM [arm64Invert(cc)] cmp)
+(CSINC [cc] x y (InvertFlags cmp)) => (CSINC [arm64Invert(cc)] x y cmp)
+(CSINV [cc] x y (InvertFlags cmp)) => (CSINV [arm64Invert(cc)] x y cmp)
+(CSNEG [cc] x y (InvertFlags cmp)) => (CSNEG [arm64Invert(cc)] x y cmp)
 
 // absorb flag constants into boolean values
 (Equal (FlagConstant [fc])) => (MOVDconst [b2i(fc.eq())])
index 0a4fd14b2b762498b1c46ba81482b68fc09d28c1..59a5ffaca4381bbda80cde365d9bcb0d25d10402 100644 (file)
@@ -472,8 +472,12 @@ func init() {
 
                // conditional instructions; auxint is
                // one of the arm64 comparison pseudo-ops (LessThan, LessThanU, etc.)
-               {name: "CSEL", argLength: 3, reg: gp2flags1, asm: "CSEL", aux: "CCop"},  // auxint(flags) ? arg0 : arg1
-               {name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"}, // auxint(flags) ? arg0 : 0
+               {name: "CSEL", argLength: 3, reg: gp2flags1, asm: "CSEL", aux: "CCop"},   // auxint(flags) ? arg0 : arg1
+               {name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"},  // auxint(flags) ? arg0 : 0
+               {name: "CSINC", argLength: 3, reg: gp2flags1, asm: "CSINC", aux: "CCop"}, // auxint(flags) ? arg0 : arg1 + 1
+               {name: "CSINV", argLength: 3, reg: gp2flags1, asm: "CSINV", aux: "CCop"}, // auxint(flags) ? arg0 : ^arg1
+               {name: "CSNEG", argLength: 3, reg: gp2flags1, asm: "CSNEG", aux: "CCop"}, // auxint(flags) ? arg0 : -arg1
+               {name: "CSETM", argLength: 1, reg: readflags, asm: "CSETM", aux: "CCop"}, // auxint(flags) ? -1 : 0
 
                // function calls
                {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                               // call static function aux.(*obj.LSym).  arg0=mem, auxint=argsize, returns mem
index 322e1c228322edc212468e6e8b8ddaeb002f4894..436a79a173370e2e2319abfa89d95158c6a35c3b 100644 (file)
@@ -1556,6 +1556,10 @@ const (
        OpARM64FRINTZD
        OpARM64CSEL
        OpARM64CSEL0
+       OpARM64CSINC
+       OpARM64CSINV
+       OpARM64CSNEG
+       OpARM64CSETM
        OpARM64CALLstatic
        OpARM64CALLclosure
        OpARM64CALLinter
@@ -20774,6 +20778,62 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:    "CSINC",
+               auxType: auxCCop,
+               argLen:  3,
+               asm:     arm64.ACSINC,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                               {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+                       outputs: []outputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+               },
+       },
+       {
+               name:    "CSINV",
+               auxType: auxCCop,
+               argLen:  3,
+               asm:     arm64.ACSINV,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                               {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+                       outputs: []outputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+               },
+       },
+       {
+               name:    "CSNEG",
+               auxType: auxCCop,
+               argLen:  3,
+               asm:     arm64.ACSNEG,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                               {1, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+                       outputs: []outputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+               },
+       },
+       {
+               name:    "CSETM",
+               auxType: auxCCop,
+               argLen:  1,
+               asm:     arm64.ACSETM,
+               reg: regInfo{
+                       outputs: []outputInfo{
+                               {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+                       },
+               },
+       },
        {
                name:         "CALLstatic",
                auxType:      auxCallOff,
index 55bb48660041411ebbdc5ccbe5d384e88b1de2c7..da80ad6fca86da2465eff5286f8069f6a550dd29 100644 (file)
@@ -69,6 +69,14 @@ func rewriteValueARM64(v *Value) bool {
                return rewriteValueARM64_OpARM64CSEL(v)
        case OpARM64CSEL0:
                return rewriteValueARM64_OpARM64CSEL0(v)
+       case OpARM64CSETM:
+               return rewriteValueARM64_OpARM64CSETM(v)
+       case OpARM64CSINC:
+               return rewriteValueARM64_OpARM64CSINC(v)
+       case OpARM64CSINV:
+               return rewriteValueARM64_OpARM64CSINV(v)
+       case OpARM64CSNEG:
+               return rewriteValueARM64_OpARM64CSNEG(v)
        case OpARM64DIV:
                return rewriteValueARM64_OpARM64DIV(v)
        case OpARM64DIVW:
@@ -3215,6 +3223,32 @@ func rewriteValueARM64_OpARM64CSEL(v *Value) bool {
        v_2 := v.Args[2]
        v_1 := v.Args[1]
        v_0 := v.Args[0]
+       // match: (CSEL [cc] (MOVDconst [-1]) (MOVDconst [0]) flag)
+       // result: (CSETM [cc] flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != -1 || v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != 0 {
+                       break
+               }
+               flag := v_2
+               v.reset(OpARM64CSETM)
+               v.AuxInt = opToAuxInt(cc)
+               v.AddArg(flag)
+               return true
+       }
+       // match: (CSEL [cc] (MOVDconst [0]) (MOVDconst [-1]) flag)
+       // result: (CSETM [arm64Negate(cc)] flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64MOVDconst || auxIntToInt64(v_0.AuxInt) != 0 || v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 {
+                       break
+               }
+               flag := v_2
+               v.reset(OpARM64CSETM)
+               v.AuxInt = opToAuxInt(arm64Negate(cc))
+               v.AddArg(flag)
+               return true
+       }
        // match: (CSEL [cc] x (MOVDconst [0]) flag)
        // result: (CSEL0 [cc] x flag)
        for {
@@ -3243,6 +3277,96 @@ func rewriteValueARM64_OpARM64CSEL(v *Value) bool {
                v.AddArg2(y, flag)
                return true
        }
+       // match: (CSEL [cc] x (ADDconst [1] a) flag)
+       // result: (CSINC [cc] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               if v_1.Op != OpARM64ADDconst || auxIntToInt64(v_1.AuxInt) != 1 {
+                       break
+               }
+               a := v_1.Args[0]
+               flag := v_2
+               v.reset(OpARM64CSINC)
+               v.AuxInt = opToAuxInt(cc)
+               v.AddArg3(x, a, flag)
+               return true
+       }
+       // match: (CSEL [cc] (ADDconst [1] a) x flag)
+       // result: (CSINC [arm64Negate(cc)] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64ADDconst || auxIntToInt64(v_0.AuxInt) != 1 {
+                       break
+               }
+               a := v_0.Args[0]
+               x := v_1
+               flag := v_2
+               v.reset(OpARM64CSINC)
+               v.AuxInt = opToAuxInt(arm64Negate(cc))
+               v.AddArg3(x, a, flag)
+               return true
+       }
+       // match: (CSEL [cc] x (MVN a) flag)
+       // result: (CSINV [cc] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               if v_1.Op != OpARM64MVN {
+                       break
+               }
+               a := v_1.Args[0]
+               flag := v_2
+               v.reset(OpARM64CSINV)
+               v.AuxInt = opToAuxInt(cc)
+               v.AddArg3(x, a, flag)
+               return true
+       }
+       // match: (CSEL [cc] (MVN a) x flag)
+       // result: (CSINV [arm64Negate(cc)] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64MVN {
+                       break
+               }
+               a := v_0.Args[0]
+               x := v_1
+               flag := v_2
+               v.reset(OpARM64CSINV)
+               v.AuxInt = opToAuxInt(arm64Negate(cc))
+               v.AddArg3(x, a, flag)
+               return true
+       }
+       // match: (CSEL [cc] x (NEG a) flag)
+       // result: (CSNEG [cc] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               if v_1.Op != OpARM64NEG {
+                       break
+               }
+               a := v_1.Args[0]
+               flag := v_2
+               v.reset(OpARM64CSNEG)
+               v.AuxInt = opToAuxInt(cc)
+               v.AddArg3(x, a, flag)
+               return true
+       }
+       // match: (CSEL [cc] (NEG a) x flag)
+       // result: (CSNEG [arm64Negate(cc)] x a flag)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64NEG {
+                       break
+               }
+               a := v_0.Args[0]
+               x := v_1
+               flag := v_2
+               v.reset(OpARM64CSNEG)
+               v.AuxInt = opToAuxInt(arm64Negate(cc))
+               v.AddArg3(x, a, flag)
+               return true
+       }
        // match: (CSEL [cc] x y (InvertFlags cmp))
        // result: (CSEL [arm64Invert(cc)] x y cmp)
        for {
@@ -3405,6 +3529,86 @@ func rewriteValueARM64_OpARM64CSEL0(v *Value) bool {
        }
        return false
 }
+func rewriteValueARM64_OpARM64CSETM(v *Value) bool {
+       v_0 := v.Args[0]
+       // match: (CSETM [cc] (InvertFlags cmp))
+       // result: (CSETM [arm64Invert(cc)] cmp)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               if v_0.Op != OpARM64InvertFlags {
+                       break
+               }
+               cmp := v_0.Args[0]
+               v.reset(OpARM64CSETM)
+               v.AuxInt = opToAuxInt(arm64Invert(cc))
+               v.AddArg(cmp)
+               return true
+       }
+       return false
+}
+func rewriteValueARM64_OpARM64CSINC(v *Value) bool {
+       v_2 := v.Args[2]
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (CSINC [cc] x y (InvertFlags cmp))
+       // result: (CSINC [arm64Invert(cc)] x y cmp)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               y := v_1
+               if v_2.Op != OpARM64InvertFlags {
+                       break
+               }
+               cmp := v_2.Args[0]
+               v.reset(OpARM64CSINC)
+               v.AuxInt = opToAuxInt(arm64Invert(cc))
+               v.AddArg3(x, y, cmp)
+               return true
+       }
+       return false
+}
+func rewriteValueARM64_OpARM64CSINV(v *Value) bool {
+       v_2 := v.Args[2]
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (CSINV [cc] x y (InvertFlags cmp))
+       // result: (CSINV [arm64Invert(cc)] x y cmp)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               y := v_1
+               if v_2.Op != OpARM64InvertFlags {
+                       break
+               }
+               cmp := v_2.Args[0]
+               v.reset(OpARM64CSINV)
+               v.AuxInt = opToAuxInt(arm64Invert(cc))
+               v.AddArg3(x, y, cmp)
+               return true
+       }
+       return false
+}
+func rewriteValueARM64_OpARM64CSNEG(v *Value) bool {
+       v_2 := v.Args[2]
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (CSNEG [cc] x y (InvertFlags cmp))
+       // result: (CSNEG [arm64Invert(cc)] x y cmp)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               y := v_1
+               if v_2.Op != OpARM64InvertFlags {
+                       break
+               }
+               cmp := v_2.Args[0]
+               v.reset(OpARM64CSNEG)
+               v.AuxInt = opToAuxInt(arm64Invert(cc))
+               v.AddArg3(x, y, cmp)
+               return true
+       }
+       return false
+}
 func rewriteValueARM64_OpARM64DIV(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
index 7579dd1890ed2fb84c5cdccd35b1be828d35570e..707f223fa3ed3916681abf6b221c0c8460c01bbe 100644 (file)
@@ -32,7 +32,7 @@ func cmovuintptr(x, y uintptr) uintptr {
                x = -y
        }
        // amd64:"CMOVQ(HI|CS)"
-       // arm64:"CSEL\t(LO|HI)"
+       // arm64:"CSNEG\tLS"
        // wasm:"Select"
        return x
 }
@@ -42,7 +42,7 @@ func cmov32bit(x, y uint32) uint32 {
                x = -y
        }
        // amd64:"CMOVL(HI|CS)"
-       // arm64:"CSEL\t(LO|HI)"
+       // arm64:"CSNEG\t(LS|HS)"
        // wasm:"Select"
        return x
 }
@@ -52,7 +52,7 @@ func cmov16bit(x, y uint16) uint16 {
                x = -y
        }
        // amd64:"CMOVW(HI|CS)"
-       // arm64:"CSEL\t(LO|HI)"
+       // arm64:"CSNEG\t(LS|HS)"
        // wasm:"Select"
        return x
 }
@@ -208,3 +208,195 @@ func cmovstore(a []int, i int, b bool) {
        // amd64:"CMOVQNE"
        a[i] = 7
 }
+
+var r0, r1, r2, r3, r4, r5 int
+
+func cmovinc(cond bool, a, b, c int) {
+       var x0, x1 int
+
+       if cond {
+               x0 = a
+       } else {
+               x0 = b + 1
+       }
+       // arm64:"CSINC\tNE", -"CSEL"
+       r0 = x0
+
+       if cond {
+               x1 = b + 1
+       } else {
+               x1 = a
+       }
+       // arm64:"CSINC\tEQ", -"CSEL"
+       r1 = x1
+
+       if cond {
+               c++
+       }
+       // arm64:"CSINC\tEQ", -"CSEL"
+       r2 = c
+}
+
+func cmovinv(cond bool, a, b int) {
+       var x0, x1 int
+
+       if cond {
+               x0 = a
+       } else {
+               x0 = ^b
+       }
+       // arm64:"CSINV\tNE", -"CSEL"
+       r0 = x0
+
+       if cond {
+               x1 = ^b
+       } else {
+               x1 = a
+       }
+       // arm64:"CSINV\tEQ", -"CSEL"
+       r1 = x1
+}
+
+func cmovneg(cond bool, a, b, c int) {
+       var x0, x1 int
+
+       if cond {
+               x0 = a
+       } else {
+               x0 = -b
+       }
+       // arm64:"CSNEG\tNE", -"CSEL"
+       r0 = x0
+
+       if cond {
+               x1 = -b
+       } else {
+               x1 = a
+       }
+       // arm64:"CSNEG\tEQ", -"CSEL"
+       r1 = x1
+}
+
+func cmovsetm(cond bool, x int) {
+       var x0, x1 int
+
+       if cond {
+               x0 = -1
+       } else {
+               x0 = 0
+       }
+       // arm64:"CSETM\tNE", -"CSEL"
+       r0 = x0
+
+       if cond {
+               x1 = 0
+       } else {
+               x1 = -1
+       }
+       // arm64:"CSETM\tEQ", -"CSEL"
+       r1 = x1
+}
+
+func cmovFcmp0(s, t float64, a, b int) {
+       var x0, x1, x2, x3, x4, x5 int
+
+       if s < t {
+               x0 = a
+       } else {
+               x0 = b + 1
+       }
+       // arm64:"CSINC\tMI", -"CSEL"
+       r0 = x0
+
+       if s <= t {
+               x1 = a
+       } else {
+               x1 = ^b
+       }
+       // arm64:"CSINV\tLS", -"CSEL"
+       r1 = x1
+
+       if s > t {
+               x2 = a
+       } else {
+               x2 = -b
+       }
+       // arm64:"CSNEG\tMI", -"CSEL"
+       r2 = x2
+
+       if s >= t {
+               x3 = -1
+       } else {
+               x3 = 0
+       }
+       // arm64:"CSETM\tLS", -"CSEL"
+       r3 = x3
+
+       if s == t {
+               x4 = a
+       } else {
+               x4 = b + 1
+       }
+       // arm64:"CSINC\tEQ", -"CSEL"
+       r4 = x4
+
+       if s != t {
+               x5 = a
+       } else {
+               x5 = b + 1
+       }
+       // arm64:"CSINC\tNE", -"CSEL"
+       r5 = x5
+}
+
+func cmovFcmp1(s, t float64, a, b int) {
+       var x0, x1, x2, x3, x4, x5 int
+
+       if s < t {
+               x0 = b + 1
+       } else {
+               x0 = a
+       }
+       // arm64:"CSINC\tPL", -"CSEL"
+       r0 = x0
+
+       if s <= t {
+               x1 = ^b
+       } else {
+               x1 = a
+       }
+       // arm64:"CSINV\tHI", -"CSEL"
+       r1 = x1
+
+       if s > t {
+               x2 = -b
+       } else {
+               x2 = a
+       }
+       // arm64:"CSNEG\tPL", -"CSEL"
+       r2 = x2
+
+       if s >= t {
+               x3 = 0
+       } else {
+               x3 = -1
+       }
+       // arm64:"CSETM\tHI", -"CSEL"
+       r3 = x3
+
+       if s == t {
+               x4 = b + 1
+       } else {
+               x4 = a
+       }
+       // arm64:"CSINC\tNE", -"CSEL"
+       r4 = x4
+
+       if s != t {
+               x5 = b + 1
+       } else {
+               x5 = a
+       }
+       // arm64:"CSINC\tEQ", -"CSEL"
+       r5 = x5
+}