Skip to content

Commit fcc82d0

Browse files
Mohamed IssaDerek White
authored andcommitted
8360116: Add support for AVX10 floating point minmax instruction
Backport-of: 5e30bf68353d989aadc2d8176181226b2debd283
1 parent b0aebfd commit fcc82d0

7 files changed

Lines changed: 461 additions & 42 deletions

File tree

src/hotspot/cpu/x86/assembler_x86.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8222,6 +8222,14 @@ void Assembler::vmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src) {
82228222
emit_int16(0x5F, (0xC0 | encode));
82238223
}
82248224

8225+
void Assembler::eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) {
8226+
assert(VM_Version::supports_avx10_2(), "");
8227+
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
8228+
attributes.set_is_evex_instruction();
8229+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes);
8230+
emit_int24(0x53, (0xC0 | encode), imm8);
8231+
}
8232+
82258233
void Assembler::vminsh(XMMRegister dst, XMMRegister nds, XMMRegister src) {
82268234
assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16");
82278235
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
@@ -8736,12 +8744,68 @@ void Assembler::vmaxps(XMMRegister dst, XMMRegister nds, XMMRegister src, int ve
87368744
emit_int16(0x5F, (0xC0 | encode));
87378745
}
87388746

8747+
void Assembler::evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) {
8748+
assert(VM_Version::supports_avx10_2(), "");
8749+
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
8750+
attributes.set_is_evex_instruction();
8751+
attributes.set_embedded_opmask_register_specifier(mask);
8752+
if (merge) {
8753+
attributes.reset_is_clear_context();
8754+
}
8755+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
8756+
emit_int24(0x52, (0xC0 | encode), imm8);
8757+
}
8758+
8759+
void Assembler::evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) {
8760+
assert(VM_Version::supports_avx10_2(), "");
8761+
InstructionMark im(this);
8762+
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
8763+
attributes.set_is_evex_instruction();
8764+
attributes.set_embedded_opmask_register_specifier(mask);
8765+
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit);
8766+
if (merge) {
8767+
attributes.reset_is_clear_context();
8768+
}
8769+
vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
8770+
emit_int8(0x52);
8771+
emit_operand(dst, src, 0);
8772+
emit_int8(imm8);
8773+
}
8774+
87398775
void Assembler::maxpd(XMMRegister dst, XMMRegister src) {
87408776
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
87418777
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
87428778
emit_int16(0x5F, (0xC0 | encode));
87438779
}
87448780

8781+
void Assembler::evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) {
8782+
assert(VM_Version::supports_avx10_2(), "");
8783+
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true);
8784+
attributes.set_is_evex_instruction();
8785+
attributes.set_embedded_opmask_register_specifier(mask);
8786+
if (merge) {
8787+
attributes.reset_is_clear_context();
8788+
}
8789+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
8790+
emit_int24(0x52, (0xC0 | encode), imm8);
8791+
}
8792+
8793+
void Assembler::evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) {
8794+
assert(VM_Version::supports_avx10_2(), "");
8795+
InstructionMark im(this);
8796+
InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
8797+
attributes.set_is_evex_instruction();
8798+
attributes.set_embedded_opmask_register_specifier(mask);
8799+
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit);
8800+
if (merge) {
8801+
attributes.reset_is_clear_context();
8802+
}
8803+
vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
8804+
emit_int8(0x52);
8805+
emit_operand(dst, src, 0);
8806+
emit_int8(imm8);
8807+
}
8808+
87458809
void Assembler::vmaxpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
87468810
assert(vector_len >= AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx(), "");
87478811
InstructionAttr attributes(vector_len, /* vex_w */true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
@@ -13130,6 +13194,14 @@ void Assembler::vminss(XMMRegister dst, XMMRegister nds, XMMRegister src) {
1313013194
emit_int16(0x5D, (0xC0 | encode));
1313113195
}
1313213196

13197+
void Assembler::eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) {
13198+
assert(VM_Version::supports_avx10_2(), "");
13199+
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
13200+
attributes.set_is_evex_instruction();
13201+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
13202+
emit_int24(0x53, (0xC0 | encode), imm8);
13203+
}
13204+
1313313205
void Assembler::vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
1313413206
assert(VM_Version::supports_avx(), "");
1313513207
InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
@@ -13138,6 +13210,14 @@ void Assembler::vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
1313813210
emit_int16(0x5D, (0xC0 | encode));
1313913211
}
1314013212

13213+
void Assembler::eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) {
13214+
assert(VM_Version::supports_avx10_2(), "");
13215+
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
13216+
attributes.set_is_evex_instruction();
13217+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
13218+
emit_int24(0x53, (0xC0 | encode), imm8);
13219+
}
13220+
1314113221
void Assembler::vcmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) {
1314213222
assert(VM_Version::supports_avx(), "");
1314313223
assert(vector_len <= AVX_256bit, "");
@@ -16506,6 +16586,34 @@ void Assembler::evminph(XMMRegister dst, XMMRegister nds, Address src, int vecto
1650616586
emit_operand(dst, src, 0);
1650716587
}
1650816588

16589+
void Assembler::evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) {
16590+
assert(VM_Version::supports_avx10_2(), "");
16591+
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true);
16592+
attributes.set_is_evex_instruction();
16593+
attributes.set_embedded_opmask_register_specifier(mask);
16594+
if (merge) {
16595+
attributes.reset_is_clear_context();
16596+
}
16597+
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes);
16598+
emit_int24(0x52, (0xC0 | encode), imm8);
16599+
}
16600+
16601+
void Assembler::evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) {
16602+
assert(VM_Version::supports_avx10_2(), "");
16603+
InstructionMark im(this);
16604+
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
16605+
attributes.set_is_evex_instruction();
16606+
attributes.set_embedded_opmask_register_specifier(mask);
16607+
if (merge) {
16608+
attributes.reset_is_clear_context();
16609+
}
16610+
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit);
16611+
vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes);
16612+
emit_int8(0x52);
16613+
emit_operand(dst, src, 0);
16614+
emit_int8(imm8);
16615+
}
16616+
1650916617
void Assembler::evmaxph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
1651016618
assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16");
1651116619
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "");

src/hotspot/cpu/x86/assembler_x86.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,17 @@ class InstructionAttr;
441441
// See fxsave and xsave(EVEX enabled) documentation for layout
442442
const int FPUStateSizeInWords = 2688 / wordSize;
443443

444+
445+
// AVX10 new minmax instruction control mask encoding.
446+
//
447+
// imm8[4] = 0 (please refer to Table 11.1 of section 11.2 of AVX10 manual[1] for details)
448+
// imm8[3:2] (sign control) = 01 (select sign, please refer to Table 11.5 of section 11.2 of AVX10 manual[1] for details)
449+
// imm8[1:0] = 00 (min) / 01 (max)
450+
//
451+
// [1] https://www.intel.com/content/www/us/en/content-details/856721/intel-advanced-vector-extensions-10-2-intel-avx10-2-architecture-specification.html?wapkw=AVX10
452+
const int AVX10_MINMAX_MAX_COMPARE_SIGN = 0x5;
453+
const int AVX10_MINMAX_MIN_COMPARE_SIGN = 0x4;
454+
444455
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
445456
// level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write
446457
// is what you get. The Assembler is generating code into a CodeBuffer.
@@ -2752,6 +2763,17 @@ class Assembler : public AbstractAssembler {
27522763
void minpd(XMMRegister dst, XMMRegister src);
27532764
void vminpd(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len);
27542765

2766+
// AVX10.2 floating point minmax instructions
2767+
void eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8);
2768+
void eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8);
2769+
void eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8);
2770+
void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len);
2771+
void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len);
2772+
void evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len);
2773+
void evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len);
2774+
void evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len);
2775+
void evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len);
2776+
27552777
// Maximum of packed integers
27562778
void pmaxsb(XMMRegister dst, XMMRegister src);
27572779
void vpmaxsb(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len);

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,21 @@ void C2_MacroAssembler::evminmax_fp(int opcode, BasicType elem_bt,
12381238
}
12391239
}
12401240

1241+
void C2_MacroAssembler::vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask,
1242+
XMMRegister src1, XMMRegister src2, int vlen_enc) {
1243+
assert(opc == Op_MinV || opc == Op_MinReductionV ||
1244+
opc == Op_MaxV || opc == Op_MaxReductionV, "sanity");
1245+
1246+
int imm8 = (opc == Op_MinV || opc == Op_MinReductionV) ? AVX10_MINMAX_MIN_COMPARE_SIGN
1247+
: AVX10_MINMAX_MAX_COMPARE_SIGN;
1248+
if (elem_bt == T_FLOAT) {
1249+
evminmaxps(dst, mask, src1, src2, true, imm8, vlen_enc);
1250+
} else {
1251+
assert(elem_bt == T_DOUBLE, "");
1252+
evminmaxpd(dst, mask, src1, src2, true, imm8, vlen_enc);
1253+
}
1254+
}
1255+
12411256
// Float/Double signum
12421257
void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero, XMMRegister one) {
12431258
assert(opcode == Op_SignumF || opcode == Op_SignumD, "sanity");
@@ -2545,12 +2560,21 @@ void C2_MacroAssembler::reduceFloatMinMax(int opcode, int vlen, bool is_dst_vali
25452560
} else { // i = [0,1]
25462561
vpermilps(wtmp, wsrc, permconst[i], vlen_enc);
25472562
}
2548-
vminmax_fp(opcode, T_FLOAT, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc);
2563+
2564+
if (VM_Version::supports_avx10_2()) {
2565+
vminmax_fp(opcode, T_FLOAT, wdst, k0, wtmp, wsrc, vlen_enc);
2566+
} else {
2567+
vminmax_fp(opcode, T_FLOAT, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc);
2568+
}
25492569
wsrc = wdst;
25502570
vlen_enc = Assembler::AVX_128bit;
25512571
}
25522572
if (is_dst_valid) {
2553-
vminmax_fp(opcode, T_FLOAT, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit);
2573+
if (VM_Version::supports_avx10_2()) {
2574+
vminmax_fp(opcode, T_FLOAT, dst, k0, wdst, dst, Assembler::AVX_128bit);
2575+
} else {
2576+
vminmax_fp(opcode, T_FLOAT, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit);
2577+
}
25542578
}
25552579
}
25562580

@@ -2576,12 +2600,23 @@ void C2_MacroAssembler::reduceDoubleMinMax(int opcode, int vlen, bool is_dst_val
25762600
assert(i == 0, "%d", i);
25772601
vpermilpd(wtmp, wsrc, 1, vlen_enc);
25782602
}
2579-
vminmax_fp(opcode, T_DOUBLE, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc);
2603+
2604+
if (VM_Version::supports_avx10_2()) {
2605+
vminmax_fp(opcode, T_DOUBLE, wdst, k0, wtmp, wsrc, vlen_enc);
2606+
} else {
2607+
vminmax_fp(opcode, T_DOUBLE, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc);
2608+
}
2609+
25802610
wsrc = wdst;
25812611
vlen_enc = Assembler::AVX_128bit;
25822612
}
2613+
25832614
if (is_dst_valid) {
2584-
vminmax_fp(opcode, T_DOUBLE, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit);
2615+
if (VM_Version::supports_avx10_2()) {
2616+
vminmax_fp(opcode, T_DOUBLE, dst, k0, wdst, dst, Assembler::AVX_128bit);
2617+
} else {
2618+
vminmax_fp(opcode, T_DOUBLE, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit);
2619+
}
25852620
}
25862621
}
25872622

src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@
7272
XMMRegister tmp, XMMRegister atmp, XMMRegister btmp,
7373
int vlen_enc);
7474

75+
void vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask,
76+
XMMRegister src1, XMMRegister src2, int vlen_enc);
77+
7578
void vpuminmaxq(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc);
7679

7780
void evminmax_fp(int opcode, BasicType elem_bt,

src/hotspot/cpu/x86/macroAssembler_x86.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8866,6 +8866,10 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM
88668866
evpminsd(dst, mask, nds, src, merge, vector_len); break;
88678867
case T_LONG:
88688868
evpminsq(dst, mask, nds, src, merge, vector_len); break;
8869+
case T_FLOAT:
8870+
evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break;
8871+
case T_DOUBLE:
8872+
evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break;
88698873
default:
88708874
fatal("Unexpected type argument %s", type2name(type)); break;
88718875
}
@@ -8881,6 +8885,10 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM
88818885
evpmaxsd(dst, mask, nds, src, merge, vector_len); break;
88828886
case T_LONG:
88838887
evpmaxsq(dst, mask, nds, src, merge, vector_len); break;
8888+
case T_FLOAT:
8889+
evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break;
8890+
case T_DOUBLE:
8891+
evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break;
88848892
default:
88858893
fatal("Unexpected type argument %s", type2name(type)); break;
88868894
}
@@ -8896,6 +8904,10 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM
88968904
evpminsd(dst, mask, nds, src, merge, vector_len); break;
88978905
case T_LONG:
88988906
evpminsq(dst, mask, nds, src, merge, vector_len); break;
8907+
case T_FLOAT:
8908+
evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break;
8909+
case T_DOUBLE:
8910+
evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break;
88998911
default:
89008912
fatal("Unexpected type argument %s", type2name(type)); break;
89018913
}
@@ -8911,6 +8923,10 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM
89118923
evpmaxsd(dst, mask, nds, src, merge, vector_len); break;
89128924
case T_LONG:
89138925
evpmaxsq(dst, mask, nds, src, merge, vector_len); break;
8926+
case T_FLOAT:
8927+
evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break;
8928+
case T_DOUBLE:
8929+
evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break;
89148930
default:
89158931
fatal("Unexpected type argument %s", type2name(type)); break;
89168932
}

0 commit comments

Comments
 (0)