Skip to content
Closed
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
100 changes: 98 additions & 2 deletions src/hotspot/cpu/aarch64/aarch64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -2685,12 +2685,55 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
return true;
}

bool can_combine_with_imm(Node* binary_node, Node* replicate_node) {
if (UseSVE == 0 || !VectorNode::is_invariant_vector(replicate_node)){
return false;
}
Node* imm_node = replicate_node->in(1);
if (!imm_node->is_Con()) {
return false;
}

const Type* t = imm_node->bottom_type();
if (!(t->isa_int() || t->isa_long())) {
return false;
Copy link
Contributor

@theRealAph theRealAph Oct 26, 2021

Choose a reason for hiding this comment

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

I'd split this up a bit.

Please consider

if (!imm_node->is_Con()  return false;

const Type t = imm_node->bottom_type();
if (! (t->isa_int() || t->isa_long))  return false;

Copy link
Author

Choose a reason for hiding this comment

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

Done

}

switch (binary_node->Opcode()) {
case Op_AndV:
case Op_OrV:
case Op_XorV: {
Assembler::SIMD_RegVariant T = Assembler::elemType_to_regVariant(Matcher::vector_element_basic_type(binary_node));
uint64_t value = t->isa_long() ? (uint64_t)imm_node->get_long() : (uint64_t)imm_node->get_int();
return Assembler::operand_valid_for_sve_logical_immediate(Assembler::regVariant_to_elemBits(T), value);
}
case Op_AddVB:
return (imm_node->get_int() <= 255 && imm_node->get_int() >= -255);
case Op_AddVS:
case Op_AddVI:
return Assembler::operand_valid_for_sve_add_sub_immediate((int64_t)imm_node->get_int());
case Op_AddVL:
return Assembler::operand_valid_for_sve_add_sub_immediate(imm_node->get_long());
default:
return false;
}
}

bool is_vector_arith_imm_pattern(Node* n, Node* m) {
if (n != NULL && m != NULL) {
return can_combine_with_imm(n, m);
}
return false;
}

// Should the matcher clone input 'm' of node 'n'?
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
// ShiftV src (ShiftCntV con)
// StoreVector (VectorStoreMask src)
// Binary src (Replicate con)
if (is_vshift_con_pattern(n, m) ||
(UseSVE > 0 && m->Opcode() == Op_VectorStoreMask && n->Opcode() == Op_StoreVector)) {
(UseSVE > 0 && m->Opcode() == Op_VectorStoreMask && n->Opcode() == Op_StoreVector) ||
is_vector_arith_imm_pattern(n, m)) {
mstack.push(m, Visit);
return true;
}
Expand Down Expand Up @@ -4611,6 +4654,17 @@ operand immL8_shift8()
interface(CONST_INTER);
%}

// 8 bit integer valid for vector add sub immediate
operand immBAddSubV()
%{
predicate(n->get_int() <= 255 && n->get_int() >= -255);
match(ConI);

op_cost(0);
format %{ %}
interface(CONST_INTER);
%}

// 32 bit integer valid for add sub immediate
operand immIAddSub()
%{
Expand All @@ -4621,8 +4675,39 @@ operand immIAddSub()
interface(CONST_INTER);
%}

// 32 bit integer valid for vector add sub immediate
operand immIAddSubV()
%{
predicate(Assembler::operand_valid_for_sve_add_sub_immediate((int64_t)n->get_int()));
match(ConI);

op_cost(0);
format %{ %}
interface(CONST_INTER);
%}

// 32 bit unsigned integer valid for logical immediate
// TODO -- check this is right when e.g the mask is 0x80000000

operand immBLog()
%{
predicate(Assembler::operand_valid_for_sve_logical_immediate(BitsPerByte, (uint64_t)n->get_int()));
match(ConI);

op_cost(0);
format %{ %}
interface(CONST_INTER);
%}

operand immSLog()
%{
predicate(Assembler::operand_valid_for_sve_logical_immediate(BitsPerShort, (uint64_t)n->get_int()));
match(ConI);

op_cost(0);
format %{ %}
interface(CONST_INTER);
%}

operand immILog()
%{
predicate(Assembler::operand_valid_for_logical_immediate(/*is32*/true, (uint64_t)n->get_int()));
Expand Down Expand Up @@ -4700,6 +4785,17 @@ operand immLAddSub()
interface(CONST_INTER);
%}

// 64 bit integer valid for addv subv immediate
operand immLAddSubV()
%{
predicate(Assembler::operand_valid_for_sve_add_sub_immediate(n->get_long()));
match(ConL);

op_cost(0);
format %{ %}
interface(CONST_INTER);
%}

// 64 bit integer valid for logical immediate
operand immLLog()
%{
Expand Down
211 changes: 211 additions & 0 deletions src/hotspot/cpu/aarch64/aarch64_sve.ad
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,217 @@ instruct vaddD_masked(vReg dst_src1, vReg src2, pRegGov pg) %{
ins_pipe(pipe_slow);
%}

// vector add reg imm (unpredicated)

instruct vaddImmB(vReg dst_src, immBAddSubV con) %{
predicate(UseSVE > 0);
match(Set dst_src (AddVB dst_src (ReplicateB con)));
ins_cost(SVE_COST);
format %{ "sve_add $dst_src, $dst_src, $con\t # vector (sve) (B)" %}
ins_encode %{
int32_t val = $con$$constant;
if (val > 0){
__ sve_add(as_FloatRegister($dst_src$$reg), __ B, val);
} else if (val < 0){
__ sve_sub(as_FloatRegister($dst_src$$reg), __ B, -val);
}
%}
ins_pipe(pipe_slow);
%}

instruct vaddImmS(vReg dst_src, immIAddSubV con) %{
predicate(UseSVE > 0);
match(Set dst_src (AddVS dst_src (ReplicateS con)));
ins_cost(SVE_COST);
format %{ "sve_add $dst_src, $dst_src, $con\t # vector (sve) (H)" %}
ins_encode %{
int32_t val = $con$$constant;
if (val > 0){
__ sve_add(as_FloatRegister($dst_src$$reg), __ H, val);
} else if (val < 0){
__ sve_sub(as_FloatRegister($dst_src$$reg), __ H, -val);
}
%}
ins_pipe(pipe_slow);
%}

instruct vaddImmI(vReg dst_src, immIAddSubV con) %{
predicate(UseSVE > 0);
match(Set dst_src (AddVI dst_src (ReplicateI con)));
ins_cost(SVE_COST);
format %{ "sve_add $dst_src, $dst_src, $con\t # vector (sve) (S)" %}
ins_encode %{
int32_t val = $con$$constant;
if (val > 0){
__ sve_add(as_FloatRegister($dst_src$$reg), __ S, val);
} else if (val < 0){
__ sve_sub(as_FloatRegister($dst_src$$reg), __ S, -val);
}
%}
ins_pipe(pipe_slow);
%}

instruct vaddImmL(vReg dst_src, immLAddSubV con) %{
predicate(UseSVE > 0);
match(Set dst_src (AddVL dst_src (ReplicateL con)));
ins_cost(SVE_COST);
format %{ "sve_add $dst_src, $dst_src, $con\t # vector (sve) (D)" %}
ins_encode %{
int32_t val = $con$$constant;
if (val > 0){
__ sve_add(as_FloatRegister($dst_src$$reg), __ D, val);
} else if (val < 0){
__ sve_sub(as_FloatRegister($dst_src$$reg), __ D, -val);
}
%}
ins_pipe(pipe_slow);
%}

// vector binary op reg imm (unpredicated)

instruct vandB(vReg dst_src, immBLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (AndV dst_src (ReplicateB con)));
ins_cost(SVE_COST);
format %{ "sve_and $dst_src, $dst_src, $con\t # vector (sve) (B)" %}
ins_encode %{
__ sve_and(as_FloatRegister($dst_src$$reg), __ B,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vandH(vReg dst_src, immSLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (AndV dst_src (ReplicateS con)));
ins_cost(SVE_COST);
format %{ "sve_and $dst_src, $dst_src, $con\t # vector (sve) (H)" %}
ins_encode %{
__ sve_and(as_FloatRegister($dst_src$$reg), __ H,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vandS(vReg dst_src, immILog con) %{
predicate(UseSVE > 0);
match(Set dst_src (AndV dst_src (ReplicateI con)));
ins_cost(SVE_COST);
format %{ "sve_and $dst_src, $dst_src, $con\t # vector (sve) (S)" %}
ins_encode %{
__ sve_and(as_FloatRegister($dst_src$$reg), __ S,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vandD(vReg dst_src, immLLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (AndV dst_src (ReplicateL con)));
ins_cost(SVE_COST);
format %{ "sve_and $dst_src, $dst_src, $con\t # vector (sve) (D)" %}
ins_encode %{
__ sve_and(as_FloatRegister($dst_src$$reg), __ D,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vorB(vReg dst_src, immBLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (OrV dst_src (ReplicateB con)));
ins_cost(SVE_COST);
format %{ "sve_orr $dst_src, $dst_src, $con\t # vector (sve) (B)" %}
ins_encode %{
__ sve_orr(as_FloatRegister($dst_src$$reg), __ B,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vorH(vReg dst_src, immSLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (OrV dst_src (ReplicateS con)));
ins_cost(SVE_COST);
format %{ "sve_orr $dst_src, $dst_src, $con\t # vector (sve) (H)" %}
ins_encode %{
__ sve_orr(as_FloatRegister($dst_src$$reg), __ H,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vorS(vReg dst_src, immILog con) %{
predicate(UseSVE > 0);
match(Set dst_src (OrV dst_src (ReplicateI con)));
ins_cost(SVE_COST);
format %{ "sve_orr $dst_src, $dst_src, $con\t # vector (sve) (S)" %}
ins_encode %{
__ sve_orr(as_FloatRegister($dst_src$$reg), __ S,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vorD(vReg dst_src, immLLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (OrV dst_src (ReplicateL con)));
ins_cost(SVE_COST);
format %{ "sve_orr $dst_src, $dst_src, $con\t # vector (sve) (D)" %}
ins_encode %{
__ sve_orr(as_FloatRegister($dst_src$$reg), __ D,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vxorB(vReg dst_src, immBLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (XorV dst_src (ReplicateB con)));
ins_cost(SVE_COST);
format %{ "sve_eor $dst_src, $dst_src, $con\t # vector (sve) (B)" %}
ins_encode %{
__ sve_eor(as_FloatRegister($dst_src$$reg), __ B,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vxorH(vReg dst_src, immSLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (XorV dst_src (ReplicateS con)));
ins_cost(SVE_COST);
format %{ "sve_eor $dst_src, $dst_src, $con\t # vector (sve) (H)" %}
ins_encode %{
__ sve_eor(as_FloatRegister($dst_src$$reg), __ H,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vxorS(vReg dst_src, immILog con) %{
predicate(UseSVE > 0);
match(Set dst_src (XorV dst_src (ReplicateI con)));
ins_cost(SVE_COST);
format %{ "sve_eor $dst_src, $dst_src, $con\t # vector (sve) (S)" %}
ins_encode %{
__ sve_eor(as_FloatRegister($dst_src$$reg), __ S,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}

instruct vxorD(vReg dst_src, immLLog con) %{
predicate(UseSVE > 0);
match(Set dst_src (XorV dst_src (ReplicateL con)));
ins_cost(SVE_COST);
format %{ "sve_eor $dst_src, $dst_src, $con\t # vector (sve) (D)" %}
ins_encode %{
__ sve_eor(as_FloatRegister($dst_src$$reg), __ D,
(uint64_t)($con$$constant));
%}
ins_pipe(pipe_slow);
%}
// vector and

instruct vand(vReg dst, vReg src1, vReg src2) %{
Expand Down
Loading