8214922: Add vectorization support for fmin/fmax

Reviewed-by: adinn, roland
This commit is contained in:
Pengfei Li 2019-03-07 02:39:06 +00:00
parent 144d81caf6
commit 1dc7271eca
8 changed files with 309 additions and 0 deletions

View file

@ -15660,6 +15660,98 @@ instruct reduce_mul2D(vRegD dst, vRegD src1, vecX src2, vecX tmp)
ins_pipe(pipe_class_default); ins_pipe(pipe_class_default);
%} %}
instruct reduce_max2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MaxReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst, TEMP tmp);
format %{ "fmaxs $dst, $src1, $src2\n\t"
"ins $tmp, S, $src2, 0, 1\n\t"
"fmaxs $dst, $dst, $tmp\t max reduction2F" %}
ins_encode %{
__ fmaxs(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
__ ins(as_FloatRegister($tmp$$reg), __ S, as_FloatRegister($src2$$reg), 0, 1);
__ fmaxs(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
%}
ins_pipe(pipe_class_default);
%}
instruct reduce_max4F(vRegF dst, vRegF src1, vecX src2) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MaxReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst);
format %{ "fmaxv $dst, T4S, $src2\n\t"
"fmaxs $dst, $dst, $src1\t max reduction4F" %}
ins_encode %{
__ fmaxv(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src2$$reg));
__ fmaxs(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
%}
ins_pipe(pipe_class_default);
%}
instruct reduce_max2D(vRegD dst, vRegD src1, vecX src2, vecX tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst (MaxReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst, TEMP tmp);
format %{ "fmaxd $dst, $src1, $src2\n\t"
"ins $tmp, D, $src2, 0, 1\n\t"
"fmaxd $dst, $dst, $tmp\t max reduction2D" %}
ins_encode %{
__ fmaxd(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
__ ins(as_FloatRegister($tmp$$reg), __ D, as_FloatRegister($src2$$reg), 0, 1);
__ fmaxd(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
%}
ins_pipe(pipe_class_default);
%}
instruct reduce_min2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MinReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst, TEMP tmp);
format %{ "fmins $dst, $src1, $src2\n\t"
"ins $tmp, S, $src2, 0, 1\n\t"
"fmins $dst, $dst, $tmp\t min reduction2F" %}
ins_encode %{
__ fmins(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
__ ins(as_FloatRegister($tmp$$reg), __ S, as_FloatRegister($src2$$reg), 0, 1);
__ fmins(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
%}
ins_pipe(pipe_class_default);
%}
instruct reduce_min4F(vRegF dst, vRegF src1, vecX src2) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MinReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst);
format %{ "fminv $dst, T4S, $src2\n\t"
"fmins $dst, $dst, $src1\t min reduction4F" %}
ins_encode %{
__ fminv(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src2$$reg));
__ fmins(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
%}
ins_pipe(pipe_class_default);
%}
instruct reduce_min2D(vRegD dst, vRegD src1, vecX src2, vecX tmp) %{
predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst (MinReductionV src1 src2));
ins_cost(INSN_COST);
effect(TEMP_DEF dst, TEMP tmp);
format %{ "fmind $dst, $src1, $src2\n\t"
"ins $tmp, D, $src2, 0, 1\n\t"
"fmind $dst, $dst, $tmp\t min reduction2D" %}
ins_encode %{
__ fmind(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
__ ins(as_FloatRegister($tmp$$reg), __ D, as_FloatRegister($src2$$reg), 0, 1);
__ fmind(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
%}
ins_pipe(pipe_class_default);
%}
// ====================VECTOR ARITHMETIC======================================= // ====================VECTOR ARITHMETIC=======================================
// --------------------------------- ADD -------------------------------------- // --------------------------------- ADD --------------------------------------
@ -17198,6 +17290,90 @@ instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{
ins_pipe(vshift128_imm); ins_pipe(vshift128_imm);
%} %}
instruct vmax2F(vecD dst, vecD src1, vecD src2)
%{
predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MaxV src1 src2));
ins_cost(INSN_COST);
format %{ "fmax $dst,$src1,$src2\t# vector (2F)" %}
ins_encode %{
__ fmax(as_FloatRegister($dst$$reg), __ T2S,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp64);
%}
instruct vmax4F(vecX dst, vecX src1, vecX src2)
%{
predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MaxV src1 src2));
ins_cost(INSN_COST);
format %{ "fmax $dst,$src1,$src2\t# vector (4S)" %}
ins_encode %{
__ fmax(as_FloatRegister($dst$$reg), __ T4S,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp128);
%}
instruct vmax2D(vecX dst, vecX src1, vecX src2)
%{
predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst (MaxV src1 src2));
ins_cost(INSN_COST);
format %{ "fmax $dst,$src1,$src2\t# vector (2D)" %}
ins_encode %{
__ fmax(as_FloatRegister($dst$$reg), __ T2D,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp128);
%}
instruct vmin2F(vecD dst, vecD src1, vecD src2)
%{
predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MinV src1 src2));
ins_cost(INSN_COST);
format %{ "fmin $dst,$src1,$src2\t# vector (2F)" %}
ins_encode %{
__ fmin(as_FloatRegister($dst$$reg), __ T2S,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp64);
%}
instruct vmin4F(vecX dst, vecX src1, vecX src2)
%{
predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
match(Set dst (MinV src1 src2));
ins_cost(INSN_COST);
format %{ "fmin $dst,$src1,$src2\t# vector (4S)" %}
ins_encode %{
__ fmin(as_FloatRegister($dst$$reg), __ T4S,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp128);
%}
instruct vmin2D(vecX dst, vecX src1, vecX src2)
%{
predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
match(Set dst (MinV src1 src2));
ins_cost(INSN_COST);
format %{ "fmin $dst,$src1,$src2\t# vector (2D)" %}
ins_encode %{
__ fmin(as_FloatRegister($dst$$reg), __ T2D,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vdop_fp128);
%}
//----------PEEPHOLE RULES----------------------------------------------------- //----------PEEPHOLE RULES-----------------------------------------------------
// These must follow all instruction definitions as they use the names // These must follow all instruction definitions as they use the names
// defined in the instructions definitions. // defined in the instructions definitions.

View file

@ -2240,6 +2240,19 @@ public:
#undef INSN #undef INSN
#define INSN(NAME, opc) \
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
starti; \
assert(T == T4S, "arrangement must be T4S"); \
f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24), f(opc, 23), \
f(T == T4S ? 0 : 1, 22), f(0b110000111110, 21, 10); rf(Vn, 5), rf(Vd, 0); \
}
INSN(fmaxv, 0);
INSN(fminv, 1);
#undef INSN
#define INSN(NAME, op0, cmode0) \ #define INSN(NAME, op0, cmode0) \
void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) { \ void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) { \
unsigned cmode = cmode0; \ unsigned cmode = cmode0; \
@ -2281,6 +2294,8 @@ public:
INSN(fsub, 0, 1, 0b110101); INSN(fsub, 0, 1, 0b110101);
INSN(fmla, 0, 0, 0b110011); INSN(fmla, 0, 0, 0b110011);
INSN(fmls, 0, 1, 0b110011); INSN(fmls, 0, 1, 0b110011);
INSN(fmax, 0, 0, 0b111101);
INSN(fmin, 0, 1, 0b111101);
#undef INSN #undef INSN

View file

@ -3802,6 +3802,7 @@ void MatchNode::count_commutative_op(int& count) {
"AndI","AndL", "AndI","AndL",
"AndV", "AndV",
"MaxI","MinI","MaxF","MinF","MaxD","MinD", "MaxI","MinI","MaxF","MinF","MaxD","MinD",
"MaxV", "MinV",
"MulI","MulL","MulF","MulD", "MulI","MulL","MulF","MulD",
"MulVS","MulVI","MulVL","MulVF","MulVD", "MulVS","MulVI","MulVL","MulVF","MulVD",
"OrI","OrL", "OrI","OrL",
@ -4177,6 +4178,7 @@ bool MatchRule::is_vector() const {
"NegVF","NegVD", "NegVF","NegVD",
"SqrtVD","SqrtVF", "SqrtVD","SqrtVF",
"AndV" ,"XorV" ,"OrV", "AndV" ,"XorV" ,"OrV",
"MaxV", "MinV",
"AddReductionVI", "AddReductionVL", "AddReductionVI", "AddReductionVL",
"AddReductionVF", "AddReductionVD", "AddReductionVF", "AddReductionVD",
"MulReductionVI", "MulReductionVL", "MulReductionVI", "MulReductionVL",
@ -4186,6 +4188,7 @@ bool MatchRule::is_vector() const {
"LShiftVB","LShiftVS","LShiftVI","LShiftVL", "LShiftVB","LShiftVS","LShiftVI","LShiftVL",
"RShiftVB","RShiftVS","RShiftVI","RShiftVL", "RShiftVB","RShiftVS","RShiftVI","RShiftVL",
"URShiftVB","URShiftVS","URShiftVI","URShiftVL", "URShiftVB","URShiftVS","URShiftVI","URShiftVL",
"MaxReductionV", "MinReductionV",
"ReplicateB","ReplicateS","ReplicateI","ReplicateL","ReplicateF","ReplicateD", "ReplicateB","ReplicateS","ReplicateI","ReplicateL","ReplicateF","ReplicateD",
"LoadVector","StoreVector", "LoadVector","StoreVector",
"FmaVD", "FmaVF","PopCountVI", "FmaVD", "FmaVF","PopCountVI",

View file

@ -374,6 +374,10 @@ macro(URShiftVL)
macro(AndV) macro(AndV)
macro(OrV) macro(OrV)
macro(XorV) macro(XorV)
macro(MinV)
macro(MaxV)
macro(MinReductionV)
macro(MaxReductionV)
macro(LoadVector) macro(LoadVector)
macro(StoreVector) macro(StoreVector)
macro(Pack) macro(Pack)

View file

@ -3349,6 +3349,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
case Op_MulReductionVL: case Op_MulReductionVL:
case Op_MulReductionVF: case Op_MulReductionVF:
case Op_MulReductionVD: case Op_MulReductionVD:
case Op_MinReductionV:
case Op_MaxReductionV:
break; break;
case Op_PackB: case Op_PackB:

View file

@ -178,6 +178,18 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case Op_XorI: case Op_XorI:
case Op_XorL: case Op_XorL:
return Op_XorV; return Op_XorV;
case Op_MinF:
assert(bt == T_FLOAT, "must be");
return Op_MinV;
case Op_MinD:
assert(bt == T_DOUBLE, "must be");
return Op_MinV;
case Op_MaxF:
assert(bt == T_FLOAT, "must be");
return Op_MaxV;
case Op_MaxD:
assert(bt == T_DOUBLE, "must be");
return Op_MaxV;
case Op_LoadB: case Op_LoadB:
case Op_LoadUB: case Op_LoadUB:
@ -377,6 +389,9 @@ VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType b
case Op_OrV: return new OrVNode (n1, n2, vt); case Op_OrV: return new OrVNode (n1, n2, vt);
case Op_XorV: return new XorVNode(n1, n2, vt); case Op_XorV: return new XorVNode(n1, n2, vt);
case Op_MinV: return new MinVNode(n1, n2, vt);
case Op_MaxV: return new MaxVNode(n1, n2, vt);
case Op_MulAddVS2VI: return new MulAddVS2VINode(n1, n2, vt); case Op_MulAddVS2VI: return new MulAddVS2VINode(n1, n2, vt);
default: default:
fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); fatal("Missed vector creation for '%s'", NodeClassNames[vopc]);
@ -582,6 +597,22 @@ int ReductionNode::opcode(int opc, BasicType bt) {
assert(bt == T_DOUBLE, "must be"); assert(bt == T_DOUBLE, "must be");
vopc = Op_MulReductionVD; vopc = Op_MulReductionVD;
break; break;
case Op_MinF:
assert(bt == T_FLOAT, "must be");
vopc = Op_MinReductionV;
break;
case Op_MinD:
assert(bt == T_DOUBLE, "must be");
vopc = Op_MinReductionV;
break;
case Op_MaxF:
assert(bt == T_FLOAT, "must be");
vopc = Op_MaxReductionV;
break;
case Op_MaxD:
assert(bt == T_DOUBLE, "must be");
vopc = Op_MaxReductionV;
break;
// TODO: add MulL for targets that support it // TODO: add MulL for targets that support it
default: default:
break; break;
@ -606,6 +637,8 @@ ReductionNode* ReductionNode::make(int opc, Node *ctrl, Node* n1, Node* n2, Basi
case Op_MulReductionVL: return new MulReductionVLNode(ctrl, n1, n2); case Op_MulReductionVL: return new MulReductionVLNode(ctrl, n1, n2);
case Op_MulReductionVF: return new MulReductionVFNode(ctrl, n1, n2); case Op_MulReductionVF: return new MulReductionVFNode(ctrl, n1, n2);
case Op_MulReductionVD: return new MulReductionVDNode(ctrl, n1, n2); case Op_MulReductionVD: return new MulReductionVDNode(ctrl, n1, n2);
case Op_MinReductionV: return new MinReductionVNode(ctrl, n1, n2);
case Op_MaxReductionV: return new MaxReductionVNode(ctrl, n1, n2);
default: default:
fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); fatal("Missed vector creation for '%s'", NodeClassNames[vopc]);
return NULL; return NULL;

View file

@ -555,6 +555,78 @@ class XorVNode : public VectorNode {
virtual int Opcode() const; virtual int Opcode() const;
}; };
//------------------------------MinVNode--------------------------------------
// Vector min
class MinVNode : public VectorNode {
public:
MinVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {}
virtual int Opcode() const;
};
//------------------------------MaxVNode--------------------------------------
// Vector max
class MaxVNode : public VectorNode {
public:
MaxVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {}
virtual int Opcode() const;
};
//------------------------------MinReductionVNode--------------------------------------
// Vector min as a reduction
class MinReductionVNode : public ReductionNode {
public:
MinReductionVNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {}
virtual int Opcode() const;
virtual const Type* bottom_type() const {
BasicType bt = in(1)->bottom_type()->basic_type();
if (bt == T_FLOAT) {
return Type::FLOAT;
} else if (bt == T_DOUBLE) {
return Type::DOUBLE;
}
assert(false, "unsupported basic type");
return NULL;
}
virtual uint ideal_reg() const {
BasicType bt = in(1)->bottom_type()->basic_type();
if (bt == T_FLOAT) {
return Op_RegF;
} else if (bt == T_DOUBLE) {
return Op_RegD;
}
assert(false, "unsupported basic type");
return 0;
}
};
//------------------------------MaxReductionVNode--------------------------------------
// Vector max as a reduction
class MaxReductionVNode : public ReductionNode {
public:
MaxReductionVNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {}
virtual int Opcode() const;
virtual const Type* bottom_type() const {
BasicType bt = in(1)->bottom_type()->basic_type();
if (bt == T_FLOAT) {
return Type::FLOAT;
} else {
return Type::DOUBLE;
}
assert(false, "unsupported basic type");
return NULL;
}
virtual uint ideal_reg() const {
BasicType bt = in(1)->bottom_type()->basic_type();
if (bt == T_FLOAT) {
return Op_RegF;
} else {
return Op_RegD;
}
assert(false, "unsupported basic type");
return 0;
}
};
//================================= M E M O R Y =============================== //================================= M E M O R Y ===============================
//------------------------------LoadVectorNode--------------------------------- //------------------------------LoadVectorNode---------------------------------

View file

@ -1808,6 +1808,10 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
declare_c2_type(AndVNode, VectorNode) \ declare_c2_type(AndVNode, VectorNode) \
declare_c2_type(OrVNode, VectorNode) \ declare_c2_type(OrVNode, VectorNode) \
declare_c2_type(XorVNode, VectorNode) \ declare_c2_type(XorVNode, VectorNode) \
declare_c2_type(MaxVNode, VectorNode) \
declare_c2_type(MinVNode, VectorNode) \
declare_c2_type(MaxReductionVNode, ReductionNode) \
declare_c2_type(MinReductionVNode, ReductionNode) \
declare_c2_type(LoadVectorNode, LoadNode) \ declare_c2_type(LoadVectorNode, LoadNode) \
declare_c2_type(StoreVectorNode, StoreNode) \ declare_c2_type(StoreVectorNode, StoreNode) \
declare_c2_type(ReplicateBNode, VectorNode) \ declare_c2_type(ReplicateBNode, VectorNode) \