https://gcc.gnu.org/g:7cb022442444833796b384684afef14d0b478941

commit r14-11298-g7cb022442444833796b384684afef14d0b478941
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Sat Feb 8 08:54:31 2025 +0100

    i386: Fix ICE with conditional QI/HI vector maxmin [PR118776]
    
    The following testcase ICEs starting with GCC 12 since r12-4526
    although the bug has been introduced already in r12-2751.
    The problem was in the addition of cond_<code><mode> define_expand
    which uses nonimmediate_operand predicates for both maxmin operands
    for all VI1248_AVX512VLBW modes.  It works fine with
    VI48_AVX512VL modes because the <code><mode>3_mask VI48_AVX512VL
    define_expand uses ix86_fixup_binary_operands_no_copy and the
    *avx512f_<code><mode>3<mask_name> VI48_AVX512VL define_insn uses
    % in constraint and !(MEM_P && MEM_P) check in condition (and
    <code><mode>3 define_expand with VI124_256_AVX512F_AVX512BW iterator
    does that too), but eventhough the 8-bit and 16-bit element maxmin
    is commutative too, the <mask_codefor><code><mode>3<mask_name>
    define_insn with VI12_AVX512VL iterator didn't use % in constraint
    to make it commutative.  So, e.g. cond_umaxv32qi define_expand
    allowed nonimmediate_operand for both umax operands, but used
    gen_umaxv32qi_mask which wasn't commutative and only allowed
    nonimmediate_operand for the second operand.
    
    The following patch fixes it by keeping the <code><mode>3
    VI124_256_AVX512F_AVX512BW define_expand as is (it does
    ix86_fixup_binary_operands_no_copy) but extending the
    <code><mode>3_mask define_expand from VI48_AVX512VL to
    VI1248_AVX512VLBW which keeps the current modes with their
    ISA conditions and adds the VI12_AVX512VL modes under additional
    TARGET_AVX512BW condition, and turning the actual define_insn
    into an * prefixed name (which it was before just for the non-masked
    case) and having the same commutative operand handling as in other
    define_insns.
    
    2025-02-08  Jakub Jelinek  <ja...@redhat.com>
    
            PR target/118776
            * config/i386/sse.md (<code><mode>3_mask): Use VI1248_AVX512VLBW
            iterator rather than VI48_AVX512VL.
            (<mask_codefor><code><mode>3<mask_name>): Rename to ...
            (*avx512bw_<code><mode>3<mask_name>): ... this.  Use
            nonimmediate_operand rather than register_operand predicate and %v
            rather than v constraint for operand 1 and adjust condition to 
reject
            MEMs in both operand 1 and 2.
    
            * gcc.target/i386/pr118776.c: New test.
    
    (cherry picked from commit 64d8ea056a5c339700118a412dea1c44a57acf55)

Diff:
---
 gcc/config/i386/sse.md                   | 18 +++++++++---------
 gcc/testsuite/gcc.target/i386/pr118776.c | 23 +++++++++++++++++++++++
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 111455cfcb79..67313d518530 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -16722,12 +16722,12 @@
 })
 
 (define_expand "<code><mode>3_mask"
-  [(set (match_operand:VI48_AVX512VL 0 "register_operand")
-       (vec_merge:VI48_AVX512VL
-         (maxmin:VI48_AVX512VL
-           (match_operand:VI48_AVX512VL 1 "nonimmediate_operand")
-           (match_operand:VI48_AVX512VL 2 "nonimmediate_operand"))
-         (match_operand:VI48_AVX512VL 3 "nonimm_or_0_operand")
+  [(set (match_operand:VI1248_AVX512VLBW 0 "register_operand")
+       (vec_merge:VI1248_AVX512VLBW
+         (maxmin:VI1248_AVX512VLBW
+           (match_operand:VI1248_AVX512VLBW 1 "nonimmediate_operand")
+           (match_operand:VI1248_AVX512VLBW 2 "nonimmediate_operand"))
+         (match_operand:VI1248_AVX512VLBW 3 "nonimm_or_0_operand")
          (match_operand:<avx512fmaskmode> 4 "register_operand")))]
   "TARGET_AVX512F"
   "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
@@ -16743,12 +16743,12 @@
    (set_attr "prefix" "maybe_evex")
    (set_attr "mode" "<sseinsnmode>")])
 
-(define_insn "<mask_codefor><code><mode>3<mask_name>"
+(define_insn "*avx512bw_<code><mode>3<mask_name>"
   [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
         (maxmin:VI12_AVX512VL
-          (match_operand:VI12_AVX512VL 1 "register_operand" "v")
+          (match_operand:VI12_AVX512VL 1 "nonimmediate_operand" "%v")
           (match_operand:VI12_AVX512VL 2 "nonimmediate_operand" "vm")))]
-  "TARGET_AVX512BW"
+  "TARGET_AVX512BW && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
   "vp<maxmin_int><ssemodesuffix>\t{%2, %1, 
%0<mask_operand3>|%0<mask_operand3>, %1, %2}"
   [(set_attr "type" "sseiadd")
    (set_attr "prefix" "evex")
diff --git a/gcc/testsuite/gcc.target/i386/pr118776.c 
b/gcc/testsuite/gcc.target/i386/pr118776.c
new file mode 100644
index 000000000000..44c18caf8967
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118776.c
@@ -0,0 +1,23 @@
+/* PR target/118776 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512bw -mavx512vl" } */
+
+void bar (unsigned char *);
+
+void
+foo (unsigned char *x)
+{
+  unsigned char b[32];
+  bar (b);
+  for (int i = 0; i < 32; i++)
+    {
+      unsigned char c = 8;
+      if (i > 3)
+       {
+         unsigned char d = b[i];
+         d = 1 > d ? 1 : d;
+         c = d;
+       }
+      x[i] = c;
+    }
+}

Reply via email to