https://gcc.gnu.org/g:30bdb83cf272c702487a72a715890994056319fe

commit r17-5211-g30bdb83cf272c702487a72a715890994056319fe
Author: Hongyu Wang <[email protected]>
Date:   Mon Oct 12 17:14:56 2026 +0800

    i386: Raise FE_INVALID for vector LTGT compares [PR127649]
    
    LTGT is a signaling compare and must raise FE_INVALID on a quiet NaN,
    like the scalar comiss it expands to. The vector expansion used quiet
    compares instead: NEQ_OQ for AVX and AVX512, and ORDERED & NE for SSE.
    
    Use the signaling NEQ_OS predicate for AVX and AVX512. Legacy SSE has
    no ordered not-equal predicate, so expand LTGT as LT | GT, which uses
    the signaling cmpltps and needs no extra instruction.
    
    gcc/ChangeLog:
    
            PR target/127649
            * config/i386/i386-expand.cc (ix86_fp_cmp_code_to_pcmp_immediate):
            Use NEQ_OS for LTGT.
            (ix86_expand_fp_vec_cmp): Expand LTGT as LT | GT.
            * config/i386/i386.cc (ix86_print_operand): Print neq_os for LTGT.
    
    gcc/testsuite/ChangeLog:
    
            PR target/127649
            * gcc.target/i386/pr127649-1.c: New test.
            * gcc.target/i386/pr127649-2.c: Likewise.

Diff:
---
 gcc/config/i386/i386-expand.cc             | 10 +++----
 gcc/config/i386/i386.cc                    |  2 +-
 gcc/testsuite/gcc.target/i386/pr127649-1.c | 37 ++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr127649-2.c | 46 ++++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 6 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index a9654e9a8354..deae439814b6 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -4818,7 +4818,7 @@ ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
     case UNEQ:
       return 0x08;
     case LTGT:
-      return 0x0c;
+      return 0x1c;
     case ORDERED:
       return 0x07;
     case UNORDERED:
@@ -4886,11 +4886,11 @@ ix86_expand_fp_vec_cmp (rtx operands[])
       switch (GET_CODE (operands[1]))
        {
        case LTGT:
-         temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
+         temp = ix86_expand_sse_cmp (operands[0], LT, operands[2],
                                      operands[3], NULL, NULL);
-         cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
-                                    operands[3], NULL, NULL);
-         code = AND;
+         cmp = ix86_expand_sse_cmp (operands[0], LT, operands[3],
+                                    operands[2], NULL, NULL);
+         code = IOR;
          break;
        case UNEQ:
          temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 4dba04774e86..8dc89f2dcde3 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -14545,7 +14545,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
            case LTGT:
              if (TARGET_AVX)
                {
-                 fputs ("neq_oq", file);
+                 fputs ("neq_os", file);
                  break;
                }
             /* FALLTHRU */
diff --git a/gcc/testsuite/gcc.target/i386/pr127649-1.c 
b/gcc/testsuite/gcc.target/i386/pr127649-1.c
new file mode 100644
index 000000000000..e1b1cb981dc8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127649-1.c
@@ -0,0 +1,37 @@
+/* PR target/127649 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx" } */
+
+/* LTGT is a signaling compare.  Use LT | GT for SSE and the NEQ_OS
+   predicate for AVX.  */
+
+void
+ltgt_sse (int *r, float *a, float *b)
+{
+  for (int i = 0; i < 1024; i++)
+    r[i] = (a[i] < b[i]) | (a[i] > b[i]);
+}
+
+__attribute__((target ("avx,no-avx512f")))
+void
+ltgt_avx (int *r, float *a, float *b)
+{
+  for (int i = 0; i < 1024; i++)
+    r[i] = (a[i] < b[i]) | (a[i] > b[i]);
+}
+
+__attribute__((target ("avx512vl")))
+void
+ltgt_avx512 (int *r, float *a, float *b)
+{
+  for (int i = 0; i < 1024; i++)
+    r[i] = (a[i] < b[i]) | (a[i] > b[i]);
+}
+
+/* { dg-final { scan-assembler-times "\[ \t\]cmpltps" 2 } } */
+/* { dg-final { scan-assembler-not "\[ \t\]cmpordps" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]cmpneqps" } } */
+/* { dg-final { scan-assembler-times "vcmpneq_osps" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpps\[ \t\]*\\\$28," 1 } } */
+/* { dg-final { scan-assembler-not "vcmpneq_oqps" } } */
+/* { dg-final { scan-assembler-not "vcmpps\[ \t\]*\\\$12," } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr127649-2.c 
b/gcc/testsuite/gcc.target/i386/pr127649-2.c
new file mode 100644
index 000000000000..04d74a229363
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127649-2.c
@@ -0,0 +1,46 @@
+/* PR target/127649 */
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2 -mno-avx" } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-additional-options "-mfpmath=sse" { target ia32 } } */
+
+#include <fenv.h>
+#include "pr127649-1.c"
+
+#define N 1024
+
+static float a[N], b[N];
+static int r[N];
+
+static void
+check (void (*fn) (int *, float *, float *))
+{
+  for (int i = 0; i < N; i++)
+    r[i] = -1;
+  feclearexcept (FE_ALL_EXCEPT);
+  fn (r, a, b);
+  if (!fetestexcept (FE_INVALID))
+    __builtin_abort ();
+  for (int i = 0; i < N; i++)
+    if (r[i] != 0)
+      __builtin_abort ();
+}
+
+int
+main (void)
+{
+  __builtin_cpu_init ();
+
+  for (int i = 0; i < N; i++)
+    {
+      a[i] = __builtin_nanf ("");
+      b[i] = 1.0f;
+    }
+
+  check (ltgt_sse);
+  if (__builtin_cpu_supports ("avx"))
+    check (ltgt_avx);
+  if (__builtin_cpu_supports ("avx512vl"))
+    check (ltgt_avx512);
+  return 0;
+}

Reply via email to