The following adds gimple_could_raise_ieee_exception_p and honors it
in DCE and DSE.
This shows, for example in gcc.dg/tree-ssa/fp-trapping-cmp-4.c,
that some passes fail to clean up after themselves when they
no longer can rely on DCE.
Bootstrapped and tested on x86_64-unknown-linux-gnu. I think we
shouldn't do something like this without also swapping the
default of -ftrapping-math. Full testsuite fallout is
+FAIL: g++.dg/opt/pr94589-5.C -std=gnu++20 scan-tree-dump-times
optimized "[ij
]_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) [ij]_[0-9]+\\\\(D\\\\)" 8
+FAIL: gcc.dg/pr94589-5.c scan-tree-dump-times optimized
"[ij]_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) [ij]_[0-9]+\\\\(D\\\\)" 24
+FAIL: gcc.dg/pr94589-5.c scan-tree-dump-times optimized
"i_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) 5\\\\.0" 24
+FAIL: gcc.dg/tree-ssa/fp-trapping-cmp-4.c scan-tree-dump-times optimized
" < " 1
+FAIL: gcc.dg/tree-ssa/fp-trapping-cmp-5.c scan-tree-dump-times optimized
" < " 1
+FAIL: gcc.dg/tree-ssa/fp-trapping-cmp-8.c scan-tree-dump dce3
"a_[0-9]+\\\\(D\\\\) > b_[0-9]+\\\\(D\\\\)"
+FAIL: gcc.dg/tree-ssa/pr125385.c scan-tree-dump-not optimized
"\\\\(float\\\\)"
+FAIL: gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c (internal compiler
error: in expand_fn_using_insn, at internal-fn.cc:270)
+FAIL: gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c (test for excess
errors)
+FAIL: gcc.dg/tree-ssa/tailcall-9.c scan-tree-dump tailc "Found tail call"
+FAIL: gcc.dg/vect/bb-slp-48.c -flto -ffat-lto-objects
scan-tree-dump-times optimized " \\\\+ " 4
+FAIL: gcc.dg/vect/bb-slp-48.c scan-tree-dump-times optimized " \\\\+ " 4
+FAIL: gcc.target/i386/opt-1.c scan-assembler prefetcht0
+FAIL: gcc.target/i386/opt-2.c scan-assembler prefetcht0
+FAIL: gcc.target/i386/pr92645-3.c scan-tree-dump-times cddce1
"BIT_FIELD_REF" 4
I'll note that, of course, RTL DCE will still elide the instructions
(so does simple-DCE on GIMPLE). Preserving the stmts won't help
with reliable access through the FP environment (one more option for
a -fno-trapping-math default). Maybe we can really go forward with
-fno-trapping-math by default for GCC 17?
Richard.
PR tree-optimization/53805
* gimple.h (gimple_could_raise_ieee_exception_p): Declare.
* gimple.cc (gimple_could_raise_ieee_exception_p): New function.
* tree-ssa-dce.cc (mark_stmt_if_obviously_necessary):
Statements that might raise IEEE exceptions are necessary.
* tree-ssa-dse.cc (pass_dse::execute): Likewise.
* gcc.dg/tree-ssa/fp-trapping-cmp-9.c: New testcase.
---
gcc/gimple.cc | 32 +++++++++++++++++++
gcc/gimple.h | 1 +
.../gcc.dg/tree-ssa/fp-trapping-cmp-9.c | 9 ++++++
gcc/tree-ssa-dce.cc | 7 ++++
gcc/tree-ssa-dse.cc | 3 +-
5 files changed, 51 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-9.c
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 04ad17f5955..72a7e3f9603 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -2493,6 +2493,38 @@ gimple_assign_rhs_could_trap_p (gimple *s)
return gimple_could_trap_p_1 (s, true, false);
}
+/* Return true if STMT could raise a IEEE exception. */
+
+bool
+gimple_could_raise_ieee_exception_p (const gimple *stmt)
+{
+ if (!flag_trapping_math)
+ return false;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_ASSIGN:
+ {
+ enum tree_code code = gimple_assign_rhs_code (stmt);
+ return (!gimple_assign_single_p (stmt)
+ && code != COND_EXPR
+ && FLOAT_TYPE_P
+ (TREE_TYPE (TREE_CODE_CLASS (code) == tcc_comparison
+ ? gimple_assign_rhs1 (stmt)
+ : gimple_assign_lhs (stmt)))
+ && operation_could_trap_p (code, true, false, NULL_TREE));
+ }
+ case GIMPLE_COND:
+ return (FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
+ && operation_could_trap_p (gimple_cond_code (stmt), true, false,
+ NULL_TREE));
+ default:
+ /* ??? This is incomplete, gcall and gasm can as well. */
+ ;
+ }
+
+ return false;
+}
/* Print debugging information for gimple stmts generated. */
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 82045c44bbe..37a86061c48 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1652,6 +1652,7 @@ void gimple_move_vops (gimple *, gimple *);
bool gimple_has_side_effects (const gimple *);
bool gimple_could_trap_p_1 (const gimple *, bool, bool);
bool gimple_could_trap_p (const gimple *);
+bool gimple_could_raise_ieee_exception_p (const gimple *);
bool gimple_assign_rhs_could_trap_p (gimple *);
extern void dump_gimple_statistics (void);
unsigned get_gimple_rhs_num_ops (enum tree_code);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-9.c
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-9.c
new file mode 100644
index 00000000000..b27386408ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-9.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+void f(double a,double b)
+{
+ _Bool c = a>b;
+}
+
+/* { dg-final { scan-tree-dump "a_\[0-9\]\+\\\(D\\\) > b_\[0-9\]\+\\\(D\\\)"
"optimized" } } */
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index a5391290c4d..c511177c16d 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -503,6 +503,13 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool
aggressive)
return;
}
+ /* Preserve statements possibly setting IEEE exceptions. */
+ if (gimple_could_raise_ieee_exception_p (stmt))
+ {
+ mark_stmt_necessary (stmt, true);
+ return;
+ }
+
if ((gimple_vdef (stmt) && keep_all_vdefs_p ())
|| stmt_may_clobber_global_p (stmt, false))
{
diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
index 0623f2c9090..62ccd87c036 100644
--- a/gcc/tree-ssa-dse.cc
+++ b/gcc/tree-ssa-dse.cc
@@ -1732,7 +1732,8 @@ pass_dse::execute (function *fun)
&& !gimple_has_side_effects (stmt)
&& !is_ctrl_altering_stmt (stmt)
&& (!stmt_could_throw_p (fun, stmt)
- || fun->can_delete_dead_exceptions))
+ || fun->can_delete_dead_exceptions)
+ && !gimple_could_raise_ieee_exception_p (stmt))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
--
2.51.0