]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR middle-end/88173: More constant folding of NaN comparisons.
authorRoger Sayle <roger@nextmovesoftware.com>
Sun, 19 Sep 2021 08:07:01 +0000 (09:07 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Sun, 19 Sep 2021 08:07:01 +0000 (09:07 +0100)
This patch tackles PR middle-end/88173 where the order of operands in
a comparison affects constant folding.  As diagnosed by Jason Merrill,
"match.pd handles these comparisons very differently".  The history is
that the middle end, typically canonicalizes comparisons to place
constants on the right, but when a comparison contains two constants
we need to check/transform both constants, i.e. on both the left and the
right.  Hence the added lines below duplicate for @0 the same transform
applied a few lines above for @1.

Whilst preparing the testcase, I noticed that this transformation is
incorrectly disabled with -fsignaling-nans even when both operands are
known not be be signaling NaNs, so I've corrected that and added a
second test case.  Unfortunately, c-c++-common/pr57371-4.c then starts
failing, as it doesn't distinguish QNaNs (which are quiet) from SNaNs
(which signal), so this patch includes a minor tweak to the expected
behaviour for QNaNs in that existing test.

2021-09-19  Roger Sayle <roger@nextmovesoftware.com>

gcc/ChangeLog
PR middle-end/88173
* match.pd (cmp @0 REAL_CST@1): When @0 is also REAL_CST, apply
the same transformations as to @1.  For comparisons against NaN,
don't check HONOR_SNANS but confirm that neither operand is a
signaling NaN.

gcc/testsuite/ChangeLog
PR middle-end/88173
* c-c++-common/pr57371-4.c: Tweak/correct test case for QNaNs.
* g++.dg/pr88173-1.C: New test case.
* g++.dg/pr88173-2.C: New test case.

gcc/match.pd
gcc/testsuite/c-c++-common/pr57371-4.c
gcc/testsuite/g++.dg/pr88173-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr88173-2.C [new file with mode: 0644]

index 097ed2e5dffdbfffaf3241acfefd691dae53584a..a063a1577b5a2b422e660f1f7a2e51f782fdea1b 100644 (file)
@@ -4482,9 +4482,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    /* a CMP (-0) -> a CMP 0  */
    (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
     (cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
+   /* (-0) CMP b -> 0 CMP b.  */
+   (if (TREE_CODE (@0) == REAL_CST
+       && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@0)))
+    (cmp { build_real (TREE_TYPE (@0), dconst0); } @1))
    /* x != NaN is always true, other ops are always false.  */
    (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
-       && ! HONOR_SNANS (@1))
+       && !tree_expr_signaling_nan_p (@1)
+       && !tree_expr_maybe_signaling_nan_p (@0))
+    { constant_boolean_node (cmp == NE_EXPR, type); })
+   /* NaN != y is always true, other ops are always false.  */
+   (if (TREE_CODE (@0) == REAL_CST
+       && REAL_VALUE_ISNAN (TREE_REAL_CST (@0))
+        && !tree_expr_signaling_nan_p (@0)
+        && !tree_expr_signaling_nan_p (@1))
     { constant_boolean_node (cmp == NE_EXPR, type); })
    /* Fold comparisons against infinity.  */
    (if (REAL_VALUE_ISINF (TREE_REAL_CST (@1))
index f43f7c22419a56661ebcb284fa648f478be1833f..d938ecdd675c3eabea2fceb724525351e45b7f28 100644 (file)
@@ -13,25 +13,25 @@ void nonfinite(unsigned short x) {
   {
     volatile int nonfinite_1;
     nonfinite_1 = (float) x > QNAN;
-    /* { dg-final { scan-tree-dump "nonfinite_1 = \\(float\\)" "original" } } */
+    /* { dg-final { scan-tree-dump "nonfinite_1 = 0" "original" } } */
   }
 
   {
     volatile int nonfinite_2;
     nonfinite_2 = (float) x >= QNAN;
-    /* { dg-final { scan-tree-dump "nonfinite_2 = \\(float\\)" "original" } } */
+    /* { dg-final { scan-tree-dump "nonfinite_2 = 0" "original" } } */
   }
 
   {
     volatile int nonfinite_3;
     nonfinite_3 = (float) x < QNAN;
-    /* { dg-final { scan-tree-dump "nonfinite_3 = \\(float\\)" "original" } } */
+    /* { dg-final { scan-tree-dump "nonfinite_3 = 0" "original" } } */
   }
 
   {
     volatile int nonfinite_4;
     nonfinite_4 = (float) x <= QNAN;
-    /* { dg-final { scan-tree-dump "nonfinite_4 = \\(float\\)" "original" } } */
+    /* { dg-final { scan-tree-dump "nonfinite_4 = 0" "original" } } */
   }
 
   {
diff --git a/gcc/testsuite/g++.dg/pr88173-1.C b/gcc/testsuite/g++.dg/pr88173-1.C
new file mode 100644 (file)
index 0000000..08fcf97
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=c++11" } */
+
+#define big __builtin_huge_val()
+#define nan __builtin_nan("")
+
+constexpr bool b1 = big > nan;
+constexpr bool b2 = nan < big;
+
diff --git a/gcc/testsuite/g++.dg/pr88173-2.C b/gcc/testsuite/g++.dg/pr88173-2.C
new file mode 100644 (file)
index 0000000..aa7d784
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsignaling-nans -std=c++11" } */
+
+#define big __builtin_huge_val()
+#define nan __builtin_nan("")
+
+constexpr bool b1 = big > nan;
+constexpr bool b2 = nan < big;
+