Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/hotspot/cpu/riscv/assembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
138 changes: 138 additions & 0 deletions src/hotspot/cpu/riscv/riscv_v.ad
Original file line number Diff line number Diff line change
Expand Up @@ -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) %{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down