--- 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;
+}
