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

Reply via email to