8257625: C2: Harden input checks in vector intrinsics

Reviewed-by: thartmann
This commit is contained in:
Vladimir Ivanov 2020-12-04 07:54:24 +00:00
parent 4390f2c8c3
commit 6845fee905
3 changed files with 185 additions and 168 deletions

@ -197,12 +197,13 @@ static bool is_klass_initialized(const TypeInstPtr* vec_klass) {
// TernaryOperation<VM> defaultImpl) {
//
bool LibraryCallKit::inline_vector_nary_operation(int n) {
const TypeInt* opr = gvn().type(argument(0))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInt* opr = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (!opr->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (opr == NULL || vector_klass == NULL || elem_klass == NULL || vlen == NULL ||
!opr->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
@ -229,6 +230,12 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
int num_elem = vlen->get_con();
int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt);
int sopc = VectorNode::opcode(opc, elem_bt);
if (sopc == 0) {
if (C->print_intrinsics()) {
tty->print_cr(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt));
}
return false; // operation not supported
}
ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass();
const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass);
@ -305,14 +312,18 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
// Sh ShuffleIota(Class<?> E, Class<?> ShuffleClass, Vector.Species<E> s, int length,
// int start, int step, int wrap, ShuffleIotaOperation<Sh, E> defaultImpl)
bool LibraryCallKit::inline_vector_shuffle_iota() {
const TypeInstPtr* shuffle_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
Node* start = argument(4);
const TypeInt* start_val = gvn().type(start)->is_int();
Node* step = argument(5);
const TypeInt* step_val = gvn().type(step)->is_int();
const TypeInt* wrap = gvn().type(argument(6))->is_int();
const TypeInstPtr* shuffle_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
const TypeInt* start_val = gvn().type(argument(4))->isa_int();
const TypeInt* step_val = gvn().type(argument(5))->isa_int();
const TypeInt* wrap = gvn().type(argument(6))->isa_int();
Node* start = argument(4);
Node* step = argument(5);
if (shuffle_klass == NULL || vlen == NULL || start_val == NULL || step_val == NULL || wrap == NULL) {
return false; // dead code
}
if (!vlen->is_con() || !is_power_of_2(vlen->get_con()) ||
shuffle_klass->const_oop() == NULL || !wrap->is_con()) {
return false; // not enough info for intrinsification
@ -396,12 +407,15 @@ bool LibraryCallKit::inline_vector_shuffle_iota() {
// VM shuffleToVector(Class<VM> VecClass, Class<?>E , Class<?> ShuffleClass, Sh s, int length,
// ShuffleToVectorOperation<VM,Sh,E> defaultImpl)
bool LibraryCallKit::inline_vector_shuffle_to_vector() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* shuffle_klass = gvn().type(argument(2))->is_instptr();
Node* shuffle = argument(3);
const TypeInt* vlen = gvn().type(argument(4))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* shuffle_klass = gvn().type(argument(2))->isa_instptr();
Node* shuffle = argument(3);
const TypeInt* vlen = gvn().type(argument(4))->isa_int();
if (vector_klass == NULL || elem_klass == NULL || shuffle_klass == NULL || shuffle->is_top() || vlen == NULL) {
return false; // dead code
}
if (!vlen->is_con() || vector_klass->const_oop() == NULL || shuffle_klass->const_oop() == NULL) {
return false; // not enough info for intrinsification
}
@ -451,11 +465,12 @@ bool LibraryCallKit::inline_vector_shuffle_to_vector() {
// long bits,
// LongFunction<V> defaultImpl)
bool LibraryCallKit::inline_vector_broadcast_coerced() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(2))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
if (vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (vector_klass == NULL || elem_klass == NULL || vlen == NULL ||
vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
@ -546,11 +561,12 @@ bool LibraryCallKit::inline_vector_broadcast_coerced() {
// StoreVectorOperation<C, V> defaultImpl) {
bool LibraryCallKit::inline_vector_mem_operation(bool is_store) {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(2))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
if (vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (vector_klass == NULL || elem_klass == NULL || vlen == NULL ||
vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
@ -708,12 +724,13 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) {
// StoreVectorOperationWithMap<C, V> defaultImpl) {
//
bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(2))->is_int();
const TypeInstPtr* vector_idx_klass = gvn().type(argument(3))->is_instptr();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
const TypeInstPtr* vector_idx_klass = gvn().type(argument(3))->isa_instptr();
if (vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || vector_idx_klass->const_oop() == NULL || !vlen->is_con()) {
if (vector_klass == NULL || elem_klass == NULL || vector_idx_klass == NULL || vlen == NULL ||
vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || vector_idx_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s",
NodeClassNames[argument(0)->Opcode()],
@ -812,12 +829,13 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) {
// Function<V,Long> defaultImpl)
bool LibraryCallKit::inline_vector_reduction() {
const TypeInt* opr = gvn().type(argument(0))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInt* opr = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (!opr->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (opr == NULL || vector_klass == NULL || elem_klass == NULL || vlen == NULL ||
!opr->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
@ -899,12 +917,13 @@ bool LibraryCallKit::inline_vector_reduction() {
// BiFunction<V, V, Boolean> defaultImpl) {
//
bool LibraryCallKit::inline_vector_test() {
const TypeInt* cond = gvn().type(argument(0))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInt* cond = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (!cond->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (cond == NULL || vector_klass == NULL || elem_klass == NULL || vlen == NULL ||
!cond->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: cond=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
@ -962,11 +981,14 @@ bool LibraryCallKit::inline_vector_test() {
// VectorBlendOp<V,M> defaultImpl) { ...
//
bool LibraryCallKit::inline_vector_blend() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* mask_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* mask_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (mask_klass == NULL || vector_klass == NULL || elem_klass == NULL || vlen == NULL) {
return false; // dead code
}
if (mask_klass->const_oop() == NULL || vector_klass->const_oop() == NULL ||
elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
@ -1032,12 +1054,15 @@ bool LibraryCallKit::inline_vector_blend() {
// VectorCompareOp<V,M> defaultImpl) { ...
//
bool LibraryCallKit::inline_vector_compare() {
const TypeInt* cond = gvn().type(argument(0))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* mask_klass = gvn().type(argument(2))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(3))->is_instptr();
const TypeInt* vlen = gvn().type(argument(4))->is_int();
const TypeInt* cond = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* mask_klass = gvn().type(argument(2))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(3))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(4))->isa_int();
if (cond == NULL || vector_klass == NULL || mask_klass == NULL || elem_klass == NULL || vlen == NULL) {
return false; // dead code
}
if (!cond->is_con() || vector_klass->const_oop() == NULL || mask_klass->const_oop() == NULL ||
elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
@ -1107,11 +1132,14 @@ bool LibraryCallKit::inline_vector_compare() {
// VectorSwizzleOp<V, Sh, S, E> defaultImpl) { ...
bool LibraryCallKit::inline_vector_rearrange() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* shuffle_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* shuffle_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (vector_klass == NULL || shuffle_klass == NULL || elem_klass == NULL || vlen == NULL) {
return false; // dead code
}
if (shuffle_klass->const_oop() == NULL || vector_klass->const_oop() == NULL ||
elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
@ -1182,11 +1210,14 @@ bool LibraryCallKit::inline_vector_rearrange() {
// VectorBroadcastIntOp<V> defaultImpl) {
//
bool LibraryCallKit::inline_vector_broadcast_int() {
const TypeInt* opr = gvn().type(argument(0))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen = gvn().type(argument(3))->is_int();
const TypeInt* opr = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (opr == NULL || vector_klass == NULL || elem_klass == NULL || vlen == NULL) {
return false; // dead code
}
if (!opr->is_con() || vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s",
@ -1213,7 +1244,19 @@ bool LibraryCallKit::inline_vector_broadcast_int() {
BasicType elem_bt = elem_type->basic_type();
int num_elem = vlen->get_con();
int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt);
if (opc == 0 || !VectorNode::is_shift_opcode(opc)) {
if (C->print_intrinsics()) {
tty->print_cr(" ** operation not supported: op=%d bt=%s", opr->get_con(), type2name(elem_bt));
}
return false; // operation not supported
}
int sopc = VectorNode::opcode(opc, elem_bt);
if (sopc == 0) {
if (C->print_intrinsics()) {
tty->print_cr(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt));
}
return false; // operation not supported
}
ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass();
const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass);
@ -1247,16 +1290,21 @@ bool LibraryCallKit::inline_vector_broadcast_int() {
// VectorConvertOp<VOUT, VIN, S> defaultImpl) {
//
bool LibraryCallKit::inline_vector_convert() {
const TypeInt* opr = gvn().type(argument(0))->is_int();
const TypeInt* opr = gvn().type(argument(0))->isa_int();
const TypeInstPtr* vector_klass_from = gvn().type(argument(1))->is_instptr();
const TypeInstPtr* elem_klass_from = gvn().type(argument(2))->is_instptr();
const TypeInt* vlen_from = gvn().type(argument(3))->is_int();
const TypeInstPtr* vector_klass_from = gvn().type(argument(1))->isa_instptr();
const TypeInstPtr* elem_klass_from = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen_from = gvn().type(argument(3))->isa_int();
const TypeInstPtr* vector_klass_to = gvn().type(argument(4))->is_instptr();
const TypeInstPtr* elem_klass_to = gvn().type(argument(5))->is_instptr();
const TypeInt* vlen_to = gvn().type(argument(6))->is_int();
const TypeInstPtr* vector_klass_to = gvn().type(argument(4))->isa_instptr();
const TypeInstPtr* elem_klass_to = gvn().type(argument(5))->isa_instptr();
const TypeInt* vlen_to = gvn().type(argument(6))->isa_int();
if (opr == NULL ||
vector_klass_from == NULL || elem_klass_from == NULL || vlen_from == NULL ||
vector_klass_to == NULL || elem_klass_to == NULL || vlen_to == NULL) {
return false; // dead code
}
if (!opr->is_con() ||
vector_klass_from->const_oop() == NULL || elem_klass_from->const_oop() == NULL || !vlen_from->is_con() ||
vector_klass_to->const_oop() == NULL || elem_klass_to->const_oop() == NULL || !vlen_to->is_con()) {
@ -1431,11 +1479,14 @@ bool LibraryCallKit::inline_vector_convert() {
// VecInsertOp<V> defaultImpl) {
//
bool LibraryCallKit::inline_vector_insert() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(2))->is_int();
const TypeInt* idx = gvn().type(argument(4))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
const TypeInt* idx = gvn().type(argument(4))->isa_int();
if (vector_klass == NULL || elem_klass == NULL || vlen == NULL || idx == NULL) {
return false; // dead code
}
if (vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con() || !idx->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s idx=%s",
@ -1521,11 +1572,14 @@ bool LibraryCallKit::inline_vector_insert() {
// VecExtractOp<V> defaultImpl) {
//
bool LibraryCallKit::inline_vector_extract() {
const TypeInstPtr* vector_klass = gvn().type(argument(0))->is_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->is_instptr();
const TypeInt* vlen = gvn().type(argument(2))->is_int();
const TypeInt* idx = gvn().type(argument(4))->is_int();
const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr();
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
const TypeInt* idx = gvn().type(argument(4))->isa_int();
if (vector_klass == NULL || elem_klass == NULL || vlen == NULL || idx == NULL) {
return false; // dead code
}
if (vector_klass->const_oop() == NULL || elem_klass->const_oop() == NULL || !vlen->is_con() || !idx->is_con()) {
if (C->print_intrinsics()) {
tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s idx=%s",

@ -43,17 +43,12 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_CHAR:
case T_SHORT: return Op_AddVS;
case T_INT: return Op_AddVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_AddL:
assert(bt == T_LONG, "must be");
return Op_AddVL;
case Op_AddF:
assert(bt == T_FLOAT, "must be");
return Op_AddVF;
case Op_AddD:
assert(bt == T_DOUBLE, "must be");
return Op_AddVD;
case Op_AddL: return (bt == T_LONG ? Op_AddVL : 0);
case Op_AddF: return (bt == T_FLOAT ? Op_AddVF : 0);
case Op_AddD: return (bt == T_DOUBLE ? Op_AddVD : 0);
case Op_SubI:
switch (bt) {
case T_BOOLEAN:
@ -61,17 +56,12 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_CHAR:
case T_SHORT: return Op_SubVS;
case T_INT: return Op_SubVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_SubL:
assert(bt == T_LONG, "must be");
return Op_SubVL;
case Op_SubF:
assert(bt == T_FLOAT, "must be");
return Op_SubVF;
case Op_SubD:
assert(bt == T_DOUBLE, "must be");
return Op_SubVD;
case Op_SubL: return (bt == T_LONG ? Op_SubVL : 0);
case Op_SubF: return (bt == T_FLOAT ? Op_SubVF : 0);
case Op_SubD: return (bt == T_DOUBLE ? Op_SubVD : 0);
case Op_MulI:
switch (bt) {
case T_BOOLEAN:return 0;
@ -79,35 +69,25 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_CHAR:
case T_SHORT: return Op_MulVS;
case T_INT: return Op_MulVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_MulL:
assert(bt == T_LONG, "must be");
return Op_MulVL;
case Op_MulL: return (bt == T_LONG ? Op_MulVL : 0);
case Op_MulF:
assert(bt == T_FLOAT, "must be");
return Op_MulVF;
return (bt == T_FLOAT ? Op_MulVF : 0);
case Op_MulD:
assert(bt == T_DOUBLE, "must be");
return Op_MulVD;
return (bt == T_DOUBLE ? Op_MulVD : 0);
case Op_FmaD:
assert(bt == T_DOUBLE, "must be");
return Op_FmaVD;
return (bt == T_DOUBLE ? Op_FmaVD : 0);
case Op_FmaF:
assert(bt == T_FLOAT, "must be");
return Op_FmaVF;
return (bt == T_FLOAT ? Op_FmaVF : 0);
case Op_CMoveF:
assert(bt == T_FLOAT, "must be");
return Op_CMoveVF;
return (bt == T_FLOAT ? Op_CMoveVF : 0);
case Op_CMoveD:
assert(bt == T_DOUBLE, "must be");
return Op_CMoveVD;
return (bt == T_DOUBLE ? Op_CMoveVD : 0);
case Op_DivF:
assert(bt == T_FLOAT, "must be");
return Op_DivVF;
return (bt == T_FLOAT ? Op_DivVF : 0);
case Op_DivD:
assert(bt == T_DOUBLE, "must be");
return Op_DivVD;
return (bt == T_DOUBLE ? Op_DivVD : 0);
case Op_AbsI:
switch (bt) {
case T_BOOLEAN:
@ -115,11 +95,10 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_BYTE: return Op_AbsVB;
case T_SHORT: return Op_AbsVS;
case T_INT: return Op_AbsVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_AbsL:
assert(bt == T_LONG, "must be");
return Op_AbsVL;
return (bt == T_LONG ? Op_AbsVL : 0);
case Op_MinI:
switch (bt) {
case T_BOOLEAN:
@ -127,17 +106,14 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_BYTE:
case T_SHORT:
case T_INT: return Op_MinV;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_MinL:
assert(bt == T_LONG, "must be");
return Op_MinV;
return (bt == T_LONG ? Op_MinV : 0);
case Op_MinF:
assert(bt == T_FLOAT, "must be");
return Op_MinV;
return (bt == T_FLOAT ? Op_MinV : 0);
case Op_MinD:
assert(bt == T_DOUBLE, "must be");
return Op_MinV;
return (bt == T_DOUBLE ? Op_MinV : 0);
case Op_MaxI:
switch (bt) {
case T_BOOLEAN:
@ -145,54 +121,38 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_BYTE:
case T_SHORT:
case T_INT: return Op_MaxV;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_MaxL:
assert(bt == T_LONG, "must be");
return Op_MaxV;
return (bt == T_LONG ? Op_MaxV : 0);
case Op_MaxF:
assert(bt == T_FLOAT, "must be");
return Op_MaxV;
return (bt == T_FLOAT ? Op_MaxV : 0);
case Op_MaxD:
assert(bt == T_DOUBLE, "must be");
return Op_MaxV;
return (bt == T_DOUBLE ? Op_MaxV : 0);
case Op_AbsF:
assert(bt == T_FLOAT, "must be");
return Op_AbsVF;
return (bt == T_FLOAT ? Op_AbsVF : 0);
case Op_AbsD:
assert(bt == T_DOUBLE, "must be");
return Op_AbsVD;
return (bt == T_DOUBLE ? Op_AbsVD : 0);
case Op_NegI:
assert(bt == T_INT, "must be");
return Op_NegVI;
return (bt == T_INT ? Op_NegVI : 0);
case Op_NegF:
assert(bt == T_FLOAT, "must be");
return Op_NegVF;
return (bt == T_FLOAT ? Op_NegVF : 0);
case Op_NegD:
assert(bt == T_DOUBLE, "must be");
return Op_NegVD;
return (bt == T_DOUBLE ? Op_NegVD : 0);
case Op_RoundDoubleMode:
assert(bt == T_DOUBLE, "must be");
return Op_RoundDoubleModeV;
return (bt == T_DOUBLE ? Op_RoundDoubleModeV : 0);
case Op_RotateLeft:
assert(bt == T_LONG || bt == T_INT, "must be");
return Op_RotateLeftV;
return (bt == T_LONG || bt == T_INT ? Op_RotateLeftV : 0);
case Op_RotateRight:
assert(bt == T_LONG || bt == T_INT, "must be");
return Op_RotateRightV;
return (bt == T_LONG || bt == T_INT ? Op_RotateRightV : 0);
case Op_SqrtF:
assert(bt == T_FLOAT, "must be");
return Op_SqrtVF;
return (bt == T_FLOAT ? Op_SqrtVF : 0);
case Op_SqrtD:
assert(bt == T_DOUBLE, "must be");
return Op_SqrtVD;
return (bt == T_DOUBLE ? Op_SqrtVD : 0);
case Op_PopCountI:
if (bt == T_INT) {
return Op_PopCountVI;
}
// Unimplemented for subword types since bit count changes
// depending on size of lane (and sign bit).
return 0;
return (bt == T_INT ? Op_PopCountVI : 0);
case Op_LShiftI:
switch (bt) {
case T_BOOLEAN:
@ -200,11 +160,10 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_CHAR:
case T_SHORT: return Op_LShiftVS;
case T_INT: return Op_LShiftVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_LShiftL:
assert(bt == T_LONG, "must be");
return Op_LShiftVL;
return (bt == T_LONG ? Op_LShiftVL : 0);
case Op_RShiftI:
switch (bt) {
case T_BOOLEAN:return Op_URShiftVB; // boolean is unsigned value
@ -212,17 +171,14 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case T_BYTE: return Op_RShiftVB;
case T_SHORT: return Op_RShiftVS;
case T_INT: return Op_RShiftVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_RShiftL:
assert(bt == T_LONG, "must be");
return Op_RShiftVL;
return (bt == T_LONG ? Op_RShiftVL : 0);
case Op_URShiftB:
assert(bt == T_BYTE, "must be");
return Op_URShiftVB;
return (bt == T_BYTE ? Op_URShiftVB : 0);
case Op_URShiftS:
assert(bt == T_SHORT, "must be");
return Op_URShiftVS;
return (bt == T_SHORT ? Op_URShiftVS : 0);
case Op_URShiftI:
switch (bt) {
case T_BOOLEAN:return Op_URShiftVB;
@ -234,11 +190,10 @@ int VectorNode::opcode(int sopc, BasicType bt) {
// a short value into int value with sign
// extension before a shift.
case T_INT: return Op_URShiftVI;
default: ShouldNotReachHere(); return 0;
default: return 0;
}
case Op_URShiftL:
assert(bt == T_LONG, "must be");
return Op_URShiftVL;
return (bt == T_LONG ? Op_URShiftVL : 0);
case Op_AndI:
case Op_AndL:
return Op_AndV;
@ -372,12 +327,14 @@ bool VectorNode::is_vector_rotate_supported(int vopc, uint vlen, BasicType bt) {
}
}
bool VectorNode::is_shift(Node* n) {
switch (n->Opcode()) {
bool VectorNode::is_shift_opcode(int opc) {
switch (opc) {
case Op_LShiftI:
case Op_LShiftL:
case Op_RShiftI:
case Op_RShiftL:
case Op_URShiftB:
case Op_URShiftS:
case Op_URShiftI:
case Op_URShiftL:
return true;
@ -386,6 +343,10 @@ bool VectorNode::is_shift(Node* n) {
}
}
bool VectorNode::is_shift(Node* n) {
return is_shift_opcode(n->Opcode());
}
bool VectorNode::is_vshift_cnt(Node* n) {
switch (n->Opcode()) {
case Op_LShiftCntV:

@ -75,6 +75,8 @@ class VectorNode : public TypeNode {
static VectorNode* make(int opc, Node* n1, Node* n2, Node* n3, uint vlen, BasicType bt);
static VectorNode* make(int vopc, Node* n1, Node* n2, Node* n3, const TypeVect* vt);
static bool is_shift_opcode(int opc);
static int opcode(int opc, BasicType bt);
static int replicate_opcode(BasicType bt);
static bool implemented(int opc, uint vlen, BasicType bt);