8341784: Refactor TypeVect to use a BasicType instead of a const Type*

Reviewed-by: kvn, jkarthikeyan
This commit is contained in:
Quan Anh Mai 2024-10-11 15:28:15 +00:00
parent 6133866150
commit 7276a1bec0
18 changed files with 131 additions and 205 deletions

View File

@ -2307,10 +2307,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return &_PR_REG_mask;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return new TypeVectMask(elemTy, length);
}
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return false;

View File

@ -1003,10 +1003,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return nullptr;
}
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return false;

View File

@ -2154,10 +2154,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return nullptr;
}
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return false;

View File

@ -1966,10 +1966,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return &_VMASK_REG_mask;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return new TypeVectMask(elemTy, length);
}
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return EnableVectorSupport && UseVectorStubs;

View File

@ -1477,10 +1477,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return nullptr;
}
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return false;

View File

@ -2231,10 +2231,6 @@ const RegMask* Matcher::predicate_reg_mask(void) {
return &_VECTMASK_REG_mask;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
return new TypeVectMask(elemTy, length);
}
// Max vector size in bytes. 0 if not supported.
int Matcher::vector_width_in_bytes(BasicType bt) {
assert(is_java_primitive(bt), "only primitive type vectors");

View File

@ -4548,7 +4548,6 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) {
const TypeVect* vec_t = last_ur->vect_type();
uint vector_length = vec_t->length();
BasicType bt = vec_t->element_basic_type();
const Type* bt_t = Type::get_const_basic_type(bt);
// Convert opcode from vector-reduction -> scalar -> normal-vector-op
const int sopc = VectorNode::scalar_opcode(last_ur->Opcode(), bt);
@ -4628,7 +4627,7 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) {
Node* identity_scalar = ReductionNode::make_identity_con_scalar(_igvn, sopc, bt);
set_ctrl(identity_scalar, C->root());
VectorNode* identity_vector = VectorNode::scalar2vector(identity_scalar, vector_length, bt_t);
VectorNode* identity_vector = VectorNode::scalar2vector(identity_scalar, vector_length, bt);
register_new_node(identity_vector, C->root());
assert(vec_t == identity_vector->vect_type(), "matching vector type");
VectorNode::trace_new_vector(identity_vector, "Unordered Reduction");

View File

@ -342,7 +342,6 @@ public:
static bool vector_needs_partial_operations(Node* node, const TypeVect* vt);
static const RegMask* predicate_reg_mask(void);
static const TypeVectMask* predicate_reg_type(const Type* elemTy, int length);
// Vector width in bytes
static int vector_width_in_bytes(BasicType bt);

View File

@ -228,8 +228,8 @@ VTransformNode* SuperWordVTransformBuilder::get_or_make_vtnode_vector_input_at_i
return shift_count;
} else {
// Replicate the scalar same_input to every vector element.
const Type* element_type = _vloop_analyzer.types().velt_type(p0);
if (index == 2 && VectorNode::is_scalar_rotate(p0) && element_type->isa_long()) {
BasicType element_type = _vloop_analyzer.types().velt_basic_type(p0);
if (index == 2 && VectorNode::is_scalar_rotate(p0) && element_type == T_LONG) {
// Scalar rotate has int rotation value, but the scalar rotate expects longs.
assert(same_input->bottom_type()->isa_int(), "scalar rotate expects int rotation");
VTransformNode* conv = new (_vtransform.arena()) VTransformConvI2LNode(_vtransform);

View File

@ -679,7 +679,7 @@ void Type::Initialize_shared(Compile* current) {
// get_zero_type() should not happen for T_CONFLICT
_zero_type[T_CONFLICT]= nullptr;
TypeVect::VECTMASK = (TypeVect*)(new TypeVectMask(TypeInt::BOOL, MaxVectorSize))->hashcons();
TypeVect::VECTMASK = (TypeVect*)(new TypeVectMask(T_BOOLEAN, MaxVectorSize))->hashcons();
mreg2type[Op_RegVectMask] = TypeVect::VECTMASK;
if (Matcher::supports_scalable_vector()) {
@ -687,20 +687,20 @@ void Type::Initialize_shared(Compile* current) {
}
// Vector predefined types, it needs initialized _const_basic_type[].
if (Matcher::vector_size_supported(T_BYTE,4)) {
TypeVect::VECTS = TypeVect::make(T_BYTE,4);
if (Matcher::vector_size_supported(T_BYTE, 4)) {
TypeVect::VECTS = TypeVect::make(T_BYTE, 4);
}
if (Matcher::vector_size_supported(T_FLOAT,2)) {
TypeVect::VECTD = TypeVect::make(T_FLOAT,2);
if (Matcher::vector_size_supported(T_FLOAT, 2)) {
TypeVect::VECTD = TypeVect::make(T_FLOAT, 2);
}
if (Matcher::vector_size_supported(T_FLOAT,4)) {
TypeVect::VECTX = TypeVect::make(T_FLOAT,4);
if (Matcher::vector_size_supported(T_FLOAT, 4)) {
TypeVect::VECTX = TypeVect::make(T_FLOAT, 4);
}
if (Matcher::vector_size_supported(T_FLOAT,8)) {
TypeVect::VECTY = TypeVect::make(T_FLOAT,8);
if (Matcher::vector_size_supported(T_FLOAT, 8)) {
TypeVect::VECTY = TypeVect::make(T_FLOAT, 8);
}
if (Matcher::vector_size_supported(T_FLOAT,16)) {
TypeVect::VECTZ = TypeVect::make(T_FLOAT,16);
if (Matcher::vector_size_supported(T_FLOAT, 16)) {
TypeVect::VECTZ = TypeVect::make(T_FLOAT, 16);
}
mreg2type[Op_VecA] = TypeVect::VECTA;
@ -2482,58 +2482,59 @@ bool TypeAry::ary_must_be_exact() const {
//==============================TypeVect=======================================
// Convenience common pre-built types.
const TypeVect *TypeVect::VECTA = nullptr; // vector length agnostic
const TypeVect *TypeVect::VECTS = nullptr; // 32-bit vectors
const TypeVect *TypeVect::VECTD = nullptr; // 64-bit vectors
const TypeVect *TypeVect::VECTX = nullptr; // 128-bit vectors
const TypeVect *TypeVect::VECTY = nullptr; // 256-bit vectors
const TypeVect *TypeVect::VECTZ = nullptr; // 512-bit vectors
const TypeVect *TypeVect::VECTMASK = nullptr; // predicate/mask vector
const TypeVect* TypeVect::VECTA = nullptr; // vector length agnostic
const TypeVect* TypeVect::VECTS = nullptr; // 32-bit vectors
const TypeVect* TypeVect::VECTD = nullptr; // 64-bit vectors
const TypeVect* TypeVect::VECTX = nullptr; // 128-bit vectors
const TypeVect* TypeVect::VECTY = nullptr; // 256-bit vectors
const TypeVect* TypeVect::VECTZ = nullptr; // 512-bit vectors
const TypeVect* TypeVect::VECTMASK = nullptr; // predicate/mask vector
//------------------------------make-------------------------------------------
const TypeVect* TypeVect::make(const Type *elem, uint length, bool is_mask) {
const TypeVect* TypeVect::make(BasicType elem_bt, uint length, bool is_mask) {
if (is_mask) {
return makemask(elem, length);
return makemask(elem_bt, length);
}
BasicType elem_bt = elem->array_element_basic_type();
assert(is_java_primitive(elem_bt), "only primitive types in vector");
assert(Matcher::vector_size_supported(elem_bt, length), "length in range");
int size = length * type2aelembytes(elem_bt);
switch (Matcher::vector_ideal_reg(size)) {
case Op_VecA:
return (TypeVect*)(new TypeVectA(elem, length))->hashcons();
return (TypeVect*)(new TypeVectA(elem_bt, length))->hashcons();
case Op_VecS:
return (TypeVect*)(new TypeVectS(elem, length))->hashcons();
return (TypeVect*)(new TypeVectS(elem_bt, length))->hashcons();
case Op_RegL:
case Op_VecD:
case Op_RegD:
return (TypeVect*)(new TypeVectD(elem, length))->hashcons();
return (TypeVect*)(new TypeVectD(elem_bt, length))->hashcons();
case Op_VecX:
return (TypeVect*)(new TypeVectX(elem, length))->hashcons();
return (TypeVect*)(new TypeVectX(elem_bt, length))->hashcons();
case Op_VecY:
return (TypeVect*)(new TypeVectY(elem, length))->hashcons();
return (TypeVect*)(new TypeVectY(elem_bt, length))->hashcons();
case Op_VecZ:
return (TypeVect*)(new TypeVectZ(elem, length))->hashcons();
return (TypeVect*)(new TypeVectZ(elem_bt, length))->hashcons();
}
ShouldNotReachHere();
return nullptr;
}
const TypeVect *TypeVect::makemask(const Type* elem, uint length) {
BasicType elem_bt = elem->array_element_basic_type();
const TypeVect* TypeVect::makemask(BasicType elem_bt, uint length) {
if (Matcher::has_predicated_vectors() &&
Matcher::match_rule_supported_vector_masked(Op_VectorLoadMask, length, elem_bt)) {
return TypeVectMask::make(elem, length);
return TypeVectMask::make(elem_bt, length);
} else {
return make(elem, length);
return make(elem_bt, length);
}
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
const Type *TypeVect::xmeet( const Type *t ) const {
// Compute the MEET of two types. Since each TypeVect is the only instance of
// its species, meeting often returns itself
const Type* TypeVect::xmeet(const Type* t) const {
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
if (this == t) {
return this;
}
// Current "this->_base" is Vector
switch (t->base()) { // switch on original type
@ -2543,13 +2544,7 @@ const Type *TypeVect::xmeet( const Type *t ) const {
default: // All else is a mistake
typerr(t);
case VectorMask: {
const TypeVectMask* v = t->is_vectmask();
assert( base() == v->base(), "");
assert(length() == v->length(), "");
assert(element_basic_type() == v->element_basic_type(), "");
return TypeVect::makemask(_elem->xmeet(v->_elem), _length);
}
case VectorMask:
case VectorA:
case VectorS:
case VectorD:
@ -2557,10 +2552,10 @@ const Type *TypeVect::xmeet( const Type *t ) const {
case VectorY:
case VectorZ: { // Meeting 2 vectors?
const TypeVect* v = t->is_vect();
assert( base() == v->base(), "");
assert(base() == v->base(), "");
assert(length() == v->length(), "");
assert(element_basic_type() == v->element_basic_type(), "");
return TypeVect::make(_elem->xmeet(v->_elem), _length);
return this;
}
case Top:
break;
@ -2569,26 +2564,26 @@ const Type *TypeVect::xmeet( const Type *t ) const {
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeVect::xdual() const {
return new TypeVect(base(), _elem->dual(), _length);
// Since each TypeVect is the only instance of its species, it is self-dual
const Type* TypeVect::xdual() const {
return this;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
bool TypeVect::eq(const Type *t) const {
const TypeVect *v = t->is_vect();
return (_elem == v->_elem) && (_length == v->_length);
bool TypeVect::eq(const Type* t) const {
const TypeVect* v = t->is_vect();
return (element_basic_type() == v->element_basic_type()) && (length() == v->length());
}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
uint TypeVect::hash(void) const {
return (uint)(uintptr_t)_elem + (uint)(uintptr_t)_length;
return (uint)base() + (uint)(uintptr_t)_elem_bt + (uint)(uintptr_t)_length;
}
//------------------------------singleton--------------------------------------
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple
// constants (Ldi nodes). Vector is singleton if all elements are the same
// constant value (when vector is created with Replicate code).
bool TypeVect::singleton(void) const {
@ -2598,52 +2593,36 @@ bool TypeVect::singleton(void) const {
}
bool TypeVect::empty(void) const {
return _elem->empty();
return false;
}
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeVect::dump2(Dict &d, uint depth, outputStream *st) const {
void TypeVect::dump2(Dict& d, uint depth, outputStream* st) const {
switch (base()) {
case VectorA:
st->print("vectora["); break;
st->print("vectora"); break;
case VectorS:
st->print("vectors["); break;
st->print("vectors"); break;
case VectorD:
st->print("vectord["); break;
st->print("vectord"); break;
case VectorX:
st->print("vectorx["); break;
st->print("vectorx"); break;
case VectorY:
st->print("vectory["); break;
st->print("vectory"); break;
case VectorZ:
st->print("vectorz["); break;
st->print("vectorz"); break;
case VectorMask:
st->print("vectormask["); break;
st->print("vectormask"); break;
default:
ShouldNotReachHere();
}
st->print("%d]:{", _length);
_elem->dump2(d, depth, st);
st->print("}");
st->print("<%c,%u>", type2char(element_basic_type()), length());
}
#endif
bool TypeVectMask::eq(const Type *t) const {
const TypeVectMask *v = t->is_vectmask();
return (element_type() == v->element_type()) && (length() == v->length());
}
const Type *TypeVectMask::xdual() const {
return new TypeVectMask(element_type()->dual(), length());
}
const TypeVectMask *TypeVectMask::make(const BasicType elem_bt, uint length) {
return make(get_const_basic_type(elem_bt), length);
}
const TypeVectMask *TypeVectMask::make(const Type* elem, uint length) {
const TypeVectMask* mtype = Matcher::predicate_reg_type(elem, length);
return (TypeVectMask*) const_cast<TypeVectMask*>(mtype)->hashcons();
const TypeVectMask* TypeVectMask::make(const BasicType elem_bt, uint length) {
return (TypeVectMask*) (new TypeVectMask(elem_bt, length))->hashcons();
}
//=============================================================================

View File

@ -784,94 +784,79 @@ public:
//------------------------------TypeVect---------------------------------------
// Class of Vector Types
class TypeVect : public Type {
const Type* _elem; // Vector's element type
const uint _length; // Elements in vector (power of 2)
const BasicType _elem_bt; // Vector's element type
const uint _length; // Elements in vector (power of 2)
protected:
TypeVect(TYPES t, const Type* elem, uint length) : Type(t),
_elem(elem), _length(length) {}
TypeVect(TYPES t, BasicType elem_bt, uint length) : Type(t),
_elem_bt(elem_bt), _length(length) {}
public:
const Type* element_type() const { return _elem; }
BasicType element_basic_type() const { return _elem->array_element_basic_type(); }
BasicType element_basic_type() const { return _elem_bt; }
uint length() const { return _length; }
uint length_in_bytes() const {
return _length * type2aelembytes(element_basic_type());
return _length * type2aelembytes(element_basic_type());
}
virtual bool eq(const Type *t) const;
virtual bool eq(const Type* t) const;
virtual uint hash() const; // Type specific hashing
virtual bool singleton(void) const; // TRUE if type is a singleton
virtual bool empty(void) const; // TRUE if type is vacuous
static const TypeVect *make(const BasicType elem_bt, uint length, bool is_mask = false) {
// Use bottom primitive type.
return make(get_const_basic_type(elem_bt), length, is_mask);
}
// Used directly by Replicate nodes to construct singleton vector.
static const TypeVect *make(const Type* elem, uint length, bool is_mask = false);
static const TypeVect* make(const BasicType elem_bt, uint length, bool is_mask = false);
static const TypeVect* makemask(const BasicType elem_bt, uint length);
static const TypeVect *makemask(const BasicType elem_bt, uint length) {
// Use bottom primitive type.
return makemask(get_const_basic_type(elem_bt), length);
}
static const TypeVect *makemask(const Type* elem, uint length);
virtual const Type* xmeet( const Type *t) const;
virtual const Type* xdual() const; // Compute dual right now.
virtual const Type *xmeet( const Type *t) const;
virtual const Type *xdual() const; // Compute dual right now.
static const TypeVect *VECTA;
static const TypeVect *VECTS;
static const TypeVect *VECTD;
static const TypeVect *VECTX;
static const TypeVect *VECTY;
static const TypeVect *VECTZ;
static const TypeVect *VECTMASK;
static const TypeVect* VECTA;
static const TypeVect* VECTS;
static const TypeVect* VECTD;
static const TypeVect* VECTX;
static const TypeVect* VECTY;
static const TypeVect* VECTZ;
static const TypeVect* VECTMASK;
#ifndef PRODUCT
virtual void dump2(Dict &d, uint, outputStream *st) const; // Specialized per-Type dumping
virtual void dump2(Dict& d, uint, outputStream* st) const; // Specialized per-Type dumping
#endif
};
class TypeVectA : public TypeVect {
friend class TypeVect;
TypeVectA(const Type* elem, uint length) : TypeVect(VectorA, elem, length) {}
TypeVectA(BasicType elem_bt, uint length) : TypeVect(VectorA, elem_bt, length) {}
};
class TypeVectS : public TypeVect {
friend class TypeVect;
TypeVectS(const Type* elem, uint length) : TypeVect(VectorS, elem, length) {}
TypeVectS(BasicType elem_bt, uint length) : TypeVect(VectorS, elem_bt, length) {}
};
class TypeVectD : public TypeVect {
friend class TypeVect;
TypeVectD(const Type* elem, uint length) : TypeVect(VectorD, elem, length) {}
TypeVectD(BasicType elem_bt, uint length) : TypeVect(VectorD, elem_bt, length) {}
};
class TypeVectX : public TypeVect {
friend class TypeVect;
TypeVectX(const Type* elem, uint length) : TypeVect(VectorX, elem, length) {}
TypeVectX(BasicType elem_bt, uint length) : TypeVect(VectorX, elem_bt, length) {}
};
class TypeVectY : public TypeVect {
friend class TypeVect;
TypeVectY(const Type* elem, uint length) : TypeVect(VectorY, elem, length) {}
TypeVectY(BasicType elem_bt, uint length) : TypeVect(VectorY, elem_bt, length) {}
};
class TypeVectZ : public TypeVect {
friend class TypeVect;
TypeVectZ(const Type* elem, uint length) : TypeVect(VectorZ, elem, length) {}
TypeVectZ(BasicType elem_bt, uint length) : TypeVect(VectorZ, elem_bt, length) {}
};
class TypeVectMask : public TypeVect {
public:
friend class TypeVect;
TypeVectMask(const Type* elem, uint length) : TypeVect(VectorMask, elem, length) {}
virtual bool eq(const Type *t) const;
virtual const Type *xdual() const;
TypeVectMask(BasicType elem_bt, uint length) : TypeVect(VectorMask, elem_bt, length) {}
static const TypeVectMask* make(const BasicType elem_bt, uint length);
static const TypeVectMask* make(const Type* elem, uint length);
};
// Set of implemented interfaces. Referenced from TypeOopPtr and TypeKlassPtr.

View File

@ -524,17 +524,16 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
Node* LibraryCallKit::partially_wrap_indexes(Node* index_vec, int num_elem, BasicType elem_bt) {
assert(elem_bt == T_BYTE, "Shuffles use byte array based backing storage.");
const TypeVect* vt = TypeVect::make(elem_bt, num_elem);
const Type* type_bt = Type::get_const_basic_type(elem_bt);
Node* mod_mask = gvn().makecon(TypeInt::make(num_elem-1));
Node* bcast_mod_mask = gvn().transform(VectorNode::scalar2vector(mod_mask, num_elem, type_bt));
Node* bcast_mod_mask = gvn().transform(VectorNode::scalar2vector(mod_mask, num_elem, elem_bt));
BoolTest::mask pred = BoolTest::ugt;
ConINode* pred_node = (ConINode*)gvn().makecon(TypeInt::make(pred));
Node* lane_cnt = gvn().makecon(TypeInt::make(num_elem));
Node* bcast_lane_cnt = gvn().transform(VectorNode::scalar2vector(lane_cnt, num_elem, type_bt));
const TypeVect* vmask_type = TypeVect::makemask(type_bt, num_elem);
Node* mask = gvn().transform(new VectorMaskCmpNode(pred, bcast_lane_cnt, index_vec, pred_node, vmask_type));
Node* bcast_lane_cnt = gvn().transform(VectorNode::scalar2vector(lane_cnt, num_elem, elem_bt));
const TypeVect* vmask_type = TypeVect::makemask(elem_bt, num_elem);
Node* mask = gvn().transform(new VectorMaskCmpNode(pred, bcast_lane_cnt, index_vec, pred_node, vmask_type));
// Make the indices greater than lane count as -ve values to match the java side implementation.
index_vec = gvn().transform(VectorNode::make(Op_AndV, index_vec, bcast_mod_mask, vt));
@ -600,8 +599,7 @@ bool LibraryCallKit::inline_vector_shuffle_iota() {
return false;
}
const Type * type_bt = Type::get_const_basic_type(elem_bt);
const TypeVect * vt = TypeVect::make(type_bt, num_elem);
const TypeVect* vt = TypeVect::make(elem_bt, num_elem);
Node* res = gvn().transform(new VectorLoadConstNode(gvn().makecon(TypeInt::ZERO), vt));
@ -609,7 +607,7 @@ bool LibraryCallKit::inline_vector_shuffle_iota() {
Node* step = argument(5);
if (step_multiply) {
Node* bcast_step = gvn().transform(VectorNode::scalar2vector(step, num_elem, type_bt));
Node* bcast_step = gvn().transform(VectorNode::scalar2vector(step, num_elem, elem_bt));
res = gvn().transform(VectorNode::make(Op_MulVB, res, bcast_step, vt));
} else if (step_val->get_con() > 1) {
Node* cnt = gvn().makecon(TypeInt::make(log2i_exact(step_val->get_con())));
@ -618,12 +616,12 @@ bool LibraryCallKit::inline_vector_shuffle_iota() {
}
if (!start_val->is_con() || start_val->get_con() != 0) {
Node* bcast_start = gvn().transform(VectorNode::scalar2vector(start, num_elem, type_bt));
Node* bcast_start = gvn().transform(VectorNode::scalar2vector(start, num_elem, elem_bt));
res = gvn().transform(VectorNode::make(Op_AddVB, res, bcast_start, vt));
}
Node * mod_val = gvn().makecon(TypeInt::make(num_elem-1));
Node * bcast_mod = gvn().transform(VectorNode::scalar2vector(mod_val, num_elem, type_bt));
Node* mod_val = gvn().makecon(TypeInt::make(num_elem-1));
Node* bcast_mod = gvn().transform(VectorNode::scalar2vector(mod_val, num_elem, elem_bt));
if (do_wrap) {
// Wrap the indices greater than lane count.
@ -802,9 +800,8 @@ bool LibraryCallKit::inline_vector_wrap_shuffle_indexes() {
Node* shuffle_vec = unbox_vector(shuffle, shuffle_box_type, shuffle_bt, num_elem, true);
const TypeVect* vt = TypeVect::make(shuffle_bt, num_elem);
const Type* shuffle_type_bt = Type::get_const_basic_type(shuffle_bt);
Node* mod_mask = gvn().makecon(TypeInt::make(num_elem-1));
Node* bcast_mod_mask = gvn().transform(VectorNode::scalar2vector(mod_mask, num_elem, shuffle_type_bt));
Node* mod_mask = gvn().makecon(TypeInt::make(num_elem - 1));
Node* bcast_mod_mask = gvn().transform(VectorNode::scalar2vector(mod_mask, num_elem, shuffle_bt));
// Wrap the indices greater than lane count.
Node* res = gvn().transform(VectorNode::make(Op_AndV, shuffle_vec, bcast_mod_mask, vt));
@ -908,7 +905,7 @@ bool LibraryCallKit::inline_vector_frombits_coerced() {
}
default: fatal("%s", type2name(elem_bt));
}
broadcast = VectorNode::scalar2vector(elem, num_elem, Type::get_const_basic_type(elem_bt), is_mask);
broadcast = VectorNode::scalar2vector(elem, num_elem, elem_bt, is_mask);
broadcast = gvn().transform(broadcast);
}
@ -1352,7 +1349,7 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) {
} else {
// Use the vector blend to implement the masked load vector. The biased elements are zeros.
Node* zero = gvn().transform(gvn().zerocon(mem_elem_bt));
zero = gvn().transform(VectorNode::scalar2vector(zero, mem_num_elem, Type::get_const_basic_type(mem_elem_bt)));
zero = gvn().transform(VectorNode::scalar2vector(zero, mem_num_elem, mem_elem_bt));
vload = gvn().transform(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, mem_num_elem, mem_elem_bt));
vload = gvn().transform(new VectorBlendNode(zero, vload, mask));
}
@ -1678,7 +1675,7 @@ bool LibraryCallKit::inline_vector_reduction() {
assert(mask != nullptr || !is_masked_op, "Masked op needs the mask value never null");
if (mask != nullptr && !use_predicate) {
Node* reduce_identity = gvn().transform(VectorNode::scalar2vector(init, num_elem, Type::get_const_basic_type(elem_bt)));
Node* reduce_identity = gvn().transform(VectorNode::scalar2vector(init, num_elem, elem_bt));
value = gvn().transform(new VectorBlendNode(reduce_identity, value, mask));
}
@ -2059,7 +2056,7 @@ bool LibraryCallKit::inline_vector_rearrange() {
const TypeVect* vt = v1->bottom_type()->is_vect();
rearrange = gvn().transform(rearrange);
Node* zero = gvn().makecon(Type::get_zero_type(elem_bt));
Node* zerovec = gvn().transform(VectorNode::scalar2vector(zero, num_elem, Type::get_const_basic_type(elem_bt)));
Node* zerovec = gvn().transform(VectorNode::scalar2vector(zero, num_elem, elem_bt));
rearrange = new VectorBlendNode(zerovec, rearrange, mask);
}
}
@ -2215,18 +2212,17 @@ bool LibraryCallKit::inline_vector_select_from() {
}
// cast index vector from elem_bt vector to byte vector
const Type * byte_bt = Type::get_const_basic_type(T_BYTE);
const TypeVect * byte_vt = TypeVect::make(byte_bt, num_elem);
const TypeVect* byte_vt = TypeVect::make(T_BYTE, num_elem);
Node* byte_shuffle = gvn().transform(VectorCastNode::make(cast_vopc, v1, T_BYTE, num_elem));
// wrap the byte vector lanes to (num_elem - 1) to form the shuffle vector where num_elem is vector length
// this is a simple AND operation as we come here only for power of two vector length
Node* mod_val = gvn().makecon(TypeInt::make(num_elem-1));
Node* bcast_mod = gvn().transform(VectorNode::scalar2vector(mod_val, num_elem, byte_bt));
Node* bcast_mod = gvn().transform(VectorNode::scalar2vector(mod_val, num_elem, T_BYTE));
byte_shuffle = gvn().transform(VectorNode::make(Op_AndV, byte_shuffle, bcast_mod, byte_vt));
// load the shuffle to use in rearrange
const TypeVect * shuffle_vt = TypeVect::make(elem_bt, num_elem);
const TypeVect* shuffle_vt = TypeVect::make(elem_bt, num_elem);
Node* load_shuffle = gvn().transform(new VectorLoadShuffleNode(byte_shuffle, shuffle_vt));
// and finally rearrange
@ -2243,7 +2239,7 @@ bool LibraryCallKit::inline_vector_select_from() {
// create a zero vector with each lane element set as zero
Node* zero = gvn().makecon(Type::get_zero_type(elem_bt));
Node* zerovec = gvn().transform(VectorNode::scalar2vector(zero, num_elem, Type::get_const_basic_type(elem_bt)));
Node* zerovec = gvn().transform(VectorNode::scalar2vector(zero, num_elem, elem_bt));
// For each lane for which mask is set, blend in the rearranged lane into zero vector
rearrange = new VectorBlendNode(zerovec, rearrange, mask);
@ -2391,9 +2387,8 @@ bool LibraryCallKit::inline_vector_broadcast_int() {
} else {
assert(is_rotate, "unexpected operation");
if (!is_const_rotate) {
const Type * type_bt = Type::get_const_basic_type(elem_bt);
cnt = elem_bt == T_LONG ? gvn().transform(new ConvI2LNode(cnt)) : cnt;
opd2 = gvn().transform(VectorNode::scalar2vector(cnt, num_elem, type_bt));
opd2 = gvn().transform(VectorNode::scalar2vector(cnt, num_elem, elem_bt));
} else {
// Constant shift value.
opd2 = cnt;
@ -3051,7 +3046,7 @@ bool LibraryCallKit::inline_index_vector() {
}
default: fatal("%s", type2name(elem_bt));
}
scale = gvn().transform(VectorNode::scalar2vector(scale, num_elem, Type::get_const_basic_type(elem_bt)));
scale = gvn().transform(VectorNode::scalar2vector(scale, num_elem, elem_bt));
index = gvn().transform(VectorNode::make(vmul_op, index, scale, vt));
}
@ -3164,7 +3159,7 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() {
}
default: fatal("%s", type2name(elem_bt));
}
indexLimit = gvn().transform(VectorNode::scalar2vector(indexLimit, num_elem, Type::get_const_basic_type(elem_bt)));
indexLimit = gvn().transform(VectorNode::scalar2vector(indexLimit, num_elem, elem_bt));
// Load the "iota" vector.
const TypeVect* vt = TypeVect::make(elem_bt, num_elem);

View File

@ -799,15 +799,13 @@ VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, Node* n3, uint vlen, B
}
// Scalar promotion
VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, const Type* opd_t, bool is_mask) {
BasicType bt = opd_t->array_element_basic_type();
VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, BasicType bt, bool is_mask) {
if (is_mask && Matcher::match_rule_supported_vector(Op_MaskAll, vlen, bt)) {
const TypeVect* vt = TypeVect::make(opd_t, vlen, true);
const TypeVect* vt = TypeVect::make(bt, vlen, true);
return new MaskAllNode(s, vt);
}
const TypeVect* vt = opd_t->singleton() ? TypeVect::make(opd_t, vlen)
: TypeVect::make(bt, vlen);
const TypeVect* vt = TypeVect::make(bt, vlen);
return new ReplicateNode(s, vt);
}
@ -1626,8 +1624,6 @@ Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_
Node* const_one_node = nullptr;
assert(cnt->bottom_type()->isa_vect(), "Unexpected shift");
const Type* elem_ty = Type::get_const_basic_type(bt);
if (bt == T_LONG) {
shift_mask_node = phase->longcon(shift_mask);
const_one_node = phase->longcon(1L);
@ -1639,8 +1635,8 @@ Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_
subVopc = VectorNode::opcode(Op_SubI, bt);
addVopc = VectorNode::opcode(Op_AddI, bt);
}
Node* vector_mask = phase->transform(VectorNode::scalar2vector(shift_mask_node, vlen, elem_ty));
Node* vector_one = phase->transform(VectorNode::scalar2vector(const_one_node, vlen, elem_ty));
Node* vector_mask = phase->transform(VectorNode::scalar2vector(shift_mask_node, vlen, bt));
Node* vector_one = phase->transform(VectorNode::scalar2vector(const_one_node, vlen, bt));
shiftRCnt = cnt;
shiftRCnt = phase->transform(VectorNode::make(Op_AndV, shiftRCnt, vector_mask, vt));
@ -1882,12 +1878,12 @@ Node* NegVNode::degenerate_integral_negate(PhaseGVN* phase, bool is_predicated)
const_one = phase->intcon(1);
add_opc = Op_AddI;
}
const_minus_one = phase->transform(VectorNode::scalar2vector(const_minus_one, vlen, Type::get_const_basic_type(bt)));
const_minus_one = phase->transform(VectorNode::scalar2vector(const_minus_one, vlen, bt));
Node* xorv = VectorNode::make(Op_XorV, in(1), const_minus_one, vt);
xorv->add_req(in(2));
xorv->add_flag(Node::Flag_is_predicated_vector);
phase->transform(xorv);
const_one = phase->transform(VectorNode::scalar2vector(const_one, vlen, Type::get_const_basic_type(bt)));
const_one = phase->transform(VectorNode::scalar2vector(const_one, vlen, bt));
Node* addv = VectorNode::make(VectorNode::opcode(add_opc, bt), xorv, const_one, vt);
addv->add_req(in(2));
addv->add_flag(Node::Flag_is_predicated_vector);
@ -1904,7 +1900,7 @@ Node* NegVNode::degenerate_integral_negate(PhaseGVN* phase, bool is_predicated)
const_zero = phase->intcon(0);
sub_opc = Op_SubI;
}
const_zero = phase->transform(VectorNode::scalar2vector(const_zero, vlen, Type::get_const_basic_type(bt)));
const_zero = phase->transform(VectorNode::scalar2vector(const_zero, vlen, bt));
return VectorNode::make(VectorNode::opcode(sub_opc, bt), const_zero, in(1), vt);
}
@ -2069,8 +2065,7 @@ Node* XorVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
if (!is_predicated_vector() && (in(1) == in(2))) {
BasicType bt = vect_type()->element_basic_type();
Node* zero = phase->transform(phase->zerocon(bt));
return VectorNode::scalar2vector(zero, length(), Type::get_const_basic_type(bt),
bottom_type()->isa_vectmask() != nullptr);
return VectorNode::scalar2vector(zero, length(), bt, bottom_type()->isa_vectmask() != nullptr);
}
return nullptr;
}

View File

@ -75,7 +75,7 @@ class VectorNode : public TypeNode {
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
static VectorNode* scalar2vector(Node* s, uint vlen, const Type* opd_t, bool is_mask = false);
static VectorNode* scalar2vector(Node* s, uint vlen, BasicType bt, bool is_mask = false);
static VectorNode* shift_count(int opc, Node* cnt, uint vlen, BasicType bt);
static VectorNode* make(int opc, Node* n1, Node* n2, uint vlen, BasicType bt, bool is_var_shift = false);
static VectorNode* make(int vopc, Node* n1, Node* n2, const TypeVect* vt, bool is_mask = false, bool is_var_shift = false);

View File

@ -422,8 +422,7 @@ void VTransformScalarNode::print_spec() const {
}
void VTransformReplicateNode::print_spec() const {
tty->print("vlen=%d element_type=", _vlen);
_element_type->dump();
tty->print("vlen=%d element_type=%s", _vlen, type2name(_element_type));
}
void VTransformShiftCountNode::print_spec() const {

View File

@ -354,9 +354,9 @@ public:
class VTransformReplicateNode : public VTransformNode {
private:
int _vlen;
const Type* _element_type;
BasicType _element_type;
public:
VTransformReplicateNode(VTransform& vtransform, int vlen, const Type* element_type) :
VTransformReplicateNode(VTransform& vtransform, int vlen, BasicType element_type) :
VTransformNode(vtransform, 2), _vlen(vlen), _element_type(element_type) {}
virtual VTransformApplyResult apply(const VLoopAnalyzer& vloop_analyzer,
const GrowableArray<Node*>& vnode_idx_to_transformed_node) const override;

View File

@ -119,13 +119,13 @@ public class IRNode {
public static final String VECTOR_SIZE_32 = VECTOR_SIZE + "32";
public static final String VECTOR_SIZE_64 = VECTOR_SIZE + "64";
private static final String TYPE_BYTE = "byte";
private static final String TYPE_CHAR = "char";
private static final String TYPE_SHORT = "short";
private static final String TYPE_INT = "int";
private static final String TYPE_LONG = "long";
private static final String TYPE_FLOAT = "float";
private static final String TYPE_DOUBLE = "double";
private static final String TYPE_BYTE = "B";
private static final String TYPE_CHAR = "C";
private static final String TYPE_SHORT = "S";
private static final String TYPE_INT = "I";
private static final String TYPE_LONG = "J";
private static final String TYPE_FLOAT = "F";
private static final String TYPE_DOUBLE = "D";
/**
* IR placeholder string to regex-for-compile-phase map.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -133,7 +133,6 @@ public class RawIRNode {
}
}
String sizeRegex = IRNode.parseVectorNodeSize(size, type, vmInfo);
return nodeRegex.replaceAll(IRNode.IS_REPLACED,
"vector[A-Za-z]\\\\[" + sizeRegex + "\\\\]:\\\\{" + type + "\\\\}");
return nodeRegex.replaceAll(IRNode.IS_REPLACED, "vector[A-Za-z]<" + type + "," + sizeRegex + ">");
}
}