diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 61de983bb02c00..5c664e01397d1f 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -294,7 +294,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD, ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED, ssa.OpRISCV64FSGNJD, ssa.OpRISCV64MIN, ssa.OpRISCV64MAX, ssa.OpRISCV64MINU, ssa.OpRISCV64MAXU, - ssa.OpRISCV64SH1ADD, ssa.OpRISCV64SH2ADD, ssa.OpRISCV64SH3ADD: + ssa.OpRISCV64SH1ADD, ssa.OpRISCV64SH2ADD, ssa.OpRISCV64SH3ADD, + ssa.OpRISCV64CZEROEQZ, ssa.OpRISCV64CZERONEZ: r := v.Reg() r1 := v.Args[0].Reg() r2 := v.Args[1].Reg() diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go index dc433ff9749150..db27665be54b73 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go @@ -520,6 +520,10 @@ func init() { // ====+============================= {name: "FCLASSS", argLength: 1, reg: fpgp, asm: "FCLASSS", typ: "Int64"}, // classify float32 {name: "FCLASSD", argLength: 1, reg: fpgp, asm: "FCLASSD", typ: "Int64"}, // classify float64 + + // RISC-V Integer Conditional (Zicond) operations extension + {name: "CZEROEQZ", argLength: 2, reg: gp21, asm: "CZEROEQZ"}, + {name: "CZERONEZ", argLength: 2, reg: gp21, asm: "CZERONEZ"}, } RISCV64blocks := []blockData{ diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules index 7acaa2f3fec546..2f9b8808920fe7 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules @@ -23,3 +23,33 @@ (SRAI [0] x) => x (SRLI [0] x) => x (SLLI [0] x) => x + +// "Zicond" Extension for Integer Conditional Operations +// (x == 0) ? x : y +(CondSelect x y (SEQZ x)) && buildcfg.GORISCV64 >= 23 => (CZEROEQZ y x) +// (z == 0) ? (x + y) : y +(CondSelect (ADD x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (ADD x (CZERONEZ y z)) +// (z != 0) ? (x + y) : y +(CondSelect (ADD x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (ADD x (CZEROEQZ y z)) +// (z == 0) ? (x - y) : y +(CondSelect (SUB x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (SUB x (CZERONEZ y z)) +// (z != 0) ? (x - y) : y +(CondSelect (SUB x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (SUB x (CZEROEQZ y z)) +// (z == 0) ? (x | y) : y +(CondSelect (OR x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR x (CZERONEZ y z)) +// (z != 0) ? (x | y) : y +(CondSelect (OR x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR x (CZEROEQZ y z)) +// (z == 0) ? (x ^ y) : y +(CondSelect (XOR x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (XOR x (CZERONEZ y z)) +// (z != 0) ? (x ^ y) : y +(CondSelect (XOR x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (XOR x (CZEROEQZ y z)) +// (z == 0) ? (x & y) : y +(CondSelect (AND x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR (AND x y) (CZEROEQZ x z)) +// (z != 0) ? (x & y) : y +(CondSelect (AND x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR (AND x y) (CZERONEZ x z)) +// (z == 0) ? x : y +(CondSelect x y (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR (CZERONEZ x z) (CZEROEQZ y z)) +// (z != 0) ? x : y +(CondSelect x y (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR (CZEROEQZ x z) (CZERONEZ y z)) +// Make sure we can rewrite all CondSelects. +(CondSelect x y cond) && buildcfg.GORISCV64 >= 23 => (OR (CZEROEQZ x cond) (CZERONEZ y cond)) diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index a7d339cad064ac..66922b7ab09fba 100644 --- a/src/cmd/compile/internal/ssa/branchelim.go +++ b/src/cmd/compile/internal/ssa/branchelim.go @@ -4,7 +4,10 @@ package ssa -import "cmd/internal/src" +import ( + "cmd/internal/src" + "internal/buildcfg" +) // branchelim tries to eliminate branches by // generating CondSelect instructions. @@ -24,6 +27,10 @@ func branchelim(f *Func) { switch f.Config.arch { case "arm64", "ppc64le", "ppc64", "amd64", "wasm", "loong64": // implemented + case "riscv64": + if buildcfg.GORISCV64 < 23 { + return + } default: return } diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index b4aae50b895ff8..76df7d999bee11 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2648,6 +2648,8 @@ const ( OpRISCV64LoweredFMAXD OpRISCV64FCLASSS OpRISCV64FCLASSD + OpRISCV64CZEROEQZ + OpRISCV64CZERONEZ OpS390XFADDS OpS390XFADD @@ -35662,6 +35664,34 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "CZEROEQZ", + argLen: 2, + asm: riscv.ACZEROEQZ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + outputs: []outputInfo{ + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, + { + name: "CZERONEZ", + argLen: 2, + asm: riscv.ACZERONEZ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + outputs: []outputInfo{ + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, { name: "FADDS", diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go b/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go index d2c3a8f73df2e9..e7336e4d489b2e 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go @@ -2,8 +2,12 @@ package ssa +import "internal/buildcfg" + func rewriteValueRISCV64latelower(v *Value) bool { switch v.Op { + case OpCondSelect: + return rewriteValueRISCV64latelower_OpCondSelect(v) case OpRISCV64AND: return rewriteValueRISCV64latelower_OpRISCV64AND(v) case OpRISCV64NOT: @@ -21,6 +25,373 @@ func rewriteValueRISCV64latelower(v *Value) bool { } return false } +func rewriteValueRISCV64latelower_OpCondSelect(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (CondSelect x y (SEQZ x)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (CZEROEQZ y x) + for { + t := v.Type + x := v_0 + y := v_1 + if v_2.Op != OpRISCV64SEQZ || x != v_2.Args[0] || !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64CZEROEQZ) + v.Type = t + v.AddArg2(y, x) + return true + } + // match: (CondSelect (ADD x y) x (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (ADD x (CZERONEZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64ADD { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SEQZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64ADD) + v0 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (ADD x y) x (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (ADD x (CZEROEQZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64ADD { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SNEZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64ADD) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (SUB x y) x (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (SUB x (CZERONEZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64SUB { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 || v_2.Op != OpRISCV64SEQZ { + break + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64SUB) + v0 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (SUB x y) x (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (SUB x (CZEROEQZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64SUB { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 || v_2.Op != OpRISCV64SNEZ { + break + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64SUB) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (OR x y) x (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR x (CZERONEZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64OR { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SEQZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (OR x y) x (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR x (CZEROEQZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64OR { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SNEZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (XOR x y) x (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (XOR x (CZERONEZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64XOR { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SEQZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64XOR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (XOR x y) x (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (XOR x (CZEROEQZ y z)) + for { + t := v.Type + if v_0.Op != OpRISCV64XOR { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SNEZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64XOR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(y, z) + v.AddArg2(x, v0) + return true + } + break + } + // match: (CondSelect (AND x y) x (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR (AND x y) (CZEROEQZ x z)) + for { + t := v.Type + if v_0.Op != OpRISCV64AND { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SEQZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64AND, t) + v0.AddArg2(x, y) + v1 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v1.AddArg2(x, z) + v.AddArg2(v0, v1) + return true + } + break + } + // match: (CondSelect (AND x y) x (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR (AND x y) (CZERONEZ x z)) + for { + t := v.Type + if v_0.Op != OpRISCV64AND { + break + } + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + if x != v_1 || v_2.Op != OpRISCV64SNEZ { + continue + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + continue + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64AND, t) + v0.AddArg2(x, y) + v1 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v1.AddArg2(x, z) + v.AddArg2(v0, v1) + return true + } + break + } + // match: (CondSelect x y (SEQZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR (CZERONEZ x z) (CZEROEQZ y z)) + for { + t := v.Type + x := v_0 + y := v_1 + if v_2.Op != OpRISCV64SEQZ { + break + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v0.AddArg2(x, z) + v1 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v1.AddArg2(y, z) + v.AddArg2(v0, v1) + return true + } + // match: (CondSelect x y (SNEZ z)) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR (CZEROEQZ x z) (CZERONEZ y z)) + for { + t := v.Type + x := v_0 + y := v_1 + if v_2.Op != OpRISCV64SNEZ { + break + } + z := v_2.Args[0] + if !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(x, z) + v1 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v1.AddArg2(y, z) + v.AddArg2(v0, v1) + return true + } + // match: (CondSelect x y cond) + // cond: buildcfg.GORISCV64 >= 23 + // result: (OR (CZEROEQZ x cond) (CZERONEZ y cond)) + for { + t := v.Type + x := v_0 + y := v_1 + cond := v_2 + if !(buildcfg.GORISCV64 >= 23) { + break + } + v.reset(OpRISCV64OR) + v0 := b.NewValue0(v.Pos, OpRISCV64CZEROEQZ, t) + v0.AddArg2(x, cond) + v1 := b.NewValue0(v.Pos, OpRISCV64CZERONEZ, t) + v1.AddArg2(y, cond) + v.AddArg2(v0, v1) + return true + } + return false +} func rewriteValueRISCV64latelower_OpRISCV64AND(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go index 97be0ced75d19d..8670d0e65c71e3 100644 --- a/test/codegen/condmove.go +++ b/test/codegen/condmove.go @@ -15,6 +15,9 @@ func cmovint(c int) int { // arm64:"CSEL\tLT" // ppc64x:"ISEL\t[$]0" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -26,6 +29,9 @@ func cmovchan(x, y chan int) chan int { // arm64:"CSEL\tNE" // ppc64x:"ISEL\t[$]2" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -37,6 +43,9 @@ func cmovuintptr(x, y uintptr) uintptr { // arm64:"CSNEG\tLS" // ppc64x:"ISEL\t[$]1" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -48,6 +57,9 @@ func cmov32bit(x, y uint32) uint32 { // arm64:"CSNEG\t(LS|HS)" // ppc64x:"ISEL\t[$]1" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -59,6 +71,9 @@ func cmov16bit(x, y uint16) uint16 { // arm64:"CSNEG\t(LS|HS)" // ppc64x:"ISEL\t[$][01]" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -73,6 +88,9 @@ func cmovfloateq(x, y float64) int { // arm64:"CSEL\tEQ" // ppc64x:"ISEL\t[$]2" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return a } @@ -85,6 +103,9 @@ func cmovfloatne(x, y float64) int { // arm64:"CSEL\tNE" // ppc64x:"ISEL\t[$]2" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return a } @@ -112,6 +133,9 @@ func cmovfloatint2(x, y float64) float64 { // arm64:"CSEL\tMI" // ppc64x:"ISEL\t[$]0" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r = r - ldexp(y, rexp-yexp) } return r @@ -127,6 +151,9 @@ func cmovloaded(x [4]int, y int) int { // arm64:"CSEL\tNE" // ppc64x:"ISEL\t[$]2" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR`, -`SNEZ` return y } @@ -139,6 +166,9 @@ func cmovuintptr2(x, y uintptr) uintptr { // arm64:"CSEL\tEQ" // ppc64x:"ISEL\t[$]2" // wasm:"Select" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR`, -`SEQZ` return a } @@ -165,6 +195,9 @@ func cmovinvert1(x, y int64) int64 { y = -y } // amd64:"CMOVQGT" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return y } func cmovinvert2(x, y int64) int64 { @@ -179,6 +212,9 @@ func cmovinvert3(x, y int64) int64 { y = -y } // amd64:"CMOVQEQ" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return y } func cmovinvert4(x, y int64) int64 { @@ -186,6 +222,9 @@ func cmovinvert4(x, y int64) int64 { y = -y } // amd64:"CMOVQNE" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return y } func cmovinvert5(x, y uint64) uint64 { @@ -193,6 +232,9 @@ func cmovinvert5(x, y uint64) uint64 { y = -y } // amd64:"CMOVQCS" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return y } func cmovinvert6(x, y uint64) uint64 { @@ -200,6 +242,9 @@ func cmovinvert6(x, y uint64) uint64 { y = -y } // amd64:"CMOVQLS" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return y } @@ -217,6 +262,9 @@ func cmovstore(a []int, i int, b bool) { i += 42 } // amd64:"CMOVQNE" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` a[i] = 7 } @@ -231,6 +279,9 @@ func cmovinc(cond bool, a, b, c int) { x0 = b + 1 } // arm64:"CSINC\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if cond { @@ -239,6 +290,9 @@ func cmovinc(cond bool, a, b, c int) { x1 = a } // arm64:"CSINC\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 if cond { @@ -257,6 +311,9 @@ func cmovinv(cond bool, a, b int) { x0 = ^b } // arm64:"CSINV\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if cond { @@ -265,6 +322,9 @@ func cmovinv(cond bool, a, b int) { x1 = a } // arm64:"CSINV\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 } @@ -277,6 +337,9 @@ func cmovneg(cond bool, a, b, c int) { x0 = -b } // arm64:"CSNEG\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if cond { @@ -285,6 +348,9 @@ func cmovneg(cond bool, a, b, c int) { x1 = a } // arm64:"CSNEG\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 } @@ -297,6 +363,9 @@ func cmovsetm(cond bool, x int) { x0 = 0 } // arm64:"CSETM\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if cond { @@ -305,6 +374,9 @@ func cmovsetm(cond bool, x int) { x1 = -1 } // arm64:"CSETM\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 } @@ -317,6 +389,9 @@ func cmovFcmp0(s, t float64, a, b int) { x0 = b + 1 } // arm64:"CSINC\tMI", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if s <= t { @@ -325,6 +400,9 @@ func cmovFcmp0(s, t float64, a, b int) { x1 = ^b } // arm64:"CSINV\tLS", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 if s > t { @@ -333,6 +411,9 @@ func cmovFcmp0(s, t float64, a, b int) { x2 = -b } // arm64:"CSNEG\tMI", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r2 = x2 if s >= t { @@ -341,6 +422,9 @@ func cmovFcmp0(s, t float64, a, b int) { x3 = 0 } // arm64:"CSETM\tLS", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r3 = x3 if s == t { @@ -349,6 +433,9 @@ func cmovFcmp0(s, t float64, a, b int) { x4 = b + 1 } // arm64:"CSINC\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r4 = x4 if s != t { @@ -357,6 +444,9 @@ func cmovFcmp0(s, t float64, a, b int) { x5 = b + 1 } // arm64:"CSINC\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r5 = x5 } @@ -369,6 +459,9 @@ func cmovFcmp1(s, t float64, a, b int) { x0 = a } // arm64:"CSINC\tPL", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r0 = x0 if s <= t { @@ -377,6 +470,9 @@ func cmovFcmp1(s, t float64, a, b int) { x1 = a } // arm64:"CSINV\tHI", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r1 = x1 if s > t { @@ -385,6 +481,9 @@ func cmovFcmp1(s, t float64, a, b int) { x2 = a } // arm64:"CSNEG\tPL", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r2 = x2 if s >= t { @@ -393,6 +492,9 @@ func cmovFcmp1(s, t float64, a, b int) { x3 = -1 } // arm64:"CSETM\tHI", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r3 = x3 if s == t { @@ -401,6 +503,9 @@ func cmovFcmp1(s, t float64, a, b int) { x4 = a } // arm64:"CSINC\tNE", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r4 = x4 if s != t { @@ -409,6 +514,9 @@ func cmovFcmp1(s, t float64, a, b int) { x5 = a } // arm64:"CSINC\tEQ", -"CSEL" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` r5 = x5 } @@ -418,6 +526,9 @@ func cmovzero1(c bool) int { x = 182 } // loong64:"MASKEQZ", -"MASKNEZ" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -427,6 +538,9 @@ func cmovzero2(c bool) int { x = 182 } // loong64:"MASKNEZ", -"MASKEQZ" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -440,6 +554,9 @@ func cmovzeroreg0(a, b int) int { x = a } // ppc64x:"ISEL\t[$]2, R[0-9]+, R0, R[0-9]+" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -449,6 +566,9 @@ func cmovzeroreg1(a, b int) int { x = 0 } // ppc64x:"ISEL\t[$]2, R0, R[0-9]+, R[0-9]+" + // riscv64/rva20u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva22u64:-`CZEROEQZ`, -`CZERONEZ` + // riscv64/rva23u64:`CZEROEQZ`, `CZERONEZ`, `OR` return x } @@ -507,3 +627,111 @@ func cmovmathhalveu(a uint, b bool) uint { // wasm:"I64ShrU", -"Select" return a } + +func cmoveAddZero(cond, a, b int) int { + result := a + if cond == 0 { + result = a + b + } + // riscv64/rva23u64:`CZERONEZ`, `ADD`, -`SEQZ`, -`CZEROEQZ`, -`OR` + return result +} + +func cmoveAddNonZero(cond, a, b int) int { + var result int + if cond != 0 { + result = a + b + } else { + result = a + } + // riscv64/rva23u64:`CZEROEQZ`, `ADD`, -`SNEZ`, -`CZERONEZ`, -`OR` + return result +} + +func cmoveSubZero(cond, a, b int) int { + var result int + if cond == 0 { + result = a - b + } else { + result = a + } + // riscv64/rva23u64:`CZERONEZ`, `SUB`, -`SEQZ`, -`CZEROEQZ`, -`OR` + return result +} + +func cmoveSubNonZero(cond, a, b int) int { + var result int + if cond != 0 { + result = a - b + } else { + result = a + } + // riscv64/rva23u64:`CZEROEQZ`, `SUB`, -`SNEZ`, -`CZERONEZ`, -`OR` + return result +} + +func cmoveOrZero(cond, a, b int) int { + var result int + if cond == 0 { + result = a | b + } else { + result = a + } + // riscv64/rva23u64:`CZERONEZ`, `OR`, -`SEQZ`, -`CZEROEQZ` + return result +} + +func cmoveOrNonZero(cond, a, b int) int { + var result int + if cond != 0 { + result = a | b + } else { + result = a + } + // riscv64/rva23u64:`CZEROEQZ`, `OR`, -`SNEZ`, -`CZERONEZ` + return result +} + +func cmoveXorZero(cond, a, b int) int { + var result int + if cond == 0 { + result = a ^ b + } else { + result = a + } + // riscv64/rva23u64:`CZERONEZ`, `XOR`, -`SEQZ`, -`CZEROEQZ`, -`OR` + return result +} + +func cmoveXorNonZero(cond, a, b int) int { + var result int + if cond != 0 { + result = a ^ b + } else { + result = a + } + // riscv64/rva23u64:`CZEROEQZ`, `XOR`, -`SNEZ`, -`CZERONEZ`, -`OR` + return result +} + +func cmoveAndZero(cond, a, b int) int { + var result int + if cond == 0 { + result = a & b + } else { + result = a + } + // riscv64/rva23u64:`CZEROEQZ`, `AND`, `OR`, -`SEQZ`, -`CZERONEZ` + return result +} + +func CondAndNonZero(cond, a, b int) int { + var result int + if cond != 0 { + result = a & b + } else { + result = a + } + // riscv64/rva23u64:`CZERONEZ`, `AND`, `OR`, -`SNEZ`, -`CZEROEQZ` + return result +}