Message ID | alpine.DEB.2.20.1801052112460.4805@digraph.polyomino.org.uk |
---|---|
State | New |
Headers | show |
Series | Fix folding of Inf/NaN comparisons for -ftrapping-math (PR tree-optimization/64811) | expand |
On January 5, 2018 10:13:34 PM GMT+01:00, Joseph Myers <joseph@codesourcery.com> wrote: >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. OK to commit? OK. Richard. >gcc: >2018-01-05 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. > >gcc/testsuite: >2018-01-05 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. > >Index: gcc/match.pd >=================================================================== >--- gcc/match.pd (revision 256279) >+++ gcc/match.pd (working copy) >@@ -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 >Index: gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x >=================================================================== >--- gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (nonexistent) >+++ gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (working copy) >@@ -0,0 +1,2 @@ >+lappend additional_flags "-fno-trapping-math" >+return 0 >Index: gcc/testsuite/gcc.dg/torture/inf-compare-1.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-1.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-1.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-2.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-2.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-2.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-3.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-3.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-3.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-4.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-4.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-4.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-5.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-5.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-5.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-6.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-6.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-6.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-7.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-7.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-7.c (working copy) >@@ -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 (); >+} >Index: gcc/testsuite/gcc.dg/torture/inf-compare-8.c >=================================================================== >--- gcc/testsuite/gcc.dg/torture/inf-compare-8.c (nonexistent) >+++ gcc/testsuite/gcc.dg/torture/inf-compare-8.c (working copy) >@@ -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 (); >+}
Joseph, On Sat, Jan 06, 2018 at 08:45:33AM +0100, Richard Biener wrote: > On January 5, 2018 10:13:34 PM GMT+01:00, Joseph Myers <joseph@codesourcery.com> wrote: > >unrelated. OK to commit? > > OK. > > Richard. > >Index: gcc/match.pd > >=================================================================== > >--- gcc/match.pd (revision 256279) > >+++ gcc/match.pd (working copy) > >+ /* 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. */ What does "x a NaN" mean? x OP NaN resp. x CMP 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. */ Likewise. > >Index: gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x > >=================================================================== > >--- gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (nonexistent) > >+++ gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (working copy) > >@@ -0,0 +1,2 @@ > >+lappend additional_flags "-fno-trapping-math" > >+return 0 > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-1.c > >=================================================================== > >--- gcc/testsuite/gcc.dg/torture/inf-compare-1.c (nonexistent) > >+++ gcc/testsuite/gcc.dg/torture/inf-compare-1.c (working copy) > >@@ -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 (); > >+} Shouldn't run tests return 0 here? Also drop the exit() declaration since it's unused? Same for all new tests in this patch. thanks, > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-2.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-3.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-4.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-5.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-6.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-7.c > >Index: gcc/testsuite/gcc.dg/torture/inf-compare-8.c
On Wed, 10 Jan 2018, Bernhard Reutner-Fischer wrote: > > >+ /* 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. */ > > What does "x a NaN" mean? x OP NaN resp. x CMP NaN ? That x is a NaN. fpclassify (x) == FP_NAN. It's not a C comparison operator since NaNs compare unequal to everything. > Shouldn't run tests return 0 here? Also drop the exit() declaration > since it's unused? C99 automatically returns 0 from the end of main, but it's true the default style would be exit (0) in tests.
On Wed, Jan 10, 2018 at 08:17:08PM +0000, Joseph Myers wrote: > On Wed, 10 Jan 2018, Bernhard Reutner-Fischer wrote: > > > > >+ /* 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. */ > > > > What does "x a NaN" mean? x OP NaN resp. x CMP NaN ? > > That x is a NaN. fpclassify (x) == FP_NAN. It's not a C comparison So s/for x a NaN/if x is a NaN/ wouldn't have thrown me off. > operator since NaNs compare unequal to everything. > > > Shouldn't run tests return 0 here? Also drop the exit() declaration > > since it's unused? > > C99 automatically returns 0 from the end of main, but it's true the > default style would be exit (0) in tests. Ah right fenv_exceptions even sets -std=gnu99 and fenv support would require a minimum of C99 anyway so you're of course right. Obviously i'm half asleep, sorry for the noise.. thanks,
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 256279) +++ gcc/match.pd (working copy) @@ -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 Index: gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x =================================================================== --- gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (nonexistent) +++ gcc/testsuite/gcc.c-torture/execute/ieee/fp-cmp-7.x (working copy) @@ -0,0 +1,2 @@ +lappend additional_flags "-fno-trapping-math" +return 0 Index: gcc/testsuite/gcc.dg/torture/inf-compare-1.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-1.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-2.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-2.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-3.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-3.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-3.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-4.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-4.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-4.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-5.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-5.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-5.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-6.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-6.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-6.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-7.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-7.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-7.c (working copy) @@ -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 (); +} Index: gcc/testsuite/gcc.dg/torture/inf-compare-8.c =================================================================== --- gcc/testsuite/gcc.dg/torture/inf-compare-8.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/inf-compare-8.c (working copy) @@ -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 (); +}