]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Enable 512-bit byte dot-product only under AVX512BW [PR126098]
authorliuhongt <hongtao.liu@intel.com>
Fri, 3 Jul 2026 13:46:32 +0000 (06:46 -0700)
committerliuhongt <hongtao.liu@intel.com>
Mon, 6 Jul 2026 02:28:12 +0000 (19:28 -0700)
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<ssedvecmodelower><mode>): Use VI1_AVX512 instead of
VI1_AVX512VNNIBW so V64QI is enabled only under AVX512BW.
(udot_prod<ssedvecmodelower><mode>): Likewise.

gcc/testsuite/ChangeLog:

PR target/126098
* gcc.target/i386/pr126098.c: New test.

gcc/config/i386/sse.md
gcc/testsuite/gcc.target/i386/pr126098.c [new file with mode: 0644]

index 7f652a13c87d0cc09a4894b39dd27b3c9eda787f..0f35b20006dc61e1159e68dc5bbabfe7ad5afe6c 100644 (file)
 (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")])
 
 (define_expand "sdot_prod<ssedvecmodelower><mode>"
   [(match_operand:<ssedvecmode> 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:<ssedvecmode> 3 "register_operand")]
   "TARGET_SSE2"
 {
 
 (define_expand "udot_prod<ssedvecmodelower><mode>"
   [(match_operand:<ssedvecmode> 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:<ssedvecmode> 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 (file)
index 0000000..afba6e6
--- /dev/null
@@ -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;
+}