For `(i == j) || (i < j)` this can be combined to just `i <= j` without
worrying about removal of a trap as a NaN would cause the the equal to be
false which will cause not to short circuit and the trapping instruction
will always be executed.
`(i != j) && (i < j)` has the same reasoning.
Bootstrapped and tested on x86_64-linux-gnu.
PR tree-optimization/126138
gcc/ChangeLog:
* fold-const.cc (combine_comparisons): Allow eq to combine
with || and ne combine with eq if the original rcode was trapping
and the new code is trapping.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/fp-trapping-cmp-1.c: New test.
Signed-off-by: Andrea Pinski <[email protected]>
---
gcc/fold-const.cc | 13 +++++++++---
.../gcc.dg/tree-ssa/fp-trapping-cmp-1.c | 21 +++++++++++++++++++
2 files changed, 31 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index d80d6ed1f86..34cdfa243a0 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -3002,14 +3002,21 @@ combine_comparisons (enum tree_code code, enum
tree_code lcode,
|| (code == TRUTH_ANDIF_EXPR && !(lcompcode & COMPCODE_UNORD)))
rtrap = false;
+ /* Allow combining of `a != b && a < b` since NAN will cause != to be
+ always true, and `a < b` will cause a trap. This is trap neutral. */
+ if (code == TRUTH_ANDIF_EXPR && lcompcode == COMPCODE_NE && rtrap &&
trap)
+ ;
+ /* Likewise of `a == b || a < b` for the same reason. */
+ else if (code == TRUTH_ORIF_EXPR && lcompcode == COMPCODE_EQ && rtrap
&& trap)
+ ;
/* If the comparison was short-circuited, and only the RHS
trapped, we may now generate a spurious trap. */
- if (rtrap && !ltrap
- && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
+ else if (rtrap && !ltrap
+ && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
return ERROR_MARK;
/* If we changed the conditions that cause a trap, we lose. */
- if ((ltrap || rtrap) != trap)
+ else if ((ltrap || rtrap) != trap)
return ERROR_MARK;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
new file mode 100644
index 00000000000..9d88dc10c2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrapping-math -fdump-tree-original
-fdump-tree-optimized" } */
+/* PR tree-optimization/126138 */
+
+/* (eq || trap) -> trap is fine as eq will be false for NaN
+ which means it is not short circuit and will cause a trap
+ on the trapping instruction always. */
+int
+f (double i, double j)
+{
+ return (i == j) || (i < j);
+}
+/* (ne && trap) -> trap has a story. */
+int
+f1 (double i, double j)
+{
+ return (i != j) && (i < j);
+}
+/* { dg-final { scan-tree-dump-not " && " "original" } } */
+/* { dg-final { scan-tree-dump-not " \\\|\\\| " "original" } } */
+/* { dg-final { scan-tree-dump-not " if " "optimized" } } */
--
2.43.0