diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index d1b6897f287c8..24912fd3028b3 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -2232,6 +2232,44 @@ void Assembler::cvttss2sil(Register dst, XMMRegister src) { emit_int16(0x2C, (0xC0 | encode)); } +void Assembler::evcvttss2sisl(Register dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttss2sisl(Register dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + +void Assembler::evcvttss2sisq(Register dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttss2sisq(Register dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::cvttpd2dq(XMMRegister dst, XMMRegister src) { int vector_len = VM_Version::supports_avx512novl() ? AVX_512bit : AVX_128bit; InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2317,6 +2355,25 @@ void Assembler::vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x5B, (0xC0 | encode)); } +void Assembler::evcvttps2dqs(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttps2dqs(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::vcvttpd2dq(XMMRegister dst, XMMRegister src, int vector_len) { assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2324,6 +2381,25 @@ void Assembler::vcvttpd2dq(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16((unsigned char)0xE6, (0xC0 | encode)); } +void Assembler::evcvttpd2dqs(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttpd2dqs(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::vcvtps2dq(XMMRegister dst, XMMRegister src, int vector_len) { assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), ""); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2339,6 +2415,25 @@ void Assembler::evcvttps2qq(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x7A, (0xC0 | encode)); } +void Assembler::evcvttps2qqs(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttps2qqs(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_HV, /* input_size_in_bits */ EVEX_32bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::evcvtpd2qq(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2363,6 +2458,25 @@ void Assembler::evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x7A, (0xC0 | encode)); } +void Assembler::evcvttpd2qqs(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttpd2qqs(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::evcvtqq2pd(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -14993,6 +15107,44 @@ void Assembler::cvttsd2siq(Register dst, Address src) { emit_operand(dst, src, 0); } +void Assembler::evcvttsd2sisl(Register dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttsd2sisl(Register dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + +void Assembler::evcvttsd2sisq(Register dst, XMMRegister src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x6D, (0xC0 | encode)); +} + +void Assembler::evcvttsd2sisq(Register dst, Address src) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit); + attributes.set_is_evex_instruction(); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes); + emit_int8((unsigned char)0x6D); + emit_operand(dst, src, 0); +} + void Assembler::cvttsd2siq(Register dst, XMMRegister src) { InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 45c24f8c83256..c3b1f183b4eb2 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1309,11 +1309,19 @@ class Assembler : public AbstractAssembler { void cvttsd2sil(Register dst, XMMRegister src); void cvttsd2siq(Register dst, Address src); void cvttsd2siq(Register dst, XMMRegister src); + void evcvttsd2sisl(Register dst, XMMRegister src); + void evcvttsd2sisl(Register dst, Address src); + void evcvttsd2sisq(Register dst, XMMRegister src); + void evcvttsd2sisq(Register dst, Address src); // Convert with Truncation Scalar Single-Precision Floating-Point Value to Doubleword Integer void cvttss2sil(Register dst, XMMRegister src); void cvttss2siq(Register dst, XMMRegister src); void cvtss2sil(Register dst, XMMRegister src); + void evcvttss2sisl(Register dst, XMMRegister src); + void evcvttss2sisl(Register dst, Address src); + void evcvttss2sisq(Register dst, XMMRegister src); + void evcvttss2sisq(Register dst, Address src); // Convert vector double to int void cvttpd2dq(XMMRegister dst, XMMRegister src); @@ -1325,7 +1333,11 @@ class Assembler : public AbstractAssembler { // Convert vector float to int/long void vcvtps2dq(XMMRegister dst, XMMRegister src, int vector_len); void vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttps2dqs(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttps2dqs(XMMRegister dst, Address src, int vector_len); void evcvttps2qq(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttps2qqs(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttps2qqs(XMMRegister dst, Address src, int vector_len); // Convert vector long to vector FP void evcvtqq2ps(XMMRegister dst, XMMRegister src, int vector_len); @@ -1334,9 +1346,13 @@ class Assembler : public AbstractAssembler { // Convert vector double to long void evcvtpd2qq(XMMRegister dst, XMMRegister src, int vector_len); void evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttpd2qqs(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttpd2qqs(XMMRegister dst, Address src, int vector_len); // Convert vector double to int void vcvttpd2dq(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttpd2dqs(XMMRegister dst, XMMRegister src, int vector_len); + void evcvttpd2dqs(XMMRegister dst, Address src, int vector_len); // Evex casts with truncation void evpmovwb(XMMRegister dst, XMMRegister src, int vector_len); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 8c3f33e0aca9b..45ba50570e84f 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -5058,7 +5058,7 @@ void C2_MacroAssembler::vector_cast_int_to_subword(BasicType to_elem_bt, XMMRegi } /* - * Algorithm for vector D2L and F2I conversions:- + * Algorithm for vector D2L and F2I conversions (AVX 10.2 unsupported):- * a) Perform vector D2L/F2I cast. * b) Choose fast path if none of the result vector lane contains 0x80000000 value. * It signifies that source value could be any of the special floating point @@ -5163,6 +5163,86 @@ void C2_MacroAssembler::vector_castD2X_evex(BasicType to_elem_bt, XMMRegister ds } } +void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { + switch(to_elem_bt) { + case T_LONG: + evcvttps2qqs(dst, src, vec_enc); + break; + case T_INT: + evcvttps2dqs(dst, src, vec_enc); + break; + case T_SHORT: + evcvttps2dqs(dst, src, vec_enc); + evpmovdw(dst, dst, vec_enc); + break; + case T_BYTE: + evcvttps2dqs(dst, src, vec_enc); + evpmovdb(dst, dst, vec_enc); + break; + default: assert(false, "%s", type2name(to_elem_bt)); + } +} + +void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { + switch(to_elem_bt) { + case T_LONG: + evcvttps2qqs(dst, src, vec_enc); + break; + case T_INT: + evcvttps2dqs(dst, src, vec_enc); + break; + case T_SHORT: + evcvttps2dqs(dst, src, vec_enc); + evpmovdw(dst, dst, vec_enc); + break; + case T_BYTE: + evcvttps2dqs(dst, src, vec_enc); + evpmovdb(dst, dst, vec_enc); + break; + default: assert(false, "%s", type2name(to_elem_bt)); + } +} + +void C2_MacroAssembler::vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { + switch(to_elem_bt) { + case T_LONG: + evcvttpd2qqs(dst, src, vec_enc); + break; + case T_INT: + evcvttpd2dqs(dst, src, vec_enc); + break; + case T_SHORT: + evcvttpd2dqs(dst, src, vec_enc); + evpmovdw(dst, dst, vec_enc); + break; + case T_BYTE: + evcvttpd2dqs(dst, src, vec_enc); + evpmovdb(dst, dst, vec_enc); + break; + default: assert(false, "%s", type2name(to_elem_bt)); + } +} + +void C2_MacroAssembler::vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { + switch(to_elem_bt) { + case T_LONG: + evcvttpd2qqs(dst, src, vec_enc); + break; + case T_INT: + evcvttpd2dqs(dst, src, vec_enc); + break; + case T_SHORT: + evcvttpd2dqs(dst, src, vec_enc); + evpmovdw(dst, dst, vec_enc); + break; + case T_BYTE: + evcvttpd2dqs(dst, src, vec_enc); + evpmovdb(dst, dst, vec_enc); + break; + default: assert(false, "%s", type2name(to_elem_bt)); + } +} + void C2_MacroAssembler::vector_round_double_evex(XMMRegister dst, XMMRegister src, AddressLiteral double_sign_flip, AddressLiteral new_mxcsr, int vec_enc, Register tmp, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2) { diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 950fcb7529083..aaee25f440a69 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -347,6 +347,13 @@ XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, XMMRegister xtmp5, AddressLiteral float_sign_flip, Register rscratch, int vec_enc); + void vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); + + void vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); + + void vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); + + void vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); void vector_cast_double_to_int_special_cases_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, XMMRegister xtmp5, Register rscratch, diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 2eb748e350c05..efe0482e095ff 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -7664,8 +7664,11 @@ instruct vcastFtoD_reg(vec dst, vec src) %{ instruct castFtoX_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n->in(1)) < 64 && - type2aelembytes(Matcher::vector_element_basic_type(n)) <= 4); + predicate(!VM_Version::supports_avx10_2() && + !VM_Version::supports_avx512vl() && + Matcher::vector_length_in_bytes(n->in(1)) < 64 && + type2aelembytes(Matcher::vector_element_basic_type(n)) <= 4 && + is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastF2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP xtmp4, KILL cr); format %{ "vector_cast_f2x $dst,$src\t! using $xtmp1, $xtmp2, $xtmp3 and $xtmp4 as TEMP" %} @@ -7687,7 +7690,8 @@ instruct castFtoX_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec %} instruct castFtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rFlagsReg cr) %{ - predicate((VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n->in(1)) == 64) && + predicate(!VM_Version::supports_avx10_2() && + (VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n->in(1)) == 64) && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastF2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, KILL cr); @@ -7709,6 +7713,33 @@ instruct castFtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, k ins_pipe( pipe_slow ); %} +instruct castFtoX_reg_avx10(vec dst, vec src) %{ + predicate(VM_Version::supports_avx10_2() && + is_integral_type(Matcher::vector_element_basic_type(n))); + match(Set dst (VectorCastF2X src)); + format %{ "vector_cast_f2x_avx10 $dst, $src\t!" %} + ins_encode %{ + BasicType to_elem_bt = Matcher::vector_element_basic_type(this); + int vlen_enc = (to_elem_bt == T_LONG) ? vector_length_encoding(this) : vector_length_encoding(this, $src); + __ vector_castF2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct castFtoX_mem_avx10(vec dst, memory src) %{ + predicate(VM_Version::supports_avx10_2() && + is_integral_type(Matcher::vector_element_basic_type(n))); + match(Set dst (VectorCastF2X (LoadVector src))); + format %{ "vector_cast_f2x_avx10 $dst, $src\t!" %} + ins_encode %{ + int vlen = Matcher::vector_length(this); + BasicType to_elem_bt = Matcher::vector_element_basic_type(this); + int vlen_enc = (to_elem_bt == T_LONG) ? vector_length_encoding(this) : vector_length_encoding(vlen * sizeof(jfloat)); + __ vector_castF2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct vcastDtoF_reg(vec dst, vec src) %{ predicate(Matcher::vector_element_basic_type(n) == T_FLOAT); match(Set dst (VectorCastD2X src)); @@ -7721,7 +7752,9 @@ instruct vcastDtoF_reg(vec dst, vec src) %{ %} instruct castDtoX_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, vec xtmp5, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n->in(1)) < 64 && + predicate(!VM_Version::supports_avx10_2() && + !VM_Version::supports_avx512vl() && + Matcher::vector_length_in_bytes(n->in(1)) < 64 && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastD2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP xtmp4, TEMP xtmp5, KILL cr); @@ -7737,7 +7770,8 @@ instruct castDtoX_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec %} instruct castDtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rFlagsReg cr) %{ - predicate((VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n->in(1)) == 64) && + predicate(!VM_Version::supports_avx10_2() && + (VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n->in(1)) == 64) && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastD2X src)); effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, KILL cr); @@ -7753,6 +7787,33 @@ instruct castDtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, k ins_pipe( pipe_slow ); %} +instruct castDtoX_reg_avx10(vec dst, vec src) %{ + predicate(VM_Version::supports_avx10_2() && + is_integral_type(Matcher::vector_element_basic_type(n))); + match(Set dst (VectorCastD2X src)); + format %{ "vector_cast_d2x_avx10 $dst, $src\t!" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this, $src); + BasicType to_elem_bt = Matcher::vector_element_basic_type(this); + __ vector_castD2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct castDtoX_mem_avx10(vec dst, memory src) %{ + predicate(VM_Version::supports_avx10_2() && + is_integral_type(Matcher::vector_element_basic_type(n))); + match(Set dst (VectorCastD2X (LoadVector src))); + format %{ "vector_cast_d2x_avx10 $dst, $src\t!" %} + ins_encode %{ + int vlen = Matcher::vector_length(this); + int vlen_enc = vector_length_encoding(vlen * sizeof(jdouble)); + BasicType to_elem_bt = Matcher::vector_element_basic_type(this); + __ vector_castD2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct vucast(vec dst, vec src) %{ match(Set dst (VectorUCastB2X src)); match(Set dst (VectorUCastS2X src)); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 932dc9e1ca754..b091b39396006 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -11715,6 +11715,7 @@ instruct convD2F_reg_mem(regF dst, memory src) // XXX do mem variants instruct convF2I_reg_reg(rRegI dst, regF src, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (ConvF2I src)); effect(KILL cr); format %{ "convert_f2i $dst, $src" %} @@ -11724,8 +11725,31 @@ instruct convF2I_reg_reg(rRegI dst, regF src, rFlagsReg cr) ins_pipe(pipe_slow); %} +instruct convF2I_reg_reg_avx10(rRegI dst, regF src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvF2I src)); + format %{ "evcvttss2sisl $dst, $src" %} + ins_encode %{ + __ evcvttss2sisl($dst$$Register, $src$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + +instruct convF2I_reg_mem_avx10(rRegI dst, memory src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvF2I (LoadF src))); + format %{ "evcvttss2sisl $dst, $src" %} + ins_encode %{ + __ evcvttss2sisl($dst$$Register, $src$$Address); + %} + ins_pipe(pipe_slow); +%} + instruct convF2L_reg_reg(rRegL dst, regF src, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (ConvF2L src)); effect(KILL cr); format %{ "convert_f2l $dst, $src"%} @@ -11735,8 +11759,31 @@ instruct convF2L_reg_reg(rRegL dst, regF src, rFlagsReg cr) ins_pipe(pipe_slow); %} +instruct convF2L_reg_reg_avx10(rRegL dst, regF src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvF2L src)); + format %{ "evcvttss2sisq $dst, $src" %} + ins_encode %{ + __ evcvttss2sisq($dst$$Register, $src$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + +instruct convF2L_reg_mem_avx10(rRegL dst, memory src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvF2L (LoadF src))); + format %{ "evcvttss2sisq $dst, $src" %} + ins_encode %{ + __ evcvttss2sisq($dst$$Register, $src$$Address); + %} + ins_pipe(pipe_slow); +%} + instruct convD2I_reg_reg(rRegI dst, regD src, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (ConvD2I src)); effect(KILL cr); format %{ "convert_d2i $dst, $src"%} @@ -11746,8 +11793,31 @@ instruct convD2I_reg_reg(rRegI dst, regD src, rFlagsReg cr) ins_pipe(pipe_slow); %} +instruct convD2I_reg_reg_avx10(rRegI dst, regD src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvD2I src)); + format %{ "evcvttsd2sisl $dst, $src" %} + ins_encode %{ + __ evcvttsd2sisl($dst$$Register, $src$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + +instruct convD2I_reg_mem_avx10(rRegI dst, memory src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvD2I (LoadD src))); + format %{ "evcvttsd2sisl $dst, $src" %} + ins_encode %{ + __ evcvttsd2sisl($dst$$Register, $src$$Address); + %} + ins_pipe(pipe_slow); +%} + instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (ConvD2L src)); effect(KILL cr); format %{ "convert_d2l $dst, $src"%} @@ -11757,6 +11827,28 @@ instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr) ins_pipe(pipe_slow); %} +instruct convD2L_reg_reg_avx10(rRegL dst, regD src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvD2L src)); + format %{ "evcvttsd2sisq $dst, $src" %} + ins_encode %{ + __ evcvttsd2sisq($dst$$Register, $src$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + +instruct convD2L_reg_mem_avx10(rRegL dst, memory src) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (ConvD2L (LoadD src))); + format %{ "evcvttsd2sisq $dst, $src" %} + ins_encode %{ + __ evcvttsd2sisq($dst$$Register, $src$$Address); + %} + ins_pipe(pipe_slow); +%} + instruct round_double_reg(rRegL dst, regD src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr) %{ match(Set dst (RoundD src)); diff --git a/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java new file mode 100644 index 0000000000000..595d423506b55 --- /dev/null +++ b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2025, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** +* @test +* @bug 8364305 +* @summary Test scalar float/double to integral cast +* @requires vm.compiler2.enabled +* @library /test/lib / +* @run main/othervm/native compiler.floatingpoint.ScalarFPtoIntCastTest +*/ + +package compiler.floatingpoint; + +import compiler.lib.ir_framework.*; +import java.util.Random; + +public class ScalarFPtoIntCastTest { + private static final int COUNT = 16; + private float[] float_arr; + private double[] double_arr; + private long[] long_arr; + private int[] int_arr; + private short[] short_arr; + private byte[] byte_arr; + + public static void main(String[] args) { + TestFramework testFramework = new TestFramework(); + testFramework.setDefaultWarmup(5000).start(); + } + + public ScalarFPtoIntCastTest() { + float_arr = new float[COUNT]; + double_arr = new double[COUNT]; + long_arr = new long[COUNT]; + int_arr = new int[COUNT]; + short_arr = new short[COUNT]; + byte_arr = new byte[COUNT]; + + Random ran = new Random(0); + for (int i = 0; i < COUNT; i++) { + int floor_val = ran.nextInt(Byte.MAX_VALUE); + int ceil_val = floor_val + 1; + long_arr[i] = (long) floor_val; + int_arr[i] = floor_val; + short_arr[i] = (short) floor_val; + byte_arr[i] = (byte) floor_val; + float_arr[i] = ran.nextFloat(floor_val, ceil_val); + double_arr[i] = ran.nextDouble(floor_val, ceil_val); + } + } + + @Test + @IR(counts = {IRNode.CONV_F2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void float2int() { + checkf2int(); + } + + public void checkf2int() { + for (int i = 0; i < COUNT; i++) { + float float_val = float_arr[i]; + int expected = (int) float_val; + if (int_arr[i] != expected) { + throw new RuntimeException("Invalid result: int_arr[" + i + "] = " + int_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_F2L, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_F2L, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_F2L_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void float2long() { + checkf2long(); + } + + public void checkf2long() { + for (int i = 0; i < COUNT; i++) { + float float_val = float_arr[i]; + long expected = (long) float_val; + if (long_arr[i] != expected) { + throw new RuntimeException("Invalid result: long_arr[" + i + "] = " + long_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_F2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void float2short() { + checkf2short(); + } + + public void checkf2short() { + for (int i = 0; i < COUNT; i++) { + float float_val = float_arr[i]; + short expected = (short) float_val; + if (short_arr[i] != expected) { + throw new RuntimeException("Invalid result: short_arr[" + i + "] = " + short_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_F2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void float2byte() { + checkf2byte(); + } + + public void checkf2byte() { + for (int i = 0; i < COUNT; i++) { + float float_val = float_arr[i]; + byte expected = (byte) float_val; + if (byte_arr[i] != expected) { + throw new RuntimeException("Invalid result: byte_arr[" + i + "] = " + byte_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_D2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void double2int() { + checkd2int(); + } + + public void checkd2int() { + for (int i = 0; i < COUNT; i++) { + double double_val = double_arr[i]; + int expected = (int) double_val; + if (int_arr[i] != expected) { + throw new RuntimeException("Invalid result: int_arr[" + i + "] = " + int_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_D2L, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_D2L, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_D2L_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void double2long() { + checkd2long(); + } + + public void checkd2long() { + for (int i = 0; i < COUNT; i++) { + double double_val = double_arr[i]; + long expected = (long) double_val; + if (long_arr[i] != expected) { + throw new RuntimeException("Invalid result: long_arr[" + i + "] = " + long_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_D2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void double2short() { + checkd2short(); + } + + public void checkd2short() { + for (int i = 0; i < COUNT; i++) { + double double_val = double_arr[i]; + short expected = (short) double_val; + if (short_arr[i] != expected) { + throw new RuntimeException("Invalid result: short_arr[" + i + "] = " + short_arr[i] + " != " + expected); + } + } + } + + @Test + @IR(counts = {IRNode.CONV_D2I, "> 0"}) + @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfCPUFeature = {"avx10_2", "false"}) + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) + public void double2byte() { + checkd2byte(); + } + + public void checkd2byte() { + for (int i = 0; i < COUNT; i++) { + double double_val = double_arr[i]; + byte expected = (byte) double_val; + if (byte_arr[i] != expected) { + throw new RuntimeException("Invalid result: byte_arr[" + i + "] = " + byte_arr[i] + " != " + expected); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 7fb1eeb800c91..2bffac20c8918 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -610,11 +610,31 @@ public class IRNode { beforeMatchingNameRegex(CONV, "Conv"); } + public static final String CONV_D2I = PREFIX + "CONV_D2I" + POSTFIX; + static { + beforeMatchingNameRegex(CONV_D2I, "ConvD2I"); + } + + public static final String CONV_D2L = PREFIX + "CONV_D2L" + POSTFIX; + static { + beforeMatchingNameRegex(CONV_D2L, "ConvD2L"); + } + public static final String CONV_F2HF = PREFIX + "CONV_F2HF" + POSTFIX; static { beforeMatchingNameRegex(CONV_F2HF, "ConvF2HF"); } + public static final String CONV_F2I = PREFIX + "CONV_F2I" + POSTFIX; + static { + beforeMatchingNameRegex(CONV_F2I, "ConvF2I"); + } + + public static final String CONV_F2L = PREFIX + "CONV_F2L" + POSTFIX; + static { + beforeMatchingNameRegex(CONV_F2L, "ConvF2L"); + } + public static final String CONV_I2L = PREFIX + "CONV_I2L" + POSTFIX; static { beforeMatchingNameRegex(CONV_I2L, "ConvI2L"); @@ -2665,6 +2685,66 @@ public class IRNode { machOnlyNameRegex(VSTOREMASK_TRUECOUNT, "vstoremask_truecount_neon"); } + public static final String X86_SCONV_D2I = PREFIX + "X86_SCONV_D2I" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_D2I, "convD2I_reg_reg"); + } + + public static final String X86_SCONV_D2L = PREFIX + "X86_SCONV_D2L" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_D2L, "convD2L_reg_reg"); + } + + public static final String X86_SCONV_F2I = PREFIX + "X86_SCONV_F2I" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_F2I, "convF2I_reg_reg"); + } + + public static final String X86_SCONV_F2L = PREFIX + "X86_SCONV_F2L" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_F2L, "convF2L_reg_reg"); + } + + public static final String X86_SCONV_D2I_AVX10 = PREFIX + "X86_SCONV2_D2I_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_D2I_AVX10, "convD2I_(reg_reg|reg_mem)_avx10"); + } + + public static final String X86_SCONV_D2L_AVX10 = PREFIX + "X86_SCONV_D2L_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_D2L_AVX10, "convD2L_(reg_reg|reg_mem)_avx10"); + } + + public static final String X86_SCONV_F2I_AVX10 = PREFIX + "X86_SCONV_F2I_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_F2I_AVX10, "convF2I_(reg_reg|reg_mem)_avx10"); + } + + public static final String X86_SCONV_F2L_AVX10 = PREFIX + "X86_SCONV_F2L_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_SCONV_F2L_AVX10, "convF2L_(reg_reg|reg_mem)_avx10"); + } + + public static final String X86_VCAST_F2X = PREFIX + "X86_VCAST_F2X" + POSTFIX; + static { + machOnlyNameRegex(X86_VCAST_F2X, "castFtoX_reg_(av|eve)x"); + } + + public static final String X86_VCAST_D2X = PREFIX + "X86_VCAST_D2X" + POSTFIX; + static { + machOnlyNameRegex(X86_VCAST_D2X, "castDtoX_reg_(av|eve)x"); + } + + public static final String X86_VCAST_F2X_AVX10 = PREFIX + "X86_VCAST_F2X_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_VCAST_F2X_AVX10, "castFtoX_(reg|mem)_avx10"); + } + + public static final String X86_VCAST_D2X_AVX10 = PREFIX + "X86_VCAST_D2X_AVX10" + POSTFIX; + static { + machOnlyNameRegex(X86_VCAST_D2X_AVX10, "castDtoX_(reg|mem)_avx10"); + } + public static final String XOR = PREFIX + "XOR" + POSTFIX; static { beforeMatchingNameRegex(XOR, "Xor(I|L)"); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 16b4654013af6..c05124edcd78c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -106,6 +106,7 @@ public class IREncodingPrinter { "avx512_fp16", "avx512_vnni", "avx512_vbmi", + "avx10_2", "bmi2", // AArch64 "sha3", diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java index 8d5d872375ff2..1037a2989f92e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -23,8 +23,8 @@ /** * @test -* @bug 8287835 -* @summary Test float/double to integral cast +* @bug 8287835 8364305 +* @summary Test vector float/double to integral cast * @modules jdk.incubator.vector * @requires vm.compiler2.enabled * @library /test/lib / @@ -87,7 +87,11 @@ public VectorFPtoIntCastTest() { @Test @IR(counts = {IRNode.VECTOR_CAST_F2I, IRNode.VECTOR_SIZE_16, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void float2int() { var cvec = (IntVector)fvec512.convertShape(VectorOperators.F2I, ispec512, 0); cvec.intoArray(int_arr, 0); @@ -96,7 +100,7 @@ public void float2int() { public void checkf2int(int len) { for (int i = 0; i < len; i++) { - int expected = (int)float_arr[i]; + int expected = (int) float_arr[i]; if (int_arr[i] != expected) { throw new RuntimeException("Invalid result: int_arr[" + i + "] = " + int_arr[i] + " != " + expected); } @@ -105,7 +109,11 @@ public void checkf2int(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_F2L, IRNode.VECTOR_SIZE_8, "> 0"}, - applyIfCPUFeature = {"avx512dq", "true"}) + applyIfCPUFeatureOr = {"avx512dq", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void float2long() { var cvec = (LongVector)fvec512.convertShape(VectorOperators.F2L, lspec512, 0); cvec.intoArray(long_arr, 0); @@ -114,7 +122,7 @@ public void float2long() { public void checkf2long(int len) { for (int i = 0; i < len; i++) { - long expected = (long)float_arr[i]; + long expected = (long) float_arr[i]; if (long_arr[i] != expected) { throw new RuntimeException("Invalid result: long_arr[" + i + "] = " + long_arr[i] + " != " + expected); } @@ -123,7 +131,11 @@ public void checkf2long(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE_16, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void float2short() { var cvec = (ShortVector)fvec512.convertShape(VectorOperators.F2S, sspec256, 0); cvec.intoArray(short_arr, 0); @@ -132,7 +144,7 @@ public void float2short() { public void checkf2short(int len) { for (int i = 0; i < len; i++) { - short expected = (short)float_arr[i]; + short expected = (short) float_arr[i]; if (short_arr[i] != expected) { throw new RuntimeException("Invalid result: short_arr[" + i + "] = " + short_arr[i] + " != " + expected); } @@ -141,7 +153,11 @@ public void checkf2short(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_F2B, IRNode.VECTOR_SIZE_16, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void float2byte() { var cvec = (ByteVector)fvec512.convertShape(VectorOperators.F2B, bspec128, 0); cvec.intoArray(byte_arr, 0); @@ -150,7 +166,7 @@ public void float2byte() { public void checkf2byte(int len) { for (int i = 0; i < len; i++) { - byte expected = (byte)float_arr[i]; + byte expected = (byte) float_arr[i]; if (byte_arr[i] != expected) { throw new RuntimeException("Invalid result: byte_arr[" + i + "] = " + byte_arr[i] + " != " + expected); } @@ -159,7 +175,11 @@ public void checkf2byte(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_D2I, IRNode.VECTOR_SIZE_8, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void double2int() { var cvec = (IntVector)dvec512.convertShape(VectorOperators.D2I, ispec256, 0); cvec.intoArray(int_arr, 0); @@ -168,7 +188,7 @@ public void double2int() { public void checkd2int(int len) { for (int i = 0; i < len; i++) { - int expected = (int)double_arr[i]; + int expected = (int) double_arr[i]; if (int_arr[i] != expected) { throw new RuntimeException("Invalid result: int_arr[" + i + "] = " + int_arr[i] + " != " + expected); } @@ -177,7 +197,11 @@ public void checkd2int(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_D2L, IRNode.VECTOR_SIZE_8, "> 0"}, - applyIfCPUFeature = {"avx512dq", "true"}) + applyIfCPUFeatureOr = {"avx512dq", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void double2long() { var cvec = (LongVector)dvec512.convertShape(VectorOperators.D2L, lspec512, 0); cvec.intoArray(long_arr, 0); @@ -186,7 +210,7 @@ public void double2long() { public void checkd2long(int len) { for (int i = 0; i < len; i++) { - long expected = (long)double_arr[i]; + long expected = (long) double_arr[i]; if (long_arr[i] != expected) { throw new RuntimeException("Invalid result: long_arr[" + i + "] = " + long_arr[i] + " != " + expected); } @@ -195,7 +219,11 @@ public void checkd2long(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE_8, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void double2short() { var cvec = (ShortVector)dvec512.convertShape(VectorOperators.D2S, sspec128, 0); cvec.intoArray(short_arr, 0); @@ -204,7 +232,7 @@ public void double2short() { public void checkd2short(int len) { for (int i = 0; i < len; i++) { - short expected = (short)double_arr[i]; + short expected = (short) double_arr[i]; if (short_arr[i] != expected) { throw new RuntimeException("Invalid result: short_arr[" + i + "] = " + short_arr[i] + " != " + expected); } @@ -213,7 +241,11 @@ public void checkd2short(int len) { @Test @IR(counts = {IRNode.VECTOR_CAST_D2B, IRNode.VECTOR_SIZE_8, "> 0"}, - applyIfCPUFeature = {"avx512f", "true"}) + applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public void double2byte() { var cvec = (ByteVector)dvec512.convertShape(VectorOperators.D2B, bspec64, 0); cvec.intoArray(byte_arr, 0); @@ -222,7 +254,7 @@ public void double2byte() { public void checkd2byte(int len) { for (int i = 0; i < len; i++) { - byte expected = (byte)double_arr[i]; + byte expected = (byte) double_arr[i]; if (byte_arr[i] != expected) { throw new RuntimeException("Invalid result: byte_arr[" + i + "] = " + byte_arr[i] + " != " + expected); } diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java index 3fa636b42f78e..4db973ff7287c 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java @@ -294,8 +294,12 @@ public double[] convertCharToDouble() { // ---------------- Convert F/D to I/L ---------------- @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, - counts = {IRNode.VECTOR_CAST_F2I, IRNode.VECTOR_SIZE + "min(max_float, max_int)", ">0"}) + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "avx10_2", "true", "rvv", "true"}, + counts = {IRNode.VECTOR_CAST_F2I, IRNode.VECTOR_SIZE + "min(max_float, max_int)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public int[] convertFloatToInt() { int[] res = new int[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -305,8 +309,12 @@ public int[] convertFloatToInt() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "rvv", "true"}, - counts = {IRNode.VECTOR_CAST_F2L, IRNode.VECTOR_SIZE + "min(max_float, max_long)", ">0"}) + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "avx10_2", "true", "rvv", "true"}, + counts = {IRNode.VECTOR_CAST_F2L, IRNode.VECTOR_SIZE + "min(max_float, max_long)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public long[] convertFloatToLong() { long[] res = new long[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -316,8 +324,12 @@ public long[] convertFloatToLong() { } @Test - @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "rvv", "true"}, - counts = {IRNode.VECTOR_CAST_D2I, IRNode.VECTOR_SIZE + "min(max_double, max_int)", ">0"}) + @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "avx10_2", "true", "rvv", "true"}, + counts = {IRNode.VECTOR_CAST_D2I, IRNode.VECTOR_SIZE + "min(max_double, max_int)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public int[] convertDoubleToInt() { int[] res = new int[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -327,8 +339,12 @@ public int[] convertDoubleToInt() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "rvv", "true"}, - counts = {IRNode.VECTOR_CAST_D2L, IRNode.VECTOR_SIZE + "min(max_double, max_long)", ">0"}) + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "avx10_2", "true", "rvv", "true"}, + counts = {IRNode.VECTOR_CAST_D2L, IRNode.VECTOR_SIZE + "min(max_double, max_long)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIfCPUFeature = {"avx10_2", "true"}) public long[] convertDoubleToLong() { long[] res = new long[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -339,9 +355,15 @@ public long[] convertDoubleToLong() { // ---------------- Convert F/D to Subword-I ---------------- @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "avx10_2", "true", "rvv", "true"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, - counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_short)", ">0"}) + counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_short)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, + applyIfCPUFeature = {"avx10_2", "true"}) public short[] convertFloatToShort() { short[] res = new short[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -358,9 +380,15 @@ public short[] convertFloatToShort() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "avx10_2", "true", "rvv", "true"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, - counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_char)", ">0"}) + counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_char)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, + applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, + applyIfCPUFeature = {"avx10_2", "true"}) public char[] convertFloatToChar() { char[] res = new char[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -379,10 +407,16 @@ public char[] convertFloatToChar() { @Test @IR(applyIfCPUFeature = {"rvv", "true"}, applyIf = {"MaxVectorSize", ">=32"}, - counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_short)", ">0"}) - @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true"}, + counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_short)", "> 0"}) + @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "avx10_2", "true"}, + applyIf = {"MaxVectorSize", ">=16"}, + counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_short)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, - counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_short)", ">0"}) + applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + applyIf = {"MaxVectorSize", ">=16"}, + applyIfCPUFeature = {"avx10_2", "true"}) public short[] convertDoubleToShort() { short[] res = new short[SIZE]; for (int i = 0; i < SIZE; i++) { @@ -393,11 +427,17 @@ public short[] convertDoubleToShort() { @Test @IR(applyIfCPUFeature = {"rvv", "true"}, - applyIf = {"MaxVectorSize", ">=32"}, - counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_char)", ">0"}) - @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true"}, + applyIf = {"MaxVectorSize", ">= 32"}, + counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_char)", "> 0"}) + @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "avx10_2", "true"}, + applyIf = {"MaxVectorSize", ">= 16"}, + counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_char)", "> 0"}) + @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, + applyIf = {"MaxVectorSize", ">=16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, - counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_char)", ">0"}) + applyIfCPUFeature = {"avx10_2", "true"}) public char[] convertDoubleToChar() { char[] res = new char[SIZE]; for (int i = 0; i < SIZE; i++) {