Skip to content

Commit

Permalink
8256614: AArch64: Add SVE backend implementation for integer min/max
Browse files Browse the repository at this point in the history
Reviewed-by: adinn
  • Loading branch information
Xiaohong Gong authored and Ningsheng Jian committed Nov 24, 2020
1 parent 372595c commit 67a9590
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 59 deletions.
89 changes: 49 additions & 40 deletions src/hotspot/cpu/aarch64/aarch64_sve.ad
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@ source %{
return vt->element_basic_type();
}

static Assembler::SIMD_RegVariant elemBytes_to_regVariant(int esize) {
switch(esize) {
case 1:
return Assembler::B;
case 2:
return Assembler::H;
case 4:
return Assembler::S;
case 8:
return Assembler::D;
default:
assert(false, "unsupported");
ShouldNotReachHere();
}
return Assembler::INVALID;
}

static Assembler::SIMD_RegVariant elemType_to_regVariant(BasicType bt) {
return elemBytes_to_regVariant(type2aelembytes(bt));
}

typedef void (C2_MacroAssembler::* sve_mem_insn_predicate)(FloatRegister Rt, Assembler::SIMD_RegVariant T,
PRegister Pg, const Address &adr);

Expand Down Expand Up @@ -464,56 +485,44 @@ instruct vdivD(vReg dst_src1, vReg src2) %{
ins_pipe(pipe_slow);
%}

// vector max

instruct vmaxF(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length() >= 4 &&
n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst_src1 (MaxV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "sve_fmax $dst_src1, $dst_src1, $src2\t # vector (sve) (S)" %}
ins_encode %{
__ sve_fmax(as_FloatRegister($dst_src1$$reg), __ S,
ptrue, as_FloatRegister($src2$$reg));
%}
ins_pipe(pipe_slow);
%}

instruct vmaxD(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst_src1 (MaxV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "sve_fmax $dst_src1, $dst_src1, $src2\t # vector (sve) (D)" %}
ins_encode %{
__ sve_fmax(as_FloatRegister($dst_src1$$reg), __ D,
ptrue, as_FloatRegister($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
// vector min/max

instruct vminF(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length() >= 4 &&
n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
instruct vmin(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
match(Set dst_src1 (MinV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "sve_fmin $dst_src1, $dst_src1, $src2\t # vector (sve) (S)" %}
format %{ "sve_min $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
ins_encode %{
__ sve_fmin(as_FloatRegister($dst_src1$$reg), __ S,
ptrue, as_FloatRegister($src2$$reg));
BasicType bt = vector_element_basic_type(this);
Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
if (is_floating_point_type(bt)) {
__ sve_fmin(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
} else {
assert(is_integral_type(bt), "Unsupported type");
__ sve_smin(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
}
%}
ins_pipe(pipe_slow);
%}

instruct vminD(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst_src1 (MinV dst_src1 src2));
instruct vmax(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
match(Set dst_src1 (MaxV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "sve_fmin $dst_src1, $dst_src1, $src2\t # vector (sve) (D)" %}
format %{ "sve_max $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
ins_encode %{
__ sve_fmin(as_FloatRegister($dst_src1$$reg), __ D,
ptrue, as_FloatRegister($src2$$reg));
BasicType bt = vector_element_basic_type(this);
Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
if (is_floating_point_type(bt)) {
__ sve_fmax(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
} else {
assert(is_integral_type(bt), "Unsupported type");
__ sve_smax(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
}
%}
ins_pipe(pipe_slow);
%}
Expand Down
76 changes: 58 additions & 18 deletions src/hotspot/cpu/aarch64/aarch64_sve_ad.m4
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,27 @@ source %{
return vt->element_basic_type();
}

static Assembler::SIMD_RegVariant elemBytes_to_regVariant(int esize) {
switch(esize) {
case 1:
return Assembler::B;
case 2:
return Assembler::H;
case 4:
return Assembler::S;
case 8:
return Assembler::D;
default:
assert(false, "unsupported");
ShouldNotReachHere();
}
return Assembler::INVALID;
}

static Assembler::SIMD_RegVariant elemType_to_regVariant(BasicType bt) {
return elemBytes_to_regVariant(type2aelembytes(bt));
}

typedef void (C2_MacroAssembler::* sve_mem_insn_predicate)(FloatRegister Rt, Assembler::SIMD_RegVariant T,
PRegister Pg, const Address &adr);

Expand Down Expand Up @@ -319,28 +340,47 @@ instruct vdiv$1(vReg dst_src1, vReg src2) %{
VDIVF(F, S, 4)
VDIVF(D, D, 2)

dnl
dnl BINARY_OP_TRUE_PREDICATE_ETYPE($1, $2, $3, $4, $5, $6 )
dnl BINARY_OP_TRUE_PREDICATE_ETYPE(insn_name, op_name, element_type, size, min_vec_len, insn)
define(`BINARY_OP_TRUE_PREDICATE_ETYPE', `
instruct $1(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5 &&
n->bottom_type()->is_vect()->element_basic_type() == $3);
match(Set dst_src1 ($2 dst_src1 src2));
// vector min/max

instruct vmin(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
match(Set dst_src1 (MinV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "$6 $dst_src1, $dst_src1, $src2\t # vector (sve) ($4)" %}
format %{ "sve_min $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
ins_encode %{
__ $6(as_FloatRegister($dst_src1$$reg), __ $4,
ptrue, as_FloatRegister($src2$$reg));
BasicType bt = vector_element_basic_type(this);
Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
if (is_floating_point_type(bt)) {
__ sve_fmin(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
} else {
assert(is_integral_type(bt), "Unsupported type");
__ sve_smin(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
}
%}
ins_pipe(pipe_slow);
%}')dnl
dnl
// vector max
BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxF, MaxV, T_FLOAT, S, 4, sve_fmax)
BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxD, MaxV, T_DOUBLE, D, 2, sve_fmax)
BINARY_OP_TRUE_PREDICATE_ETYPE(vminF, MinV, T_FLOAT, S, 4, sve_fmin)
BINARY_OP_TRUE_PREDICATE_ETYPE(vminD, MinV, T_DOUBLE, D, 2, sve_fmin)
%}

instruct vmax(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
match(Set dst_src1 (MaxV dst_src1 src2));
ins_cost(SVE_COST);
format %{ "sve_max $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
ins_encode %{
BasicType bt = vector_element_basic_type(this);
Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
if (is_floating_point_type(bt)) {
__ sve_fmax(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
} else {
assert(is_integral_type(bt), "Unsupported type");
__ sve_smax(as_FloatRegister($dst_src1$$reg), size,
ptrue, as_FloatRegister($src2$$reg));
}
%}
ins_pipe(pipe_slow);
%}

dnl
dnl VFMLA($1 $2 $3 )
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/assembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,7 @@ class Assembler : public AbstractAssembler {
};

enum SIMD_RegVariant {
B, H, S, D, Q
B, H, S, D, Q, INVALID
};

enum shift_kind { LSL, LSR, ASR, ROR };
Expand Down

1 comment on commit 67a9590

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.