Hi,

The unordered compares (UNLT, UNLE, UNGT, UNGE and UNEQ) must not raise
FE_INVALID on a quiet NaN.  AVX and AVX512 have an imm8 encoding for the
quiet _UQ predicate of each, so just select it.

Legacy SSE2 has only 8 predicates and can express UNGE/UNGT/UNLT/UNLE
only as the signaling NLT/NLE. So reject those four codes in the packed
FP vec_cmp expanders under trapping math and NaNs are honored.

Bootstrapped & regtested under x86_64-pc-linux-gnu. Ok for trunk?

gcc/ChangeLog:

        PR target/127177
        * config/i386/i386-expand.cc (ix86_fp_cmp_code_to_pcmp_immediate):
        Return the _UQ predicate immediates for UNLE, UNLT, UNGE, UNGT and
        UNEQ.
        * config/i386/i386.cc (ix86_print_operand):Likewise to print the
        _uq suffixed AVX predicates for these codes.
        * config/i386/predicates.md (ix86_fp_vec_cmp_operator): New
        predicate.
        * config/i386/sse.md (vec_cmp<mode><sseintvecmodelower>): Use the
        new predicate for the VF_128 compare.
        * config/i386/mmx.md (vec_cmpv2sfv2si): Likewise.

gcc/testsuite/ChangeLog:

        PR target/127177
        * gcc.target/i386/pr127177-1.c: New test.
        * gcc.target/i386/pr127177-2.c: Likewise.
        * gcc.target/i386/pr127177-3.c: Likewise.
        * gcc.target/i386/pr127177-4.c: Likewise.
        * gcc.target/i386/pr127177-5.c: Likewise.
---
 gcc/config/i386/i386-expand.cc             | 10 +++---
 gcc/config/i386/i386.cc                    | 11 +++---
 gcc/config/i386/mmx.md                     |  2 +-
 gcc/config/i386/predicates.md              | 10 ++++++
 gcc/config/i386/sse.md                     |  2 +-
 gcc/testsuite/gcc.target/i386/pr127177-1.c | 27 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr127177-2.c | 13 ++++++++
 gcc/testsuite/gcc.target/i386/pr127177-3.c | 13 ++++++++
 gcc/testsuite/gcc.target/i386/pr127177-4.c |  9 +++++
 gcc/testsuite/gcc.target/i386/pr127177-5.c | 39 ++++++++++++++++++++++
 10 files changed, 124 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr127177-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr127177-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr127177-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr127177-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr127177-5.c

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 1b76fe91ca2..d567bd74a99 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -4803,15 +4803,15 @@ ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
     case LT:
       return 0x01;
     case UNLE:
-      return 0x0a;
+      return 0x1a;
     case UNLT:
-      return 0x09;
+      return 0x19;
     case UNGE:
-      return 0x05;
+      return 0x15;
     case UNGT:
-      return 0x06;
+      return 0x16;
     case UNEQ:
-      return 0x18;
+      return 0x08;
     case LTGT:
       return 0x0c;
     case ORDERED:
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3f00ddaa547..6fce408aa43 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -14489,7 +14489,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
            case UNEQ:
              if (TARGET_AVX)
                {
-                 fputs ("eq_us", file);
+                 fputs ("eq_uq", file);
                  break;
                }
             /* FALLTHRU */
@@ -14499,7 +14499,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
            case UNLT:
              if (TARGET_AVX)
                {
-                 fputs ("nge", file);
+                 fputs ("nge_uq", file);
                  break;
                }
             /* FALLTHRU */
@@ -14509,7 +14509,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
            case UNLE:
              if (TARGET_AVX)
                {
-                 fputs ("ngt", file);
+                 fputs ("ngt_uq", file);
                  break;
                }
             /* FALLTHRU */
@@ -14537,7 +14537,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
                }
             /* FALLTHRU */
            case UNGE:
-             fputs ("nlt", file);
+             /* Only AVX has the quiet form.  */
+             fputs (TARGET_AVX ? "nlt_uq" : "nlt", file);
              break;
            case GT:
              if (TARGET_AVX)
@@ -14547,7 +14548,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
                }
             /* FALLTHRU */
            case UNGT:
-             fputs ("nle", file);
+             fputs (TARGET_AVX ? "nle_uq" : "nle", file);
              break;
            case ORDERED:
              fputs ("ord", file);
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 640b2c0e63f..fc6286cfed2 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -1254,7 +1254,7 @@ (define_insn "mmx_gev2sf3"
 
 (define_expand "vec_cmpv2sfv2si"
   [(set (match_operand:V2SI 0 "register_operand")
-       (match_operator:V2SI 1 ""
+       (match_operator:V2SI 1 "ix86_fp_vec_cmp_operator"
          [(match_operand:V2SF 2 "nonimmediate_operand")
           (match_operand:V2SF 3 "nonimmediate_operand")]))]
   "TARGET_MMX_WITH_SSE && ix86_partial_vec_fp_math"
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 289bf807e11..6e805d8ac64 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1568,6 +1568,16 @@ (define_predicate "sse_comparison_operator"
        (and (match_test "TARGET_AVX")
            (match_code "ge,gt,uneq,unle,unlt,ltgt"))))
 
+;; SSE2 doesn't have quiet vector compare for LT/LE/GT/GE, so
+;; disable them under trapping-math or HONOR_NANS.
+
+(define_predicate "ix86_fp_vec_cmp_operator"
+  (and (match_operand 0 "comparison_operator")
+       (ior (not (match_code "unlt,unle,ungt,unge"))
+           (match_test "TARGET_AVX
+                        || !flag_trapping_math
+                        || !HONOR_NANS (GET_MODE (XEXP (op, 0)))"))))
+
 (define_predicate "ix86_comparison_int_operator"
   (match_code "ne,eq,ge,gt,le,lt"))
 
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index fe25d3cdce4..c74d88f1b12 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -5431,7 +5431,7 @@ (define_expand "vec_cmp<mode><sseintvecmodelower>"
 
 (define_expand "vec_cmp<mode><sseintvecmodelower>"
   [(set (match_operand:<sseintvecmode> 0 "register_operand")
-       (match_operator:<sseintvecmode> 1 ""
+       (match_operator:<sseintvecmode> 1 "ix86_fp_vec_cmp_operator"
          [(match_operand:VF_128 2 "register_operand")
           (match_operand:VF_128 3 "vector_operand")]))]
   "TARGET_SSE"
diff --git a/gcc/testsuite/gcc.target/i386/pr127177-1.c 
b/gcc/testsuite/gcc.target/i386/pr127177-1.c
new file mode 100644
index 00000000000..979c677d3d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127177-1.c
@@ -0,0 +1,27 @@
+/* PR target/127177 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mno-avx512f -ftrapping-math 
-fdump-tree-vect-details" } */
+
+/* The unordered compares are quiet, under AVX use the _uq predicates by
+   force.  */
+
+#define TEST(NAME, EXPR)                       \
+  void NAME (int *r, float *a, float *b)       \
+  {                                            \
+    for (int i = 0; i < 1024; i++)             \
+      r[i] = EXPR;                             \
+  }
+
+TEST (t_isless, __builtin_isless (a[i], b[i]))
+TEST (t_islessequal, __builtin_islessequal (a[i], b[i]))
+TEST (t_isgreater, __builtin_isgreater (a[i], b[i]))
+TEST (t_isgreaterequal, __builtin_isgreaterequal (a[i], b[i]))
+TEST (t_uneq, !__builtin_islessgreater (a[i], b[i]))
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 5 "vect" } } */
+/* { dg-final { scan-assembler-times "vcmpnlt_uqps" 2 } } */
+/* { dg-final { scan-assembler-times "vcmpnle_uqps" 2 } } */
+/* { dg-final { scan-assembler-times "vcmpeq_uqps" 1 } } */
+/* { dg-final { scan-assembler-not "vcmpnltps" } } */
+/* { dg-final { scan-assembler-not "vcmpnleps" } } */
+/* { dg-final { scan-assembler-not "vcmpeq_usps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr127177-2.c 
b/gcc/testsuite/gcc.target/i386/pr127177-2.c
new file mode 100644
index 00000000000..998ff323b7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127177-2.c
@@ -0,0 +1,13 @@
+/* PR target/127177 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vl -ftrapping-math" } */
+
+#include "pr127177-1.c"
+
+/* { dg-final { scan-assembler "vcmpps\[ \t\]*\\\$21," } } */
+/* { dg-final { scan-assembler "vcmpps\[ \t\]*\\\$22," } } */
+/* { dg-final { scan-assembler "vcmpps\[ \t\]*\\\$25," } } */
+/* { dg-final { scan-assembler "vcmpps\[ \t\]*\\\$26," } } */
+/* { dg-final { scan-assembler "vcmpps\[ \t\]*\\\$8," } } */
+/* { dg-final { scan-assembler-not "vcmpps\[ \t\]*\\\$\[569\]," } } */
+/* { dg-final { scan-assembler-not "vcmpps\[ \t\]*\\\$1\[08\]," } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr127177-3.c 
b/gcc/testsuite/gcc.target/i386/pr127177-3.c
new file mode 100644
index 00000000000..e8190721730
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127177-3.c
@@ -0,0 +1,13 @@
+/* PR target/127177 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx -ftrapping-math -fdump-tree-vect-details" 
} */
+
+/* With SSE2 only the unordered compares except UNEQ should not be vectorized 
under
+   -ftrapping-math, as they may raise FE_INVALID.  */
+
+#include "pr127177-1.c"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-assembler-not "cmpnltps" } } */
+/* { dg-final { scan-assembler-not "cmpnleps" } } */
+/* { dg-final { scan-assembler "ucomiss" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr127177-4.c 
b/gcc/testsuite/gcc.target/i386/pr127177-4.c
new file mode 100644
index 00000000000..96ec7ff8862
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127177-4.c
@@ -0,0 +1,9 @@
+/* PR target/127177 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx -fno-trapping-math 
-fdump-tree-vect-details" } */
+
+/* Without -ftrapping-math the loops should be vectorized.  */
+
+#include "pr127177-1.c"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 5 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr127177-5.c 
b/gcc/testsuite/gcc.target/i386/pr127177-5.c
new file mode 100644
index 00000000000..f388e0366ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127177-5.c
@@ -0,0 +1,39 @@
+/* PR target/127177 */
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2 -mno-avx -ftrapping-math" } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-additional-options "-mfpmath=sse" { target ia32 } } */
+
+#include <fenv.h>
+
+float a[64], b[64];
+int r[64];
+
+__attribute__((noipa)) void
+t_islessequal (int *r, float *a, float *b, int n)
+{
+  for (int i = 0; i < n; i++)
+    r[i] = __builtin_islessequal (a[i], b[i]);
+}
+
+int
+main (void)
+{
+  for (int i = 0; i < 64; i++)
+    {
+      a[i] = __builtin_nanf ("");      /* quiet NaN */
+      b[i] = 1.0f;
+    }
+
+  /* A qNaN operand must not raise FE_INVALID here.  */
+  feclearexcept (FE_INVALID);
+  t_islessequal (r, a, b, 64);
+  if (fetestexcept (FE_INVALID))
+    __builtin_abort ();
+
+  for (int i = 0; i < 64; i++)
+    if (r[i] != 0)
+      __builtin_abort ();
+
+  return 0;
+}
-- 
2.31.1

Reply via email to