* [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
@ 2017-07-07 4:59 Yuri Gribov
2017-07-07 17:07 ` Joseph Myers
0 siblings, 1 reply; 9+ messages in thread
From: Yuri Gribov @ 2017-07-07 4:59 UTC (permalink / raw)
To: GCC Patches; +Cc: Joseph Myers, glisse
[-- Attachment #1: Type: text/plain, Size: 230 bytes --]
Hi all,
This is an updated version of patch in
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00034.html . It should
be much more complete, both in functionality and in tests.
Bootstrapped and regtested on x64. Ok for trunk?
-Y
[-- Attachment #2: pr57371-2.patch --]
[-- Type: application/octet-stream, Size: 12650 bytes --]
diff -rupN -x '*.git*' gcc/gcc/match.pd gcc-57371/gcc/match.pd
--- gcc/gcc/match.pd 2017-06-29 21:14:57.000000000 +0200
+++ gcc-57371/gcc/match.pd 2017-07-07 06:28:55.000000000 +0200
@@ -2804,6 +2804,90 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (! HONOR_NANS (@0))
(cmp @0 @1))))))
+/* Optimize various special cases of (FTYPE) N CMP CST. */
+(for cmp (lt le eq ne ge gt)
+ icmp (le le eq ne ge ge)
+ (simplify
+ (cmp (float @0) REAL_CST@1)
+ (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@1))
+ && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1)))
+ (with
+ {
+ tree itype = TREE_TYPE (@0);
+ gcc_assert (INTEGRAL_TYPE_P (itype));
+ signop isign = TYPE_SIGN (itype);
+
+ format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
+
+ /* INT?_MIN is power-of-two so it takes
+ only one mantissa bit. */
+ bool signed_p = isign == SIGNED;
+ bool itype_fits_ftype_p
+ = TYPE_PRECISION (itype) - signed_p <= significand_size (fmt);
+ }
+ /* TODO: allow non-fitting itype when -fno-trapping-math. */
+ (if (itype_fits_ftype_p)
+ (with
+ {
+ REAL_VALUE_TYPE imin, imax;
+ real_from_integer (&imin, fmt, wi::min_value (itype), isign);
+ real_from_integer (&imax, fmt, wi::max_value (itype), isign);
+
+ const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
+ REAL_VALUE_TYPE icst;
+ bool cst_int_p = false;
+
+ if (cmp == GT_EXPR || cmp == GE_EXPR)
+ real_ceil (&icst, fmt, cst);
+ else if (cmp == LT_EXPR || cmp == LE_EXPR)
+ real_floor (&icst, fmt, cst);
+ else
+ real_trunc (&icst, fmt, cst);
+
+ cst_int_p = real_identical (&icst, cst);
+ if (!cst_int_p && cmp == GT_EXPR)
+ icmp = GE_EXPR;
+ else if (!cst_int_p && cmp == LT_EXPR)
+ icmp = LE_EXPR;
+
+ bool overflow_p = false;
+ wide_int icst_val
+ = real_to_integer (&icst, &overflow_p, TYPE_PRECISION (itype));
+ }
+
+ (switch
+
+ /* Optimize cases when CST is outside of ITYPE's range. */
+ (if (real_compare (LT_EXPR, cst, &imin))
+ { constant_boolean_node (cmp == GT_EXPR || cmp == GE_EXPR || cmp == NE_EXPR,
+ type); })
+ (if (real_compare (GT_EXPR, cst, &imax))
+ { constant_boolean_node (cmp == LT_EXPR || cmp == LE_EXPR || cmp == NE_EXPR,
+ type); })
+
+ /* Remove cast if CST is an integer representable by ITYPE. */
+ (if (cst_int_p)
+ (cmp @0 { gcc_assert (!overflow_p);
+ wide_int_to_tree (itype, icst_val); })
+ )
+
+ /* When CST is fractional, optimize
+ (FTYPE) N == CST -> 0
+ (FTYPE) N != CST -> 1. */
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+
+ /* Otherwise replace with sensible integer constant. */
+ (with
+ {
+ gcc_assert (!overflow_p);
+ gcc_assert (real_compare (GE_EXPR, &icst, &imin)
+ && real_compare (LE_EXPR, &icst, &imax));
+ gcc_assert (wi::ge_p (icst_val, wi::min_value (itype), isign)
+ && wi::le_p (icst_val, wi::max_value (itype), isign));
+ }
+ (icmp @0 { wide_int_to_tree (itype, icst_val); })))))))))
+
/* Fold A /[ex] B CMP C to A CMP B * C. */
(for cmp (eq ne)
(simplify
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-1.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-1.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-1.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-1.c 2017-07-06 22:26:33.000000000 +0200
@@ -0,0 +1,270 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+#include <limits.h>
+
+/* Original testcase from PR. */
+
+int foo1 (short x) {
+ return (double) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+int foo2 (short x) {
+ return (float) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+int foo3 (int x) {
+ return (double) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+/* Tests when RHS is within range of integer type. */
+
+void in_range (unsigned short x)
+{
+ {
+ volatile int in_range_1;
+ in_range_1 = (float) x > 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_1 = x > 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_2;
+ in_range_2 = (float) x < 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_2 = x <= 99" "original" } } */
+ }
+
+ {
+ volatile int in_range_3;
+ in_range_3 = (float) x > 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_3 = x (>= 101|> 100)" "original" } } */
+ }
+
+ {
+ volatile int in_range_4;
+ in_range_4 = (float) x < 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_4 = x <= 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_5;
+ in_range_5 = (float) x == 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_5 = x == 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_6;
+ in_range_6 = (float) x != 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_6 = x != 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_7;
+ in_range_7 = (float) x == 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_7 = 0" "original" } } */
+ }
+
+ {
+ volatile int in_range_8;
+ in_range_8 = (float) x != 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_8 = 1" "original" } } */
+ }
+}
+
+/* Tests for cases where RHS is out of range of integer type. */
+
+void out_range (unsigned short x)
+{
+ {
+ volatile int out_range_1;
+ out_range_1 = (float) x > -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_1 = 1" "original" } } */
+ }
+
+ {
+ volatile int out_range_2;
+ out_range_2 = (float) x >= -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_2 = 1" "original" } } */
+ }
+
+ {
+ volatile int out_range_3;
+ out_range_3 = (float) x < -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_3 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_4;
+ out_range_4 = (float) x <= -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_4 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_5;
+ out_range_5 = (float) x == -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_5 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_6;
+ out_range_6 = (float) x != -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_6 = 1" "original" } } */
+ }
+}
+
+/* Tests when RHS is at boundary of integer type. */
+
+void lo_bounds (unsigned short x)
+{
+ {
+ volatile int lo_bounds_1;
+ lo_bounds_1 = (float) x > 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_1 = x (>|!=) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_2;
+ lo_bounds_2 = (float) x >= 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_2 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_3;
+ lo_bounds_3 = (float) x < 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_3 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_4;
+ lo_bounds_4 = (float) x <= 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_4 = x (<=|==) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_5;
+ lo_bounds_5 = (float) x > 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_5 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_6;
+ lo_bounds_6 = (float) x >= 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_6 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_7;
+ lo_bounds_7 = (float) x < 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_7 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_8;
+ lo_bounds_8 = (float) x <= 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_8 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_9;
+ lo_bounds_9 = (float) x > 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_9 = x (>= 1|!= 0)" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_10;
+ lo_bounds_10 = (float) x >= 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_10 = x (>= 1|!= 0)" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_11;
+ lo_bounds_11 = (float) x < 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_11 = x (<=|==) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_12;
+ lo_bounds_12 = (float) x <= 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_12 = x (<=|==) 0" "original" } } */
+ }
+}
+
+void hi_bounds (unsigned short x)
+{
+ {
+ volatile int hi_bounds_1;
+ hi_bounds_1 = (float) x > USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_1 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_2;
+ hi_bounds_2 = (float) x >= USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_2 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_3;
+ hi_bounds_3 = (float) x < USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_3 = x (<|!=) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_4;
+ hi_bounds_4 = (float) x <= USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_4 = 1" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_5;
+ hi_bounds_5 = (float) x > USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_5 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_6;
+ hi_bounds_6 = (float) x >= USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_6 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_7;
+ hi_bounds_7 = (float) x < USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_7 = x (<= 65534|!= 65535)" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_8;
+ hi_bounds_8 = (float) x <= USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_8 = x (<= 65534|!= 65535)" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_9;
+ hi_bounds_9 = (float) x > USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_9 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_10;
+ hi_bounds_10 = (float) x >= USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_10 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_11;
+ hi_bounds_11 = (float) x < USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_11 = 1" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_12;
+ hi_bounds_12 = (float) x <= USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_12 = 1" "original" } } */
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "original" } } */
+/* { dg-final { scan-tree-dump-not "\\(double\\)" "original" } } */
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-2.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-2.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-2.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-2.c 2017-07-06 19:30:06.000000000 +0200
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+/* We can not get rid of comparison in tests below because of
+ potential inexact exception.
+
+ TODO: enable when -fno-trapping-math. */
+
+int foo1(int x) {
+ /* { dg-final { scan-tree-dump "\\(float\\)" "optimized" } } */
+ return (float) x != 0;
+}
+
+int foo2(long long x) {
+ /* { dg-final { scan-tree-dump "\\(double\\)" "optimized" } } */
+ return (double) x != 0;
+}
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-3.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-3.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-3.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-3.c 2017-07-06 19:29:55.000000000 +0200
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+/* { dg-require-effective-target int128 } */
+
+/* We can not get rid of comparison in tests below because of
+ potential overflow exception.
+
+ TODO: enable when -fno-trapping-math. */
+
+int foo(__int128_t x) {
+ /* { dg-final { scan-tree-dump "\\(float\\)" "optimized" } } */
+ return (float) x != 0;
+}
diff -rupN -x '*.git*' gcc/gcc/testsuite/gcc.dg/pr57371-4.c gcc-57371/gcc/testsuite/gcc.dg/pr57371-4.c
--- gcc/gcc/testsuite/gcc.dg/pr57371-4.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/gcc.dg/pr57371-4.c 2017-07-06 19:29:58.000000000 +0200
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+/* { dg-require-effective-target dfp } */
+
+/* We do not support DFPs. */
+
+int foo(short x) {
+ /* { dg-final { scan-tree-dump "\\(_Decimal32\\)" "optimized" } } */
+ return (_Decimal32) x != 0;
+}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-07 4:59 [PATCHv2][PR 57371] Remove useless floating point casts in comparisons Yuri Gribov
@ 2017-07-07 17:07 ` Joseph Myers
2017-07-07 21:27 ` Yuri Gribov
0 siblings, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2017-07-07 17:07 UTC (permalink / raw)
To: Yuri Gribov; +Cc: GCC Patches, glisse
On Fri, 7 Jul 2017, Yuri Gribov wrote:
> Hi all,
>
> This is an updated version of patch in
> https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00034.html . It should
> be much more complete, both in functionality and in tests.
I think there should be tests when the constant is an infinity (of either
sign) or NaN (quiet or signaling).
I suspect infinities would already work with the patch as-is (the logic
dealing with constants outside the range of the integer type). I'm less
clear that NaNs would work properly. (If the comparison is == or != you
can optimize it for quiet NaNs, to false and true respectively. If it's a
signaling NaN, or < <= > >=, optimizing to false is only valid with
-fno-trapping-math, as it would lose an "invalid" exception.)
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-07 17:07 ` Joseph Myers
@ 2017-07-07 21:27 ` Yuri Gribov
2017-07-07 22:52 ` Joseph Myers
0 siblings, 1 reply; 9+ messages in thread
From: Yuri Gribov @ 2017-07-07 21:27 UTC (permalink / raw)
To: Joseph Myers; +Cc: GCC Patches, glisse
[-- Attachment #1: Type: text/plain, Size: 1028 bytes --]
On Fri, Jul 7, 2017 at 6:07 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Fri, 7 Jul 2017, Yuri Gribov wrote:
>
>> Hi all,
>>
>> This is an updated version of patch in
>> https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00034.html . It should
>> be much more complete, both in functionality and in tests.
>
> I think there should be tests when the constant is an infinity (of either
> sign) or NaN (quiet or signaling).
Indeed.
> I suspect infinities would already work with the patch as-is (the logic
> dealing with constants outside the range of the integer type). I'm less
> clear that NaNs would work properly. (If the comparison is == or != you
> can optimize it for quiet NaNs, to false and true respectively. If it's a
> signaling NaN, or < <= > >=, optimizing to false is only valid with
> -fno-trapping-math, as it would lose an "invalid" exception.)
It's actually under -fsignaling-nans (which if off by default). I've
attached updated patch, tests are still running but perhaps you could
take a look?
-Y
[-- Attachment #2: pr57371-3.patch --]
[-- Type: application/octet-stream, Size: 16119 bytes --]
2017-07-07 Yury Gribov <tetra2005@gmail.com>
PR tree-optimization/57371
* match.pd: New pattern.
* testsuite/c-c++-common/pr57371-1.c: New test.
* testsuite/c-c++-common/pr57371-2.c: New test.
* testsuite/c-c++-common/pr57371-3.c: New test.
* testsuite/c-c++-common/pr57371-4.c: New test.
* testsuite/gcc.dg/pr57371-5.c: New test.
diff -rupN -x '*.git*' gcc/gcc/match.pd gcc-57371/gcc/match.pd
--- gcc/gcc/match.pd 2017-07-07 09:47:42.000000000 +0200
+++ gcc-57371/gcc/match.pd 2017-07-07 22:05:01.000000000 +0200
@@ -2804,6 +2804,93 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (! HONOR_NANS (@0))
(cmp @0 @1))))))
+/* Optimize various special cases of (FTYPE) N CMP CST. */
+(for cmp (lt le eq ne ge gt)
+ icmp (le le eq ne ge ge)
+ (simplify
+ (cmp (float @0) REAL_CST@1)
+ (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@1))
+ && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1)))
+ (with
+ {
+ tree itype = TREE_TYPE (@0);
+ gcc_assert (INTEGRAL_TYPE_P (itype));
+ signop isign = TYPE_SIGN (itype);
+
+ format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
+
+ const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
+ bool snan_p
+ = real_issignaling_nan (cst) && HONOR_NANS (TREE_TYPE (@1));
+
+ /* INT?_MIN is power-of-two so it takes
+ only one mantissa bit. */
+ bool signed_p = isign == SIGNED;
+ bool itype_fits_ftype_p
+ = TYPE_PRECISION (itype) - signed_p <= significand_size (fmt);
+ }
+ /* TODO: allow non-fitting itype and SNaNs
+ when -fno-trapping-math. */
+ (if (itype_fits_ftype_p && ! snan_p)
+ (with
+ {
+ REAL_VALUE_TYPE imin, imax;
+ real_from_integer (&imin, fmt, wi::min_value (itype), isign);
+ real_from_integer (&imax, fmt, wi::max_value (itype), isign);
+
+ REAL_VALUE_TYPE icst;
+ if (cmp == GT_EXPR || cmp == GE_EXPR)
+ real_ceil (&icst, fmt, cst);
+ else if (cmp == LT_EXPR || cmp == LE_EXPR)
+ real_floor (&icst, fmt, cst);
+ else
+ real_trunc (&icst, fmt, cst);
+
+ bool cst_int_p = real_identical (&icst, cst);
+
+ if (!cst_int_p && cmp == GT_EXPR)
+ icmp = GE_EXPR;
+ else if (!cst_int_p && cmp == LT_EXPR)
+ icmp = LE_EXPR;
+
+ bool overflow_p = false;
+ wide_int icst_val
+ = real_to_integer (&icst, &overflow_p, TYPE_PRECISION (itype));
+ }
+
+ (switch
+
+ /* Optimize cases when CST is outside of ITYPE's range. */
+ (if (real_compare (LT_EXPR, cst, &imin))
+ { constant_boolean_node (cmp == GT_EXPR || cmp == GE_EXPR || cmp == NE_EXPR,
+ type); })
+ (if (real_compare (GT_EXPR, cst, &imax))
+ { constant_boolean_node (cmp == LT_EXPR || cmp == LE_EXPR || cmp == NE_EXPR,
+ type); })
+
+ /* Remove cast if CST is an integer representable by ITYPE. */
+ (if (cst_int_p)
+ (cmp @0 { gcc_assert (!overflow_p);
+ wide_int_to_tree (itype, icst_val); })
+ )
+
+ /* When CST is fractional, optimize
+ (FTYPE) N == CST -> 0
+ (FTYPE) N != CST -> 1. */
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+
+ /* Otherwise replace with sensible integer constant. */
+ (with
+ {
+ gcc_assert (!overflow_p);
+ gcc_assert (real_compare (GE_EXPR, &icst, &imin)
+ && real_compare (LE_EXPR, &icst, &imax));
+ gcc_assert (wi::ge_p (icst_val, wi::min_value (itype), isign)
+ && wi::le_p (icst_val, wi::max_value (itype), isign));
+ }
+ (icmp @0 { wide_int_to_tree (itype, icst_val); })))))))))
+
/* Fold A /[ex] B CMP C to A CMP B * C. */
(for cmp (eq ne)
(simplify
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-1.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-1.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-1.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-1.c 2017-07-07 21:52:28.000000000 +0200
@@ -0,0 +1,363 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+#include <limits.h>
+
+/* Original testcase from PR. */
+
+int foo1 (short x) {
+ return (double) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+int foo2 (short x) {
+ return (float) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+int foo3 (int x) {
+ return (double) x != 0;
+ /* { dg-final { scan-tree-dump "return (<retval> = )?x != 0" "original" } } */
+}
+
+/* Tests when RHS is within range of integer type. */
+
+void in_range (unsigned short x)
+{
+ {
+ volatile int in_range_1;
+ in_range_1 = (float) x > 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_1 = x > 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_2;
+ in_range_2 = (float) x < 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_2 = x <= 99" "original" } } */
+ }
+
+ {
+ volatile int in_range_3;
+ in_range_3 = (float) x > 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_3 = x (>= 101|> 100)" "original" } } */
+ }
+
+ {
+ volatile int in_range_4;
+ in_range_4 = (float) x < 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_4 = x <= 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_5;
+ in_range_5 = (float) x == 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_5 = x == 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_6;
+ in_range_6 = (float) x != 100.0f;
+ /* { dg-final { scan-tree-dump "in_range_6 = x != 100" "original" } } */
+ }
+
+ {
+ volatile int in_range_7;
+ in_range_7 = (float) x == 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_7 = 0" "original" } } */
+ }
+
+ {
+ volatile int in_range_8;
+ in_range_8 = (float) x != 100.5f;
+ /* { dg-final { scan-tree-dump "in_range_8 = 1" "original" } } */
+ }
+}
+
+/* Tests for cases where RHS is out of range of integer type. */
+
+void out_range (unsigned short x)
+{
+ {
+ volatile int out_range_1;
+ out_range_1 = (float) x > -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_1 = 1" "original" } } */
+ }
+
+ {
+ volatile int out_range_2;
+ out_range_2 = (float) x >= -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_2 = 1" "original" } } */
+ }
+
+ {
+ volatile int out_range_3;
+ out_range_3 = (float) x < -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_3 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_4;
+ out_range_4 = (float) x <= -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_4 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_5;
+ out_range_5 = (float) x == -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_5 = 0" "original" } } */
+ }
+
+ {
+ volatile int out_range_6;
+ out_range_6 = (float) x != -100.5f;
+ /* { dg-final { scan-tree-dump "out_range_6 = 1" "original" } } */
+ }
+}
+
+/* Tests when RHS is at boundary of integer type. */
+
+void lo_bounds (unsigned short x)
+{
+ {
+ volatile int lo_bounds_1;
+ lo_bounds_1 = (float) x > 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_1 = x (>|!=) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_2;
+ lo_bounds_2 = (float) x >= 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_2 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_3;
+ lo_bounds_3 = (float) x < 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_3 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_4;
+ lo_bounds_4 = (float) x <= 0x0;
+ /* { dg-final { scan-tree-dump "lo_bounds_4 = x (<=|==) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_5;
+ lo_bounds_5 = (float) x > 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_5 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_6;
+ lo_bounds_6 = (float) x >= 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_6 = 1" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_7;
+ lo_bounds_7 = (float) x < 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_7 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_8;
+ lo_bounds_8 = (float) x <= 0x0 - 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_8 = 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_9;
+ lo_bounds_9 = (float) x > 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_9 = x (>= 1|!= 0)" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_10;
+ lo_bounds_10 = (float) x >= 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_10 = x (>= 1|!= 0)" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_11;
+ lo_bounds_11 = (float) x < 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_11 = x (<=|==) 0" "original" } } */
+ }
+
+ {
+ volatile int lo_bounds_12;
+ lo_bounds_12 = (float) x <= 0x0 + 0.5f;
+ /* { dg-final { scan-tree-dump "lo_bounds_12 = x (<=|==) 0" "original" } } */
+ }
+}
+
+void hi_bounds (unsigned short x)
+{
+ {
+ volatile int hi_bounds_1;
+ hi_bounds_1 = (float) x > USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_1 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_2;
+ hi_bounds_2 = (float) x >= USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_2 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_3;
+ hi_bounds_3 = (float) x < USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_3 = x (<|!=) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_4;
+ hi_bounds_4 = (float) x <= USHRT_MAX;
+ /* { dg-final { scan-tree-dump "hi_bounds_4 = 1" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_5;
+ hi_bounds_5 = (float) x > USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_5 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_6;
+ hi_bounds_6 = (float) x >= USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_6 = x (>=|==) 65535" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_7;
+ hi_bounds_7 = (float) x < USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_7 = x (<= 65534|!= 65535)" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_8;
+ hi_bounds_8 = (float) x <= USHRT_MAX - 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_8 = x (<= 65534|!= 65535)" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_9;
+ hi_bounds_9 = (float) x > USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_9 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_10;
+ hi_bounds_10 = (float) x >= USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_10 = 0" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_11;
+ hi_bounds_11 = (float) x < USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_11 = 1" "original" } } */
+ }
+
+ {
+ volatile int hi_bounds_12;
+ hi_bounds_12 = (float) x <= USHRT_MAX + 0.5f;
+ /* { dg-final { scan-tree-dump "hi_bounds_12 = 1" "original" } } */
+ }
+}
+
+/* Tests with non-finite float consts. */
+
+void nonfinite (unsigned short x)
+{
+#define INFINITY __builtin_inff ()
+
+ {
+ volatile int nonfinite_1;
+ nonfinite_1 = (float) x > INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_1 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_2;
+ nonfinite_2 = (float) x >= INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_2 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_3;
+ nonfinite_3 = (float) x < INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_3 = 1" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_4;
+ nonfinite_4 = (float) x <= INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_4 = 1" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_5;
+ nonfinite_5 = (float) x > -INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_5 = 1" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_6;
+ nonfinite_6 = (float) x >= -INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_6 = 1" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_7;
+ nonfinite_7 = (float) x < -INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_7 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_8;
+ nonfinite_8 = (float) x <= -INFINITY;
+ /* { dg-final { scan-tree-dump "nonfinite_8 = 0" "original" } } */
+ }
+
+#define QNAN __builtin_nanf ("0")
+
+ {
+ volatile int nonfinite_9;
+ nonfinite_9 = (float) x > QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_9 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_10;
+ nonfinite_10 = (float) x >= QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_10 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_11;
+ nonfinite_11 = (float) x < QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_11 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_12;
+ nonfinite_12 = (float) x <= QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_12 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_13;
+ nonfinite_13 = (float) x == QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_13 = 0" "original" } } */
+ }
+
+ {
+ volatile int nonfinite_14;
+ nonfinite_14 = (float) x != QNAN;
+ /* { dg-final { scan-tree-dump "nonfinite_14 = 1" "original" } } */
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "original" } } */
+/* { dg-final { scan-tree-dump-not "\\(double\\)" "original" } } */
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-2.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-2.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-2.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-2.c 2017-07-06 19:30:06.000000000 +0200
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+/* We can not get rid of comparison in tests below because of
+ potential inexact exception.
+
+ TODO: enable when -fno-trapping-math. */
+
+int foo1(int x) {
+ /* { dg-final { scan-tree-dump "\\(float\\)" "optimized" } } */
+ return (float) x != 0;
+}
+
+int foo2(long long x) {
+ /* { dg-final { scan-tree-dump "\\(double\\)" "optimized" } } */
+ return (double) x != 0;
+}
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-3.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-3.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-3.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-3.c 2017-07-06 19:29:55.000000000 +0200
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+/* { dg-require-effective-target int128 } */
+
+/* We can not get rid of comparison in tests below because of
+ potential overflow exception.
+
+ TODO: enable when -fno-trapping-math. */
+
+int foo(__int128_t x) {
+ /* { dg-final { scan-tree-dump "\\(float\\)" "optimized" } } */
+ return (float) x != 0;
+}
diff -rupN -x '*.git*' gcc/gcc/testsuite/c-c++-common/pr57371-4.c gcc-57371/gcc/testsuite/c-c++-common/pr57371-4.c
--- gcc/gcc/testsuite/c-c++-common/pr57371-4.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/c-c++-common/pr57371-4.c 2017-07-07 23:10:28.000000000 +0200
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fsignaling-nans -fdump-tree-optimized" } */
+
+/* We can not get rid of comparison in tests below because of
+ signalling NaN exception.
+
+ TODO: enable when -fno-trapping-math. */
+
+int foo(unsigned short x) {
+ /* { dg-final { scan-tree-dump "\\(float\\)" "optimized" } } */
+ return (float) x != __builtin_nansf ("0");
+}
diff -rupN -x '*.git*' gcc/gcc/testsuite/gcc.dg/pr57371-5.c gcc-57371/gcc/testsuite/gcc.dg/pr57371-5.c
--- gcc/gcc/testsuite/gcc.dg/pr57371-5.c 1970-01-01 01:00:00.000000000 +0100
+++ gcc-57371/gcc/testsuite/gcc.dg/pr57371-5.c 2017-07-06 19:29:58.000000000 +0200
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+/* { dg-require-effective-target dfp } */
+
+/* We do not support DFPs. */
+
+int foo(short x) {
+ /* { dg-final { scan-tree-dump "\\(_Decimal32\\)" "optimized" } } */
+ return (_Decimal32) x != 0;
+}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-07 21:27 ` Yuri Gribov
@ 2017-07-07 22:52 ` Joseph Myers
2017-07-08 4:31 ` Yuri Gribov
0 siblings, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2017-07-07 22:52 UTC (permalink / raw)
To: Yuri Gribov; +Cc: GCC Patches, glisse
On Fri, 7 Jul 2017, Yuri Gribov wrote:
> > I suspect infinities would already work with the patch as-is (the logic
> > dealing with constants outside the range of the integer type). I'm less
> > clear that NaNs would work properly. (If the comparison is == or != you
> > can optimize it for quiet NaNs, to false and true respectively. If it's a
> > signaling NaN, or < <= > >=, optimizing to false is only valid with
> > -fno-trapping-math, as it would lose an "invalid" exception.)
>
> It's actually under -fsignaling-nans (which if off by default). I've
No, ordered comparisons with qNaNs should result in exceptions, so it's
not valid by default to optimize them to false (whereas it is valid for
equality comparisons, as those only raise exceptions for signaling NaNs).
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-07 22:52 ` Joseph Myers
@ 2017-07-08 4:31 ` Yuri Gribov
2017-07-08 4:34 ` Yuri Gribov
2017-07-10 10:06 ` Joseph Myers
0 siblings, 2 replies; 9+ messages in thread
From: Yuri Gribov @ 2017-07-08 4:31 UTC (permalink / raw)
To: Joseph Myers; +Cc: GCC Patches, glisse
On Fri, Jul 7, 2017 at 11:51 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Fri, 7 Jul 2017, Yuri Gribov wrote:
>
>> > I suspect infinities would already work with the patch as-is (the logic
>> > dealing with constants outside the range of the integer type). I'm less
>> > clear that NaNs would work properly. (If the comparison is == or != you
>> > can optimize it for quiet NaNs, to false and true respectively. If it's a
>> > signaling NaN, or < <= > >=, optimizing to false is only valid with
>> > -fno-trapping-math, as it would lose an "invalid" exception.)
>>
>> It's actually under -fsignaling-nans (which if off by default). I've
>
> No, ordered comparisons with qNaNs should result in exceptions,
I assume you mean sNaNs.
> so it's not valid by default to optimize them to false (whereas it is valid for
> equality comparisons, as those only raise exceptions for signaling NaNs).
I'm afraid this is default GCC behavior atm - e.g. check existing
/* a CMP (-0) -> a CMP 0 */
...
(if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
&& ! HONOR_SNANS (@1))
{ constant_boolean_node (cmp == NE_EXPR, type); })
(this pattern causes testcase in my patch pr53731-5.c to be optimized).
Or documentation for -fsignaling-nans which says that "the default is
-fno-signaling-nans" and it "may change the number of exceptions
visible with signaling NaNs".
In any case, decision to optimize sNaNs is done in HONOR_NANS macro
which my code duly checks so I'm not really sure what else needs to be
done about discussed patch in this regards.
-Y
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-08 4:31 ` Yuri Gribov
@ 2017-07-08 4:34 ` Yuri Gribov
2017-07-10 10:06 ` Joseph Myers
1 sibling, 0 replies; 9+ messages in thread
From: Yuri Gribov @ 2017-07-08 4:34 UTC (permalink / raw)
To: Joseph Myers; +Cc: GCC Patches, glisse
On Sat, Jul 8, 2017 at 5:30 AM, Yuri Gribov <tetra2005@gmail.com> wrote:
> On Fri, Jul 7, 2017 at 11:51 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Fri, 7 Jul 2017, Yuri Gribov wrote:
>>
>>> > I suspect infinities would already work with the patch as-is (the logic
>>> > dealing with constants outside the range of the integer type). I'm less
>>> > clear that NaNs would work properly. (If the comparison is == or != you
>>> > can optimize it for quiet NaNs, to false and true respectively. If it's a
>>> > signaling NaN, or < <= > >=, optimizing to false is only valid with
>>> > -fno-trapping-math, as it would lose an "invalid" exception.)
>>>
>>> It's actually under -fsignaling-nans (which if off by default). I've
>>
>> No, ordered comparisons with qNaNs should result in exceptions,
>
> I assume you mean sNaNs.
>
>> so it's not valid by default to optimize them to false (whereas it is valid for
>> equality comparisons, as those only raise exceptions for signaling NaNs).
>
> I'm afraid this is default GCC behavior atm - e.g. check existing
> /* a CMP (-0) -> a CMP 0 */
> ...
> (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
> && ! HONOR_SNANS (@1))
> { constant_boolean_node (cmp == NE_EXPR, type); })
> (this pattern causes testcase in my patch pr53731-5.c to be optimized).
>
> Or documentation for -fsignaling-nans which says that "the default is
> -fno-signaling-nans" and it "may change the number of exceptions
> visible with signaling NaNs".
>
> In any case, decision to optimize sNaNs is done in HONOR_NANS macro
> which my code duly checks
Actually I should probly change this to be HONOR_SNANS to enable sNaN
optimization by default (like other matchers do).
> so I'm not really sure what else needs to be
> done about discussed patch in this regards.
>
> -Y
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-08 4:31 ` Yuri Gribov
2017-07-08 4:34 ` Yuri Gribov
@ 2017-07-10 10:06 ` Joseph Myers
2017-07-10 10:22 ` Yuri Gribov
1 sibling, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2017-07-10 10:06 UTC (permalink / raw)
To: Yuri Gribov; +Cc: GCC Patches, glisse
On Sat, 8 Jul 2017, Yuri Gribov wrote:
> On Fri, Jul 7, 2017 at 11:51 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> > On Fri, 7 Jul 2017, Yuri Gribov wrote:
> >
> >> > I suspect infinities would already work with the patch as-is (the logic
> >> > dealing with constants outside the range of the integer type). I'm less
> >> > clear that NaNs would work properly. (If the comparison is == or != you
> >> > can optimize it for quiet NaNs, to false and true respectively. If it's a
> >> > signaling NaN, or < <= > >=, optimizing to false is only valid with
> >> > -fno-trapping-math, as it would lose an "invalid" exception.)
> >>
> >> It's actually under -fsignaling-nans (which if off by default). I've
> >
> > No, ordered comparisons with qNaNs should result in exceptions,
>
> I assume you mean sNaNs.
No, I mean qNaNs, as I said. Any of < <= > >= with a NaN argument,
whether quiet or signaling, raise "invalid"; == and != only raise
"invalid" for sNaNs, not qNaNs. (For a few architectures this is broken
in GCC; see bug 52451 for x86, 58684 for powerpc, 77918 for s390. We
should not introduce more instances of such breakage, and should fix it
where it exists.)
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-10 10:06 ` Joseph Myers
@ 2017-07-10 10:22 ` Yuri Gribov
2017-07-10 11:03 ` Joseph Myers
0 siblings, 1 reply; 9+ messages in thread
From: Yuri Gribov @ 2017-07-10 10:22 UTC (permalink / raw)
To: Joseph Myers; +Cc: GCC Patches, glisse
On Mon, Jul 10, 2017 at 11:06 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Sat, 8 Jul 2017, Yuri Gribov wrote:
>
>> On Fri, Jul 7, 2017 at 11:51 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> > On Fri, 7 Jul 2017, Yuri Gribov wrote:
>> >
>> >> > I suspect infinities would already work with the patch as-is (the logic
>> >> > dealing with constants outside the range of the integer type). I'm less
>> >> > clear that NaNs would work properly. (If the comparison is == or != you
>> >> > can optimize it for quiet NaNs, to false and true respectively. If it's a
>> >> > signaling NaN, or < <= > >=, optimizing to false is only valid with
>> >> > -fno-trapping-math, as it would lose an "invalid" exception.)
>> >>
>> >> It's actually under -fsignaling-nans (which if off by default). I've
>> >
>> > No, ordered comparisons with qNaNs should result in exceptions,
>>
>> I assume you mean sNaNs.
>
> No, I mean qNaNs, as I said. Any of < <= > >= with a NaN argument,
> whether quiet or signaling, raise "invalid"; == and != only raise
> "invalid" for sNaNs, not qNaNs. (For a few architectures this is broken
> in GCC; see bug 52451 for x86, 58684 for powerpc, 77918 for s390. We
> should not introduce more instances of such breakage, and should fix it
> where it exists.)
Oh, I see. Assuming that I fix this (in obvious way, by changing
real_issignaling_nan to real_is_nan) and boostrap/regtest, is the rest
of the patch ok?
-Y
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCHv2][PR 57371] Remove useless floating point casts in comparisons
2017-07-10 10:22 ` Yuri Gribov
@ 2017-07-10 11:03 ` Joseph Myers
0 siblings, 0 replies; 9+ messages in thread
From: Joseph Myers @ 2017-07-10 11:03 UTC (permalink / raw)
To: Yuri Gribov; +Cc: GCC Patches, glisse
On Mon, 10 Jul 2017, Yuri Gribov wrote:
> On Mon, Jul 10, 2017 at 11:06 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> > On Sat, 8 Jul 2017, Yuri Gribov wrote:
> >
> >> On Fri, Jul 7, 2017 at 11:51 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> >> > On Fri, 7 Jul 2017, Yuri Gribov wrote:
> >> >
> >> >> > I suspect infinities would already work with the patch as-is (the logic
> >> >> > dealing with constants outside the range of the integer type). I'm less
> >> >> > clear that NaNs would work properly. (If the comparison is == or != you
> >> >> > can optimize it for quiet NaNs, to false and true respectively. If it's a
> >> >> > signaling NaN, or < <= > >=, optimizing to false is only valid with
> >> >> > -fno-trapping-math, as it would lose an "invalid" exception.)
> >> >>
> >> >> It's actually under -fsignaling-nans (which if off by default). I've
> >> >
> >> > No, ordered comparisons with qNaNs should result in exceptions,
> >>
> >> I assume you mean sNaNs.
> >
> > No, I mean qNaNs, as I said. Any of < <= > >= with a NaN argument,
> > whether quiet or signaling, raise "invalid"; == and != only raise
> > "invalid" for sNaNs, not qNaNs. (For a few architectures this is broken
> > in GCC; see bug 52451 for x86, 58684 for powerpc, 77918 for s390. We
> > should not introduce more instances of such breakage, and should fix it
> > where it exists.)
>
> Oh, I see. Assuming that I fix this (in obvious way, by changing
> real_issignaling_nan to real_is_nan) and boostrap/regtest, is the rest
> of the patch ok?
Please send the updated patch (including any testcase updates needed) for
review.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-07-10 11:03 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-07 4:59 [PATCHv2][PR 57371] Remove useless floating point casts in comparisons Yuri Gribov
2017-07-07 17:07 ` Joseph Myers
2017-07-07 21:27 ` Yuri Gribov
2017-07-07 22:52 ` Joseph Myers
2017-07-08 4:31 ` Yuri Gribov
2017-07-08 4:34 ` Yuri Gribov
2017-07-10 10:06 ` Joseph Myers
2017-07-10 10:22 ` Yuri Gribov
2017-07-10 11:03 ` Joseph Myers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).