@@ -393,6 +393,32 @@ source %{
393393 return false;
394394 }
395395
396+ bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
397+ // Only SVE supports the predicate feature.
398+ if (UseSVE == 0) {
399+ // On architectures that do not support predicate, masks are stored in
400+ // general vector registers (TypeVect) with sizes ranging from TypeVectA
401+ // to TypeVectX based on the vector size in bytes.
402+ assert(vt->isa_vectmask() == nullptr, "mask type is not matched");
403+ return false;
404+ }
405+
406+ assert(vt->isa_vectmask() != nullptr, "expected TypeVectMask on SVE");
407+ switch (opcode) {
408+ case Op_VectorMaskToLong:
409+ case Op_VectorLongToMask:
410+ // These operations lack native SVE predicate instructions and are
411+ // implemented using general vector instructions instead. Use vector
412+ // registers rather than predicate registers to save the mask for
413+ // better performance.
414+ return false;
415+ default:
416+ // By default, the mask operations are implemented with predicate
417+ // instructions with a predicate input/output.
418+ return true;
419+ }
420+ }
421+
396422 // Assert that the given node is not a variable shift.
397423 bool assert_not_var_shift(const Node* n) {
398424 assert(!n->as_ShiftV()->is_var_shift(), "illegal variable shift");
@@ -6249,31 +6275,44 @@ instruct vmask_tolong_neon(iRegLNoSp dst, vReg src) %{
62496275 ins_pipe(pipe_slow);
62506276%}
62516277
6252- instruct vmask_tolong_sve(iRegLNoSp dst, pReg src, vReg tmp1, vReg tmp2) %{
6253- predicate(UseSVE > 0);
6278+ instruct vmask_tolong_sve(iRegLNoSp dst, vReg src, vReg tmp) %{
6279+ predicate(UseSVE > 0 && !VM_Version::supports_svebitperm());
6280+ match(Set dst (VectorMaskToLong src));
6281+ effect(TEMP tmp);
6282+ format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp" %}
6283+ ins_encode %{
6284+ // Input "src" is a vector of boolean represented as
6285+ // bytes with 0x00/0x01 as element values.
6286+ __ sve_vmask_tolong($dst$$Register, $src$$FloatRegister,
6287+ $tmp$$FloatRegister, Matcher::vector_length(this, $src));
6288+ %}
6289+ ins_pipe(pipe_slow);
6290+ %}
6291+
6292+ instruct vmask_tolong_sve2(iRegLNoSp dst, vReg src, vReg tmp1, vReg tmp2) %{
6293+ predicate(VM_Version::supports_svebitperm());
62546294 match(Set dst (VectorMaskToLong src));
62556295 effect(TEMP tmp1, TEMP tmp2);
6256- format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp1, $tmp2" %}
6296+ format %{ "vmask_tolong_sve2 $dst, $src\t# KILL $tmp1, $tmp2" %}
62576297 ins_encode %{
6258- __ sve_vmask_tolong($dst$$Register, $src$$PRegister,
6259- Matcher::vector_element_basic_type(this, $src),
6260- Matcher::vector_length(this, $src),
6261- $tmp1$$FloatRegister, $tmp2$$FloatRegister);
6298+ // Input "src" is a vector of boolean represented as
6299+ // bytes with 0x00/0x01 as element values.
6300+ __ sve2_vmask_tolong($dst$$Register, $src$$FloatRegister,
6301+ $tmp1$$FloatRegister, $tmp2$$FloatRegister,
6302+ Matcher::vector_length(this, $src));
62626303 %}
62636304 ins_pipe(pipe_slow);
62646305%}
62656306
62666307// fromlong
62676308
6268- instruct vmask_fromlong(pReg dst, iRegL src, vReg tmp1, vReg tmp2 ) %{
6309+ instruct vmask_fromlong(vReg dst, iRegL src, vReg tmp ) %{
62696310 match(Set dst (VectorLongToMask src));
6270- effect(TEMP tmp1 , TEMP tmp2 );
6271- format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp1, $tmp2 " %}
6311+ effect(TEMP_DEF dst , TEMP tmp );
6312+ format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp " %}
62726313 ins_encode %{
6273- __ sve_vmask_fromlong($dst$$PRegister, $src$$Register,
6274- Matcher::vector_element_basic_type(this),
6275- Matcher::vector_length(this),
6276- $tmp1$$FloatRegister, $tmp2$$FloatRegister);
6314+ __ sve_vmask_fromlong($dst$$FloatRegister, $src$$Register,
6315+ $tmp$$FloatRegister, Matcher::vector_length(this));
62776316 %}
62786317 ins_pipe(pipe_slow);
62796318%}
0 commit comments