8296515: RISC-V: Small refactoring for MaxReductionV/MinReductionV/AddReductionV node implementation

Reviewed-by: luhenry, dzhang, yzhu, fyang
This commit is contained in:
Gui Cao 2022-11-09 09:38:36 +00:00 committed by Fei Yang
parent 82cbfb5fb0
commit fef68bbaf6
4 changed files with 73 additions and 169 deletions

@ -1690,27 +1690,36 @@ bool C2_MacroAssembler::in_scratch_emit_size() {
return MacroAssembler::in_scratch_emit_size();
}
void C2_MacroAssembler::reduce_operation(Register dst, VectorRegister tmp,
Register src1, VectorRegister src2,
BasicType bt, REDUCTION_OP op) {
void C2_MacroAssembler::rvv_reduce_integral(Register dst, VectorRegister tmp,
Register src1, VectorRegister src2,
BasicType bt, int opc) {
assert(bt == T_BYTE || bt == T_SHORT || bt == T_INT || bt == T_LONG, "unsupported element type");
Assembler::SEW sew = Assembler::elemtype_to_sew(bt);
vsetvli(t0, x0, sew);
vmv_s_x(tmp, src1);
switch (op) {
case REDUCTION_OP::ADD:
switch (opc) {
case Op_AddReductionVI:
case Op_AddReductionVL:
vredsum_vs(tmp, src2, tmp);
break;
case REDUCTION_OP::AND:
case Op_AndReductionV:
vredand_vs(tmp, src2, tmp);
break;
case REDUCTION_OP::OR:
case Op_OrReductionV:
vredor_vs(tmp, src2, tmp);
break;
case REDUCTION_OP::XOR:
case Op_XorReductionV:
vredxor_vs(tmp, src2, tmp);
break;
case Op_MaxReductionV:
vredmax_vs(tmp, src2, tmp);
break;
case Op_MinReductionV:
vredmin_vs(tmp, src2, tmp);
break;
default:
ShouldNotReachHere();
}

@ -195,8 +195,8 @@
VectorRegister tmp1, VectorRegister tmp2,
bool is_double, bool is_min);
void reduce_operation(Register dst, VectorRegister tmp,
Register src1, VectorRegister src2,
BasicType bt, REDUCTION_OP op);
void rvv_reduce_integral(Register dst, VectorRegister tmp,
Register src1, VectorRegister src2,
BasicType bt, int opc);
#endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP

@ -1300,7 +1300,4 @@ class SkipIfEqual {
~SkipIfEqual();
};
// reduction related operations
enum REDUCTION_OP {ADD, AND, OR, XOR};
#endif // CPU_RISCV_MACROASSEMBLER_RISCV_HPP

@ -809,7 +809,9 @@ instruct vnegD(vReg dst, vReg src) %{
// vector and reduction
instruct reduce_andI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) != T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AndReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
@ -818,8 +820,8 @@ instruct reduce_andI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::AND);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -834,8 +836,8 @@ instruct reduce_andL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::AND);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -843,7 +845,9 @@ instruct reduce_andL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector or reduction
instruct reduce_orI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) != T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (OrReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
@ -852,8 +856,8 @@ instruct reduce_orI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::OR);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -868,8 +872,8 @@ instruct reduce_orL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::OR);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -877,7 +881,9 @@ instruct reduce_orL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector xor reduction
instruct reduce_xorI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) != T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (XorReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
@ -886,8 +892,8 @@ instruct reduce_xorI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::XOR);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -902,82 +908,44 @@ instruct reduce_xorL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
"vmv.x.s $dst, $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_operation($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, REDUCTION_OP::XOR);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
// vector add reduction
instruct reduce_addB(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
format %{ "vmv.s.x $tmp, $src1\t#@reduce_addB\n\t"
"vredsum.vs $tmp, $src2, $tmp\n\t"
"vmv.x.s $dst, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e8);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg),
as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
%}
ins_pipe(pipe_slow);
%}
instruct reduce_addS(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
format %{ "vmv.s.x $tmp, $src1\t#@reduce_addS\n\t"
"vredsum.vs $tmp, $src2, $tmp\n\t"
"vmv.x.s $dst, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e16);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg),
as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
%}
ins_pipe(pipe_slow);
%}
instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
format %{ "vmv.s.x $tmp, $src1\t#@reduce_addI\n\t"
"vredsum.vs $tmp, $src2, $tmp\n\t"
"vmv.x.s $dst, $tmp" %}
"vmv.x.s $dst, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e32);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg),
as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
instruct reduce_addL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
match(Set dst (AddReductionVL src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
format %{ "vmv.s.x $tmp, $src1\t#@reduce_addL\n\t"
"vredsum.vs $tmp, $src2, $tmp\n\t"
"vmv.x.s $dst, $tmp" %}
"vmv.x.s $dst, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e64);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg),
as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
@ -1017,135 +985,65 @@ instruct reduce_addD(fRegD src1_dst, vReg src2, vReg tmp) %{
%}
// vector integer max reduction
instruct vreduce_maxB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
match(Set dst (MaxReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_maxB $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e8);
__ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
Label Ldone;
__ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone);
__ mv(as_Register($dst$$reg), as_Register($src1$$reg));
__ bind(Ldone);
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_maxS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
match(Set dst (MaxReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_maxS $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e16);
__ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
Label Ldone;
__ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone);
__ mv(as_Register($dst$$reg), as_Register($src1$$reg));
__ bind(Ldone);
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_maxI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MaxReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_maxI $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e32);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_maxL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
match(Set dst (MaxReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_maxL $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e64);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
// vector integer min reduction
instruct vreduce_minB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
match(Set dst (MinReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_minB $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e8);
__ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
Label Ldone;
__ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone);
__ mv(as_Register($dst$$reg), as_Register($src1$$reg));
__ bind(Ldone);
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_minS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
match(Set dst (MinReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_minS $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e16);
__ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
Label Ldone;
__ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone);
__ mv(as_Register($dst$$reg), as_Register($src1$$reg));
__ bind(Ldone);
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_minI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MinReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_minI $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e32);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}
instruct vreduce_minL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG);
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
match(Set dst (MinReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
format %{ "vreduce_minL $dst, $src1, $src2, $tmp" %}
ins_encode %{
__ vsetvli(t0, x0, Assembler::e64);
__ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register);
__ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg));
__ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ rvv_reduce_integral($dst$$Register, as_VectorRegister($tmp$$reg),
$src1$$Register, as_VectorRegister($src2$$reg), bt, this->ideal_Opcode());
%}
ins_pipe(pipe_slow);
%}