OSDN Git Service

/c-family
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-reassoc.c
index 6cd3ceb..987ec65 100644 (file)
@@ -1,5 +1,6 @@
 /* Reassociation for trees.
-   Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Daniel Berlin <dan@dberlin.org>
 
 This file is part of GCC.
@@ -467,8 +468,7 @@ eliminate_duplicate_pair (enum tree_code opcode,
            {
              VEC_free (operand_entry_t, heap, *ops);
              *ops = NULL;
-             add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
-                                                integer_zero_node));
+             add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (last->op)));
              *all_done = true;
            }
          else
@@ -535,8 +535,7 @@ eliminate_plus_minus_pair (enum tree_code opcode,
            }
 
          VEC_ordered_remove (operand_entry_t, *ops, i);
-         add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
-                                           integer_zero_node));
+         add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (oe->op)));
          VEC_ordered_remove (operand_entry_t, *ops, currindex);
          reassociate_stats.ops_eliminated ++;
 
@@ -623,7 +622,7 @@ eliminate_not_pairs (enum tree_code opcode,
            }
 
          if (opcode == BIT_AND_EXPR)
-           oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
+           oe->op = build_zero_cst (TREE_TYPE (oe->op));
          else if (opcode == BIT_IOR_EXPR)
            oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
                                          TYPE_PRECISION (TREE_TYPE (oe->op)));
@@ -1016,7 +1015,7 @@ undistribute_ops_list (enum tree_code opcode,
   candidates = sbitmap_alloc (length);
   sbitmap_zero (candidates);
   nr_candidates = 0;
-  for (i = 0; VEC_iterate (operand_entry_t, *ops, i, oe1); ++i)
+  FOR_EACH_VEC_ELT (operand_entry_t, *ops, i, oe1)
     {
       enum tree_code dcode;
       gimple oe1def;
@@ -1067,7 +1066,7 @@ undistribute_ops_list (enum tree_code opcode,
       linearize_expr_tree (&subops[i], oedef,
                           associative_tree_code (oecode), false);
 
-      for (j = 0; VEC_iterate (operand_entry_t, subops[i], j, oe1); ++j)
+      FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
        {
          oecount c;
          void **slot;
@@ -1093,14 +1092,13 @@ undistribute_ops_list (enum tree_code opcode,
   htab_delete (ctable);
 
   /* Sort the counting table.  */
-  qsort (VEC_address (oecount, cvec), VEC_length (oecount, cvec),
-        sizeof (oecount), oecount_cmp);
+  VEC_qsort (oecount, cvec, oecount_cmp);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       oecount *c;
       fprintf (dump_file, "Candidates:\n");
-      for (j = 0; VEC_iterate (oecount, cvec, j, c); ++j)
+      FOR_EACH_VEC_ELT (oecount, cvec, j, c)
        {
          fprintf (dump_file, "  %u %s: ", c->cnt,
                   c->oecode == MULT_EXPR
@@ -1139,7 +1137,7 @@ undistribute_ops_list (enum tree_code opcode,
          if (oecode != c->oecode)
            continue;
 
-         for (j = 0; VEC_iterate (operand_entry_t, subops[i], j, oe1); ++j)
+         FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
            {
              if (oe1->op == c->op)
                {
@@ -1178,7 +1176,7 @@ undistribute_ops_list (enum tree_code opcode,
                }
              zero_one_operation (&oe2->op, c->oecode, c->op);
              sum = build_and_add_sum (tmpvar, oe1->op, oe2->op, opcode);
-             oe2->op = fold_convert (TREE_TYPE (oe2->op), integer_zero_node);
+             oe2->op = build_zero_cst (TREE_TYPE (oe2->op));
              oe2->rank = 0;
              oe1->op = gimple_get_lhs (sum);
            }
@@ -1282,6 +1280,20 @@ eliminate_redundant_comparison (enum tree_code opcode,
       if (!useless_type_conversion_p (TREE_TYPE (curr->op), TREE_TYPE (t)))
        t = fold_convert (TREE_TYPE (curr->op), t);
 
+      if (TREE_CODE (t) != INTEGER_CST
+         && !operand_equal_p (t, curr->op, 0))
+       {
+         enum tree_code subcode;
+         tree newop1, newop2;
+         if (!COMPARISON_CLASS_P (t))
+           continue;
+         extract_ops_from_tree (t, &subcode, &newop1, &newop2);
+         STRIP_USELESS_TYPE_CONVERSION (newop1);
+         STRIP_USELESS_TYPE_CONVERSION (newop2);
+         if (!is_gimple_val (newop1) || !is_gimple_val (newop2))
+           continue;
+       }
+
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, "Equivalence: ");
@@ -1314,9 +1326,14 @@ eliminate_redundant_comparison (enum tree_code opcode,
          enum tree_code subcode;
          tree newop1;
          tree newop2;
+         gcc_assert (COMPARISON_CLASS_P (t));
          tmpvar = create_tmp_var (TREE_TYPE (t), NULL);
          add_referenced_var (tmpvar);
          extract_ops_from_tree (t, &subcode, &newop1, &newop2);
+         STRIP_USELESS_TYPE_CONVERSION (newop1);
+         STRIP_USELESS_TYPE_CONVERSION (newop2);
+         gcc_checking_assert (is_gimple_val (newop1)
+                              && is_gimple_val (newop2));
          sum = build_and_add_sum (tmpvar, newop1, newop2, subcode);
          curr->op = gimple_get_lhs (sum);
        }
@@ -1784,13 +1801,15 @@ linearize_expr_tree (VEC(operand_entry_t, heap) **ops, gimple stmt,
   if (TREE_CODE (binlhs) == SSA_NAME)
     {
       binlhsdef = SSA_NAME_DEF_STMT (binlhs);
-      binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode, loop);
+      binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
+                        && !stmt_could_throw_p (binlhsdef));
     }
 
   if (TREE_CODE (binrhs) == SSA_NAME)
     {
       binrhsdef = SSA_NAME_DEF_STMT (binrhs);
-      binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode, loop);
+      binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
+                        && !stmt_could_throw_p (binrhsdef));
     }
 
   /* If the LHS is not reassociable, but the RHS is, we need to swap
@@ -1864,7 +1883,7 @@ repropagate_negates (void)
   unsigned int i = 0;
   tree negate;
 
-  for (i = 0; VEC_iterate (tree, plus_negates, i, negate); i++)
+  FOR_EACH_VEC_ELT (tree, plus_negates, i, negate)
     {
       gimple user = get_single_immediate_use (negate);
 
@@ -1949,7 +1968,7 @@ static bool
 can_reassociate_p (tree op)
 {
   tree type = TREE_TYPE (op);
-  if (INTEGRAL_TYPE_P (type)
+  if ((INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
       || NON_SAT_FIXED_POINT_TYPE_P (type)
       || (flag_associative_math && FLOAT_TYPE_P (type)))
     return true;
@@ -2025,7 +2044,8 @@ reassociate_bb (basic_block bb)
     {
       gimple stmt = gsi_stmt (gsi);
 
-      if (is_gimple_assign (stmt))
+      if (is_gimple_assign (stmt)
+         && !stmt_could_throw_p (stmt))
        {
          tree lhs, rhs1, rhs2;
          enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
@@ -2065,9 +2085,16 @@ reassociate_bb (basic_block bb)
          rhs1 = gimple_assign_rhs1 (stmt);
          rhs2 = gimple_assign_rhs2 (stmt);
 
-         if (!can_reassociate_p (lhs)
-             || !can_reassociate_p (rhs1)
-             || !can_reassociate_p (rhs2))
+         /* For non-bit or min/max operations we can't associate
+            all types.  Verify that here.  */
+         if (rhs_code != BIT_IOR_EXPR
+             && rhs_code != BIT_AND_EXPR
+             && rhs_code != BIT_XOR_EXPR
+             && rhs_code != MIN_EXPR
+             && rhs_code != MAX_EXPR
+             && (!can_reassociate_p (lhs)
+                 || !can_reassociate_p (rhs1)
+                 || !can_reassociate_p (rhs2)))
            continue;
 
          if (associative_tree_code (rhs_code))
@@ -2081,18 +2108,12 @@ reassociate_bb (basic_block bb)
 
              gimple_set_visited (stmt, true);
              linearize_expr_tree (&ops, stmt, true, true);
-             qsort (VEC_address (operand_entry_t, ops),
-                    VEC_length (operand_entry_t, ops),
-                    sizeof (operand_entry_t),
-                    sort_by_operand_rank);
+             VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
              optimize_ops_list (rhs_code, &ops);
              if (undistribute_ops_list (rhs_code, &ops,
                                         loop_containing_stmt (stmt)))
                {
-                 qsort (VEC_address (operand_entry_t, ops),
-                        VEC_length (operand_entry_t, ops),
-                        sizeof (operand_entry_t),
-                        sort_by_operand_rank);
+                 VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
                  optimize_ops_list (rhs_code, &ops);
                }
 
@@ -2141,7 +2162,7 @@ dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops)
   operand_entry_t oe;
   unsigned int i;
 
-  for (i = 0; VEC_iterate (operand_entry_t, ops, i, oe); i++)
+  FOR_EACH_VEC_ELT (operand_entry_t, ops, i, oe)
     {
       fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
       print_generic_expr (file, oe->op, 0);
@@ -2276,7 +2297,10 @@ struct gimple_opt_pass pass_reassoc =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
+  TODO_verify_ssa
+    | TODO_verify_flow
+    | TODO_dump_func
+    | TODO_ggc_collect                 /* todo_flags_finish */
  }
 };