Hi! As the testcase shows, a REAL_CST can appear in MINUS_EXPR as second operand (that is not canonicalized to PLUS_EXPR of negated value, unlike integer constants (with exception of minimum value)). The following patch handles constants there and punts if it isn't SSA_NAME or a constant that can be negated.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-10-10 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/54877 * tree-vect-loop.c (vect_is_simple_reduction_1): For MINUS_EXPR, check if rhs2 is SSA_NAME, if not and is constant, try to negate it, otherwise bail out. * gcc.dg/torture/pr54877.c: New test. --- gcc/tree-vect-loop.c.jj 2012-10-05 13:21:22.000000000 +0200 +++ gcc/tree-vect-loop.c 2012-10-09 20:45:18.559048120 +0200 @@ -2382,16 +2382,41 @@ vect_is_simple_reduction_1 (loop_vec_inf if (orig_code == MINUS_EXPR) { tree rhs = gimple_assign_rhs2 (def_stmt); - tree negrhs = copy_ssa_name (rhs, NULL); - gimple negate_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, negrhs, - rhs, NULL); - gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt); - set_vinfo_for_stmt (negate_stmt, new_stmt_vec_info (negate_stmt, - loop_info, NULL)); - gsi_insert_before (&gsi, negate_stmt, GSI_NEW_STMT); - gimple_assign_set_rhs2 (def_stmt, negrhs); - gimple_assign_set_rhs_code (def_stmt, PLUS_EXPR); - update_stmt (def_stmt); + + if (TREE_CODE (rhs) == SSA_NAME) + { + tree negrhs = copy_ssa_name (rhs, NULL); + gimple negate_stmt + = gimple_build_assign_with_ops (NEGATE_EXPR, negrhs, rhs, NULL); + gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt); + set_vinfo_for_stmt (negate_stmt, + new_stmt_vec_info (negate_stmt, + loop_info, NULL)); + gsi_insert_before (&gsi, negate_stmt, GSI_NEW_STMT); + gimple_assign_set_rhs2 (def_stmt, negrhs); + gimple_assign_set_rhs_code (def_stmt, PLUS_EXPR); + update_stmt (def_stmt); + orig_code = PLUS_EXPR; + } + else if (is_gimple_constant (rhs) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (rhs)))) + { + tree negrhs = fold_unary (NEGATE_EXPR, TREE_TYPE (rhs), rhs); + if (negrhs && is_gimple_val (negrhs)) + { + gimple_assign_set_rhs2 (def_stmt, negrhs); + gimple_assign_set_rhs_code (def_stmt, PLUS_EXPR); + update_stmt (def_stmt); + orig_code = PLUS_EXPR; + } + } + if (orig_code == MINUS_EXPR) + { + if (dump_kind_p (MSG_NOTE)) + report_vect_op (MSG_NOTE, def_stmt, + "reduction: unhandled minus expr: "); + return NULL; + } } /* Reduction is safe. We're dealing with one of the following: --- gcc/testsuite/gcc.dg/torture/pr54877.c.jj 2012-10-09 20:50:43.083259039 +0200 +++ gcc/testsuite/gcc.dg/torture/pr54877.c 2012-10-09 20:51:40.463941703 +0200 @@ -0,0 +1,23 @@ +/* PR tree-optimization/54877 */ +/* { dg-do run } */ +/* { dg-options "-ffast-math" } */ + +extern void abort (void); + +int +foo (void) +{ + double d; + int i; + for (i = 0, d = 0; i < 64; i++) + d--; + return (int) d; +} + +int +main () +{ + if (foo () != -64) + abort (); + return 0; +} Jakub