OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index cfe6696..531565e 100644 (file)
@@ -1,7 +1,7 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012 Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
 
@@ -119,6 +119,19 @@ mark_addressable (tree x)
       && TREE_CODE (x) != RESULT_DECL)
     return;
   TREE_ADDRESSABLE (x) = 1;
+
+  /* Also mark the artificial SSA_NAME that points to the partition of X.  */
+  if (TREE_CODE (x) == VAR_DECL
+      && !DECL_EXTERNAL (x)
+      && !TREE_STATIC (x)
+      && cfun->gimple_df != NULL
+      && cfun->gimple_df->decls_to_pointers != NULL)
+    {
+      void *namep
+       = pointer_map_contains (cfun->gimple_df->decls_to_pointers, x); 
+      if (namep)
+       TREE_ADDRESSABLE (*(tree *)namep) = 1;
+    }
 }
 
 /* Return a hash value for a formal temporary table entry.  */
@@ -162,7 +175,7 @@ gimple_tree_eq (const void *p1, const void *p2)
    before the def/use vectors have been constructed.  */
 
 void
-gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
 {
   gimple_stmt_iterator si;
 
@@ -177,6 +190,15 @@ gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
   gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
 }
 
+/* Shorter alias name for the above function for use in gimplify.c
+   only.  */
+
+static inline void
+gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+{
+  gimple_seq_add_stmt_without_update (seq_p, gs);
+}
+
 /* Append sequence SRC to the end of sequence *DST_P.  If *DST_P is
    NULL, a new sequence is allocated.   This function is
    similar to gimple_seq_add_seq, but does not scan the operands.
@@ -495,7 +517,8 @@ create_tmp_reg (tree type, const char *prefix)
 static inline tree
 create_tmp_from_val (tree val)
 {
-  return create_tmp_var (TREE_TYPE (val), get_name (val));
+  /* Drop all qualifiers and address-space information from the value type.  */
+  return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
@@ -858,9 +881,10 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location)
   way to go.  */
 
 /* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
-   These nodes model computations that should only be done once.  If we
-   were to unshare something like SAVE_EXPR(i++), the gimplification
-   process would create wrong code.  */
+   These nodes model computations that must be done once.  If we were to
+   unshare something like SAVE_EXPR(i++), the gimplification process would
+   create wrong code.  However, if DATA is non-null, it must hold a pointer
+   set that is used to unshare the subtrees of these nodes.  */
 
 static tree
 mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
@@ -900,9 +924,9 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-/* Callback for walk_tree to unshare most of the shared trees rooted at
-   *TP.  If *TP has been visited already (i.e., TREE_VISITED (*TP) == 1),
-   then *TP is deep copied by calling mostly_copy_tree_r.  */
+/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
+   If *TP has been visited already, then *TP is deeply copied by calling
+   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
 
 static tree
 copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
@@ -939,34 +963,37 @@ copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-/* Unshare most of the shared trees rooted at *TP. */
+/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
+   copy_if_shared_r callback unmodified.  */
 
 static inline void
-copy_if_shared (tree *tp)
+copy_if_shared (tree *tp, void *data)
 {
-  /* If the language requires deep unsharing, we need a pointer set to make
-     sure we don't repeatedly unshare subtrees of unshareable nodes.  */
-  struct pointer_set_t *visited
-    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
-  walk_tree (tp, copy_if_shared_r, visited, NULL);
-  if (visited)
-    pointer_set_destroy (visited);
+  walk_tree (tp, copy_if_shared_r, data, NULL);
 }
 
-/* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
-   bodies of any nested functions if we are unsharing the entire body of
-   FNDECL.  */
+/* Unshare all the trees in the body of FNDECL, as well as in the bodies of
+   any nested functions.  */
 
 static void
-unshare_body (tree *body_p, tree fndecl)
+unshare_body (tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_get_node (fndecl);
+  /* If the language requires deep unsharing, we need a pointer set to make
+     sure we don't repeatedly unshare subtrees of unshareable nodes.  */
+  struct pointer_set_t *visited
+    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
 
-  copy_if_shared (body_p);
+  copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
+  copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
+  copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
 
-  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
+  if (visited)
+    pointer_set_destroy (visited);
+
+  if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+      unshare_body (cgn->decl);
 }
 
 /* Callback for walk_tree to unmark the visited trees rooted at *TP.
@@ -999,15 +1026,17 @@ unmark_visited (tree *tp)
 /* Likewise, but mark all trees as not visited.  */
 
 static void
-unvisit_body (tree *body_p, tree fndecl)
+unvisit_body (tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_get_node (fndecl);
 
-  unmark_visited (body_p);
+  unmark_visited (&DECL_SAVED_TREE (fndecl));
+  unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
+  unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
 
-  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
+  if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+      unvisit_body (cgn->decl);
 }
 
 /* Unconditionally make an unshared copy of EXPR.  This is used when using
@@ -1081,6 +1110,15 @@ voidify_wrapper_expr (tree wrapper, tree temp)
              break;
 
            default:
+             /* Assume that any tree upon which voidify_wrapper_expr is
+                directly called is a wrapper, and that its body is op0.  */
+             if (p == &wrapper)
+               {
+                 TREE_SIDE_EFFECTS (*p) = 1;
+                 TREE_TYPE (*p) = void_type_node;
+                 p = &TREE_OPERAND (*p, 0);
+                 break;
+               }
              goto out;
            }
        }
@@ -1207,7 +1245,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
          && !DECL_HAS_VALUE_EXPR_P (t)
          /* Only care for variables that have to be in memory.  Others
             will be rewritten into SSA names, hence moved to the top-level.  */
-         && needs_to_live_in_memory (t))
+         && !is_gimple_reg (t))
        {
          tree clobber = build_constructor (TREE_TYPE (t), NULL);
          TREE_THIS_VOLATILE (clobber) = 1;
@@ -1400,6 +1438,13 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
       && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
     gimplify_type_sizes (TREE_TYPE (decl), seq_p);
 
+  /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
+     in case its size expressions contain problematic nodes like CALL_EXPR.  */
+  if (TREE_CODE (decl) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (decl)
+      && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
+    gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
+
   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
       tree init = DECL_INITIAL (decl);
@@ -2449,7 +2494,6 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
          CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
            = CALL_EXPR_RETURN_SLOT_OPT (call);
          CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
-         CALL_CANNOT_INLINE_P (*expr_p) = CALL_CANNOT_INLINE_P (call);
          SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
          TREE_BLOCK (*expr_p) = TREE_BLOCK (call);
 
@@ -3699,7 +3743,8 @@ optimize_compound_literals_in_ctor (tree orig_ctor)
 
          if (!TREE_ADDRESSABLE (value)
              && !TREE_ADDRESSABLE (decl)
-             && init)
+             && init
+             && TREE_CODE (init) == CONSTRUCTOR)
            newval = optimize_compound_literals_in_ctor (init);
        }
       if (newval == value)
@@ -4394,7 +4439,14 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
                /* It's OK to use the target directly if it's being
                   initialized. */
                use_target = true;
-             else if (!is_gimple_non_addressable (*to_p))
+             else if (variably_modified_type_p (TREE_TYPE (*to_p), NULL_TREE))
+               /* Always use the target and thus RSO for variable-sized types.
+                  GIMPLE cannot deal with a variable-sized assignment
+                  embedded in a call statement.  */
+               use_target = true;
+             else if (TREE_CODE (*to_p) != SSA_NAME
+                     && (!is_gimple_variable (*to_p)
+                         || needs_to_live_in_memory (*to_p)))
                /* Don't use the original target if it's already addressable;
                   if its address escapes, and the called function uses the
                   NRV optimization, a conforming program could see *to_p
@@ -5209,13 +5261,16 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
      any cleanups collected outside the CLEANUP_POINT_EXPR.  */
   int old_conds = gimplify_ctxp->conditions;
   gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
+  bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
   gimplify_ctxp->conditions = 0;
   gimplify_ctxp->conditional_cleanups = NULL;
+  gimplify_ctxp->in_cleanup_point_expr = true;
 
   gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
 
   gimplify_ctxp->conditions = old_conds;
   gimplify_ctxp->conditional_cleanups = old_cleanups;
+  gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
 
   for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
     {
@@ -5391,7 +5446,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
       /* Add a clobber for the temporary going out of scope, like
         gimplify_bind_expr.  */
-      if (needs_to_live_in_memory (temp))
+      if (gimplify_ctxp->in_cleanup_point_expr
+         && needs_to_live_in_memory (temp))
        {
          tree clobber = build_constructor (TREE_TYPE (temp), NULL);
          TREE_THIS_VOLATILE (clobber) = true;
@@ -7027,15 +7083,23 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              ret = GS_OK;
              break;
            }
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_mem_ref_addr, fb_rvalue);
-         if (ret == GS_ERROR)
-           break;
+         /* Avoid re-gimplifying the address operand if it is already
+            in suitable form.  Re-gimplifying would mark the address
+            operand addressable.  Always gimplify when not in SSA form
+            as we still may have to gimplify decls with value-exprs.  */
+         if (!gimplify_ctxp || !gimplify_ctxp->into_ssa
+             || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
+           {
+             ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                                  is_gimple_mem_ref_addr, fb_rvalue);
+             if (ret == GS_ERROR)
+               break;
+           }
          recalculate_side_effects (*expr_p);
          ret = GS_ALL_DONE;
          break;
 
-         /* Constants need not be gimplified.  */
+       /* Constants need not be gimplified.  */
        case INTEGER_CST:
        case REAL_CST:
        case FIXED_CST:
@@ -7884,9 +7948,7 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
      a VAR_DECL.  If it's a VAR_DECL from another function, the gimplifier
      will want to replace it with a new variable, but that will cause problems
      if this type is from outside the function.  It's OK to have that here.  */
-  if (expr == NULL_TREE || TREE_CONSTANT (expr)
-      || TREE_CODE (expr) == VAR_DECL
-      || CONTAINS_PLACEHOLDER_P (expr))
+  if (is_gimple_sizepos (expr))
     return;
 
   type = TREE_TYPE (expr);
@@ -7915,13 +7977,12 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
     }
 }
 
-/* Gimplify the body of statements pointed to by BODY_P and return a
-   GIMPLE_BIND containing the sequence of GIMPLE statements
-   corresponding to BODY_P.  FNDECL is the function decl containing
-   *BODY_P.  */
+/* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
+   containing the sequence of corresponding GIMPLE statements.  If DO_PARMS
+   is true, also gimplify the parameters.  */
 
 gimple
-gimplify_body (tree *body_p, tree fndecl, bool do_parms)
+gimplify_body (tree fndecl, bool do_parms)
 {
   location_t saved_location = input_location;
   gimple_seq parm_stmts, seq;
@@ -7942,8 +8003,8 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
      It would seem we don't have to do this for nested functions because
      they are supposed to be output and then the outer function gimplified
      first, but the g++ front end doesn't always do it that way.  */
-  unshare_body (body_p, fndecl);
-  unvisit_body (body_p, fndecl);
+  unshare_body (fndecl);
+  unvisit_body (fndecl);
 
   cgn = cgraph_get_node (fndecl);
   if (cgn && cgn->origin)
@@ -7954,11 +8015,11 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
 
   /* Resolve callee-copies.  This has to be done before processing
      the body so that DECL_VALUE_EXPR gets processed correctly.  */
-  parm_stmts = (do_parms) ? gimplify_parameters () : NULL;
+  parm_stmts = do_parms ? gimplify_parameters () : NULL;
 
   /* Gimplify the function's body.  */
   seq = NULL;
-  gimplify_stmt (body_p, &seq);
+  gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
   outer_bind = gimple_seq_first_stmt (seq);
   if (!outer_bind)
     {
@@ -7974,7 +8035,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   else
     outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
 
-  *body_p = NULL_TREE;
+  DECL_SAVED_TREE (fndecl) = NULL_TREE;
 
   /* If we had callee-copies statements, insert them at the beginning
      of the function and clear DECL_VALUE_EXPR_P on the parameters.  */
@@ -8092,7 +8153,7 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
+  bind = gimplify_body (fndecl, true);
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */