8257165: C2: Improve box elimination for vector masks and shuffles

Reviewed-by: kvn, thartmann
This commit is contained in:
Vladimir Ivanov 2020-11-30 10:36:38 +00:00
parent 4e55d0f31e
commit 337d7bce03
3 changed files with 93 additions and 33 deletions

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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; }
};