diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 4773043e1ba07..63d5d4f3e613d 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1904,8 +1904,14 @@ enum VectorMask { INSN(vand_vv, 0b1010111, 0b000, 0b001001); // Vector Single-Width Integer Add and Subtract - INSN(vsub_vv, 0b1010111, 0b000, 0b000010); INSN(vadd_vv, 0b1010111, 0b000, 0b000000); + INSN(vsub_vv, 0b1010111, 0b000, 0b000010); + + // Vector Saturating Integer Add and Subtract + INSN(vsadd_vv, 0b1010111, 0b000, 0b100001); + INSN(vsaddu_vv, 0b1010111, 0b000, 0b100000); + INSN(vssub_vv, 0b1010111, 0b000, 0b100011); + INSN(vssubu_vv, 0b1010111, 0b000, 0b100010); // Vector Register Gather Instructions INSN(vrgather_vv, 0b1010111, 0b000, 0b001100); diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 58c788747976e..96647c12f52fd 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -651,6 +651,144 @@ instruct vsubL_vx_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// -------- vector saturating integer operations + +// vector saturating signed integer addition + +instruct vsadd(vReg dst, vReg src1, vReg src2) %{ + predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned()); + match(Set dst (SaturatingAddV src1 src2)); + ins_cost(VEC_COST); + format %{ "vsadd $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vsadd_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating unsigned integer addition + +instruct vsaddu(vReg dst, vReg src1, vReg src2) %{ + predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned()); + match(Set dst (SaturatingAddV src1 src2)); + ins_cost(VEC_COST); + format %{ "vsaddu $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vsaddu_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating signed integer addition (predicated) + +instruct vsadd_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{ + predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned()); + match(Set dst_src (SaturatingAddV (Binary dst_src src1) v0)); + ins_cost(VEC_COST); + format %{ "vsadd_masked $dst_src, $dst_src, $src1, $v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vsadd_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), + as_VectorRegister($src1$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating unsigned integer addition (predicated) + +instruct vsaddu_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{ + predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned()); + match(Set dst_src (SaturatingAddV (Binary dst_src src1) v0)); + ins_cost(VEC_COST); + format %{ "vsaddu_masked $dst_src, $dst_src, $src1, $v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vsaddu_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), + as_VectorRegister($src1$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating signed integer subtraction + +instruct vssub(vReg dst, vReg src1, vReg src2) %{ + predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned()); + match(Set dst (SaturatingSubV src1 src2)); + ins_cost(VEC_COST); + format %{ "vssub $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vssub_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating unsigned integer subtraction + +instruct vssubu(vReg dst, vReg src1, vReg src2) %{ + predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned()); + match(Set dst (SaturatingSubV src1 src2)); + ins_cost(VEC_COST); + format %{ "vssubu $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vssubu_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating signed integer subtraction (predicated) + +instruct vssub_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{ + predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned()); + match(Set dst_src (SaturatingSubV (Binary dst_src src1) v0)); + ins_cost(VEC_COST); + format %{ "vssub_masked $dst_src, $dst_src, $src1, $v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vssub_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), + as_VectorRegister($src1$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +// vector saturating unsigned integer subtraction (predicated) + +instruct vssubu_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{ + predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned()); + match(Set dst_src (SaturatingSubV (Binary dst_src src1) v0)); + ins_cost(VEC_COST); + format %{ "vssubu_masked $dst_src, $dst_src, $src1, $v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + assert(is_integral_type(bt), "unsupported type"); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vssubu_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), + as_VectorRegister($src1$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + // vector and instruct vand(vReg dst, vReg src1, vReg src2) %{ diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorCommutativeOperSharingTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorCommutativeOperSharingTest.java index c3e0cbc3a9af5..a51946dd69857 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorCommutativeOperSharingTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorCommutativeOperSharingTest.java @@ -147,7 +147,8 @@ public void checkVectorIRSharing2() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VI, IRNode.VECTOR_SIZE_ANY, " 2 "}, applyIfCPUFeature = {"avx2", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VI, IRNode.VECTOR_SIZE_ANY, " 2 "}, + applyIfCPUFeatureOr = {"avx2", "true", "rvv", "true"}) public void testVectorIRSharing3(int index) { IntVector vec1 = IntVector.fromArray(I_SPECIES, ia, index); IntVector vec2 = IntVector.fromArray(I_SPECIES, ib, index); diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java index 84aaacb3a01cb..887c41efd48e6 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java @@ -166,7 +166,7 @@ public VectorSaturatedOperationsTest() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void sadd_byte() { for (int i = 0; i < COUNT; i += bspec.length()) { @@ -189,7 +189,7 @@ public void sadd_byte_verify() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void sadd_short() { for (int i = 0; i < COUNT; i += sspec.length()) { @@ -212,7 +212,7 @@ public void sadd_short_verify() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VI, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VI, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void sadd_int() { for (int i = 0; i < COUNT; i += ispec.length()) { @@ -235,7 +235,7 @@ public void sadd_int_verify() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VL, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VL, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void sadd_long() { for (int i = 0; i < COUNT; i += lspec.length()) { @@ -260,7 +260,7 @@ public void sadd_long_verify() { @Test @IR(counts = {IRNode.SATURATING_ADD_VB, " >0 " , "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void suadd_byte() { for (int i = 0; i < COUNT; i += bspec.length()) { @@ -285,7 +285,7 @@ public void suadd_byte_verify() { @Test @IR(counts = {IRNode.SATURATING_ADD_VS, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void suadd_short() { for (int i = 0; i < COUNT; i += sspec.length()) { @@ -310,7 +310,7 @@ public void suadd_short_verify() { @Test @IR(counts = {IRNode.SATURATING_ADD_VI, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void suadd_int() { for (int i = 0; i < COUNT; i += ispec.length()) { @@ -335,7 +335,7 @@ public void suadd_int_verify() { @Test @IR(counts = {IRNode.SATURATING_ADD_VL, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void suadd_long() { for (int i = 0; i < COUNT; i += lspec.length()) { @@ -358,7 +358,7 @@ public void suadd_long_verify() { } @Test - @IR(counts = {IRNode.SATURATING_SUB_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_SUB_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void ssub_byte() { for (int i = 0; i < COUNT; i += bspec.length()) { @@ -381,7 +381,7 @@ public void ssub_byte_verify() { } @Test - @IR(counts = {IRNode.SATURATING_SUB_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_SUB_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void ssub_short() { for (int i = 0; i < COUNT; i += sspec.length()) { @@ -404,7 +404,7 @@ public void ssub_short_verify() { } @Test - @IR(counts = {IRNode.SATURATING_SUB_VI, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_SUB_VI, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void ssub_int() { for (int i = 0; i < COUNT; i += ispec.length()) { @@ -427,7 +427,7 @@ public void ssub_int_verify() { } @Test - @IR(counts = {IRNode.SATURATING_SUB_VL, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_SUB_VL, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void ssub_long() { for (int i = 0; i < COUNT; i += lspec.length()) { @@ -452,7 +452,7 @@ public void ssub_long_verify() { @Test @IR(counts = {IRNode.SATURATING_SUB_VB, " >0 " , "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void susub_byte() { for (int i = 0; i < COUNT; i += bspec.length()) { @@ -477,7 +477,7 @@ public void susub_byte_verify() { @Test @IR(counts = {IRNode.SATURATING_SUB_VS, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void susub_short() { for (int i = 0; i < COUNT; i += sspec.length()) { @@ -502,7 +502,7 @@ public void susub_short_verify() { @Test @IR(counts = {IRNode.SATURATING_SUB_VI, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void susub_int() { for (int i = 0; i < COUNT; i += ispec.length()) { @@ -527,7 +527,7 @@ public void susub_int_verify() { @Test @IR(counts = {IRNode.SATURATING_SUB_VL, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @Warmup(value = 10000) public void susub_long() { for (int i = 0; i < COUNT; i += lspec.length()) { @@ -550,7 +550,7 @@ public void susub_long_verify() { } @Test - @IR(counts = {IRNode.SATURATING_ADD_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_ADD_VB, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @IR(counts = {IRNode.VECTOR_BLEND_B, " >0 "}, applyIfCPUFeatureAnd = {"asimd", "true", "sve2", "false"}) @IR(failOn = IRNode.VECTOR_BLEND_B, applyIfCPUFeature = {"sve2", "true"}) @Warmup(value = 10000) @@ -576,7 +576,7 @@ public void sadd_masked_verify() { } @Test - @IR(counts = {IRNode.SATURATING_SUB_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + @IR(counts = {IRNode.SATURATING_SUB_VS, " >0 "}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @IR(counts = {IRNode.VECTOR_BLEND_S, " >0 "}, applyIfCPUFeatureAnd = {"asimd", "true", "sve2", "false"}) @IR(failOn = IRNode.VECTOR_BLEND_S, applyIfCPUFeature = {"sve2", "true"}) @Warmup(value = 10000) @@ -604,7 +604,7 @@ public void ssub_masked_verify() { @Test @IR(counts = {IRNode.SATURATING_ADD_VI, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) @IR(counts = {IRNode.VECTOR_BLEND_I, " >0 "}, applyIfCPUFeatureAnd = {"asimd", "true", "sve2", "false"}) @IR(failOn = IRNode.VECTOR_BLEND_I, applyIfCPUFeature = {"sve2", "true"}) @Warmup(value = 10000) @@ -632,7 +632,7 @@ public void suadd_masked_verify() { @Test @IR(counts = {IRNode.SATURATING_SUB_VL, " >0 ", "unsigned_vector_node", " >0 "}, phase = {CompilePhase.BEFORE_MATCHING}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}) @IR(counts = {IRNode.VECTOR_BLEND_L, " >0 "}, applyIfCPUFeatureAnd = {"asimd", "true", "sve2", "false"}) @IR(failOn = IRNode.VECTOR_BLEND_L, applyIfCPUFeature = {"sve2", "true"}) @Warmup(value = 10000)