On February 6, 2018 9:40:37 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >As the following testcase shows, dom2 miscompiles floating point x - x >into 0.0 even when x could be infinity and x - x then a NaN. >The corresponding match.pd optimization is: >/* Simplify x - x. > This is unsafe for certain floats even in non-IEEE formats. > In IEEE, it is unsafe because it does wrong for NaNs. > Also note that operand_equal_p is always false if an operand > is volatile. */ >(simplify > (minus @0 @0) > (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (type)) > { build_zero_cst (type); })) >The patch makes it match what match.pd does. >We also have: > /* X / X is one. */ > (simplify > (div @0 @0) >/* But not for 0 / 0 so that we can get the proper warnings and errors. > And not for _Fract types where we can't build 1. */ > (if (!integer_zerop (@0) && !ALL_FRACT_MODE_P (TYPE_MODE (type))) > { build_one_cst (type); })) >We can ignore the 0 / 0 case, we have both operands SSA_NAMEs and >match.pd >only avoids optimizing away literal 0 / 0, but the rest is valid, some >fract >types don't have a way to express 1. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. I wonder why we have to re-implement all this in DOM. there's enough of match and simplify interfaces to make it use that? Richard. >2018-02-06 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/84235 > * tree-ssa-scopedtables.c > (avail_exprs_stack::simplify_binary_operation): Fir MINUS_EXPR, punt > if the subtraction is performed in floating point type where NaNs are > honored. For *DIV_EXPR, punt for ALL_FRACT_MODE_Ps where we can't > build 1. Formatting fix. > > * gcc.c-torture/execute/ieee/pr84235.c: New test. > >--- gcc/tree-ssa-scopedtables.c.jj 2018-01-03 10:19:54.528533857 +0100 >+++ gcc/tree-ssa-scopedtables.c 2018-02-06 14:58:08.944673984 +0100 >@@ -182,8 +182,15 @@ avail_exprs_stack::simplify_binary_opera > case BIT_AND_EXPR: > return gimple_assign_rhs1 (stmt); > >- case BIT_XOR_EXPR: > case MINUS_EXPR: >+ /* This is unsafe for certain floats even in non-IEEE >+ formats. In IEEE, it is unsafe because it does >+ wrong for NaNs. */ >+ if (FLOAT_TYPE_P (result_type) >+ && HONOR_NANS (result_type)) >+ break; >+ /* FALLTHRU */ >+ case BIT_XOR_EXPR: > case TRUNC_MOD_EXPR: > case CEIL_MOD_EXPR: > case FLOOR_MOD_EXPR: >@@ -195,6 +202,9 @@ avail_exprs_stack::simplify_binary_opera > case FLOOR_DIV_EXPR: > case ROUND_DIV_EXPR: > case EXACT_DIV_EXPR: >+ /* Avoid _Fract types where we can't build 1. */ >+ if (ALL_FRACT_MODE_P (TYPE_MODE (result_type))) >+ break; > return build_one_cst (result_type); > > default: >@@ -204,8 +214,8 @@ avail_exprs_stack::simplify_binary_opera > break; > } > >- default: >- break; >+ default: >+ break; > } > } > } >--- gcc/testsuite/gcc.c-torture/execute/ieee/pr84235.c.jj 2018-02-06 >15:04:26.528454766 +0100 >+++ gcc/testsuite/gcc.c-torture/execute/ieee/pr84235.c 2018-02-06 >15:05:06.836341334 +0100 >@@ -0,0 +1,11 @@ >+/* PR tree-optimization/84235 */ >+ >+int >+main () >+{ >+ double d = 1.0 / 0.0; >+ _Bool b = d == d && (d - d) != (d - d); >+ if (!b) >+ __builtin_abort (); >+ return 0; >+} > > Jakub