tree-pas.h (TODO_remove_function): New flag.
authorJan Hubicka <jh@suse.cz>
Mon, 8 Jan 2007 11:13:14 +0000 (12:13 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 8 Jan 2007 11:13:14 +0000 (11:13 +0000)
* tree-pas.h (TODO_remove_function): New flag.
(TODO_update*): Renumber.
(pass_ipa_increase_alignment,
pass_ipa_function_and_variable_visibility): New passes.
* cgraphunit.c (cgraph_increase_alignment): Move to tree-vectorizer.c
(cgraph_function_and_variable_visibility): Move to ipa.c
(cgraph_optimize): Don't call cgraph_function_and_variable_visibility,
cgraph_increase_alignment.
* ipa-inline.c (cgraph_decide_inlining): Don't push timevar.
(cgraph_decide_inlining_incrementally): Push TV_INTEGRATION before
calling tree-inline.
(cgraph_early_inlining): Do not call cgraph_remove_unreachable_nodes.
(pass_ipa_inline, pass_early_ipa_inlining): Set TODO_remove_functions
* tree-vectorizer.c (increase_alignment): Move here from cgraphunit.c
(gate_increase_alignment): New function.
(pass_ipa_increase_alignment): New pass.
* ipa.c: Inline tree-pass.h and timevar.h
(function_and_variable_visibility): Move here from cgraphunit.c
* tree-optimize.c (pass_early_local_passes): Add TODO_remove_functions.
* passes.c (init_optimization_passes): Add the two new passes.
(execute_todo): Handle cgraph_remove_functions.

From-SVN: r120576

gcc/ChangeLog
gcc/cgraphunit.c
gcc/ipa-inline.c
gcc/ipa.c
gcc/passes.c
gcc/tree-optimize.c
gcc/tree-pass.h
gcc/tree-vectorizer.c

index 169c3cd850e4c3a851149bf4e8631a3ab69eeb17..eebee13f9ee5128306585672d935c2e039e666cf 100644 (file)
@@ -1,3 +1,27 @@
+2007-01-08  Jan Hubicka  <jh@suse.cz>
+
+       * tree-pas.h (TODO_remove_function): New flag.
+       (TODO_update*): Renumber.
+       (pass_ipa_increase_alignment,
+       pass_ipa_function_and_variable_visibility): New passes.
+       * cgraphunit.c (cgraph_increase_alignment): Move to tree-vectorizer.c
+       (cgraph_function_and_variable_visibility): Move to ipa.c
+       (cgraph_optimize): Don't call cgraph_function_and_variable_visibility,
+       cgraph_increase_alignment.
+       * ipa-inline.c (cgraph_decide_inlining): Don't push timevar.
+       (cgraph_decide_inlining_incrementally): Push TV_INTEGRATION before
+       calling tree-inline.
+       (cgraph_early_inlining): Do not call cgraph_remove_unreachable_nodes.
+       (pass_ipa_inline, pass_early_ipa_inlining): Set TODO_remove_functions
+       * tree-vectorizer.c (increase_alignment): Move here from cgraphunit.c
+       (gate_increase_alignment): New function.
+       (pass_ipa_increase_alignment): New pass.
+       * ipa.c: Inline tree-pass.h and timevar.h
+       (function_and_variable_visibility): Move here from cgraphunit.c
+       * tree-optimize.c (pass_early_local_passes): Add TODO_remove_functions.
+       * passes.c (init_optimization_passes): Add the two new passes.
+       (execute_todo): Handle cgraph_remove_functions.
+
 2007-01-08  Nick Clifton  <nickc@redhat.com>
 
        * config/frv/predicates.md (reg_or_0_operand): Accept
index e6f9db4a22c0804c1d49602464d99ae4f53a89de..f75d7b82f9234c94e8366973efb83007d90c6ae2 100644 (file)
@@ -165,7 +165,6 @@ static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
 static void cgraph_expand_function (struct cgraph_node *);
 static void cgraph_output_pending_asms (void);
-static void cgraph_increase_alignment (void);
 
 static FILE *cgraph_dump_file;
 
@@ -1138,78 +1137,6 @@ cgraph_output_in_order (void)
   cgraph_asm_nodes = NULL;
 }
 
-/* Mark visibility of all functions.
-
-   A local function is one whose calls can occur only in the current
-   compilation unit and all its calls are explicit, so we can change
-   its calling convention.  We simply mark all static functions whose
-   address is not taken as local.
-
-   We also change the TREE_PUBLIC flag of all declarations that are public
-   in language point of view but we want to overwrite this default
-   via visibilities for the backend point of view.  */
-
-static void
-cgraph_function_and_variable_visibility (void)
-{
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
-
-  for (node = cgraph_nodes; node; node = node->next)
-    {
-      if (node->reachable
-         && (DECL_COMDAT (node->decl)
-             || (!flag_whole_program
-                 && TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
-       node->local.externally_visible = true;
-      if (!node->local.externally_visible && node->analyzed
-         && !DECL_EXTERNAL (node->decl))
-       {
-         gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl));
-         TREE_PUBLIC (node->decl) = 0;
-       }
-      node->local.local = (!node->needed
-                          && node->analyzed
-                          && !DECL_EXTERNAL (node->decl)
-                          && !node->local.externally_visible);
-    }
-  for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
-    {
-      if (vnode->needed
-         && !flag_whole_program
-         && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
-       vnode->externally_visible = 1;
-      if (!vnode->externally_visible)
-       {
-         gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl));
-         TREE_PUBLIC (vnode->decl) = 0;
-       }
-     gcc_assert (TREE_STATIC (vnode->decl));
-    }
-
-  /* Because we have to be conservative on the boundaries of source
-     level units, it is possible that we marked some functions in
-     reachable just because they might be used later via external
-     linkage, but after making them local they are really unreachable
-     now.  */
-  cgraph_remove_unreachable_nodes (true, cgraph_dump_file);
-
-  if (cgraph_dump_file)
-    {
-      fprintf (cgraph_dump_file, "\nMarking local functions:");
-      for (node = cgraph_nodes; node; node = node->next)
-       if (node->local.local)
-         fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
-      fprintf (cgraph_dump_file, "\n\n");
-      fprintf (cgraph_dump_file, "\nMarking externally visible functions:");
-      for (node = cgraph_nodes; node; node = node->next)
-       if (node->local.externally_visible)
-         fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
-      fprintf (cgraph_dump_file, "\n\n");
-    }
-  cgraph_function_flags_ready = true;
-}
-
 /* Return true when function body of DECL still needs to be kept around
    for later re-use.  */
 bool
@@ -1273,13 +1200,6 @@ cgraph_optimize (void)
     }
   if (!quiet_flag)
     fprintf (stderr, "Performing interprocedural optimizations\n");
-
-  cgraph_function_and_variable_visibility ();
-  if (cgraph_dump_file)
-    {
-      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.  */
@@ -1289,7 +1209,6 @@ cgraph_optimize (void)
   /* This pass remove bodies of extern inline functions we never inlined.
      Do this later so other IPA passes see what is really going on.  */
   cgraph_remove_unreachable_nodes (false, dump_file);
-  cgraph_increase_alignment ();
   cgraph_global_info_ready = true;
   if (cgraph_dump_file)
     {
@@ -1357,52 +1276,6 @@ cgraph_optimize (void)
     }
 #endif
 }
-
-/* Increase alignment of global arrays to improve vectorization potential.
-   TODO:
-   - Consider also structs that have an array field.
-   - Use ipa analysis to prune arrays that can't be vectorized?
-     This should involve global alignment analysis and in the future also
-     array padding.  */
-
-static void
-cgraph_increase_alignment (void)
-{
-  if (flag_section_anchors && flag_tree_vectorize)
-    {
-      struct varpool_node *vnode;
-
-      /* Increase the alignment of all global arrays for vectorization.  */
-      for (vnode = varpool_nodes_queue;
-           vnode;
-           vnode = vnode->next_needed)
-        {
-          tree vectype, decl = vnode->decl;
-          unsigned int alignment;
-
-          if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
-            continue;
-          vectype = get_vectype_for_scalar_type (TREE_TYPE (TREE_TYPE (decl)));
-          if (!vectype)
-            continue;
-          alignment = TYPE_ALIGN (vectype);
-          if (DECL_ALIGN (decl) >= alignment)
-            continue;
-
-          if (vect_can_force_dr_alignment_p (decl, alignment))
-            { 
-              DECL_ALIGN (decl) = TYPE_ALIGN (vectype);
-              DECL_USER_ALIGN (decl) = 1;
-              if (cgraph_dump_file)
-                { 
-                  fprintf (cgraph_dump_file, "Increasing alignment of decl: ");
-                  print_generic_expr (cgraph_dump_file, decl, TDF_SLIM);
-                }
-            }
-        }
-    }
-}
-
 /* Generate and emit a static constructor or destructor.  WHICH must be
    one of 'I' or 'D'.  BODY should be a STATEMENT_LIST containing
    GENERIC statements.  */
index ec2438411c930cf77cea04a17f34ca129c5f92eb..bf9790fd47d6822f8f0e3d40ee1208192af56017 100644 (file)
@@ -925,7 +925,6 @@ cgraph_decide_inlining (void)
   int old_insns = 0;
   int i;
 
-  timevar_push (TV_INLINE_HEURISTICS);
   max_count = 0;
   for (node = cgraph_nodes; node; node = node->next)
     if (node->analyzed && (node->needed || node->reachable))
@@ -1083,7 +1082,6 @@ cgraph_decide_inlining (void)
             ncalls_inlined, nfunctions_inlined, initial_insns,
             overall_insns);
   free (order);
-  timevar_pop (TV_INLINE_HEURISTICS);
   return 0;
 }
 
@@ -1146,6 +1144,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, bool early)
        }
   if (early && inlined)
     {
+      timevar_push (TV_INTEGRATION);
       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
       tree_register_cfg_hooks ();
       current_function_decl = node->decl;
@@ -1153,6 +1152,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, bool early)
       node->local.self_insns = node->global.insns;
       current_function_decl = NULL;
       pop_cfun ();
+      timevar_pop (TV_INTEGRATION);
     }
   return inlined;
 }
@@ -1172,12 +1172,13 @@ struct tree_opt_pass pass_ipa_inline =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_INTEGRATION,                      /* tv_id */
+  TV_INLINE_HEURISTICS,                        /* tv_id */
   0,                                   /* properties_required */
   PROP_cfg,                            /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_cgraph | TODO_dump_func,   /* todo_flags_finish */
+  TODO_dump_cgraph | TODO_dump_func
+  | TODO_remove_functions,             /* todo_flags_finish */
   0                                    /* letter */
 };
 
@@ -1223,7 +1224,6 @@ cgraph_early_inlining (void)
            ggc_collect ();
        }
     }
-  cgraph_remove_unreachable_nodes (true, dump_file);
 #ifdef ENABLE_CHECKING
   for (node = cgraph_nodes; node; node = node->next)
     gcc_assert (!node->global.inlined_to);
@@ -1249,12 +1249,13 @@ struct tree_opt_pass pass_early_ipa_inline =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_INTEGRATION,                      /* tv_id */
+  TV_INLINE_HEURISTICS,                        /* tv_id */
   0,                                   /* properties_required */
   PROP_cfg,                            /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_cgraph | TODO_dump_func,   /* todo_flags_finish */
+  TODO_dump_cgraph | TODO_dump_func
+  | TODO_remove_functions,             /* todo_flags_finish */
   0                                    /* letter */
 };
 
index f45c0583876d33ea68e76115b4d293f97012e340..68e65a9e80c705f2a47c6f82d97c5a884f924283 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -23,6 +23,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "coretypes.h"
 #include "tm.h"
 #include "cgraph.h"
+#include "tree-pass.h"
+#include "timevar.h"
 
 /* Fill array order with all nodes with output flag set in the reverse
    topological order.  */
@@ -206,3 +208,85 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     fprintf (file, "\nReclaimed %i insns", insns);
   return changed;
 }
+
+/* Mark visibility of all functions.
+
+   A local function is one whose calls can occur only in the current
+   compilation unit and all its calls are explicit, so we can change
+   its calling convention.  We simply mark all static functions whose
+   address is not taken as local.
+
+   We also change the TREE_PUBLIC flag of all declarations that are public
+   in language point of view but we want to overwrite this default
+   via visibilities for the backend point of view.  */
+
+static void
+function_and_variable_visibility (void)
+{
+  struct cgraph_node *node;
+  struct varpool_node *vnode;
+
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      if (node->reachable
+         && (DECL_COMDAT (node->decl)
+             || (!flag_whole_program
+                 && TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
+       node->local.externally_visible = true;
+      if (!node->local.externally_visible && node->analyzed
+         && !DECL_EXTERNAL (node->decl))
+       {
+         gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl));
+         TREE_PUBLIC (node->decl) = 0;
+       }
+      node->local.local = (!node->needed
+                          && node->analyzed
+                          && !DECL_EXTERNAL (node->decl)
+                          && !node->local.externally_visible);
+    }
+  for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+    {
+      if (vnode->needed
+         && !flag_whole_program
+         && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
+       vnode->externally_visible = 1;
+      if (!vnode->externally_visible)
+       {
+         gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl));
+         TREE_PUBLIC (vnode->decl) = 0;
+       }
+     gcc_assert (TREE_STATIC (vnode->decl));
+    }
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "\nMarking local functions:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->local.local)
+         fprintf (dump_file, " %s", cgraph_node_name (node));
+      fprintf (dump_file, "\n\n");
+      fprintf (dump_file, "\nMarking externally visible functions:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->local.externally_visible)
+         fprintf (dump_file, " %s", cgraph_node_name (node));
+      fprintf (dump_file, "\n\n");
+    }
+  cgraph_function_flags_ready = true;
+}
+
+struct tree_opt_pass pass_ipa_function_and_variable_visibility = 
+{
+  "visibility",                                /* name */
+  NULL,                                        /* gate */
+  function_and_variable_visibility,    /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_CGRAPHOPT,                                /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_remove_functions | TODO_dump_cgraph,/* todo_flags_finish */
+  0                                    /* letter */
+};
index 91c9f1eff2a1400923b3bb074eb721f4d0ec0535..d8b7f110eac85f196e82518ce2f2c17486177b3f 100644 (file)
@@ -439,8 +439,10 @@ init_optimization_passes (void)
 #define NEXT_PASS(PASS)  (p = next_pass_1 (p, &PASS))
   /* Interprocedural optimization passes.  */
   p = &all_ipa_passes;
+  NEXT_PASS (pass_ipa_function_and_variable_visibility);
   NEXT_PASS (pass_early_ipa_inline);
   NEXT_PASS (pass_early_local_passes);
+  NEXT_PASS (pass_ipa_increase_alignment);
   NEXT_PASS (pass_ipa_cp);
   NEXT_PASS (pass_ipa_inline);
   NEXT_PASS (pass_ipa_reference);
@@ -830,6 +832,13 @@ execute_todo (unsigned int flags)
 
   do_per_function (execute_function_todo, (void *)(size_t) flags);
 
+  /* Always remove functions just as before inlining: IPA passes might be
+     interested to see bodies of extern inline functions that are not inlined
+     to analyze side effects.  The full removal is done just at the end
+     of IPA pass queue.  */
+  if (flags & TODO_remove_functions)
+    cgraph_remove_unreachable_nodes (true, dump_file);
+
   if ((flags & TODO_dump_cgraph)
       && dump_file && !current_function_decl)
     {
index e67b0ef2e122f339913038bebd2e2e892903ce85..6c5fb550ff5d058819cc7a7ce6c19860476cc3f4 100644 (file)
@@ -101,7 +101,7 @@ struct tree_opt_pass pass_early_local_passes =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
+  TODO_remove_functions,               /* todo_flags_finish */
   0                                    /* letter */
 };
 
index 0cec9d4f993c71b910a4e4955c98a29035a310ad..49fd58cc2e80edcc7e313b6e05e01e862400bad1 100644 (file)
@@ -166,6 +166,7 @@ struct dump_file_info
 #define TODO_cleanup_cfg               (1 << 5)
 #define TODO_verify_loops              (1 << 6)
 #define TODO_dump_cgraph               (1 << 7)
+#define TODO_remove_functions          (1 << 8)
 
 /* To-do flags for calls to update_ssa.  */
 
@@ -177,13 +178,13 @@ struct dump_file_info
    in blocks that have one or more edges with no incoming definition
    for O_j.  This would lead to uninitialized warnings for O_j's
    symbol.  */
-#define TODO_update_ssa                        (1 << 8)
+#define TODO_update_ssa                        (1 << 9)
 
 /* Update the SSA form without inserting any new PHI nodes at all.
    This is used by passes that have either inserted all the PHI nodes
    themselves or passes that need only to patch use-def and def-def
    chains for virtuals (e.g., DCE).  */
-#define TODO_update_ssa_no_phi         (1 << 9)
+#define TODO_update_ssa_no_phi         (1 << 10)
 
 /* Insert PHI nodes everywhere they are needed.  No pruning of the
    IDF is done.  This is used by passes that need the PHI nodes for
@@ -194,7 +195,7 @@ struct dump_file_info
    may be doing something wrong.  Inserting PHI nodes for an old name
    where not all edges carry a new replacement may lead to silent
    codegen errors or spurious uninitialized warnings.  */
-#define TODO_update_ssa_full_phi       (1 << 10)
+#define TODO_update_ssa_full_phi       (1 << 11)
 
 /* Passes that update the SSA form on their own may want to delegate
    the updating of virtual names to the generic updater.  Since FUD
@@ -202,20 +203,20 @@ struct dump_file_info
    to do.  NOTE: If this flag is used, any OLD->NEW mappings for real
    names are explicitly destroyed and only the symbols marked for
    renaming are processed.  */
-#define TODO_update_ssa_only_virtuals  (1 << 11)
+#define TODO_update_ssa_only_virtuals  (1 << 12)
 
 /* Some passes leave unused local variables that can be removed from
    cfun->unexpanded_var_list.  This reduces the size of dump files and
    the memory footprint for VAR_DECLs.  */
-#define TODO_remove_unused_locals      (1 << 12)
+#define TODO_remove_unused_locals      (1 << 13)
 
 /* Internally used for the first in a sequence of passes.  It is set
    for the passes that are handed to register_dump_files.  */
-#define TODO_set_props                 (1 << 13)
+#define TODO_set_props                 (1 << 14)
 
 /* Set by passes that may make SMT's that were previously never used
    in statements, used.  */
-#define TODO_update_smt_usage           (1 << 14)
+#define TODO_update_smt_usage           (1 << 15)
 
 #define TODO_update_ssa_any            \
     (TODO_update_ssa                   \
@@ -316,6 +317,8 @@ extern struct tree_opt_pass pass_ipa_type_escape;
 extern struct tree_opt_pass pass_ipa_pta;
 extern struct tree_opt_pass pass_early_local_passes;
 extern struct tree_opt_pass pass_all_early_optimizations;
+extern struct tree_opt_pass pass_ipa_increase_alignment;
+extern struct tree_opt_pass pass_ipa_function_and_variable_visibility;
 
 extern struct tree_opt_pass pass_all_optimizations;
 extern struct tree_opt_pass pass_cleanup_cfg_post_optimizing;
index f8c01f9462146ecfdec3f5ff50c90f4229c2f4ff..aeda161cd9134d306f61078247fc6c826c52e6dc 100644 (file)
@@ -2211,3 +2211,69 @@ vectorize_loops (void)
 
   return num_vectorized_loops > 0 ? TODO_cleanup_cfg : 0;
 }
+
+/* Increase alignment of global arrays to improve vectorization potential.
+   TODO:
+   - Consider also structs that have an array field.
+   - Use ipa analysis to prune arrays that can't be vectorized?
+     This should involve global alignment analysis and in the future also
+     array padding.  */
+
+static unsigned int
+increase_alignment (void)
+{
+  struct varpool_node *vnode;
+
+  /* Increase the alignment of all global arrays for vectorization.  */
+  for (vnode = varpool_nodes_queue;
+       vnode;
+       vnode = vnode->next_needed)
+    {
+      tree vectype, decl = vnode->decl;
+      unsigned int alignment;
+
+      if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
+       continue;
+      vectype = get_vectype_for_scalar_type (TREE_TYPE (TREE_TYPE (decl)));
+      if (!vectype)
+       continue;
+      alignment = TYPE_ALIGN (vectype);
+      if (DECL_ALIGN (decl) >= alignment)
+       continue;
+
+      if (vect_can_force_dr_alignment_p (decl, alignment))
+       { 
+         DECL_ALIGN (decl) = TYPE_ALIGN (vectype);
+         DECL_USER_ALIGN (decl) = 1;
+         if (dump_file)
+           { 
+             fprintf (dump_file, "Increasing alignment of decl: ");
+             print_generic_expr (dump_file, decl, TDF_SLIM);
+           }
+       }
+    }
+  return 0;
+}
+
+static int
+gate_increase_alignment (void)
+{
+  return flag_section_anchors && flag_tree_vectorize;
+}
+
+struct tree_opt_pass pass_ipa_increase_alignment = 
+{
+  "increase_alignment",                        /* name */
+  gate_increase_alignment,             /* gate */
+  increase_alignment,                  /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0,                                   /* todo_flags_finish */
+  0                                    /* letter */
+};