Skip to content
Open
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
67 changes: 53 additions & 14 deletions src/hotspot/cpu/aarch64/aarch64_vector.ad
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,32 @@ source %{
return false;
}

bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
// Only SVE supports the predicate feature.
if (UseSVE == 0) {
// On architectures that do not support predicate, masks are stored in
// general vector registers (TypeVect) with sizes ranging from TypeVectA
// to TypeVectX based on the vector size in bytes.
assert(vt->isa_vectmask() == nullptr, "mask type is not matched");
return false;
}

assert(vt->isa_vectmask() != nullptr, "expected TypeVectMask on SVE");
switch (opcode) {
case Op_VectorMaskToLong:
case Op_VectorLongToMask:
// These operations lack native SVE predicate instructions and are
// implemented using general vector instructions instead. Use vector
// registers rather than predicate registers to save the mask for
// better performance.
return false;
default:
// By default, the mask operations are implemented with predicate
// instructions with a predicate input/output.
return true;
}
}

// Assert that the given node is not a variable shift.
bool assert_not_var_shift(const Node* n) {
assert(!n->as_ShiftV()->is_var_shift(), "illegal variable shift");
Expand Down Expand Up @@ -6243,31 +6269,44 @@ instruct vmask_tolong_neon(iRegLNoSp dst, vReg src) %{
ins_pipe(pipe_slow);
%}

instruct vmask_tolong_sve(iRegLNoSp dst, pReg src, vReg tmp1, vReg tmp2) %{
predicate(UseSVE > 0);
instruct vmask_tolong_sve(iRegLNoSp dst, vReg src, vReg tmp) %{
predicate(UseSVE > 0 && !VM_Version::supports_svebitperm());
match(Set dst (VectorMaskToLong src));
effect(TEMP tmp);
format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp" %}
ins_encode %{
// Input "src" is a vector of boolean represented as
// bytes with 0x00/0x01 as element values.
__ sve_vmask_tolong($dst$$Register, $src$$FloatRegister,
$tmp$$FloatRegister, Matcher::vector_length(this, $src));
%}
ins_pipe(pipe_slow);
%}

instruct vmask_tolong_sve2(iRegLNoSp dst, vReg src, vReg tmp1, vReg tmp2) %{
predicate(VM_Version::supports_svebitperm());
match(Set dst (VectorMaskToLong src));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp1, $tmp2" %}
format %{ "vmask_tolong_sve2 $dst, $src\t# KILL $tmp1, $tmp2" %}
ins_encode %{
__ sve_vmask_tolong($dst$$Register, $src$$PRegister,
Matcher::vector_element_basic_type(this, $src),
Matcher::vector_length(this, $src),
$tmp1$$FloatRegister, $tmp2$$FloatRegister);
// Input "src" is a vector of boolean represented as
// bytes with 0x00/0x01 as element values.
__ sve2_vmask_tolong($dst$$Register, $src$$FloatRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister,
Matcher::vector_length(this, $src));
%}
ins_pipe(pipe_slow);
%}

// fromlong

instruct vmask_fromlong(pReg dst, iRegL src, vReg tmp1, vReg tmp2) %{
instruct vmask_fromlong(vReg dst, iRegL src, vReg tmp) %{
match(Set dst (VectorLongToMask src));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp1, $tmp2" %}
effect(TEMP_DEF dst, TEMP tmp);
format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp" %}
ins_encode %{
__ sve_vmask_fromlong($dst$$PRegister, $src$$Register,
Matcher::vector_element_basic_type(this),
Matcher::vector_length(this),
$tmp1$$FloatRegister, $tmp2$$FloatRegister);
__ sve_vmask_fromlong($dst$$FloatRegister, $src$$Register,
$tmp$$FloatRegister, Matcher::vector_length(this));
%}
ins_pipe(pipe_slow);
%}
Expand Down
67 changes: 53 additions & 14 deletions src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,32 @@ source %{
return false;
}

bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
// Only SVE supports the predicate feature.
if (UseSVE == 0) {
// On architectures that do not support predicate, masks are stored in
// general vector registers (TypeVect) with sizes ranging from TypeVectA
// to TypeVectX based on the vector size in bytes.
assert(vt->isa_vectmask() == nullptr, "mask type is not matched");
return false;
}

assert(vt->isa_vectmask() != nullptr, "expected TypeVectMask on SVE");
switch (opcode) {
case Op_VectorMaskToLong:
case Op_VectorLongToMask:
// These operations lack native SVE predicate instructions and are
// implemented using general vector instructions instead. Use vector
// registers rather than predicate registers to save the mask for
// better performance.
return false;
default:
// By default, the mask operations are implemented with predicate
// instructions with a predicate input/output.
return true;
}
}

// Assert that the given node is not a variable shift.
bool assert_not_var_shift(const Node* n) {
assert(!n->as_ShiftV()->is_var_shift(), "illegal variable shift");
Expand Down Expand Up @@ -4297,31 +4323,44 @@ instruct vmask_tolong_neon(iRegLNoSp dst, vReg src) %{
ins_pipe(pipe_slow);
%}

instruct vmask_tolong_sve(iRegLNoSp dst, pReg src, vReg tmp1, vReg tmp2) %{
predicate(UseSVE > 0);
instruct vmask_tolong_sve(iRegLNoSp dst, vReg src, vReg tmp) %{
predicate(UseSVE > 0 && !VM_Version::supports_svebitperm());
match(Set dst (VectorMaskToLong src));
effect(TEMP tmp);
format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp" %}
ins_encode %{
// Input "src" is a vector of boolean represented as
// bytes with 0x00/0x01 as element values.
__ sve_vmask_tolong($dst$$Register, $src$$FloatRegister,
$tmp$$FloatRegister, Matcher::vector_length(this, $src));
%}
ins_pipe(pipe_slow);
%}

instruct vmask_tolong_sve2(iRegLNoSp dst, vReg src, vReg tmp1, vReg tmp2) %{
predicate(VM_Version::supports_svebitperm());
match(Set dst (VectorMaskToLong src));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmask_tolong_sve $dst, $src\t# KILL $tmp1, $tmp2" %}
format %{ "vmask_tolong_sve2 $dst, $src\t# KILL $tmp1, $tmp2" %}
ins_encode %{
__ sve_vmask_tolong($dst$$Register, $src$$PRegister,
Matcher::vector_element_basic_type(this, $src),
Matcher::vector_length(this, $src),
$tmp1$$FloatRegister, $tmp2$$FloatRegister);
// Input "src" is a vector of boolean represented as
// bytes with 0x00/0x01 as element values.
__ sve2_vmask_tolong($dst$$Register, $src$$FloatRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister,
Matcher::vector_length(this, $src));
%}
ins_pipe(pipe_slow);
%}

// fromlong

instruct vmask_fromlong(pReg dst, iRegL src, vReg tmp1, vReg tmp2) %{
instruct vmask_fromlong(vReg dst, iRegL src, vReg tmp) %{
match(Set dst (VectorLongToMask src));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp1, $tmp2" %}
effect(TEMP_DEF dst, TEMP tmp);
format %{ "vmask_fromlong $dst, $src\t# vector (sve2). KILL $tmp" %}
ins_encode %{
__ sve_vmask_fromlong($dst$$PRegister, $src$$Register,
Matcher::vector_element_basic_type(this),
Matcher::vector_length(this),
$tmp1$$FloatRegister, $tmp2$$FloatRegister);
__ sve_vmask_fromlong($dst$$FloatRegister, $src$$Register,
$tmp$$FloatRegister, Matcher::vector_length(this));
%}
ins_pipe(pipe_slow);
%}
Expand Down
Loading