The cdce code introduces a test for a NaN using the EQ_EXPR code. The problem is EQ_EXPR can cause an exception with non-call exceptions and signaling nans turned on. This is now correctly rejected by the verfier since r16-241-g4c40e3d7b9152f. The fix is seperate out the comparison into its own statement from the GIMPLE_COND.
Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/120951 gcc/ChangeLog: * tree-call-cdce.cc (use_internal_fn): For non-call exceptions with EQ_EXPR can throw for floating point types, then create the EQ_EXPR seperately. gcc/testsuite/ChangeLog: * gcc.dg/torture/pr120951-1.c: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/testsuite/gcc.dg/torture/pr120951-1.c | 12 ++++++++++++ gcc/tree-call-cdce.cc | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr120951-1.c diff --git a/gcc/testsuite/gcc.dg/torture/pr120951-1.c b/gcc/testsuite/gcc.dg/torture/pr120951-1.c new file mode 100644 index 00000000000..4e2b41deb52 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr120951-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fnon-call-exceptions -fsignaling-nans" } */ + +/* PR tree-optimization/120951 */ + +/* cdce would create a trapping comparison inside a condition. + tests to make sure that does not happen. */ + +double f(double r, double i) { + return __builtin_fmod(r, i); +} + diff --git a/gcc/tree-call-cdce.cc b/gcc/tree-call-cdce.cc index 649c1e2b9f9..3edea754ee4 100644 --- a/gcc/tree-call-cdce.cc +++ b/gcc/tree-call-cdce.cc @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "internal-fn.h" #include "tree-dfa.h" +#include "tree-eh.h" /* This pass serves two closely-related purposes: @@ -1222,8 +1223,20 @@ use_internal_fn (gcall *call) { /* Skip the call if LHS == LHS. If we reach here, EDOM is the only valid errno value and it is used iff the result is NaN. */ - conds.quick_push (gimple_build_cond (EQ_EXPR, lhs, lhs, - NULL_TREE, NULL_TREE)); + /* In the case of non call exceptions, with signaling NaNs, EQ_EXPR + can throw an exception and that can't be part of the GIMPLE_COND. */ + if (flag_exceptions + && cfun->can_throw_non_call_exceptions + && operation_could_trap_p (EQ_EXPR, true, false, NULL_TREE)) + { + tree b = make_ssa_name (boolean_type_node); + conds.quick_push (gimple_build_assign (b, EQ_EXPR, lhs, lhs)); + conds.quick_push (gimple_build_cond (NE_EXPR, b, boolean_false_node, + NULL_TREE, NULL_TREE)); + } + else + conds.quick_push (gimple_build_cond (EQ_EXPR, lhs, lhs, + NULL_TREE, NULL_TREE)); nconds++; /* Try replacing the original call with a direct assignment to -- 2.43.0