From 983ae96f60c935aa52f482d21ae6a0d947679541 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 21 Jan 2026 11:20:18 +0000 Subject: [PATCH] 8375498: [VectorAPI] Dump primary vector IR details with -XX:+TraceNewVectors Reviewed-by: epeter --- src/hotspot/share/opto/vectorIntrinsics.cpp | 81 ++++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 6dcf4615b10..65d54e076b6 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -74,6 +74,11 @@ static bool is_vector_mask(ciKlass* klass) { return klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); } +static Node* trace_vector(Node* operation) { + VectorNode::trace_new_vector(operation, "VectorAPI"); + return operation; +} + bool LibraryCallKit::arch_supports_vector_rotate(int opc, int num_elem, BasicType elem_bt, VectorMaskUseType mask_use_type, bool has_scalar_args) { bool is_supported = true; @@ -458,7 +463,7 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { } default: fatal("unsupported arity: %d", n); } - + trace_vector(operation); if (is_masked_op && mask != nullptr) { if (use_predicate) { operation->add_req(mask); @@ -466,7 +471,7 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { } else { operation->add_flag(Node::Flag_is_predicated_using_blend); operation = gvn().transform(operation); - operation = new VectorBlendNode(opd1, operation, mask); + operation = trace_vector(new VectorBlendNode(opd1, operation, mask)); } } operation = gvn().transform(operation); @@ -627,7 +632,7 @@ bool LibraryCallKit::inline_vector_mask_operation() { mask_vec = gvn().transform(VectorStoreMaskNode::make(gvn(), mask_vec, elem_bt, num_elem)); } const Type* maskoper_ty = mopc == Op_VectorMaskToLong ? (const Type*)TypeLong::LONG : (const Type*)TypeInt::INT; - Node* maskoper = gvn().transform(VectorMaskOpNode::make(mask_vec, maskoper_ty, mopc)); + Node* maskoper = gvn().transform(trace_vector(VectorMaskOpNode::make(mask_vec, maskoper_ty, mopc))); if (mopc != Op_VectorMaskToLong) { maskoper = ConvI2L(maskoper); } @@ -710,10 +715,10 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { if (opc == Op_VectorLongToMask) { const TypeVect* vt = TypeVect::makemask(elem_bt, num_elem); if (Matcher::mask_op_prefers_predicate(opc, vt)) { - broadcast = gvn().transform(new VectorLongToMaskNode(elem, vt)); + broadcast = gvn().transform(trace_vector(new VectorLongToMaskNode(elem, vt))); } else { const TypeVect* mvt = TypeVect::make(T_BOOLEAN, num_elem); - broadcast = gvn().transform(new VectorLongToMaskNode(elem, mvt)); + broadcast = gvn().transform(trace_vector(new VectorLongToMaskNode(elem, mvt))); broadcast = gvn().transform(new VectorLoadMaskNode(broadcast, vt)); } } else { @@ -741,7 +746,7 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { } default: fatal("%s", type2name(elem_bt)); } - broadcast = VectorNode::scalar2vector(elem, num_elem, elem_bt, is_mask); + broadcast = trace_vector(VectorNode::scalar2vector(elem, num_elem, elem_bt, is_mask)); broadcast = gvn().transform(broadcast); } @@ -927,22 +932,22 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { if (is_mask) { val = gvn().transform(VectorStoreMaskNode::make(gvn(), val, elem_bt, num_elem)); } - Node* vstore = gvn().transform(StoreVectorNode::make(0, control(), memory(addr), addr, addr_type, val, store_num_elem)); + Node* vstore = gvn().transform(trace_vector(StoreVectorNode::make(0, control(), memory(addr), addr, addr_type, val, store_num_elem))); set_memory(vstore, addr_type); } else { // When using byte array, we need to load as byte then reinterpret the value. Otherwise, do a simple vector load. Node* vload = nullptr; if (mismatched_ms) { - vload = gvn().transform(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, mem_num_elem, mem_elem_bt)); + vload = gvn().transform(trace_vector(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, mem_num_elem, mem_elem_bt))); const TypeVect* to_vect_type = TypeVect::make(elem_bt, num_elem); vload = gvn().transform(new VectorReinterpretNode(vload, vload->bottom_type()->is_vect(), to_vect_type)); } else { // Special handle for masks if (is_mask) { - vload = gvn().transform(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, num_elem, T_BOOLEAN)); + vload = gvn().transform(trace_vector(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, num_elem, T_BOOLEAN))); vload = gvn().transform(new VectorLoadMaskNode(vload, TypeVect::makemask(elem_bt, num_elem))); } else { - vload = gvn().transform(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, num_elem, elem_bt)); + vload = gvn().transform(trace_vector(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, num_elem, elem_bt))); } } Node* box = box_vector(vload, vbox_type, elem_bt, num_elem); @@ -1140,7 +1145,7 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { const TypeVect* to_mask_type = TypeVect::makemask(mem_elem_bt, mem_num_elem); mask = gvn().transform(new VectorReinterpretNode(mask, from_mask_type, to_mask_type)); } - Node* vstore = gvn().transform(new StoreVectorMaskedNode(control(), memory(addr), addr, val, addr_type, mask)); + Node* vstore = gvn().transform(trace_vector(new StoreVectorMaskedNode(control(), memory(addr), addr, val, addr_type, mask))); set_memory(vstore, addr_type); } else { Node* vload = nullptr; @@ -1155,13 +1160,13 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { if (supports_predicate) { // Generate masked load vector node if predicate feature is supported. const TypeVect* vt = TypeVect::make(mem_elem_bt, mem_num_elem); - vload = gvn().transform(new LoadVectorMaskedNode(control(), memory(addr), addr, addr_type, vt, mask)); + vload = gvn().transform(trace_vector(new LoadVectorMaskedNode(control(), memory(addr), addr, addr_type, vt, mask))); } 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, 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)); + vload = gvn().transform(trace_vector(LoadVectorNode::make(0, control(), memory(addr), addr, addr_type, mem_num_elem, mem_elem_bt))); + vload = gvn().transform(trace_vector(new VectorBlendNode(zero, vload, mask))); } if (mismatched_ms) { @@ -1365,17 +1370,17 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { Node* vstore = nullptr; if (mask != nullptr) { - vstore = gvn().transform(new StoreVectorScatterMaskedNode(control(), memory(addr), addr, addr_type, val, indexes, mask)); + vstore = gvn().transform(trace_vector(new StoreVectorScatterMaskedNode(control(), memory(addr), addr, addr_type, val, indexes, mask))); } else { - vstore = gvn().transform(new StoreVectorScatterNode(control(), memory(addr), addr, addr_type, val, indexes)); + vstore = gvn().transform(trace_vector(new StoreVectorScatterNode(control(), memory(addr), addr, addr_type, val, indexes))); } set_memory(vstore, addr_type); } else { Node* vload = nullptr; if (mask != nullptr) { - vload = gvn().transform(new LoadVectorGatherMaskedNode(control(), memory(addr), addr, addr_type, vector_type, indexes, mask)); + vload = gvn().transform(trace_vector(new LoadVectorGatherMaskedNode(control(), memory(addr), addr, addr_type, vector_type, indexes, mask))); } else { - vload = gvn().transform(new LoadVectorGatherNode(control(), memory(addr), addr, addr_type, vector_type, indexes)); + vload = gvn().transform(trace_vector(new LoadVectorGatherNode(control(), memory(addr), addr, addr_type, vector_type, indexes))); } Node* box = box_vector(vload, vbox_type, elem_bt, num_elem); set_result(box); @@ -1493,7 +1498,7 @@ bool LibraryCallKit::inline_vector_reduction() { // Make an unordered Reduction node. This affects only AddReductionVF/VD and MulReductionVF/VD, // as these operations are allowed to be associative (not requiring strict order) in VectorAPI. - value = ReductionNode::make(opc, nullptr, init, value, elem_bt, /* requires_strict_order */ false); + value = trace_vector(ReductionNode::make(opc, nullptr, init, value, elem_bt, /* requires_strict_order */ false)); if (mask != nullptr && use_predicate) { value->add_req(mask); @@ -1585,7 +1590,7 @@ bool LibraryCallKit::inline_vector_test() { return false; // operand unboxing failed } - Node* cmp = gvn().transform(new VectorTestNode(opd1, opd2, booltest)); + Node* cmp = gvn().transform(trace_vector(new VectorTestNode(opd1, opd2, booltest))); BoolTest::mask test = Matcher::vectortest_mask(booltest == BoolTest::overflow, opd1->bottom_type()->isa_vectmask(), num_elem); Node* bol = gvn().transform(new BoolNode(cmp, test)); @@ -1653,7 +1658,7 @@ bool LibraryCallKit::inline_vector_blend() { return false; // operand unboxing failed } - Node* blend = gvn().transform(new VectorBlendNode(v1, v2, mask)); + Node* blend = gvn().transform(trace_vector(new VectorBlendNode(v1, v2, mask))); Node* box = box_vector(blend, vbox_type, elem_bt, num_elem); set_result(box); @@ -1748,6 +1753,7 @@ bool LibraryCallKit::inline_vector_compare() { const TypeVect* vmask_type = TypeVect::makemask(mask_bt, num_elem); Node* operation = new VectorMaskCmpNode(pred, v1, v2, pred_node, vmask_type); + trace_vector(operation); if (is_masked_op) { if (use_predicate) { @@ -1887,6 +1893,7 @@ bool LibraryCallKit::inline_vector_rearrange() { } Node* rearrange = new VectorRearrangeNode(v1, shuffle); + trace_vector(rearrange); if (is_masked_op) { if (use_predicate) { rearrange->add_req(mask); @@ -2034,6 +2041,7 @@ bool LibraryCallKit::inline_vector_select_from() { // and finally rearrange Node* rearrange = new VectorRearrangeNode(v2, shuffle); + trace_vector(rearrange); if (is_masked_op) { if (use_predicate) { // masked rearrange is supported so use that directly @@ -2193,6 +2201,7 @@ bool LibraryCallKit::inline_vector_broadcast_int() { } Node* operation = VectorNode::make(opc, opd1, opd2, num_elem, elem_bt); + trace_vector(operation); if (is_masked_op && mask != nullptr) { if (use_predicate) { operation->add_req(mask); @@ -2370,7 +2379,7 @@ bool LibraryCallKit::inline_vector_convert() { return false; } - op = gvn().transform(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_for_cast)); + op = gvn().transform(trace_vector(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_for_cast))); // Now ensure that the destination gets properly resized to needed size. op = gvn().transform(new VectorReinterpretNode(op, op->bottom_type()->is_vect(), dst_type)); } else if (num_elem_from > num_elem_to) { @@ -2391,7 +2400,7 @@ bool LibraryCallKit::inline_vector_convert() { const TypeVect* resize_type = TypeVect::make(elem_bt_from, num_elem_for_resize); op = gvn().transform(new VectorReinterpretNode(op, src_type, resize_type)); - op = gvn().transform(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_to)); + op = gvn().transform(trace_vector(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_to))); } else { // num_elem_from == num_elem_to if (is_mask) { // Make sure that cast for vector mask is implemented to particular type/size combination. @@ -2400,16 +2409,16 @@ bool LibraryCallKit::inline_vector_convert() { num_elem_to, type2name(elem_bt_to), is_mask); return false; } - op = gvn().transform(new VectorMaskCastNode(op, dst_type)); + op = gvn().transform(trace_vector(new VectorMaskCastNode(op, dst_type))); } else { // Since input and output number of elements match, and since we know this vector size is // supported, simply do a cast with no resize needed. - op = gvn().transform(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_to)); + op = gvn().transform(trace_vector(VectorCastNode::make(cast_vopc, op, elem_bt_to, num_elem_to))); } } } else if (!Type::equals(src_type, dst_type)) { assert(!is_cast, "must be reinterpret"); - op = gvn().transform(new VectorReinterpretNode(op, src_type, dst_type)); + op = gvn().transform(trace_vector(new VectorReinterpretNode(op, src_type, dst_type))); } const TypeInstPtr* vbox_type_to = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass_to); @@ -2494,7 +2503,7 @@ bool LibraryCallKit::inline_vector_insert() { default: fatal("%s", type2name(elem_bt)); break; } - Node* operation = gvn().transform(VectorInsertNode::make(opd, insert_val, idx->get_con(), gvn())); + Node* operation = gvn().transform(trace_vector(VectorInsertNode::make(opd, insert_val, idx->get_con(), gvn()))); Node* vbox = box_vector(operation, vbox_type, elem_bt, num_elem); set_result(vbox); @@ -2552,7 +2561,7 @@ bool LibraryCallKit::inline_vector_extract() { if (opd == nullptr) { return false; } - opd = gvn().transform(VectorStoreMaskNode::make(gvn(), opd, elem_bt, num_elem)); + opd = gvn().transform(trace_vector(VectorStoreMaskNode::make(gvn(), opd, elem_bt, num_elem))); opd = gvn().transform(new ExtractUBNode(opd, pos)); opd = gvn().transform(new ConvI2LNode(opd)); } else if (arch_supports_vector(Op_VectorMaskToLong, num_elem, elem_bt, VecMaskUseLoad)) { @@ -2562,7 +2571,7 @@ bool LibraryCallKit::inline_vector_extract() { } // VectorMaskToLongNode requires the input is either a mask or a vector with BOOLEAN type. if (!Matcher::mask_op_prefers_predicate(Op_VectorMaskToLong, opd->bottom_type()->is_vect())) { - opd = gvn().transform(VectorStoreMaskNode::make(gvn(), opd, elem_bt, num_elem)); + opd = gvn().transform(trace_vector(VectorStoreMaskNode::make(gvn(), opd, elem_bt, num_elem))); } // ((toLong() >>> pos) & 1L opd = gvn().transform(new VectorMaskToLongNode(opd, TypeLong::LONG)); @@ -2680,8 +2689,8 @@ static Node* LowerSelectFromTwoVectorOperation(PhaseGVN& phase, Node* index_vec, vmask_type = TypeVect::makemask(elem_bt, num_elem); mask = phase.transform(new VectorMaskCastNode(mask, vmask_type)); - Node* p1 = phase.transform(new VectorRearrangeNode(src1, wrapped_index_vec)); - Node* p2 = phase.transform(new VectorRearrangeNode(src2, wrapped_index_vec)); + Node* p1 = phase.transform(trace_vector(new VectorRearrangeNode(src1, wrapped_index_vec))); + Node* p2 = phase.transform(trace_vector(new VectorRearrangeNode(src2, wrapped_index_vec))); return new VectorBlendNode(p2, p1, mask); } @@ -2799,7 +2808,7 @@ bool LibraryCallKit::inline_vector_select_from_two_vectors() { Node* wrap_mask = gvn().makecon(TypeInteger::make(indexRangeMask, indexRangeMask, Type::WidenMin, index_elem_bt != T_LONG ? T_INT : index_elem_bt)); Node* wrap_mask_vec = gvn().transform(VectorNode::scalar2vector(wrap_mask, num_elem, index_elem_bt, false)); opd1 = gvn().transform(VectorNode::make(Op_AndV, opd1, wrap_mask_vec, opd1->bottom_type()->is_vect())); - operation = gvn().transform(VectorNode::make(Op_SelectFromTwoVector, opd1, opd2, opd3, vt)); + operation = gvn().transform(trace_vector(VectorNode::make(Op_SelectFromTwoVector, opd1, opd2, opd3, vt))); } // Wrap it up in VectorBox to keep object type information. @@ -2884,7 +2893,7 @@ bool LibraryCallKit::inline_vector_compress_expand() { } const TypeVect* vt = TypeVect::make(elem_bt, num_elem, opc == Op_CompressM); - Node* operation = gvn().transform(VectorNode::make(opc, opd1, mask, vt)); + Node* operation = gvn().transform(trace_vector(VectorNode::make(opc, opd1, mask, vt))); // Wrap it up in VectorBox to keep object type information. const TypeInstPtr* box_type = opc == Op_CompressM ? mbox_type : vbox_type; @@ -3017,12 +3026,12 @@ bool LibraryCallKit::inline_index_vector() { default: fatal("%s", type2name(elem_bt)); } scale = gvn().transform(VectorNode::scalar2vector(scale, num_elem, elem_bt)); - index = gvn().transform(VectorNode::make(vmul_op, index, scale, vt)); + index = gvn().transform(trace_vector(VectorNode::make(vmul_op, index, scale, vt))); } // Add "opd" if addition is needed. if (needs_add) { - index = gvn().transform(VectorNode::make(vadd_op, opd, index, vt)); + index = gvn().transform(trace_vector(VectorNode::make(vadd_op, opd, index, vt))); } Node* vbox = box_vector(index, vbox_type, elem_bt, num_elem); set_result(vbox); @@ -3139,7 +3148,7 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { // Compute the vector mask with "mask = iota < indexLimit". ConINode* pred_node = (ConINode*)gvn().makecon(TypeInt::make(BoolTest::lt)); const TypeVect* vmask_type = TypeVect::makemask(elem_bt, num_elem); - mask = gvn().transform(new VectorMaskCmpNode(BoolTest::lt, iota, indexLimit, pred_node, vmask_type)); + mask = gvn().transform(trace_vector(new VectorMaskCmpNode(BoolTest::lt, iota, indexLimit, pred_node, vmask_type))); } Node* vbox = box_vector(mask, box_type, elem_bt, num_elem); set_result(vbox);