On Fri, Oct 20, 2017 at 2:15 PM, Joseph Myers <jos...@codesourcery.com> 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 <ubiz...@gmail.com> 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 <ubiz...@gmail.com> 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; +}