PR tree-optimization/37315
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Sep 2008 18:16:26 +0000 (18:16 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Sep 2008 18:16:26 +0000 (18:16 +0000)
* cgraph.c (cgraph_create_edge): Use gimple_has_body_p.
* cgraphunit.c (verify_cgraph_node): drop gimple_body check.
(cgraph_analyze_functions): Use node->analyzed
(cgraph_mark_functions_to_output): Likewise.
(cgraph_expand_function): All functions can be released after
expanding.
(cgraph_optimize): Use gimple_has_body_p.
* ipa-inline.c (cgraph_clone_inlined_nodes): Use analyzed flag.
(cgraph_decide_inlining_incrementally): Likewise.
(inline_transform): Inline transform.
* tree-inline.c (initialize_cfun): Do now shallow copy structure;
copy fields needed.
(inlinable_function_p): Drop gimple_body check.
(expand_call_inline): Use gimple_has_body_p.
* gimple.c (gimple_has_body_p): New.
* gimple.h (gimple_has_body_p): Add prototype.
* tree-cfg.c (execute_build_cfg): Remove gimple_body.
(dump_function_to_file): Use gimple_has_body_p check.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139945 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraphunit.c
gcc/gimple.c
gcc/gimple.h
gcc/ipa-inline.c
gcc/tree-cfg.c
gcc/tree-inline.c

index 0b1b999..b3bad2f 100644 (file)
@@ -1,3 +1,25 @@
+2008-09-03  Jan Hubicka  <jh@suse.cz>
+
+       PR tree-optimization/37315
+       * cgraph.c (cgraph_create_edge): Use gimple_has_body_p.
+       * cgraphunit.c (verify_cgraph_node): drop gimple_body check.
+       (cgraph_analyze_functions): Use node->analyzed
+       (cgraph_mark_functions_to_output): Likewise.
+       (cgraph_expand_function): All functions can be released after
+       expanding.
+       (cgraph_optimize): Use gimple_has_body_p.
+       * ipa-inline.c (cgraph_clone_inlined_nodes): Use analyzed flag.
+       (cgraph_decide_inlining_incrementally): Likewise.
+       (inline_transform): Inline transform.
+       * tree-inline.c (initialize_cfun): Do now shallow copy structure;
+       copy fields needed.
+       (inlinable_function_p): Drop gimple_body check.
+       (expand_call_inline): Use gimple_has_body_p.
+       * gimple.c (gimple_has_body_p): New.
+       * gimple.h (gimple_has_body_p): Add prototype.
+       * tree-cfg.c (execute_build_cfg): Remove gimple_body.
+       (dump_function_to_file): Use gimple_has_body_p check.
+
 2008-09-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/37346
index 54d5fad..a12ed15 100644 (file)
@@ -645,7 +645,7 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
 
   gcc_assert (is_gimple_call (call_stmt));
 
-  if (!gimple_body (callee->decl))
+  if (!callee->analyzed)
     edge->inline_failed = N_("function body not available");
   else if (callee->local.redefined_extern_inline)
     edge->inline_failed = N_("redefined extern inline functions are not "
@@ -1073,7 +1073,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
     fprintf (f, " needed");
   else if (node->reachable)
     fprintf (f, " reachable");
-  if (gimple_body (node->decl))
+  if (gimple_has_body_p (node->decl))
     fprintf (f, " body");
   if (node->output)
     fprintf (f, " output");
index 43cdfda..d011041 100644 (file)
@@ -639,7 +639,6 @@ verify_cgraph_node (struct cgraph_node *node)
     }
 
   if (node->analyzed
-      && gimple_body (node->decl)
       && !TREE_ASM_WRITTEN (node->decl)
       && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to))
     {
@@ -860,7 +859,7 @@ cgraph_analyze_functions (void)
     {
       fprintf (cgraph_dump_file, "Initial entry points:");
       for (node = cgraph_nodes; node != first_analyzed; node = node->next)
-       if (node->needed && gimple_body (node->decl))
+       if (node->needed)
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n");
     }
@@ -912,7 +911,7 @@ cgraph_analyze_functions (void)
     {
       fprintf (cgraph_dump_file, "Unit entry points:");
       for (node = cgraph_nodes; node != first_analyzed; node = node->next)
-       if (node->needed && gimple_body (node->decl))
+       if (node->needed)
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n\nInitial ");
       dump_cgraph (cgraph_dump_file);
@@ -926,10 +925,10 @@ cgraph_analyze_functions (void)
       tree decl = node->decl;
       next = node->next;
 
-      if (node->local.finalized && !gimple_body (decl))
+      if (node->local.finalized && !gimple_has_body_p (decl))
        cgraph_reset_node (node);
 
-      if (!node->reachable && gimple_body (decl))
+      if (!node->reachable && gimple_has_body_p (decl))
        {
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
@@ -938,7 +937,7 @@ cgraph_analyze_functions (void)
        }
       else
        node->next_needed = NULL;
-      gcc_assert (!node->local.finalized || gimple_body (decl));
+      gcc_assert (!node->local.finalized || gimple_has_body_p (decl));
       gcc_assert (node->analyzed == node->local.finalized);
     }
   if (cgraph_dump_file)
@@ -991,7 +990,7 @@ cgraph_mark_functions_to_output (void)
       /* We need to output all local functions that are used and not
         always inlined, as well as those that are reachable from
         outside the current compilation unit.  */
-      if (gimple_body (decl)
+      if (node->analyzed
          && !node->global.inlined_to
          && (node->needed
              || (e && node->reachable))
@@ -1003,7 +1002,7 @@ cgraph_mark_functions_to_output (void)
          /* We should've reclaimed all functions that are not needed.  */
 #ifdef ENABLE_CHECKING
          if (!node->global.inlined_to
-             && gimple_body (decl)
+             && gimple_has_body_p (decl)
              && !DECL_EXTERNAL (decl))
            {
              dump_cgraph_node (stderr, node);
@@ -1011,7 +1010,7 @@ cgraph_mark_functions_to_output (void)
            }
 #endif
          gcc_assert (node->global.inlined_to
-                     || !gimple_body (decl)
+                     || !gimple_has_body_p (decl)
                      || DECL_EXTERNAL (decl));
 
        }
@@ -1039,16 +1038,13 @@ cgraph_expand_function (struct cgraph_node *node)
   tree_rest_of_compilation (decl);
 
   /* Make sure that BE didn't give up on compiling.  */
-  /* ??? Can happen with nested function of extern inline.  */
   gcc_assert (TREE_ASM_WRITTEN (decl));
   current_function_decl = NULL;
-  if (!cgraph_preserve_function_body_p (decl))
-    {
-      cgraph_release_function_body (node);
-      /* Eliminate all call edges.  This is important so the call_expr no longer
-        points to the dead function body.  */
-      cgraph_node_remove_callees (node);
-    }
+  gcc_assert (!cgraph_preserve_function_body_p (decl));
+  cgraph_release_function_body (node);
+  /* Eliminate all call edges.  This is important so the GIMPLE_CALL no longer
+     points to the dead function body.  */
+  cgraph_node_remove_callees (node);
 
   cgraph_function_flags_ready = true;
 }
@@ -1329,7 +1325,7 @@ cgraph_optimize (void)
       for (node = cgraph_nodes; node; node = node->next)
        if (node->analyzed
            && (node->global.inlined_to
-               || gimple_body (node->decl)))
+               || gimple_has_body_p (node->decl)))
          {
            error_found = true;
            dump_cgraph_node (stderr, node);
index 6e203b7..7419d85 100644 (file)
@@ -1816,6 +1816,14 @@ gimple_body (tree fndecl)
   return fn ? fn->gimple_body : NULL;
 }
 
+/* Return true when FNDECL has Gimple body either in unlowered
+   or CFG form.  */
+bool
+gimple_has_body_p (tree fndecl)
+{
+  struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+  return (gimple_body (fndecl) || (fn && fn->cfg));
+}
 
 /* Detect flags from a GIMPLE_CALL.  This is just like
    call_expr_flags, but for gimple tuples.  */
index f8af057..03b6217 100644 (file)
@@ -822,6 +822,7 @@ enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
 void sort_case_labels (VEC(tree,heap) *);
 void gimple_set_body (tree, gimple_seq);
 gimple_seq gimple_body (tree);
+bool gimple_has_body_p (tree);
 gimple_seq gimple_seq_alloc (void);
 void gimple_seq_free (gimple_seq);
 void gimple_seq_add_seq (gimple_seq *, gimple_seq);
index 4c8096a..66b9bac 100644 (file)
@@ -212,7 +212,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
          && !cgraph_new_nodes)
        {
          gcc_assert (!e->callee->global.inlined_to);
-         if (gimple_body (e->callee->decl))
+         if (e->callee->analyzed)
            overall_insns -= e->callee->global.insns, nfunctions_inlined++;
          duplicate = false;
        }
@@ -1388,7 +1388,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
            }
          continue;
        }
-      if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
+      if (!e->callee->analyzed && !e->callee->inline_decl)
        {
          if (dump_file)
            {
@@ -1463,7 +1463,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
              }
            continue;
          }
-       if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
+       if (!e->callee->analyzed && !e->callee->inline_decl)
          {
            if (dump_file)
              {
@@ -1706,7 +1706,7 @@ inline_transform (struct cgraph_node *node)
 
   /* We might need the body of this function so that we can expand
      it inline somewhere else.  */
-  if (cgraph_preserve_function_body_p (current_function_decl))
+  if (cgraph_preserve_function_body_p (node->decl))
     save_inline_function_body (node);
 
   for (e = node->callees; e; e = e->next_callee)
index 6bd8a06..ce0649d 100644 (file)
@@ -217,7 +217,10 @@ build_gimple_cfg (gimple_seq seq)
 static unsigned int
 execute_build_cfg (void)
 {
-  build_gimple_cfg (gimple_body (current_function_decl));
+  gimple_seq body = gimple_body (current_function_decl);
+
+  build_gimple_cfg (body);
+  gimple_set_body (current_function_decl, NULL);
   return 0;
 }
 
@@ -5898,7 +5901,7 @@ dump_function_to_file (tree fn, FILE *file, int flags)
   if (dsf && (flags & TDF_DETAILS))
     dump_eh_tree (file, dsf);
 
-  if (flags & TDF_RAW && !gimple_body (fn))
+  if (flags & TDF_RAW && !gimple_has_body_p (fn))
     {
       dump_node (fn, TDF_SLIM | flags, file);
       return;
index 3b77c0e..8b603f0 100644 (file)
@@ -1692,8 +1692,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 +1710,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 =
@@ -2581,12 +2605,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,
@@ -3089,7 +3107,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.