OSDN Git Service

PR c++/27714
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index 606cd75..0533592 100644 (file)
@@ -1,4 +1,4 @@
-/* Callgraph based intraprocedural optimizations.
+/* Callgraph based interprocedural optimizations.
    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -20,7 +20,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
 /* This module implements main driver of compilation process as well as
-   few basic intraprocedural optimizers.
+   few basic interprocedural optimizers.
 
    The main scope of this file is to act as an interface in between
    tree based frontends and the backend (and middle end)
@@ -172,6 +172,10 @@ static void cgraph_mark_functions_to_output (void);
 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);
+
+/* Lists all assembled variables to be sent to debugger output later on.  */
+static GTY(()) struct cgraph_varpool_node *cgraph_varpool_assembled_nodes_queue;
 
 /* Records tree nodes seen in record_reference.  Simply using
    walk_tree_without_duplicates doesn't guarantee each node is visited
@@ -855,18 +859,7 @@ cgraph_varpool_assemble_decl (struct cgraph_varpool_node *node)
       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
     {
       assemble_variable (decl, 0, 1, 0);
-      /* Local static variables are never seen by check_global_declarations
-        so we need to output debug info by hand.  */
-      if (DECL_CONTEXT (decl)
-         && (TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
-             || TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
-         && errorcount == 0 && sorrycount == 0)
-       {
-         timevar_push (TV_SYMOUT);
-         (*debug_hooks->global_decl) (decl);
-         timevar_pop (TV_SYMOUT);
-       }
-      return true;
+      return TREE_ASM_WRITTEN (decl);
     }
 
   return false;
@@ -892,11 +885,39 @@ cgraph_varpool_assemble_pending_decls (void)
 
       cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
       if (cgraph_varpool_assemble_decl (node))
-       changed = true;
-      node->next_needed = NULL;
+       {
+         changed = true;
+         node->next_needed = cgraph_varpool_assembled_nodes_queue;
+         cgraph_varpool_assembled_nodes_queue = node;
+         node->finalized = 1;
+       }
+      else
+        node->next_needed = NULL;
     }
   return changed;
 }
+/* Output all variables enqueued to be assembled.  */
+static void
+cgraph_varpool_output_debug_info (void)
+{
+  timevar_push (TV_SYMOUT);
+  if (errorcount == 0 && sorrycount == 0)
+    while (cgraph_varpool_assembled_nodes_queue)
+      {
+       struct cgraph_varpool_node *node = cgraph_varpool_assembled_nodes_queue;
+
+       /* Local static variables are never seen by check_global_declarations
+          so we need to output debug info by hand.  */
+       if (DECL_CONTEXT (node->decl)
+           && (TREE_CODE (DECL_CONTEXT (node->decl)) == BLOCK
+               || TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
+           && errorcount == 0 && sorrycount == 0)
+            (*debug_hooks->global_decl) (node->decl);
+       cgraph_varpool_assembled_nodes_queue = node->next_needed;
+       node->next_needed = 0;
+      }
+  timevar_pop (TV_SYMOUT);
+}
 
 /* Output all asm statements we have stored up to be output.  */
 
@@ -927,7 +948,8 @@ cgraph_analyze_function (struct cgraph_node *node)
   cgraph_create_edges (node, decl);
 
   node->local.inlinable = tree_inlinable_function_p (decl);
-  node->local.self_insns = estimate_num_insns (decl);
+  if (!flag_unit_at_a_time)
+    node->local.self_insns = estimate_num_insns (decl);
   if (node->local.inlinable)
     node->local.disregard_inline_limits
       = lang_hooks.tree_inlining.disregard_inline_limits (decl);
@@ -984,9 +1006,16 @@ process_function_and_variable_attributes (struct cgraph_node *first,
        }
       if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
-         if (node->local.finalized)
-           cgraph_mark_needed_node (node);
-         node->externally_visible = true;
+         if (! TREE_PUBLIC (node->decl))
+           warning (OPT_Wattributes,
+                    "%J%<externally_visible%> attribute have effect only on public objects",
+                    node->decl);
+         else
+           {
+             if (node->local.finalized)
+               cgraph_mark_needed_node (node);
+             node->local.externally_visible = true;
+           }
        }
     }
   for (vnode = cgraph_varpool_nodes; vnode != first_var; vnode = vnode->next)
@@ -1000,9 +1029,16 @@ process_function_and_variable_attributes (struct cgraph_node *first,
        }
       if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
-         if (vnode->finalized)
-           cgraph_varpool_mark_needed_node (vnode);
-         vnode->externally_visible = true;
+         if (! TREE_PUBLIC (vnode->decl))
+           warning (OPT_Wattributes,
+                    "%J%<externally_visible%> attribute have effect only on public objects",
+                    vnode->decl);
+         else
+           {
+             if (vnode->finalized)
+               cgraph_varpool_mark_needed_node (vnode);
+             vnode->externally_visible = true;
+           }
        }
     }
 }
@@ -1018,12 +1054,16 @@ cgraph_finalize_compilation_unit (void)
   static struct cgraph_node *first_analyzed;
   static struct cgraph_varpool_node *first_analyzed_var;
 
+  if (errorcount || sorrycount)
+    return;
+
   finish_aliases_1 ();
 
   if (!flag_unit_at_a_time)
     {
       cgraph_output_pending_asms ();
       cgraph_assemble_pending_functions ();
+      cgraph_varpool_output_debug_info ();
       return;
     }
 
@@ -1466,6 +1506,9 @@ ipa_passes (void)
 void
 cgraph_optimize (void)
 {
+  if (errorcount || sorrycount)
+    return;
+
 #ifdef ENABLE_CHECKING
   verify_cgraph ();
 #endif
@@ -1473,6 +1516,7 @@ cgraph_optimize (void)
     {
       cgraph_output_pending_asms ();
       cgraph_varpool_assemble_pending_decls ();
+      cgraph_varpool_output_debug_info ();
       return;
     }
 
@@ -1484,7 +1528,7 @@ cgraph_optimize (void)
 
   timevar_push (TV_CGRAPHOPT);
   if (!quiet_flag)
-    fprintf (stderr, "Performing intraprocedural optimizations\n");
+    fprintf (stderr, "Performing interprocedural optimizations\n");
 
   cgraph_function_and_variable_visibility ();
   if (cgraph_dump_file)
@@ -1500,6 +1544,7 @@ 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)
     {
@@ -1528,6 +1573,7 @@ cgraph_optimize (void)
       cgraph_varpool_remove_unreferenced_decls ();
 
       cgraph_varpool_assemble_pending_decls ();
+      cgraph_varpool_output_debug_info ();
     }
 
   if (cgraph_dump_file)
@@ -1559,6 +1605,51 @@ 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 cgraph_varpool_node *vnode;
+
+      /* Increase the alignment of all global arrays for vectorization.  */
+      for (vnode = cgraph_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.  */
@@ -1823,3 +1914,4 @@ save_inline_function_body (struct cgraph_node *node)
   return first_clone;
 }
 
+#include "gt-cgraphunit.h"