OSDN Git Service

* fold-const.c (fold): Avoid non INTEGER_TYPEs when widening
[pf3gnuchains/gcc-fork.git] / gcc / tree-sra.c
index 423ee3c..01a609a 100644 (file)
@@ -5,17 +5,17 @@
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
-   
+
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
-   
+
 GCC is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
-   
+
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
@@ -52,7 +52,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* This object of this pass is to replace a non-addressable aggregate with a
    set of independent variables.  Most of the time, all of these variables
-   will be scalars.  But a secondary objective is to break up larger 
+   will be scalars.  But a secondary objective is to break up larger
    aggregates into smaller aggregates.  In the process we may find that some
    bits of the larger aggregate can be deleted as unreferenced.
 
@@ -132,7 +132,7 @@ struct sra_elt
 };
 
 /* Random access to the child of a parent is performed by hashing.
-   This prevents quadratic behaviour, and allows SRA to function
+   This prevents quadratic behavior, and allows SRA to function
    reasonably on larger records.  */
 static htab_t sra_map;
 
@@ -182,7 +182,7 @@ type_can_be_decomposed_p (tree type)
   if (bitmap_bit_p (sra_type_decomp_cache, cache+1))
     return false;
 
-  /* The type must have a definite non-zero size.  */
+  /* The type must have a definite nonzero size.  */
   if (TYPE_SIZE (type) == NULL || integer_zerop (TYPE_SIZE (type)))
     goto fail;
 
@@ -329,7 +329,7 @@ type_can_instantiate_all_elements (tree type)
       return true;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -379,7 +379,7 @@ sra_hash_tree (tree t)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return h;
@@ -398,14 +398,14 @@ sra_elt_hash (const void *x)
 
   /* Take into account everything back up the chain.  Given that chain
      lengths are rarely very long, this should be acceptable.  If we
-     truely identify this as a performance problem, it should work to
+     truly identify this as a performance problem, it should work to
      hash the pointer value "e->parent".  */
   for (p = e->parent; p ; p = p->parent)
     h = (h * 65521) ^ sra_hash_tree (p->element);
 
   return h;
 }
-  
+
 /* Equality function for type SRA_PAIR.  */
 
 static int
@@ -446,7 +446,7 @@ sra_elt_eq (const void *x, const void *y)
       return fields_compatible_p (ae, be);
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -533,7 +533,7 @@ is_valid_const_index (tree expr)
   return true;
 }
 
-/* Create or return the SRA_ELT structure for EXPR if the expression 
+/* Create or return the SRA_ELT structure for EXPR if the expression
    refers to a scalarizable variable.  */
 
 static struct sra_elt *
@@ -682,7 +682,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
           index reference inside a loop being overridden by several constant
           index references during loop setup.  It's possible that this could
           be avoided by using dynamic usage counts based on BB trip counts
-          (based on loop analysis or profiling), but that hardly seems worth 
+          (based on loop analysis or profiling), but that hardly seems worth
           the effort.  */
        /* ??? Hack.  Figure out how to push this into the scan routines
           without duplicating too much code.  */
@@ -716,7 +716,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
 
       case BIT_FIELD_REF:
        /* A bit field reference (access to *multiple* fields simultaneously)
-          is not currently scalarized.  Consider this an access to the 
+          is not currently scalarized.  Consider this an access to the
           complete outer element, to which walk_tree will bring us next.  */
        goto use_all;
 
@@ -731,6 +731,11 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
           type other than the one we've scalarized.  */
        goto use_all;
 
+      case WITH_SIZE_EXPR:
+       /* This is a transparent wrapper.  The entire inner expression really
+          is being used.  */
+       goto use_all;
+
       use_all:
         expr_p = &TREE_OPERAND (inner, 0);
        inner = expr = *expr_p;
@@ -739,8 +744,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
       default:
 #ifdef ENABLE_CHECKING
        /* Validate that we're not missing any references.  */
-       if (walk_tree (&inner, sra_find_candidate_decl, NULL, NULL))
-         abort ();
+       gcc_assert (!walk_tree (&inner, sra_find_candidate_decl, NULL, NULL));
 #endif
        return;
       }
@@ -821,9 +825,9 @@ sra_walk_modify_expr (tree expr, block_stmt_iterator *bsi,
         The lvalue requirement prevents us from trying to directly scalarize
         the result of a function call.  Which would result in trying to call
         the function multiple times, and other evil things.  */
-      else if (!lhs_elt->is_scalar && is_gimple_addr_expr_arg (rhs))
+      else if (!lhs_elt->is_scalar && is_gimple_addressable (rhs))
        fns->ldst (lhs_elt, rhs, bsi, true);
-       
+
       /* Otherwise we're being used in some context that requires the
         aggregate to be seen as a whole.  Invoke USE.  */
       else
@@ -941,7 +945,7 @@ find_candidates_for_sra (void)
           any_set = true;
         }
     }
+
   return any_set;
 }
 
@@ -1241,7 +1245,7 @@ instantiate_missing_elements (struct sra_elt *elt)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1289,7 +1293,7 @@ decide_block_copy (struct sra_elt *elt)
 
          full_size = tree_low_cst (size_tree, 1);
 
-         /* ??? What to do here.  If there are two fields, and we've only 
+         /* ??? What to do here.  If there are two fields, and we've only
             instantiated one, then instantiating the other is clearly a win.
             If there are a large number of fields then the size of the copy
             is much more of a factor.  */
@@ -1372,9 +1376,9 @@ decide_instantiations (void)
 
   if (cleared_any)
     {
-      bitmap_operation (sra_candidates, sra_candidates, &done_head, 
+      bitmap_operation (sra_candidates, sra_candidates, &done_head,
                        BITMAP_AND_COMPL);
-      bitmap_operation (needs_copy_in, needs_copy_in, &done_head, 
+      bitmap_operation (needs_copy_in, needs_copy_in, &done_head,
                        BITMAP_AND_COMPL);
     }
   bitmap_clear (&done_head);
@@ -1392,27 +1396,13 @@ decide_instantiations (void)
 static void
 mark_all_v_defs (tree stmt)
 {
-  v_may_def_optype v_may_defs;
-  v_must_def_optype v_must_defs;
-  size_t i, n;
+  tree sym;
+  ssa_op_iter iter;
 
   get_stmt_operands (stmt);
 
-  v_may_defs = V_MAY_DEF_OPS (stmt_ann (stmt));
-  n = NUM_V_MAY_DEFS (v_may_defs);
-  for (i = 0; i < n; i++)
-    {
-      tree sym = V_MAY_DEF_RESULT (v_may_defs, i);
-      if (TREE_CODE (sym) == SSA_NAME)
-       sym = SSA_NAME_VAR (sym);
-      bitmap_set_bit (vars_to_rename, var_ann (sym)->uid);
-    }
-
-  v_must_defs = V_MUST_DEF_OPS (stmt_ann (stmt));
-  n = NUM_V_MUST_DEFS (v_must_defs);
-  for (i = 0; i < n; i++)
+  FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_VIRTUAL_DEFS)
     {
-      tree sym = V_MUST_DEF_OP (v_must_defs, i);
       if (TREE_CODE (sym) == SSA_NAME)
        sym = SSA_NAME_VAR (sym);
       bitmap_set_bit (vars_to_rename, var_ann (sym)->uid);
@@ -1447,7 +1437,7 @@ generate_one_element_ref (struct sra_elt *elt, tree base)
        return build (IMAGPART_EXPR, elt->type, base);
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1504,8 +1494,7 @@ generate_element_copy (struct sra_elt *dst, struct sra_elt *src, tree *list_p)
   for (dc = dst->children; dc ; dc = dc->sibling)
     {
       sc = lookup_element (src, dc->element, NULL, NO_INSERT);
-      if (sc == NULL)
-       abort ();
+      gcc_assert (sc);
       generate_element_copy (dc, sc, list_p);
     }
 
@@ -1513,8 +1502,7 @@ generate_element_copy (struct sra_elt *dst, struct sra_elt *src, tree *list_p)
     {
       tree t;
 
-      if (src->replacement == NULL)
-       abort ();
+      gcc_assert (src->replacement);
 
       t = build (MODIFY_EXPR, void_type_node, dst->replacement,
                 src->replacement);
@@ -1545,11 +1533,8 @@ generate_element_zero (struct sra_elt *elt, tree *list_p)
     {
       tree t;
 
-      if (elt->is_scalar)
-       t = fold_convert (elt->type, integer_zero_node);
-      else
-       /* We generated a replacement for a non-scalar?  */
-       abort ();
+      gcc_assert (elt->is_scalar);
+      t = fold_convert (elt->type, integer_zero_node);
 
       t = build (MODIFY_EXPR, void_type_node, elt->replacement, t);
       append_to_statement_list (t, list_p);
@@ -1568,7 +1553,7 @@ find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
   if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
     add_referenced_tmp_var (t);
 
-  if (DECL_P (t) || TYPE_P (t))
+  if (IS_TYPE_OR_DECL_P (t))
     *walk_subtrees = 0;
 
   return NULL;
@@ -1692,7 +1677,7 @@ insert_edge_copies (tree stmt, basic_block bb)
              first_copy = false;
            }
          else
-           bsi_insert_on_edge (e, lhd_unsave_expr_now (stmt));
+           bsi_insert_on_edge (e, unsave_expr_now (stmt));
        }
     }
 }
@@ -1775,11 +1760,9 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi,
       generate_copy_inout (elt, is_output, generate_element_ref (elt), &list);
       if (list == NULL)
        return;
+      mark_all_v_defs (expr_first (list));
       if (is_output)
-       {
-         mark_all_v_defs (expr_first (list));
-         sra_insert_after (bsi, list);
-       }
+       sra_insert_after (bsi, list);
       else
        sra_insert_before (bsi, list);
     }
@@ -1799,12 +1782,9 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
       /* If we have two scalar operands, modify the existing statement.  */
       stmt = bsi_stmt (*bsi);
 
-#ifdef ENABLE_CHECKING
       /* See the commentary in sra_walk_function concerning
         RETURN_EXPR, and why we should never see one here.  */
-      if (TREE_CODE (stmt) != MODIFY_EXPR)
-       abort ();
-#endif
+      gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR);
 
       TREE_OPERAND (stmt, 0) = lhs_elt->replacement;
       TREE_OPERAND (stmt, 1) = rhs_elt->replacement;
@@ -1813,7 +1793,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
   else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy)
     {
       /* If either side requires a block copy, then sync the RHS back
-        to the original structure, leave the original assignment 
+        to the original structure, leave the original assignment
         statement (which will perform the block copy), then load the
         LHS values out of its now-updated original structure.  */
       /* ??? Could perform a modified pair-wise element copy.  That
@@ -1846,8 +1826,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
 
       list = NULL;
       generate_element_copy (lhs_elt, rhs_elt, &list);
-      if (list == NULL)
-       abort ();
+      gcc_assert (list);
       sra_replace (bsi, list);
     }
 }
@@ -1905,8 +1884,7 @@ scalarize_init (struct sra_elt *lhs_elt, tree rhs, block_stmt_iterator *bsi)
     {
       /* The LHS is fully instantiated.  The list of initializations
         replaces the original structure assignment.  */
-      if (!list)
-       abort ();
+      gcc_assert (list);
       mark_all_v_defs (bsi_stmt (*bsi));
       sra_replace (bsi, list);
     }
@@ -1925,7 +1903,7 @@ mark_notrap (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       TREE_THIS_NOTRAP (t) = 1;
       *walk_subtrees = 0;
     }
-  else if (DECL_P (t) || TYPE_P (t))
+  else if (IS_TYPE_OR_DECL_P (t))
     *walk_subtrees = 0;
 
   return NULL;
@@ -1940,8 +1918,7 @@ scalarize_ldst (struct sra_elt *elt, tree other,
                block_stmt_iterator *bsi, bool is_output)
 {
   /* Shouldn't have gotten called for a scalar.  */
-  if (elt->replacement)
-    abort ();
+  gcc_assert (!elt->replacement);
 
   if (elt->use_block_copy)
     {
@@ -1959,8 +1936,7 @@ scalarize_ldst (struct sra_elt *elt, tree other,
 
       mark_all_v_defs (stmt);
       generate_copy_inout (elt, is_output, other, &list);
-      if (list == NULL)
-       abort ();
+      gcc_assert (list);
 
       /* Preserve EH semantics.  */
       if (stmt_ends_bb_p (stmt))
@@ -1975,7 +1951,7 @@ scalarize_ldst (struct sra_elt *elt, tree other,
 
          /* Replace the old statement with this new representative.  */
          bsi_replace (bsi, first, true);
-         
+
          if (!tsi_end_p (tsi))
            {
              /* If any reference would trap, then they all would.  And more
@@ -2007,7 +1983,7 @@ scalarize_parms (void)
   size_t i;
 
   EXECUTE_IF_SET_IN_BITMAP (needs_copy_in, 0, i,
-    { 
+    {
       tree var = referenced_var (i);
       struct sra_elt *elt = lookup_element (NULL, var, NULL, NO_INSERT);
       generate_copy_inout (elt, true, var, &list);
@@ -2104,7 +2080,7 @@ gate_sra (void)
   return flag_tree_sra != 0;
 }
 
-struct tree_opt_pass pass_sra = 
+struct tree_opt_pass pass_sra =
 {
   "sra",                               /* name */
   gate_sra,                            /* gate */
@@ -2113,10 +2089,11 @@ struct tree_opt_pass pass_sra =
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   TV_TREE_SRA,                         /* tv_id */
-  PROP_cfg | PROP_ssa,                 /* properties_required */
+  PROP_cfg | PROP_ssa | PROP_alias,    /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_dump_func | TODO_rename_vars
-    | TODO_ggc_collect | TODO_verify_ssa  /* todo_flags_finish */
+    | TODO_ggc_collect | TODO_verify_ssa,  /* todo_flags_finish */
+  0                                    /* letter */
 };