8355699: RISC-V: support SUADD/SADD/SUSUB/SSUB

Reviewed-by: fyang, luhenry
This commit is contained in:
Hamlin Li 2025-05-07 08:33:49 +00:00
parent da004cb657
commit 1a4bbb0027
4 changed files with 167 additions and 22 deletions

View File

@ -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);

View File

@ -650,6 +650,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) %{

View File

@ -147,7 +147,8 @@ public class VectorCommutativeOperSharingTest {
}
@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);

View File

@ -166,7 +166,7 @@ public class 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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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 class 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"})
@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 class VectorSaturatedOperationsTest {
}
@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 class VectorSaturatedOperationsTest {
@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 class VectorSaturatedOperationsTest {
@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)