diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50456696bcb..18dd9dc4a31 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2008-02-20 Richard Guenther + + * tree.h (fold_real_zero_addition_p): Declare. + * fold-const.c (fold_real_zero_addition_p): Export. + * tree-ssa-reassoc.c (eliminate_using_constants): Also handle + floating-point operations with zero and one. + 2008-02-20 Paolo Bonzini * doc/install.texi: Correct references to CFLAGS, replacing them diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a33b2b07a46..aba71b6bf41 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -134,7 +134,6 @@ static tree extract_muldiv_1 (tree, tree, enum tree_code, tree, bool *); static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree, tree, tree, tree, int); -static bool fold_real_zero_addition_p (const_tree, const_tree, int); static tree fold_mathfn_compare (enum built_in_function, enum tree_code, tree, tree, tree); static tree fold_inf_compare (enum tree_code, tree, tree, tree); @@ -6426,7 +6425,7 @@ fold_binary_op_with_conditional_arg (enum tree_code code, X - 0 is not the same as X because 0 - 0 is -0. In other rounding modes, X + 0 is not the same as X because -0 + 0 is 0. */ -static bool +bool fold_real_zero_addition_p (const_tree type, const_tree addend, int negate) { if (!real_zerop (addend)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4037344d742..7e947ec4b27 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-02-20 Richard Guenther + + * gcc.dg/tree-ssa/reassoc-13.c: New testcase. + 2008-02-20 Ira Rosen * lib/target-supports.exp (check_effective_target_vect_unpack): diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c new file mode 100644 index 00000000000..4d4dfeb446b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ffast-math -fdump-tree-reassoc1 -fdump-tree-optimized" } */ + +double foo(double a) +{ + double tmp = 5.0; + double tmp2 = a + tmp; + tmp2 = tmp2 - a; + return a + tmp2 - 5.0; +} + +/* { dg-final { scan-tree-dump-not "\\\+ 0.0" "reassoc1" } } */ +/* { dg-final { scan-tree-dump "return a;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index a4118c92339..6e6f5f7f442 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "pointer-set.h" #include "cfgloop.h" +#include "flags.h" /* This is a simple global reassociation pass. It is, in part, based on the LLVM pass of the same name (They do some things more/less @@ -598,8 +599,10 @@ eliminate_using_constants (enum tree_code opcode, VEC(operand_entry_t, heap) **ops) { operand_entry_t oelast = VEC_last (operand_entry_t, *ops); + tree type = TREE_TYPE (oelast->op); - if (oelast->rank == 0 && INTEGRAL_TYPE_P (TREE_TYPE (oelast->op))) + if (oelast->rank == 0 + && (INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type))) { switch (opcode) { @@ -660,7 +663,11 @@ eliminate_using_constants (enum tree_code opcode, } break; case MULT_EXPR: - if (integer_zerop (oelast->op)) + if (integer_zerop (oelast->op) + || (FLOAT_TYPE_P (type) + && !HONOR_NANS (TYPE_MODE (type)) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)) + && real_zerop (oelast->op))) { if (VEC_length (operand_entry_t, *ops) != 1) { @@ -675,7 +682,10 @@ eliminate_using_constants (enum tree_code opcode, return; } } - else if (integer_onep (oelast->op)) + else if (integer_onep (oelast->op) + || (FLOAT_TYPE_P (type) + && !HONOR_SNANS (TYPE_MODE (type)) + && real_onep (oelast->op))) { if (VEC_length (operand_entry_t, *ops) != 1) { @@ -690,7 +700,11 @@ eliminate_using_constants (enum tree_code opcode, case BIT_XOR_EXPR: case PLUS_EXPR: case MINUS_EXPR: - if (integer_zerop (oelast->op)) + if (integer_zerop (oelast->op) + || (FLOAT_TYPE_P (type) + && (opcode == PLUS_EXPR || opcode == MINUS_EXPR) + && fold_real_zero_addition_p (type, oelast->op, + opcode == MINUS_EXPR))) { if (VEC_length (operand_entry_t, *ops) != 1) { diff --git a/gcc/tree.h b/gcc/tree.h index 99c4aeadab1..f98afe9be80 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4851,6 +4851,8 @@ extern enum tree_code invert_tree_comparison (enum tree_code, bool); extern bool tree_expr_nonzero_p (tree); extern bool tree_expr_nonzero_warnv_p (tree, bool *); +extern bool fold_real_zero_addition_p (const_tree, const_tree, int); + /* In builtins.c */ extern tree fold_call_expr (tree, bool); extern tree fold_builtin_fputs (tree, tree, bool, bool, tree);