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