On Fri, Oct 20, 2017 at 2:15 PM, Joseph Myers <[email protected]> wrote:
> This is PR target/52451.
>
> A testcase (conditional on the fenv_exceptions effective-target) that
> ordered comparisons with quiet NaNs set FE_INVALID would be a good idea,
> but it would need XFAILing for powerpc (bug 58684) and s390 (bug 77918).
Joseph,
thanks for pointing out a PR reference and a suggestion for a testcase.
Please find attached a new version of the patch, including the
comprehensive tests.
2017-10-20 Uros Bizjak <[email protected]>
PR target/52451
* config/i386/i386.c (ix86_fp_compare_mode): Return CCFPmode
for ordered inequality comparisons even with TARGET_IEEE_FP.
2017-10-20 Uros Bizjak <[email protected]>
PR target/52451
* gcc.dg/torture/pr52451.c: New test.
Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
Uros.
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 253949)
+++ config/i386/i386.c (working copy)
@@ -21500,14 +21500,35 @@
Return the appropriate mode to use. */
machine_mode
-ix86_fp_compare_mode (enum rtx_code)
+ix86_fp_compare_mode (enum rtx_code code)
{
- /* ??? In order to make all comparisons reversible, we do all comparisons
- non-trapping when compiling for IEEE. Once gcc is able to distinguish
- all forms trapping and nontrapping comparisons, we can make inequality
- comparisons trapping again, since it results in better code when using
- FCOM based compares. */
- return TARGET_IEEE_FP ? CCFPUmode : CCFPmode;
+ if (!TARGET_IEEE_FP)
+ return CCFPmode;
+
+ switch (code)
+ {
+ case GT:
+ case GE:
+ case LT:
+ case LE:
+ return CCFPmode;
+
+ case EQ:
+ case NE:
+
+ case LTGT:
+ case UNORDERED:
+ case ORDERED:
+ case UNLT:
+ case UNLE:
+ case UNGT:
+ case UNGE:
+ case UNEQ:
+ return CCFPUmode;
+
+ default:
+ gcc_unreachable ();
+ }
}
machine_mode
Index: testsuite/gcc.dg/torture/pr52451.c
===================================================================
--- testsuite/gcc.dg/torture/pr52451.c (nonexistent)
+++ testsuite/gcc.dg/torture/pr52451.c (working copy)
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+#define TEST_C_NOEX(CMP, S) \
+ r = nan##S CMP arg##S; \
+ if (fetestexcept (FE_INVALID)) \
+ __builtin_abort ()
+
+#define TEST_B_NOEX(FN, S) \
+ r = __builtin_##FN (nan##S, arg##S); \
+ if (fetestexcept (FE_INVALID)) \
+ __builtin_abort ()
+
+#define TEST_C_EX(CMP, S) \
+ r = nan##S CMP arg##S; \
+ if (!fetestexcept (FE_INVALID)) \
+ __builtin_abort (); \
+ feclearexcept (FE_INVALID)
+
+#define TEST(TYPE, S) \
+ volatile TYPE nan##S = __builtin_nan##S (""); \
+ volatile TYPE arg##S = 1.0##S; \
+ \
+ TEST_C_NOEX (==, S); \
+ TEST_C_NOEX (!=, S); \
+ \
+ TEST_B_NOEX (isgreater, S); \
+ TEST_B_NOEX (isless, S); \
+ TEST_B_NOEX (isgreaterequal, S); \
+ TEST_B_NOEX (islessequal, S); \
+ \
+ TEST_B_NOEX (islessgreater, S); \
+ TEST_B_NOEX (isunordered, S); \
+ \
+ TEST_C_EX (>, S); \
+ TEST_C_EX (<, S); \
+ TEST_C_EX (>=, S); \
+ TEST_C_EX (<=, S)
+
+int
+main (void)
+{
+ volatile int r;
+
+ feclearexcept (FE_INVALID);
+
+ TEST (float, f);
+ TEST (double, );
+ TEST (long double, l);
+
+ return 0;
+}