diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp index a2b38ee4a48..ab3fca9b003 100644 --- a/src/hotspot/cpu/riscv/matcher_riscv.hpp +++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp @@ -168,7 +168,7 @@ // BoolTest mask for vector test intrinsics static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { - return BoolTest::illegal; + return is_alltrue ? BoolTest::eq : BoolTest::ne; } // Returns pre-selection estimated size of a vector operation. diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 92e49b508a5..e37ce24b7f5 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -4281,4 +4281,111 @@ instruct vmask_fromlong(vRegMask dst, iRegL src) %{ __ vmv_s_x(as_VectorRegister($dst$$reg), $src$$Register); %} ins_pipe(pipe_slow); +%} + +// ------------------------------ VectorTest ----------------------------------- + +// anytrue + +// Not matched. Condition is negated and value zero is moved to the right side in CMoveINode::Ideal. + +// instruct cmovI_vtest_anytrue(iRegINoSp dst, cmpOp cop, vRegMask op1, vRegMask op2, immI0 zero, immI_1 one) %{ +// predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne && +// static_cast(n->in(1)->in(2))->get_predicate() == BoolTest::ne); +// match(Set dst (CMoveI (Binary cop (VectorTest op1 op2)) (Binary zero one))); +// format %{ "CMove $dst, (vectortest $cop $op1 $op2), zero, one\t#@cmovI_vtest_anytrue" %} +// ins_encode %{ +// BasicType bt = Matcher::vector_element_basic_type(this, $op1); +// uint vector_length = Matcher::vector_length(this, $op1); +// __ vsetvli_helper(bt, vector_length); +// __ vcpop_m($dst$$Register, as_VectorRegister($op1$$reg)); +// __ snez($dst$$Register, $dst$$Register); +// %} +// ins_pipe(pipe_slow); +// %} + +instruct cmovI_vtest_anytrue_negate(iRegINoSp dst, cmpOp cop, vRegMask op1, vRegMask op2, immI0 zero, immI_1 one) %{ + predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq && + static_cast(n->in(1)->in(2))->get_predicate() == BoolTest::ne); + match(Set dst (CMoveI (Binary cop (VectorTest op1 op2)) (Binary one zero))); + format %{ "CMove $dst, (vectortest $cop $op1 $op2), zero, one\t#@cmovI_vtest_anytrue_negate" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $op1); + uint vector_length = Matcher::vector_length(this, $op1); + __ vsetvli_helper(bt, vector_length); + __ vcpop_m($dst$$Register, as_VectorRegister($op1$$reg)); + __ snez($dst$$Register, $dst$$Register); + %} + ins_pipe(pipe_slow); +%} + +// alltrue + +// Not matched. Condition is negated and value zero is moved to the right side in CMoveINode::Ideal. + +// instruct cmovI_vtest_alltrue(iRegINoSp dst, cmpOp cop, vRegMask op1, vRegMask op2, immI0 zero, immI_1 one) %{ +// predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq && +// static_cast(n->in(1)->in(2))->get_predicate() == BoolTest::overflow); +// match(Set dst (CMoveI (Binary cop (VectorTest op1 op2)) (Binary zero one))); +// format %{ "CMove $dst, (vectortest $cop $op1 $op2), zero, one\t#@cmovI_vtest_alltrue" %} +// ins_encode %{ +// BasicType bt = Matcher::vector_element_basic_type(this, $op1); +// uint vector_length = Matcher::vector_length(this, $op1); +// __ vsetvli_helper(bt, vector_length); +// __ vcpop_m($dst$$Register, as_VectorRegister($op1$$reg)); +// __ sub($dst$$Register, $dst$$Register, vector_length); +// __ seqz($dst$$Register, $dst$$Register); +// %} +// ins_pipe(pipe_slow); +// %} + +instruct cmovI_vtest_alltrue_negate(iRegINoSp dst, cmpOp cop, vRegMask op1, vRegMask op2, immI0 zero, immI_1 one) %{ + predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne && + static_cast(n->in(1)->in(2))->get_predicate() == BoolTest::overflow); + match(Set dst (CMoveI (Binary cop (VectorTest op1 op2)) (Binary one zero))); + format %{ "CMove $dst, (vectortest $cop $op1 $op2), zero, one\t#@cmovI_vtest_alltrue_negate" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $op1); + uint vector_length = Matcher::vector_length(this, $op1); + __ vsetvli_helper(bt, vector_length); + __ vcpop_m($dst$$Register, as_VectorRegister($op1$$reg)); + __ sub($dst$$Register, $dst$$Register, vector_length); + __ seqz($dst$$Register, $dst$$Register); + %} + ins_pipe(pipe_slow); +%} + +// anytrue + +instruct vtest_anytrue_branch(cmpOpEqNe cop, vRegMask op1, vRegMask op2, label lbl) %{ + predicate(static_cast(n->in(2))->get_predicate() == BoolTest::ne); + match(If cop (VectorTest op1 op2)); + effect(USE lbl); + format %{ "b$cop (vectortest ne $op1, $op2) $lbl\t#@vtest_anytrue_branch" %} + ins_encode %{ + uint vector_length = Matcher::vector_length(this, $op1); + BasicType bt = Matcher::vector_element_basic_type(this, $op1); + __ vsetvli_helper(bt, vector_length); + __ vcpop_m(t0, as_VectorRegister($op1$$reg)); + __ enc_cmpEqNe_imm0_branch($cop$$cmpcode, t0, *($lbl$$label), /* is_far */ true); + %} + ins_pipe(pipe_slow); +%} + +// alltrue + +instruct vtest_alltrue_branch(cmpOpEqNe cop, vRegMask op1, vRegMask op2, label lbl) %{ + predicate(static_cast(n->in(2))->get_predicate() == BoolTest::overflow); + match(If cop (VectorTest op1 op2)); + effect(USE lbl); + format %{ "b$cop (vectortest overflow $op1, $op2) $lbl\t#@vtest_alltrue_branch" %} + ins_encode %{ + uint vector_length = Matcher::vector_length(this, $op1); + BasicType bt = Matcher::vector_element_basic_type(this, $op1); + __ vsetvli_helper(bt, vector_length); + __ vcpop_m(t0, as_VectorRegister($op1$$reg)); + __ sub(t0, t0, vector_length); + __ enc_cmpEqNe_imm0_branch($cop$$cmpcode, t0, *($lbl$$label), /* is_far */ true); + %} + ins_pipe(pipe_slow); %} \ No newline at end of file