]> gcc.gnu.org Git - gcc.git/commitdiff
cgraph.c (cgraph_exapnd_queue): Rename to...
authorJan Hubicka <jh@suse.cz>
Sat, 30 Dec 2006 11:58:01 +0000 (12:58 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 30 Dec 2006 11:58:01 +0000 (11:58 +0000)
* cgraph.c (cgraph_exapnd_queue): Rename to...
(cgraph_new_nodes): ... this one.
(cgraph_state): New global variable.
(cgraph_add_new_function): Work in more cases.
* cgraph.h (cgraph_expand_queue): Rename to ...
(cgraph_new_nodes): ... this one.
(cgraph_state): New enum and static variable.
(cgraph_add_new_function): Update prototype.
(cgraph_process_new_functions): New.
* omp-low.c (expand_omp_parallel): Update.
* cgraphunit.c (initialize_inline_failed): Declare early.
(cgraph_process_new_functions): New function.
(cgraph_assemble_pending_functions): Use it.
(cgraph_expand_all_functions): Use it.
(cgraph_optimize): Use it; set cgraph_state.
* passes.c (execute_one_pass, execute_ipa_pass_list): Process new
functions

From-SVN: r120282

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/omp-low.c
gcc/passes.c

index 24a46cb97bd27165d49680be97a601a64587d658..b728b00e54cdf3f3c3741337d5afae45a53b3762 100644 (file)
@@ -1,3 +1,23 @@
+2006-12-29  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_exapnd_queue): Rename to...
+       (cgraph_new_nodes): ... this one.
+       (cgraph_state): New global variable.
+       (cgraph_add_new_function): Work in more cases.
+       * cgraph.h (cgraph_expand_queue): Rename to ...
+       (cgraph_new_nodes): ... this one.
+       (cgraph_state): New enum and static variable.
+       (cgraph_add_new_function): Update prototype.
+       (cgraph_process_new_functions): New.
+       * omp-low.c (expand_omp_parallel): Update.
+       * cgraphunit.c (initialize_inline_failed): Declare early.
+       (cgraph_process_new_functions): New function.
+       (cgraph_assemble_pending_functions): Use it.
+       (cgraph_expand_all_functions): Use it.
+       (cgraph_optimize): Use it; set cgraph_state.
+       * passes.c (execute_one_pass, execute_ipa_pass_list): Process new
+       functions
+
 2006-12-29  Kazu Hirata  <kazu@codesourcery.com>
 
        * tree-cfg.c (last_stmt_ptr): Remove.
index d35b4db5a569ba5b3104a8c8a76ac19e00fcd5e4..21e821c2b4df030cf2594455e69e551e9650eee4 100644 (file)
@@ -97,10 +97,10 @@ struct cgraph_node *cgraph_nodes;
 /* Queue of cgraph nodes scheduled to be lowered.  */
 struct cgraph_node *cgraph_nodes_queue;
 
-/* Queue of cgraph nodes scheduled to be expanded.  This is a
+/* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
    may generate new functions that need to be optimized and expanded.  */
-struct cgraph_node *cgraph_expand_queue;
+struct cgraph_node *cgraph_new_nodes;
 
 /* Number of nodes in existence.  */
 int cgraph_n_nodes;
@@ -111,6 +111,9 @@ int cgraph_max_uid;
 /* Set when whole unit has been analyzed so we can access global info.  */
 bool cgraph_global_info_ready = false;
 
+/* What state callgraph is in right now.  */
+enum cgraph_state cgraph_state = CGRAPH_STATE_CONSTRUCTION;
+
 /* Set when the cgraph is fully build and the basic flags are computed.  */
 bool cgraph_function_flags_ready = false;
 
@@ -911,23 +914,60 @@ cgraph_function_body_availability (struct cgraph_node *node)
   return avail;
 }
 
-/* Add the function FNDECL to the call graph.  FNDECL is assumed to be
-   in low GIMPLE form and ready to be processed by cgraph_finalize_function.
+/* Add the function FNDECL to the call graph.
+   Unlike cgraph_finalize_function, this function is intended to be used
+   by middle end and allows insertion of new function at arbitrary point
+   of compilation.  The function can be either in high, low or SSA form
+   GIMPLE.
 
-   When operating in unit-at-a-time, a new callgraph node is added to
-   CGRAPH_EXPAND_QUEUE, which is processed after all the original
-   functions in the call graph .
+   The function is assumed to be reachable and have address taken (so no
+   API breaking optimizations are performed on it).  
 
-   When not in unit-at-a-time, the new callgraph node is added to
-   CGRAPH_NODES_QUEUE for cgraph_assemble_pending_functions to
-   process.  */
+   Main work done by this function is to enqueue the function for later
+   processing to avoid need the passes to be re-entrant.  */
 
 void
-cgraph_add_new_function (tree fndecl)
+cgraph_add_new_function (tree fndecl, bool lowered)
 {
-  struct cgraph_node *n = cgraph_node (fndecl);
-  n->next_needed = cgraph_expand_queue;
-  cgraph_expand_queue = n;
+  struct cgraph_node *node;
+  switch (cgraph_state)
+    {
+      case CGRAPH_STATE_CONSTRUCTION:
+       /* Just enqueue function to be processed at nearest occurence.  */
+       node = cgraph_node (fndecl);
+       node->next_needed = cgraph_new_nodes;
+       if (lowered)
+         node->lowered = true;
+       cgraph_new_nodes = node;
+        break;
+
+      case CGRAPH_STATE_IPA:
+      case CGRAPH_STATE_EXPANSION:
+       /* Bring the function into finalized state and enqueue for later
+          analyzing and compilation.  */
+       node = cgraph_node (fndecl);
+       node->local.local = false;
+       node->local.finalized = true;
+       node->reachable = node->needed = true;
+       if (lowered)
+         node->lowered = true;
+       node->next_needed = cgraph_new_nodes;
+       cgraph_new_nodes = node;
+        break;
+
+      case CGRAPH_STATE_FINISHED:
+       /* At the very end of compilation we have to do all the work up
+          to expansion.  */
+       push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+       current_function_decl = fndecl;
+       tree_register_cfg_hooks ();
+       if (!lowered)
+          tree_lowering_passes (fndecl);
+       tree_rest_of_compilation (fndecl);
+       pop_cfun ();
+       current_function_decl = NULL;
+       break;
+    }
 }
 
 #include "gt-cgraph.h"
index 8d4fe750b05773a61f98218b3383918506248e07..e363819f166bd648e40139526621bee14b015295 100644 (file)
@@ -254,9 +254,21 @@ extern GTY(()) struct cgraph_node *cgraph_nodes;
 extern GTY(()) int cgraph_n_nodes;
 extern GTY(()) int cgraph_max_uid;
 extern bool cgraph_global_info_ready;
+enum cgraph_state
+{
+  /* Callgraph is being constructed.  It is safe to add new functions.  */
+  CGRAPH_STATE_CONSTRUCTION,
+  /* Callgraph is built and IPA passes are being run.  */
+  CGRAPH_STATE_IPA,
+  /* Functions are now ordered and being passed to RTL expanders.  */
+  CGRAPH_STATE_EXPANSION,
+  /* All cgraph expansion is done.  */
+  CGRAPH_STATE_FINISHED
+};
+extern enum cgraph_state cgraph_state;
 extern bool cgraph_function_flags_ready;
 extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
-extern GTY(()) struct cgraph_node *cgraph_expand_queue;
+extern GTY(()) struct cgraph_node *cgraph_new_nodes;
 
 extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
 extern GTY(()) int cgraph_order;
@@ -295,7 +307,7 @@ void cgraph_unnest_node (struct cgraph_node *);
 enum availability cgraph_function_body_availability (struct cgraph_node *);
 bool cgraph_is_master_clone (struct cgraph_node *);
 struct cgraph_node *cgraph_master_clone (struct cgraph_node *);
-void cgraph_add_new_function (tree);
+void cgraph_add_new_function (tree, bool);
 
 /* In cgraphunit.c  */
 void cgraph_finalize_function (tree, bool);
@@ -316,6 +328,7 @@ struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
 void cgraph_analyze_function (struct cgraph_node *);
 struct cgraph_node *save_inline_function_body (struct cgraph_node *);
 void record_references_in_initializer (tree);
+bool cgraph_process_new_functions (void);
 
 /* In ipa.c  */
 bool cgraph_remove_unreachable_nodes (bool, FILE *);
index 578b36c198377b76c924b5de1c433e7fe6911fd4..0aa9f7de124c92ac97d25759bbc4b2fb266da31d 100644 (file)
@@ -167,6 +167,7 @@ static void cgraph_expand_function (struct cgraph_node *);
 static tree record_reference (tree *, int *, void *);
 static void cgraph_output_pending_asms (void);
 static void cgraph_increase_alignment (void);
+static void initialize_inline_failed (struct cgraph_node *);
 
 /* Records tree nodes seen in record_reference.  Simply using
    walk_tree_without_duplicates doesn't guarantee each node is visited
@@ -262,6 +263,77 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
   return false;
 }
 
+/* Process CGRAPH_NEW_FUNCTIONS and perform actions neccesary to add these
+   functions into callgraph in a way so they look like ordinary reachable
+   functions inserted into callgraph already at construction time.  */
+
+bool
+cgraph_process_new_functions (void)
+{
+  bool output = false;
+  tree fndecl;
+  struct cgraph_node *node;
+
+  /*  Note that this queue may grow as its being processed, as the new
+      functions may generate new ones.  */
+  while (cgraph_new_nodes)
+    {
+      node = cgraph_new_nodes;
+      fndecl = node->decl;
+      cgraph_new_nodes = cgraph_new_nodes->next_needed;
+      switch (cgraph_state)
+       {
+       case CGRAPH_STATE_CONSTRUCTION:
+         /* At construction time we just need to finalize function and move
+            it into reachable functions list.  */
+
+         node->next_needed = NULL;
+         cgraph_finalize_function (fndecl, false);
+         cgraph_mark_reachable_node (node);
+         output = true;
+         break;
+
+       case CGRAPH_STATE_IPA:
+         /* When IPA optimization already started, do all essential
+            transformations that has been already performed on the whole
+            cgraph but not on this function.  */
+
+         tree_register_cfg_hooks ();
+         if (!node->analyzed)
+           cgraph_analyze_function (node);
+         push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+         current_function_decl = fndecl;
+         node->local.inlinable = tree_inlinable_function_p (fndecl);
+         node->local.self_insns = estimate_num_insns (fndecl);
+         node->local.disregard_inline_limits
+           = lang_hooks.tree_inlining.disregard_inline_limits (fndecl);
+         /* Inlining characteristics are maintained by the
+            cgraph_mark_inline.  */
+         node->global.insns = node->local.self_insns;
+         initialize_inline_failed (node);
+         if (flag_really_no_inline && !node->local.disregard_inline_limits)
+            node->local.inlinable = 0;
+         free_dominance_info (CDI_POST_DOMINATORS);
+         free_dominance_info (CDI_DOMINATORS);
+         pop_cfun ();
+         current_function_decl = NULL;
+         break;
+
+       case CGRAPH_STATE_EXPANSION:
+         /* Functions created during expansion shall be compiled
+            directly.  */
+         node->output = 0;
+         cgraph_expand_function (node);
+         break;
+
+       default:
+         gcc_unreachable ();
+         break;
+       }
+    }
+  return output;
+}
+
 /* When not doing unit-at-a-time, output all functions enqueued.
    Return true when such a functions were found.  */
 
@@ -288,18 +360,7 @@ cgraph_assemble_pending_functions (void)
          cgraph_expand_function (n);
          output = true;
        }
-    }
-
-  /* Process CGRAPH_EXPAND_QUEUE, these are functions created during
-     the expansion process.  Note that this queue may grow as its
-     being processed, as the new functions may generate new ones.  */
-  while (cgraph_expand_queue)
-    {
-      struct cgraph_node *n = cgraph_expand_queue;
-      cgraph_expand_queue = cgraph_expand_queue->next_needed;
-      n->next_needed = NULL;
-      cgraph_finalize_function (n->decl, false);
-      output = true;
+      output |= cgraph_process_new_functions ();
     }
 
   return output;
@@ -1161,21 +1222,10 @@ cgraph_expand_all_functions (void)
          cgraph_expand_function (node);
        }
     }
+  cgraph_process_new_functions ();
 
   free (order);
 
-  /* Process CGRAPH_EXPAND_QUEUE, these are functions created during
-     the expansion process.  Note that this queue may grow as its
-     being processed, as the new functions may generate new ones.  */
-  while (cgraph_expand_queue)
-    {
-      node = cgraph_expand_queue;
-      cgraph_expand_queue = cgraph_expand_queue->next_needed;
-      node->next_needed = NULL;
-      node->output = 0;
-      node->lowered = DECL_STRUCT_FUNCTION (node->decl)->cfg != NULL;
-      cgraph_expand_function (node);
-    }
 }
 
 /* This is used to sort the node types by the cgraph order number.  */
@@ -1383,6 +1433,9 @@ cgraph_optimize (void)
 #endif
   if (!flag_unit_at_a_time)
     {
+      cgraph_assemble_pending_functions ();
+      cgraph_process_new_functions ();
+      cgraph_state = CGRAPH_STATE_FINISHED;
       cgraph_output_pending_asms ();
       varpool_assemble_pending_decls ();
       varpool_output_debug_info ();
@@ -1408,6 +1461,7 @@ cgraph_optimize (void)
       fprintf (cgraph_dump_file, "Marked ");
       dump_cgraph (cgraph_dump_file);
     }
+  cgraph_state = CGRAPH_STATE_IPA;
     
   /* Don't run the IPA passes if there was any error or sorry messages.  */
   if (errorcount == 0 && sorrycount == 0)
@@ -1440,6 +1494,7 @@ cgraph_optimize (void)
 
   cgraph_mark_functions_to_output ();
 
+  cgraph_state = CGRAPH_STATE_EXPANSION;
   if (!flag_toplevel_reorder)
     cgraph_output_in_order ();
   else
@@ -1452,6 +1507,8 @@ cgraph_optimize (void)
       varpool_assemble_pending_decls ();
       varpool_output_debug_info ();
     }
+  cgraph_process_new_functions ();
+  cgraph_state = CGRAPH_STATE_FINISHED;
 
   if (cgraph_dump_file)
     {
@@ -1581,14 +1638,8 @@ cgraph_build_static_cdtor (char which, tree body, int priority)
 
   gimplify_function_tree (decl);
 
-  /* ??? We will get called LATE in the compilation process.  */
-  if (cgraph_global_info_ready)
-    {
-      tree_lowering_passes (decl);
-      tree_rest_of_compilation (decl);
-    }
-  else
-    cgraph_finalize_function (decl, 0);
+  cgraph_add_new_function (decl, false);
+  cgraph_mark_needed_node (cgraph_node (decl));
 
   if (targetm.have_ctors_dtors)
     {
index f3f4113b98c4bd85cef1c1dcb083dfd720e603bb..e863568d5c4df7a0c0c01bf5722a75bb47f15424 100644 (file)
@@ -2533,7 +2533,7 @@ expand_omp_parallel (struct omp_region *region)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
       DECL_STRUCT_FUNCTION (child_fn)->curr_properties
        = cfun->curr_properties;
-      cgraph_add_new_function (child_fn);
+      cgraph_add_new_function (child_fn, true);
 
       /* Convert OMP_RETURN into a RETURN_EXPR.  */
       if (exit_bb)
index 38c95cdaf2bce0c966dbbe0e2a52d853249ca445..458842163bcd95be0df861bccc58e76c65ac4306 100644 (file)
@@ -947,6 +947,9 @@ execute_one_pass (struct tree_opt_pass *pass)
   /* Run post-pass cleanup and verification.  */
   execute_todo (todo_after | pass->todo_flags_finish);
 
+  if (!current_function_decl)
+    cgraph_process_new_functions ();
+
   /* Flush and close dump file.  */
   if (dump_file_name)
     {
@@ -986,6 +989,8 @@ execute_ipa_pass_list (struct tree_opt_pass *pass)
       gcc_assert (!cfun);
       if (execute_one_pass (pass) && pass->sub)
        do_per_function ((void (*)(void *))execute_pass_list, pass->sub);
+      if (!current_function_decl)
+       cgraph_process_new_functions ();
       pass = pass->next;
     }
   while (pass);
This page took 0.097345 seconds and 5 git commands to generate.