aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2018-01-09 13:25:38 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2018-01-09 13:25:38 +0000
commite96a5786c75a9fb7c1720a0a4860e990bcc830bf (patch)
treea89520fd45e90056d90ab7810d9c09d60ed7698d /gcc
parentaa5bfa8d5d9b5751bc6b1854d663fbf777849711 (diff)
downloadgcc-e96a5786c75a9fb7c1720a0a4860e990bcc830bf.zip
gcc-e96a5786c75a9fb7c1720a0a4860e990bcc830bf.tar.gz
gcc-e96a5786c75a9fb7c1720a0a4860e990bcc830bf.tar.bz2
Fix folding of Inf/NaN comparisons for -ftrapping-math (PR tree-optimization/64811).
The folding of comparisons against Inf (to constants or comparisons with the maximum finite value) has various cases where it introduces or loses "invalid" exceptions for comparisons with NaNs. Folding x > +Inf to 0 should not be about HONOR_SNANS - ordered comparisons of both quiet and signaling NaNs should raise invalid. x <= +Inf is not the same as x == x, because again that loses an exception (equality comparisons don't raise exceptions except for signaling NaNs). x == +Inf is not the same as x > DBL_MAX, and a similar issue applies with the x != +Inf case - that transformation causes a spurious exception. This patch fixes the conditionals on the folding to avoid such introducing or losing exceptions. Bootstrapped with no regressions on x86_64-pc-linux-gnu (where the cases involving spurious exceptions wouldn't have failed anyway before GCC 8 because of unordered comparisons wrongly always having formerly been used by the back end). Also tested for powerpc-linux-gnu soft-float that this fixes many glibc math/ test failures that arose in that configuration because this folding affected the IBM long double support in libgcc (no such failures appeared for hard-float because of the bug of powerpc hard-float always using unordered comparisons) - some failures remain, but I believe them to be unrelated. PR tree-optimization/64811 gcc: * match.pd: When optimizing comparisons with Inf, avoid introducing or losing exceptions from comparisons with NaN. gcc/testsuite: * gcc.dg/torture/inf-compare-1.c, gcc.dg/torture/inf-compare-2.c, gcc.dg/torture/inf-compare-3.c, gcc.dg/torture/inf-compare-4.c, gcc.dg/torture/inf-compare-5.c, gcc.dg/torture/inf-compare-6.c, gcc.dg/torture/inf-compare-7.c, gcc.dg/torture/inf-compare-8.c: New tests. * gcc.c-torture/execute/ieee/fp-cmp-7.x: New file. From-SVN: r256380
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/match.pd27
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x2
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-2.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-3.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-4.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-5.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-6.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-7.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/inf-compare-8.c19
12 files changed, 185 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d9089b..24fd1b4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-09 Joseph Myers <joseph@codesourcery.com>
+
+ PR tree-optimization/64811
+ * match.pd: When optimizing comparisons with Inf, avoid
+ introducing or losing exceptions from comparisons with NaN.
+
2018-01-09 Martin Liska <mliska@suse.cz>
PR sanitizer/82517
diff --git a/gcc/match.pd b/gcc/match.pd
index 915c20f..435125a 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3050,18 +3050,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
code = swap_tree_comparison (code);
}
(switch
- /* x > +Inf is always false, if with ignore sNANs. */
+ /* x > +Inf is always false, if we ignore NaNs or exceptions. */
(if (code == GT_EXPR
- && ! HONOR_SNANS (@0))
+ && !(HONOR_NANS (@0) && flag_trapping_math))
{ constant_boolean_node (false, type); })
(if (code == LE_EXPR)
- /* x <= +Inf is always true, if we don't case about NaNs. */
+ /* x <= +Inf is always true, if we don't care about NaNs. */
(if (! HONOR_NANS (@0))
{ constant_boolean_node (true, type); }
- /* x <= +Inf is the same as x == x, i.e. !isnan(x). */
- (eq @0 @0)))
- /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */
- (if (code == EQ_EXPR || code == GE_EXPR)
+ /* x <= +Inf is the same as x == x, i.e. !isnan(x), but this loses
+ an "invalid" exception. */
+ (if (!flag_trapping_math)
+ (eq @0 @0))))
+ /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX, but
+ for == this introduces an exception for x a NaN. */
+ (if ((code == EQ_EXPR && !(HONOR_NANS (@0) && flag_trapping_math))
+ || code == GE_EXPR)
(with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
(if (neg)
(lt @0 { build_real (TREE_TYPE (@0), max); })
@@ -3072,7 +3076,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (neg)
(ge @0 { build_real (TREE_TYPE (@0), max); })
(le @0 { build_real (TREE_TYPE (@0), max); }))))
- /* x != +Inf is always equal to !(x > DBL_MAX). */
+ /* x != +Inf is always equal to !(x > DBL_MAX), but this introduces
+ an exception for x a NaN so use an unordered comparison. */
(if (code == NE_EXPR)
(with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
(if (! HONOR_NANS (@0))
@@ -3080,10 +3085,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(ge @0 { build_real (TREE_TYPE (@0), max); })
(le @0 { build_real (TREE_TYPE (@0), max); }))
(if (neg)
- (bit_xor (lt @0 { build_real (TREE_TYPE (@0), max); })
- { build_one_cst (type); })
- (bit_xor (gt @0 { build_real (TREE_TYPE (@0), max); })
- { build_one_cst (type); }))))))))))
+ (unge @0 { build_real (TREE_TYPE (@0), max); })
+ (unle @0 { build_real (TREE_TYPE (@0), max); }))))))))))
/* If this is a comparison of a real constant with a PLUS_EXPR
or a MINUS_EXPR of a real constant, we can convert it into a
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7f90a43..679b22a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2018-01-09 Joseph Myers <joseph@codesourcery.com>
+
+ PR tree-optimization/64811
+ * gcc.dg/torture/inf-compare-1.c, gcc.dg/torture/inf-compare-2.c,
+ gcc.dg/torture/inf-compare-3.c, gcc.dg/torture/inf-compare-4.c,
+ gcc.dg/torture/inf-compare-5.c, gcc.dg/torture/inf-compare-6.c,
+ gcc.dg/torture/inf-compare-7.c, gcc.dg/torture/inf-compare-8.c:
+ New tests.
+ * gcc.c-torture/execute/ieee/fp-cmp-7.x: New file.
+
2018-01-09 Georg-Johann Lay <avr@gjlay.de>
PR target/79883
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x
new file mode 100644
index 0000000..35f7a0a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x
@@ -0,0 +1,2 @@
+lappend additional_flags "-fno-trapping-math"
+return 0
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-1.c b/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
new file mode 100644
index 0000000..0f45108
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x > __builtin_inf ();
+ if (i != 0 || !fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-2.c b/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
new file mode 100644
index 0000000..ba73395
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x < -__builtin_inf ();
+ if (i != 0 || !fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-3.c b/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
new file mode 100644
index 0000000..e545d3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x <= __builtin_inf ();
+ if (i != 0 || !fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-4.c b/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
new file mode 100644
index 0000000..fca6cbf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x >= -__builtin_inf ();
+ if (i != 0 || !fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-5.c b/gcc/testsuite/gcc.dg/torture/inf-compare-5.c
new file mode 100644
index 0000000..d7f17e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-5.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x == __builtin_inf ();
+ if (i != 0 || fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-6.c b/gcc/testsuite/gcc.dg/torture/inf-compare-6.c
new file mode 100644
index 0000000..2dd862b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-6.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x == -__builtin_inf ();
+ if (i != 0 || fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-7.c b/gcc/testsuite/gcc.dg/torture/inf-compare-7.c
new file mode 100644
index 0000000..36676b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-7.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x != __builtin_inf ();
+ if (i != 1 || fetestexcept (FE_INVALID))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-8.c b/gcc/testsuite/gcc.dg/torture/inf-compare-8.c
new file mode 100644
index 0000000..cfda813
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-8.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+volatile double x = __builtin_nan ("");
+volatile int i;
+
+int
+main (void)
+{
+ i = x != -__builtin_inf ();
+ if (i != 1 || fetestexcept (FE_INVALID))
+ abort ();
+}