The following is another tiny step towards preserving IEEE exceptions
of comparisons. When DCE leaves us with a diamond without code
or a PHI CFG cleanup will elide the control statement even when that
can trap. The following keeps doing that but preserves the trapping
comparison by splitting it out as (dead) assignment.
I'll note the testcase has the inner comparison elided by DCE
(which is also wrong on its own, but combination could have
realized this as overall valid transform). Fixing that part
of DCE would have prevented the CFG cleanup issue, but I think
it's worth fixing anyway.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
PR tree-optimization/53805
* tree-cfg.cc (gimple_try_redirect_by_replacing_jump):
When the comparison in a gcond traps, preserve it as
the RHS of an assignment.
* gcc.dg/tree-ssa/fp-trapping-cmp-8.c: New testcase.
---
gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-8.c | 13 +++++++++++++
gcc/tree-cfg.cc | 13 ++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-8.c
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-8.c
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-8.c
new file mode 100644
index 00000000000..f63be3669d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftrapping-math -fdump-tree-dce3" } */
+
+int
+f (double a, double b)
+{
+ if (a > b)
+ if (a < b)
+ return 1;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "a_\[0-9\]\+\\\(D\\\) > b_\[0-9\]\+\\\(D\\\)"
"dce3" } } */
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index c7f2f987b25..2aea266f0ff 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -6149,7 +6149,18 @@ gimple_try_redirect_by_replacing_jump (edge e,
basic_block target)
if (gimple_code (stmt) == GIMPLE_COND || gimple_code (stmt) == GIMPLE_SWITCH)
{
- gsi_remove (&i, true);
+ /* When a comparison can trap preserve it, but not the control flow. */
+ if (gimple_code (stmt) == GIMPLE_COND
+ && gimple_could_trap_p (stmt))
+ {
+ gimple *s = gimple_build_assign (make_ssa_name (boolean_type_node),
+ gimple_cond_code (stmt),
+ gimple_cond_lhs (stmt),
+ gimple_cond_rhs (stmt));
+ gsi_replace (&i, s, false);
+ }
+ else
+ gsi_remove (&i, true);
e = ssa_redirect_edge (e, target);
e->flags = EDGE_FALLTHRU;
return e;
--
2.51.0