This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] Whole program optimization


Hi,
before the discussion settles down, I am committing the attached patch
that adds externally_visible flag needed by Kenny's new aliasing code.

Bootstrapped/regtested i686-pc-gnu-linux.
Honza


2005-05-26  Jan Hubicka  <jh@suse.cz>
	* cgraph.c (dump_cgraph_node): Print new flags.
	(dump_cgraph_varpool_node): Likewise.
	* cgraph.h (cgraph_local_info): Add externally_visible flag.
	(cgraph_varpool_node): Likewise.
	(cgraph_function_flags_ready): Declare.
	* cgraph.c (cgraph_mark_local_functions): Rename to ...
	(cgraph_function_and_variable_visibility) ... this one; handle
	externally_visible flags.
	(cgraph_finalize_function): Deal properly with early cleanups.
	(cgraph_optimize): Update call of
	cgraph_function_and_variable_visibility.
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.74
diff -c -3 -p -r1.74 cgraph.c
*** cgraph.c	27 May 2005 21:17:48 -0000	1.74
--- cgraph.c	2 Jun 2005 10:57:05 -0000
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 582,591 ****
--- 582,597 ----
      fprintf (f, " output");
    if (node->local.local)
      fprintf (f, " local");
+   if (node->local.externally_visible)
+     fprintf (f, " externally_visible");
+   if (node->local.finalized)
+     fprintf (f, " finalized");
    if (node->local.disregard_inline_limits)
      fprintf (f, " always_inline");
    else if (node->local.inlinable)
      fprintf (f, " inlinable");
+   if (node->local.redefined_extern_inline)
+     fprintf (f, " redefined_extern_inline");
    if (TREE_ASM_WRITTEN (node->decl))
      fprintf (f, " asm_written");
  
*************** dump_cgraph_varpool_node (FILE *f, struc
*** 639,644 ****
--- 645,652 ----
      fprintf (f, " finalized");
    if (node->output)
      fprintf (f, " output");
+   if (node->externally_visible)
+     fprintf (f, " externally_visible");
    fprintf (f, "\n");
  }
  
*************** cgraph_varpool_finalize_decl (tree decl)
*** 824,829 ****
--- 832,842 ----
  
    if (decide_is_variable_needed (node, decl))
      cgraph_varpool_mark_needed_node (node);
+   /* Since we reclaim unrechable nodes at the end of every language
+      level unit, we need to be conservative about possible entry points
+      there.  */
+   if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+     cgraph_varpool_mark_needed_node (node);
    if (cgraph_global_info_ready || !flag_unit_at_a_time)
      cgraph_varpool_assemble_pending_decls ();
  }
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.55
diff -c -3 -p -r1.55 cgraph.h
*** cgraph.h	27 May 2005 21:17:49 -0000	1.55
--- cgraph.h	2 Jun 2005 10:57:05 -0000
*************** struct cgraph_local_info GTY(())
*** 36,41 ****
--- 36,44 ----
       and its address is never taken.  */
    bool local;
  
+   /* Set when function is visible by other units.  */
+   bool externally_visible;
+ 
    /* Set once it has been finalized so we consider it to be output.  */
    bool finalized;
  
*************** struct cgraph_varpool_node GTY(())
*** 177,182 ****
--- 180,187 ----
    bool finalized;
    /* Set when function is scheduled to be assembled.  */
    bool output;
+   /* Set when function is visible by other units.  */
+   bool externally_visible;
    /* Set for aliases once they got through assemble_alias.  */
    bool alias;
  };
*************** extern GTY(()) struct cgraph_node *cgrap
*** 185,190 ****
--- 190,196 ----
  extern GTY(()) int cgraph_n_nodes;
  extern GTY(()) int cgraph_max_uid;
  extern bool cgraph_global_info_ready;
+ extern bool cgraph_function_flags_ready;
  extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
  
  extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.110
diff -c -3 -p -r1.110 cgraphunit.c
*** cgraphunit.c	29 May 2005 19:38:31 -0000	1.110
--- cgraphunit.c	2 Jun 2005 10:57:05 -0000
*************** static void cgraph_expand_all_functions 
*** 170,176 ****
  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_mark_local_functions (void);
  static void cgraph_analyze_function (struct cgraph_node *node);
  
  /* Records tree nodes seen in record_reference.  Simply using
--- 170,175 ----
*************** cgraph_finalize_function (tree decl, boo
*** 422,427 ****
--- 421,432 ----
    if (decide_is_function_needed (node, decl))
      cgraph_mark_needed_node (node);
  
+   /* Since we reclaim unrechable nodes at the end of every language
+      level unit, we need to be conservative about possible entry points
+      there.  */
+   if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+     cgraph_mark_reachable_node (node);
+ 
    /* If not unit at a time, go ahead and emit everything we've found
       to be reachable at this time.  */
    if (!nested)
*************** cgraph_expand_all_functions (void)
*** 1016,1040 ****
    free (order);
  }
  
! /* Mark all local 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.  */
  
  static void
! cgraph_mark_local_functions (void)
  {
    struct cgraph_node *node;
  
-   /* Figure out functions we want to assemble.  */
    for (node = cgraph_nodes; node; node = node->next)
      {
        node->local.local = (!node->needed
! 		           && DECL_SAVED_TREE (node->decl)
! 		           && !TREE_PUBLIC (node->decl));
      }
  
    if (cgraph_dump_file)
      {
--- 1021,1067 ----
    free (order);
  }
  
! /* 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 cgraph_varpool_node *vnode;
  
    for (node = cgraph_nodes; node; node = node->next)
      {
+       if (node->reachable
+ 	  && (DECL_COMDAT (node->decl)
+ 	      || (TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
+ 	node->local.externally_visible = 1;
        node->local.local = (!node->needed
! 			   && node->analyzed
! 			   && node->local.externally_visible);
      }
+   for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+     {
+       if (vnode->needed
+ 	  && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
+ 	vnode->externally_visible = 1;
+      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)
      {
*************** cgraph_mark_local_functions (void)
*** 1043,1049 ****
--- 1070,1082 ----
  	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
*************** cgraph_optimize (void)
*** 1088,1094 ****
    if (!quiet_flag)
      fprintf (stderr, "Performing intraprocedural optimizations\n");
  
!   cgraph_mark_local_functions ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "Marked ");
--- 1121,1127 ----
    if (!quiet_flag)
      fprintf (stderr, "Performing intraprocedural optimizations\n");
  
!   cgraph_function_and_variable_visibility ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "Marked ");


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]