From: liuhongt Date: Fri, 3 Jul 2026 13:46:32 +0000 (-0700) Subject: i386: Enable 512-bit byte dot-product only under AVX512BW [PR126098] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5be7b70e769e6e992dbf631cd37e24bd9da9e05e;p=thirdparty%2Fgcc.git i386: Enable 512-bit byte dot-product only under AVX512BW [PR126098] The byte sdot_prod/udot_prod expanders used the VI1_AVX512VNNIBW iterator, which enabled V64QI under AVX512BW || AVX512VNNI. But VNNI has no same-sign byte instruction (VPDPBUSD is mixed-sign, i.e. usdot), so the same-sign byte case always emulates via vec_unpacks/vec_unpacku, and for V64QI that widening is vpmov[sz]xbw, which needs AVX512BW. With -mavx512vnni alone the optab was offered but couldn't be emulated: (set (reg:V32HI) (sign_extend:V32HI (reg:V32QI))) fails to match, ICEing in extract_insn during vregs. Use the VI1_AVX512 iterator instead (V64QI under AVX512BW), matching the sibling usdot_prod, and drop VI1_AVX512VNNIBW. The word sdot_prod uses a separate iterator (VI2_AVX512VNNIBW) and is left unchanged: its V32HI VNNI path is vpdpwssd on the 16-bit inputs directly, so no widening is needed. gcc/ChangeLog: PR target/126098 * config/i386/sse.md (VI1_AVX512VNNIBW): Remove. (sdot_prod): Use VI1_AVX512 instead of VI1_AVX512VNNIBW so V64QI is enabled only under AVX512BW. (udot_prod): Likewise. gcc/testsuite/ChangeLog: PR target/126098 * gcc.target/i386/pr126098.c: New test. --- diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 7f652a13c87..0f35b20006d 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -631,10 +631,6 @@ (define_mode_iterator VI1_AVX512VNNI [(V64QI "TARGET_AVX512VNNI") (V32QI "TARGET_AVX2") V16QI]) -(define_mode_iterator VI1_AVX512VNNIBW - [(V64QI "TARGET_AVX512BW || TARGET_AVX512VNNI") - (V32QI "TARGET_AVX2") V16QI]) - (define_mode_iterator VI12_256_512_AVX512VL [V64QI (V32QI "TARGET_AVX512VL") V32HI (V16HI "TARGET_AVX512VL")]) @@ -32542,8 +32538,8 @@ (define_expand "sdot_prod" [(match_operand: 0 "register_operand") - (match_operand:VI1_AVX512VNNIBW 1 "register_operand") - (match_operand:VI1_AVX512VNNIBW 2 "register_operand") + (match_operand:VI1_AVX512 1 "register_operand") + (match_operand:VI1_AVX512 2 "register_operand") (match_operand: 3 "register_operand")] "TARGET_SSE2" { @@ -32590,8 +32586,8 @@ (define_expand "udot_prod" [(match_operand: 0 "register_operand") - (match_operand:VI1_AVX512VNNIBW 1 "register_operand") - (match_operand:VI1_AVX512VNNIBW 2 "register_operand") + (match_operand:VI1_AVX512 1 "register_operand") + (match_operand:VI1_AVX512 2 "register_operand") (match_operand: 3 "register_operand")] "TARGET_SSE2" { diff --git a/gcc/testsuite/gcc.target/i386/pr126098.c b/gcc/testsuite/gcc.target/i386/pr126098.c new file mode 100644 index 00000000000..afba6e60955 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126098.c @@ -0,0 +1,16 @@ +/* PR target/126098 */ +/* { dg-do compile } */ +/* { dg-options "-mavx512vnni -O3" } */ + +/* AVX512VNNI does not imply AVX512BW, so the byte (V64QI) dot-product must + not be advertised as available: emulating it needs vpmovsxbw on 512-bit + vectors, which requires AVX512BW. Advertising it led to an unrecognizable + (sign_extend:V32HI (reg:V32QI)) insn and an ICE in extract_insn. */ + +char *fn_c, *fn_d; +int fn() { + int res = 0; + for (int i = 0; i < 64; ++i) + res += fn_c[i] * fn_d[i]; + return res; +}