8257165: C2: Improve box elimination for vector masks and shuffles
Reviewed-by: kvn, thartmann
This commit is contained in:
parent
4e55d0f31e
commit
337d7bce03
@ -328,7 +328,7 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc,
|
||||
value = gvn.transform(VectorStoreMaskNode::make(gvn, value, bt, num_elem));
|
||||
// Although type of mask depends on its definition, in terms of storage everything is stored in boolean array.
|
||||
bt = T_BOOLEAN;
|
||||
assert(value->as_Vector()->bottom_type()->is_vect()->element_basic_type() == bt,
|
||||
assert(value->bottom_type()->is_vect()->element_basic_type() == bt,
|
||||
"must be consistent with mask representation");
|
||||
}
|
||||
|
||||
@ -389,7 +389,8 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
|
||||
Node* obj = vec_unbox->obj();
|
||||
const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr();
|
||||
ciInstanceKlass* from_kls = tinst->klass()->as_instance_klass();
|
||||
BasicType bt = vec_unbox->vect_type()->element_basic_type();
|
||||
const TypeVect* vt = vec_unbox->bottom_type()->is_vect();
|
||||
BasicType bt = vt->element_basic_type();
|
||||
BasicType masktype = bt;
|
||||
BasicType elem_bt;
|
||||
|
||||
@ -428,7 +429,6 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
|
||||
|
||||
Node* adr = kit.array_element_address(vec_field_ld, gvn.intcon(0), bt);
|
||||
const TypePtr* adr_type = adr->bottom_type()->is_ptr();
|
||||
const TypeVect* vt = vec_unbox->bottom_type()->is_vect();
|
||||
int num_elem = vt->length();
|
||||
Node* vec_val_load = LoadVectorNode::make(0,
|
||||
ctrl,
|
||||
@ -441,14 +441,13 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
|
||||
|
||||
C->set_max_vector_size(MAX2(C->max_vector_size(), vt->length_in_bytes()));
|
||||
|
||||
if (is_vector_mask(from_kls) && masktype != T_BOOLEAN) {
|
||||
assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect mask type consistency");
|
||||
if (is_vector_mask(from_kls)) {
|
||||
vec_val_load = gvn.transform(new VectorLoadMaskNode(vec_val_load, TypeVect::make(masktype, num_elem)));
|
||||
} else if (is_vector_shuffle(from_kls)) {
|
||||
if (vec_unbox->is_shuffle_to_vector() == false) {
|
||||
assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect shuffle type consistency");
|
||||
vec_val_load = gvn.transform(new VectorLoadShuffleNode(vec_val_load, TypeVect::make(masktype, num_elem)));
|
||||
} else if (elem_bt != T_BYTE) {
|
||||
} else {
|
||||
vec_val_load = gvn.transform(VectorCastNode::make(Op_VectorCastB2X, vec_val_load, elem_bt, num_elem));
|
||||
}
|
||||
}
|
||||
|
@ -1010,6 +1010,24 @@ ReductionNode* ReductionNode::make(int opc, Node *ctrl, Node* n1, Node* n2, Basi
|
||||
}
|
||||
}
|
||||
|
||||
Node* VectorLoadMaskNode::Identity(PhaseGVN* phase) {
|
||||
BasicType out_bt = type()->is_vect()->element_basic_type();
|
||||
if (out_bt == T_BOOLEAN) {
|
||||
return in(1); // redundant conversion
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Node* VectorStoreMaskNode::Identity(PhaseGVN* phase) {
|
||||
// Identity transformation on boolean vectors.
|
||||
// VectorStoreMask (VectorLoadMask bv) elem_size ==> bv
|
||||
// vector[n]{bool} => vector[n]{t} => vector[n]{bool}
|
||||
if (in(1)->Opcode() == Op_VectorLoadMask) {
|
||||
return in(1)->in(1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
VectorStoreMaskNode* VectorStoreMaskNode::make(PhaseGVN& gvn, Node* in, BasicType in_type, uint num_elem) {
|
||||
assert(in->bottom_type()->isa_vect(), "sanity");
|
||||
const TypeVect* vt = TypeVect::make(T_BOOLEAN, num_elem);
|
||||
@ -1046,6 +1064,17 @@ int VectorCastNode::opcode(BasicType bt) {
|
||||
}
|
||||
}
|
||||
|
||||
Node* VectorCastNode::Identity(PhaseGVN* phase) {
|
||||
if (!in(1)->is_top()) {
|
||||
BasicType in_bt = in(1)->bottom_type()->is_vect()->element_basic_type();
|
||||
BasicType out_bt = vect_type()->element_basic_type();
|
||||
if (in_bt == out_bt) {
|
||||
return in(1); // redundant cast
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Node* ReductionNode::make_reduction_input(PhaseGVN& gvn, int opc, BasicType bt) {
|
||||
int vopc = opcode(opc, bt);
|
||||
guarantee(vopc != opc, "Vector reduction for '%s' is not implemented", NodeClassNames[opc]);
|
||||
@ -1219,11 +1248,48 @@ Node* VectorInsertNode::make(Node* vec, Node* new_val, int position) {
|
||||
return new VectorInsertNode(vec, new_val, pos, vec->bottom_type()->is_vect());
|
||||
}
|
||||
|
||||
Node* VectorUnboxNode::Identity(PhaseGVN *phase) {
|
||||
Node* VectorUnboxNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* n = obj()->uncast();
|
||||
if (EnableVectorReboxing && n->Opcode() == Op_VectorBox) {
|
||||
if (Type::cmp(bottom_type(), n->in(VectorBoxNode::Value)->bottom_type()) == 0) {
|
||||
return n->in(VectorBoxNode::Value);
|
||||
// Handled by VectorUnboxNode::Identity()
|
||||
} else {
|
||||
VectorBoxNode* vbox = static_cast<VectorBoxNode*>(n);
|
||||
ciKlass* vbox_klass = vbox->box_type()->klass();
|
||||
const TypeVect* in_vt = vbox->vec_type();
|
||||
const TypeVect* out_vt = type()->is_vect();
|
||||
assert(in_vt->length() == out_vt->length(), "mismatch on number of elements");
|
||||
Node* value = vbox->in(VectorBoxNode::Value);
|
||||
|
||||
bool is_vector_mask = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass());
|
||||
bool is_vector_shuffle = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorShuffle_klass());
|
||||
if (is_vector_mask) {
|
||||
// VectorUnbox (VectorBox vmask) ==> VectorLoadMask (VectorStoreMask vmask)
|
||||
value = phase->transform(VectorStoreMaskNode::make(*phase, value, in_vt->element_basic_type(), in_vt->length()));
|
||||
return new VectorLoadMaskNode(value, out_vt);
|
||||
} else if (is_vector_shuffle) {
|
||||
if (is_shuffle_to_vector()) {
|
||||
// VectorUnbox (VectorBox vshuffle) ==> VectorCastB2X vshuffle
|
||||
return new VectorCastB2XNode(value, out_vt);
|
||||
} else {
|
||||
// VectorUnbox (VectorBox vshuffle) ==> VectorLoadShuffle vshuffle
|
||||
return new VectorLoadShuffleNode(value, out_vt);
|
||||
}
|
||||
} else {
|
||||
assert(false, "type mismatch on vector: %s", vbox_klass->name()->as_utf8());
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node* VectorUnboxNode::Identity(PhaseGVN* phase) {
|
||||
Node* n = obj()->uncast();
|
||||
if (EnableVectorReboxing && n->Opcode() == Op_VectorBox) {
|
||||
if (Type::cmp(bottom_type(), n->in(VectorBoxNode::Value)->bottom_type()) == 0) {
|
||||
return n->in(VectorBoxNode::Value); // VectorUnbox (VectorBox v) ==> v
|
||||
} else {
|
||||
// Handled by VectorUnboxNode::Ideal().
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -1144,13 +1144,8 @@ class VectorTestNode : public Node {
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
|
||||
public:
|
||||
VectorTestNode( Node *in1, Node *in2, BoolTest::mask predicate) : Node(NULL, in1, in2), _predicate(predicate) {
|
||||
assert(in1->is_Vector() || in1->is_LoadVector(), "must be vector");
|
||||
assert(in2->is_Vector() || in2->is_LoadVector(), "must be vector");
|
||||
assert(in1->bottom_type()->is_vect()->element_basic_type() == in2->bottom_type()->is_vect()->element_basic_type(),
|
||||
"same type elements are needed");
|
||||
assert(in1->bottom_type()->is_vect()->length() == in2->bottom_type()->is_vect()->length(),
|
||||
"same number of elements is needed");
|
||||
VectorTestNode(Node* in1, Node* in2, BoolTest::mask predicate) : Node(NULL, in1, in2), _predicate(predicate) {
|
||||
assert(in2->bottom_type()->is_vect() == in2->bottom_type()->is_vect(), "same vector type");
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual uint hash() const { return Node::hash() + _predicate; }
|
||||
@ -1188,37 +1183,34 @@ class VectorRearrangeNode : public VectorNode {
|
||||
Node* vec_shuffle() const { return in(2); }
|
||||
};
|
||||
|
||||
|
||||
class VectorLoadMaskNode : public VectorNode {
|
||||
public:
|
||||
VectorLoadMaskNode(Node* in, const TypeVect* vt)
|
||||
: VectorNode(in, vt) {
|
||||
assert(in->is_LoadVector(), "expected load vector");
|
||||
assert(in->as_LoadVector()->vect_type()->element_basic_type() == T_BOOLEAN, "must be boolean");
|
||||
}
|
||||
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
class VectorLoadShuffleNode : public VectorNode {
|
||||
public:
|
||||
VectorLoadShuffleNode(Node* in, const TypeVect* vt)
|
||||
: VectorNode(in, vt) {
|
||||
assert(in->is_LoadVector(), "expected load vector");
|
||||
assert(in->as_LoadVector()->vect_type()->element_basic_type() == T_BYTE, "must be BYTE");
|
||||
assert(in->bottom_type()->is_vect()->element_basic_type() == T_BYTE, "must be BYTE");
|
||||
}
|
||||
|
||||
int GetOutShuffleSize() const { return type2aelembytes(vect_type()->element_basic_type()); }
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
class VectorLoadMaskNode : public VectorNode {
|
||||
public:
|
||||
VectorLoadMaskNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {
|
||||
assert(in->bottom_type()->is_vect()->element_basic_type() == T_BOOLEAN, "must be boolean");
|
||||
}
|
||||
|
||||
virtual int Opcode() const;
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
};
|
||||
|
||||
class VectorStoreMaskNode : public VectorNode {
|
||||
protected:
|
||||
VectorStoreMaskNode(Node* in1, ConINode* in2, const TypeVect* vt)
|
||||
: VectorNode(in1, in2, vt) { }
|
||||
VectorStoreMaskNode(Node* in1, ConINode* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {}
|
||||
|
||||
public:
|
||||
virtual int Opcode() const;
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
|
||||
static VectorStoreMaskNode* make(PhaseGVN& gvn, Node* in, BasicType in_type, uint num_elem);
|
||||
};
|
||||
@ -1237,7 +1229,7 @@ class VectorReinterpretNode : public VectorNode {
|
||||
virtual bool cmp( const Node &n ) const {
|
||||
return VectorNode::cmp(n) && !Type::cmp(_src_vt,((VectorReinterpretNode&)n)._src_vt);
|
||||
}
|
||||
virtual Node *Identity(PhaseGVN *phase);
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
@ -1250,6 +1242,8 @@ class VectorCastNode : public VectorNode {
|
||||
static VectorCastNode* make(int vopc, Node* n1, BasicType bt, uint vlen);
|
||||
static int opcode(BasicType bt);
|
||||
static bool implemented(BasicType bt, uint vlen);
|
||||
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
};
|
||||
|
||||
class VectorCastB2XNode : public VectorCastNode {
|
||||
@ -1370,7 +1364,8 @@ class VectorUnboxNode : public VectorNode {
|
||||
virtual int Opcode() const;
|
||||
Node* obj() const { return in(2); }
|
||||
Node* mem() const { return in(1); }
|
||||
virtual Node *Identity(PhaseGVN *phase);
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
Node* Ideal(PhaseGVN* phase, bool can_reshape);
|
||||
bool is_shuffle_to_vector() { return _shuffle_to_vector; }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user