OSDN Git Service

* tree-parloops.c: Change license to GPLv3.
[pf3gnuchains/gcc-fork.git] / gcc / tree-inline.c
index 3b77c0e..075e575 100644 (file)
@@ -129,7 +129,7 @@ static void unsave_expr_1 (tree);
 static tree unsave_r (tree *, int *, void *);
 static void declare_inline_vars (tree, tree);
 static void remap_save_expr (tree *, void *, int *);
-static void add_lexical_block (tree current_block, tree new_block);
+static void prepend_lexical_block (tree current_block, tree new_block);
 static tree copy_decl_to_var (tree, copy_body_data *);
 static tree copy_result_decl_to_var (tree, copy_body_data *);
 static tree copy_decl_maybe_to_var (tree, copy_body_data *);
@@ -512,7 +512,10 @@ remap_blocks (tree block, copy_body_data *id)
   remap_block (&new_tree, id);
   gcc_assert (new_tree != block);
   for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
-    add_lexical_block (new_tree, remap_blocks (t, id));
+    prepend_lexical_block (new_tree, remap_blocks (t, id));
+  /* Blocks are in arbitrary order, but make things slightly prettier and do
+     not swap order when producing a copy.  */
+  BLOCK_SUBBLOCKS (new_tree) = blocks_nreverse (BLOCK_SUBBLOCKS (new_tree));
   return new_tree;
 }
 
@@ -707,6 +710,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
                    {
                      *tp = build1 (INDIRECT_REF, type, new_tree);
                      TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
+                     TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
                    }
                }
              *walk_subtrees = 0;
@@ -1026,6 +1030,7 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
   gimple copy = NULL;
   struct walk_stmt_info wi;
   tree new_block;
+  bool skip_first = false;
 
   /* Begin by recognizing trees that we'll completely rewrite for the
      inlining context.  Our output for these trees is completely
@@ -1047,7 +1052,11 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
         already been set (e.g. a recent "foo (&result_decl, ...)");
         just toss the entire GIMPLE_RETURN.  */
       if (retval && TREE_CODE (retval) != RESULT_DECL)
-       copy = gimple_build_assign (id->retvar, retval);
+        {
+         copy = gimple_build_assign (id->retvar, retval);
+         /* id->retvar is already substituted.  Skip it on later remapping.  */
+         skip_first = true;
+       }
       else
        return gimple_build_nop ();
     }
@@ -1213,7 +1222,10 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
   /* Remap all the operands in COPY.  */
   memset (&wi, 0, sizeof (wi));
   wi.info = id;
-  walk_gimple_op (copy, remap_gimple_op_r, &wi); 
+  if (skip_first)
+    walk_tree (gimple_op_ptr (copy, 1), remap_gimple_op_r, &wi, NULL);
+  else
+    walk_gimple_op (copy, remap_gimple_op_r, &wi); 
 
   /* We have to handle EH region remapping of GIMPLE_RESX specially because
      the region number is not an operand.  */
@@ -1232,7 +1244,7 @@ static basic_block
 copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
          gcov_type count_scale)
 {
-  gimple_stmt_iterator gsi, copy_gsi;
+  gimple_stmt_iterator gsi, copy_gsi, seq_gsi;
   basic_block copy_basic_block;
   tree decl;
 
@@ -1263,6 +1275,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
        continue;
 
       gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, orig_stmt);
+      seq_gsi = copy_gsi;
 
       /* With return slot optimization we can end up with
         non-gimple (foo *)&this->m, fix that here.  */
@@ -1271,21 +1284,31 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
          && !is_gimple_val (gimple_assign_rhs1 (stmt)))
        {
          tree new_rhs;
-         new_rhs = force_gimple_operand_gsi (&copy_gsi,
+         new_rhs = force_gimple_operand_gsi (&seq_gsi,
                                              gimple_assign_rhs1 (stmt),
                                              true, NULL, true, GSI_SAME_STMT);
          gimple_assign_set_rhs1 (stmt, new_rhs);
+         id->regimplify = false;
        }
-      else if (id->regimplify)
-       gimple_regimplify_operands (stmt, &copy_gsi);
 
-      gsi_insert_after (&copy_gsi, stmt, GSI_NEW_STMT);
+      gsi_insert_after (&seq_gsi, stmt, GSI_NEW_STMT);
+
+      if (id->regimplify)
+       gimple_regimplify_operands (stmt, &seq_gsi);
+
+      /* If copy_basic_block has been empty at the start of this iteration,
+        call gsi_start_bb again to get at the newly added statements.  */
+      if (gsi_end_p (copy_gsi))
+       copy_gsi = gsi_start_bb (copy_basic_block);
+      else
+       gsi_next (&copy_gsi);
 
       /* Process the new statement.  The call to gimple_regimplify_operands
         possibly turned the statement into multiple statements, we
         need to process all of them.  */
-      while (!gsi_end_p (copy_gsi))
+      do
        {
+         stmt = gsi_stmt (copy_gsi);
          if (is_gimple_call (stmt)
              && gimple_call_va_arg_pack_p (stmt)
              && id->gimple_call)
@@ -1331,6 +1354,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
              gimple_call_set_lhs (new_call, gimple_call_lhs (stmt));
 
              gsi_replace (&copy_gsi, new_call, false);
+             gimple_set_bb (stmt, NULL);
              stmt = new_call;
            }
          else if (is_gimple_call (stmt)
@@ -1458,6 +1482,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 
          gsi_next (&copy_gsi);
        }
+      while (!gsi_end_p (copy_gsi));
 
       copy_gsi = gsi_last_bb (copy_basic_block);
     }
@@ -1692,8 +1717,6 @@ static void
 initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count,
                 int frequency)
 {
-  struct function *new_cfun
-     = (struct function *) ggc_alloc_cleared (sizeof (struct function));
   struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
   gcov_type count_scale, frequency_scale;
 
@@ -1712,14 +1735,40 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count,
 
   /* Register specific tree functions.  */
   gimple_register_cfg_hooks ();
-  *new_cfun = *DECL_STRUCT_FUNCTION (callee_fndecl);
-  new_cfun->funcdef_no = get_next_funcdef_no ();
-  VALUE_HISTOGRAMS (new_cfun) = NULL;
-  new_cfun->local_decls = NULL;
-  new_cfun->cfg = NULL;
-  new_cfun->decl = new_fndecl /*= copy_node (callee_fndecl)*/;
-  DECL_STRUCT_FUNCTION (new_fndecl) = new_cfun;
-  push_cfun (new_cfun);
+
+  /* Get clean struct function.  */
+  push_struct_function (new_fndecl);
+
+  /* We will rebuild these, so just sanity check that they are empty.  */
+  gcc_assert (VALUE_HISTOGRAMS (cfun) == NULL);
+  gcc_assert (cfun->local_decls == NULL);
+  gcc_assert (cfun->cfg == NULL);
+  gcc_assert (cfun->decl == new_fndecl);
+
+  /* No need to copy; this is initialized later in compilation.  */
+  gcc_assert (!src_cfun->calls_setjmp);
+  gcc_assert (!src_cfun->calls_alloca);
+
+  /* Copy items we preserve during clonning.  */
+  cfun->static_chain_decl = src_cfun->static_chain_decl;
+  cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
+  cfun->function_end_locus = src_cfun->function_end_locus;
+  cfun->curr_properties = src_cfun->curr_properties;
+  cfun->last_verified = src_cfun->last_verified;
+  if (src_cfun->ipa_transforms_to_apply)
+    cfun->ipa_transforms_to_apply = VEC_copy (ipa_opt_pass, heap,
+                                             src_cfun->ipa_transforms_to_apply);
+  cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
+  cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
+  cfun->function_frequency = src_cfun->function_frequency;
+  cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
+  cfun->stdarg = src_cfun->stdarg;
+  cfun->dont_save_pending_sizes_p = src_cfun->dont_save_pending_sizes_p;
+  cfun->after_inlining = src_cfun->after_inlining;
+  cfun->returns_struct = src_cfun->returns_struct;
+  cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
+  cfun->after_tree_profile = src_cfun->after_tree_profile;
+
   init_empty_tree_cfg ();
 
   ENTRY_BLOCK_PTR->count =
@@ -1864,40 +1913,32 @@ self_inlining_addr_expr (tree value, tree fn)
 static void
 insert_init_stmt (basic_block bb, gimple init_stmt)
 {
-  gimple_stmt_iterator si = gsi_last_bb (bb);
-  gimple_stmt_iterator i;
-  gimple_seq seq = gimple_seq_alloc ();
-  struct gimplify_ctx gctx;
-
-  push_gimplify_context (&gctx);
-
-  i = gsi_start (seq);
-  gimple_regimplify_operands (init_stmt, &i);
-
-  if (init_stmt
-      && !gimple_seq_empty_p (seq))
-    {
-      /* The replacement can expose previously unreferenced
-        variables.  */
-      if (gimple_in_ssa_p (cfun))
-        for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
-         find_new_referenced_vars (gsi_stmt (i));
-
-      /* Insert the gimplified sequence needed for INIT_STMT
-        after SI.  INIT_STMT will be inserted after SEQ.  */
-      gsi_insert_seq_after (&si, seq, GSI_NEW_STMT);
-     }
-
-  pop_gimplify_context (NULL);
-
   /* If VAR represents a zero-sized variable, it's possible that the
      assignment statement may result in no gimple statements.  */
   if (init_stmt)
-    gsi_insert_after (&si, init_stmt, GSI_NEW_STMT);
+    {
+      gimple_stmt_iterator si = gsi_last_bb (bb);
 
-  if (gimple_in_ssa_p (cfun))
-    for (;!gsi_end_p (si); gsi_next (&si))
-      mark_symbols_for_renaming (gsi_stmt (si));
+      /* We can end up with init statements that store to a non-register
+         from a rhs with a conversion.  Handle that here by forcing the
+        rhs into a temporary.  gimple_regimplify_operands is not
+        prepared to do this for us.  */
+      if (!is_gimple_reg (gimple_assign_lhs (init_stmt))
+         && is_gimple_reg_type (TREE_TYPE (gimple_assign_lhs (init_stmt)))
+         && gimple_assign_rhs_class (init_stmt) == GIMPLE_UNARY_RHS)
+       {
+         tree rhs = build1 (gimple_assign_rhs_code (init_stmt),
+                            gimple_expr_type (init_stmt),
+                            gimple_assign_rhs1 (init_stmt));
+         rhs = force_gimple_operand_gsi (&si, rhs, true, NULL_TREE, false,
+                                         GSI_NEW_STMT);
+         gimple_assign_set_rhs_code (init_stmt, TREE_CODE (rhs));
+         gimple_assign_set_rhs1 (init_stmt, rhs);
+       }
+      gsi_insert_after (&si, init_stmt, GSI_NEW_STMT);
+      gimple_regimplify_operands (init_stmt, &si);
+      mark_symbols_for_renaming (init_stmt);
+    }
 }
 
 /* Initialize parameter P with VALUE.  If needed, produce init statement
@@ -2276,13 +2317,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 bool
 tree_inlinable_function_p (tree fn)
 {
-  bool ret = inlinable_function_p (fn);
-
-  if (getenv ("TUPLES_INLINE"))
-    fprintf (stderr, "Function %s is %sinlinable\n", get_name (fn),
-            ret ? "" : "not ");
-
-  return ret;
+  return inlinable_function_p (fn);
 }
 
 static const char *inline_forbidden_reason;
@@ -2554,6 +2589,7 @@ inlinable_function_p (tree fn)
   /* We only warn for functions declared `inline' by the user.  */
   do_warning = (warn_inline
                && DECL_DECLARED_INLINE_P (fn)
+               && !DECL_NO_INLINE_WARNING_P (fn)
                && !DECL_IN_SYSTEM_HEADER (fn));
 
   always_inline = lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn));
@@ -2581,12 +2617,6 @@ inlinable_function_p (tree fn)
       inlinable = false;
     }
 
-  /* If we don't have the function body available, we can't inline it.
-     However, this should not be recorded since we also get here for
-     forward declared inline functions.  Therefore, return at once.  */
-  if (!gimple_body (fn))
-    return false;
-
   else if (inline_forbidden_p (fn))
     {
       /* See if we should warn about uninlinable functions.  Previously,
@@ -3009,16 +3039,10 @@ count_insns_seq (gimple_seq seq, eni_weights *weights)
 /* Install new lexical TREE_BLOCK underneath 'current_block'.  */
 
 static void
-add_lexical_block (tree current_block, tree new_block)
+prepend_lexical_block (tree current_block, tree new_block)
 {
-  tree *blk_p;
-
-  /* Walk to the last sub-block.  */
-  for (blk_p = &BLOCK_SUBBLOCKS (current_block);
-       *blk_p;
-       blk_p = &BLOCK_CHAIN (*blk_p))
-    ;
-  *blk_p = new_block;
+  BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (current_block);
+  BLOCK_SUBBLOCKS (current_block) = new_block;
   BLOCK_SUPERCONTEXT (new_block) = current_block;
 }
 
@@ -3089,7 +3113,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
      gimple_body.  */
   if (!DECL_INITIAL (fn)
       && DECL_ABSTRACT_ORIGIN (fn)
-      && gimple_body (DECL_ABSTRACT_ORIGIN (fn)))
+      && gimple_has_body_p (DECL_ABSTRACT_ORIGIN (fn)))
     fn = DECL_ABSTRACT_ORIGIN (fn);
 
   /* Objective C and fortran still calls tree_rest_of_compilation directly.
@@ -3199,7 +3223,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
   id->block = make_node (BLOCK);
   BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
   BLOCK_SOURCE_LOCATION (id->block) = input_location;
-  add_lexical_block (gimple_block (stmt), id->block);
+  prepend_lexical_block (gimple_block (stmt), id->block);
 
   /* Local declarations will be replaced by their equivalents in this
      map.  */
@@ -3225,7 +3249,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
   initialize_inlined_parameters (id, stmt, fn, bb);
 
   if (DECL_INITIAL (fn))
-    add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
+    prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
 
   /* Return statements in the function body will be replaced by jumps
      to the RET_LABEL.  */