diff mbox

[1/n] Cleanup internal interfaces, GCC modularization

Message ID Pine.LNX.4.64.1203291225510.5416@jbgna.fhfr.qr
State New
Headers show

Commit Message

Richard Biener March 29, 2012, 10:31 a.m. UTC
I am playing with doing some internal interface static analysis
using the first patch below (and looking at LTO bootstrap results).

An example, obvious patch resulting from that is the 2nd patch,
resuling from the static analysis output

/space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:add_to_value can be made 
static
/space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:print_value_expressions 
can be made static

the static analysis is very verbose (and does not consider ipa-refs yet).
You also need to union results for building all frontends and all
targets (well, in theory, or you can simply manually verify things
which is a good idea anyway - even unused functions may be useful
exported when they implement a generic data structure for example).

Excercise for the reader: turn the analysis into a plugin.

Richard.





2012-03-29  Richard Guenther  <rguenther@suse.de>

	* tree-flow.h (struct pre_expr_d): Remove forward declaration.
	(add_to_value): Remove.
	(print_value_expressions): Likewise.
	* tree-ssa-pre.c (add_to_value): Make static.
	(print_value_expressions): Likewise.

Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 185918)
--- gcc/tree-flow.h	(working copy)
*************** extern bool verify_eh_dispatch_edge (gim
*** 794,803 ****
  extern void maybe_remove_unreachable_handlers (void);
  
  /* In tree-ssa-pre.c  */
- struct pre_expr_d;
- void add_to_value (unsigned int, struct pre_expr_d *);
  void debug_value_expressions (unsigned int);
- void print_value_expressions (FILE *, unsigned int);
  
  /* In tree-ssa-sink.c  */
  bool is_hidden_global_store (gimple);
--- 794,800 ----
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 185918)
--- gcc/tree-ssa-pre.c	(working copy)
*************** phi_trans_add (pre_expr e, pre_expr v, b
*** 587,593 ****
  
  /* Add expression E to the expression set of value id V.  */
  
! void
  add_to_value (unsigned int v, pre_expr e)
  {
    bitmap_set_t set;
--- 587,593 ----
  
  /* Add expression E to the expression set of value id V.  */
  
! static void
  add_to_value (unsigned int v, pre_expr e)
  {
    bitmap_set_t set;
*************** debug_bitmap_set (bitmap_set_t set)
*** 1031,1037 ****
  
  /* Print out the expressions that have VAL to OUTFILE.  */
  
! void
  print_value_expressions (FILE *outfile, unsigned int val)
  {
    bitmap_set_t set = VEC_index (bitmap_set_t, value_expressions, val);
--- 1031,1037 ----
  
  /* Print out the expressions that have VAL to OUTFILE.  */
  
! static void
  print_value_expressions (FILE *outfile, unsigned int val)
  {
    bitmap_set_t set = VEC_index (bitmap_set_t, value_expressions, val);

Comments

Jan Hubicka March 29, 2012, 1:54 p.m. UTC | #1
> 
> I am playing with doing some internal interface static analysis
> using the first patch below (and looking at LTO bootstrap results).
> 
> An example, obvious patch resulting from that is the 2nd patch,
> resuling from the static analysis output
> 
> /space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:add_to_value can be made 
> static
> /space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:print_value_expressions 
> can be made static
> 
> the static analysis is very verbose (and does not consider ipa-refs yet).
> You also need to union results for building all frontends and all
> targets (well, in theory, or you can simply manually verify things
> which is a good idea anyway - even unused functions may be useful
> exported when they implement a generic data structure for example).
> 
> Excercise for the reader: turn the analysis into a plugin.
> 
> Richard.
> 
> 
> Index: gcc/lto/lto.c
> ===================================================================
> --- gcc/lto/lto.c	(revision 185918)
> +++ gcc/lto/lto.c	(working copy)
> @@ -2721,6 +2721,65 @@ read_cgraph_and_symbols (unsigned nfiles
>    lto_symtab_merge_cgraph_nodes ();
>    ggc_collect ();
>  
> +  if (flag_wpa)
> +    {
> +      struct cgraph_node *node;
> +      FILE *f = fopen (concat (dump_base_name, ".callers", NULL), "w");
> +      for (node = cgraph_nodes; node; node = node->next)
> +	{
> +	  tree caller_tu = NULL_TREE;
> +	  struct cgraph_edge *caller;
> +	  bool found = true;
> +
> +	  if (!TREE_PUBLIC (node->decl)
> +	      || !TREE_STATIC (node->decl)
> +	      || resolution_used_from_other_file_p (node->resolution))
> +	    continue;
> +
> +	  if (!node->callers)
> +	    {
> +	      expanded_location loc = expand_location (DECL_SOURCE_LOCATION (node->decl));
> +	      fprintf (f, "%s:%s no calls\n",
> +		       loc.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
> +	    }

With Mozilla folks I used the dumps from first WPA unreachable function removal pass
with some degree of success.  This gets a lot of non-trivial cases of dead code,
but also there are a lot of funny false positives wrt comdats etc.
> +	  for (caller = node->callers; caller; caller = caller->next_caller)
> +	    {
> +	      if (!caller_tu)
> +		caller_tu = DECL_CONTEXT (caller->caller->decl);
> +	      else if (caller_tu
> +		       && DECL_CONTEXT (caller->caller->decl) != caller_tu)
> +		found = false;
> +	    }
Extending to IPA-REF should be straighforward.
> +	  if (found && caller_tu)
> +	    {
> +	      expanded_location loc1 = expand_location (DECL_SOURCE_LOCATION (node->decl));
> +	      expanded_location loc2 = expand_location (DECL_SOURCE_LOCATION (node->callers->caller->decl));
> +
> +	      if (DECL_CONTEXT (node->decl) == caller_tu)
> +		fprintf (f, "%s:%s can be made static\n",
> +			 loc1.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
Indeed, this is also useful. Any plans to turn this into general -W<something>,
or you will also stay just with an internal hack like I did? :)

Honza
Richard Biener March 30, 2012, 7:59 a.m. UTC | #2
On Thu, 29 Mar 2012, Jan Hubicka wrote:

> > 
> > I am playing with doing some internal interface static analysis
> > using the first patch below (and looking at LTO bootstrap results).
> > 
> > An example, obvious patch resulting from that is the 2nd patch,
> > resuling from the static analysis output
> > 
> > /space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:add_to_value can be made 
> > static
> > /space/rguenther/src/svn/trunk/gcc/tree-ssa-pre.c:print_value_expressions 
> > can be made static
> > 
> > the static analysis is very verbose (and does not consider ipa-refs yet).
> > You also need to union results for building all frontends and all
> > targets (well, in theory, or you can simply manually verify things
> > which is a good idea anyway - even unused functions may be useful
> > exported when they implement a generic data structure for example).
> > 
> > Excercise for the reader: turn the analysis into a plugin.
> > 
> > Richard.
> > 
> > 
> > Index: gcc/lto/lto.c
> > ===================================================================
> > --- gcc/lto/lto.c	(revision 185918)
> > +++ gcc/lto/lto.c	(working copy)
> > @@ -2721,6 +2721,65 @@ read_cgraph_and_symbols (unsigned nfiles
> >    lto_symtab_merge_cgraph_nodes ();
> >    ggc_collect ();
> >  
> > +  if (flag_wpa)
> > +    {
> > +      struct cgraph_node *node;
> > +      FILE *f = fopen (concat (dump_base_name, ".callers", NULL), "w");
> > +      for (node = cgraph_nodes; node; node = node->next)
> > +	{
> > +	  tree caller_tu = NULL_TREE;
> > +	  struct cgraph_edge *caller;
> > +	  bool found = true;
> > +
> > +	  if (!TREE_PUBLIC (node->decl)
> > +	      || !TREE_STATIC (node->decl)
> > +	      || resolution_used_from_other_file_p (node->resolution))
> > +	    continue;
> > +
> > +	  if (!node->callers)
> > +	    {
> > +	      expanded_location loc = expand_location (DECL_SOURCE_LOCATION (node->decl));
> > +	      fprintf (f, "%s:%s no calls\n",
> > +		       loc.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
> > +	    }
> 
> With Mozilla folks I used the dumps from first WPA unreachable function removal pass
> with some degree of success.  This gets a lot of non-trivial cases of dead code,
> but also there are a lot of funny false positives wrt comdats etc.
> > +	  for (caller = node->callers; caller; caller = caller->next_caller)
> > +	    {
> > +	      if (!caller_tu)
> > +		caller_tu = DECL_CONTEXT (caller->caller->decl);
> > +	      else if (caller_tu
> > +		       && DECL_CONTEXT (caller->caller->decl) != caller_tu)
> > +		found = false;
> > +	    }
> Extending to IPA-REF should be straighforward.
> > +	  if (found && caller_tu)
> > +	    {
> > +	      expanded_location loc1 = expand_location (DECL_SOURCE_LOCATION (node->decl));
> > +	      expanded_location loc2 = expand_location (DECL_SOURCE_LOCATION (node->callers->caller->decl));
> > +
> > +	      if (DECL_CONTEXT (node->decl) == caller_tu)
> > +		fprintf (f, "%s:%s can be made static\n",
> > +			 loc1.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
> Indeed, this is also useful. Any plans to turn this into general -W<something>,
> or you will also stay just with an internal hack like I did? :)

;)  The result has way too many false positives (LTO bootstrap produces
quite some dead functions due to early inlining).  So yes, this will
stay internal ;)

Richard.
diff mbox

Patch

Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 185918)
+++ gcc/lto/lto.c	(working copy)
@@ -2721,6 +2721,65 @@  read_cgraph_and_symbols (unsigned nfiles
   lto_symtab_merge_cgraph_nodes ();
   ggc_collect ();
 
+  if (flag_wpa)
+    {
+      struct cgraph_node *node;
+      FILE *f = fopen (concat (dump_base_name, ".callers", NULL), "w");
+      for (node = cgraph_nodes; node; node = node->next)
+	{
+	  tree caller_tu = NULL_TREE;
+	  struct cgraph_edge *caller;
+	  bool found = true;
+
+	  if (!TREE_PUBLIC (node->decl)
+	      || !TREE_STATIC (node->decl)
+	      || resolution_used_from_other_file_p (node->resolution))
+	    continue;
+
+	  if (!node->callers)
+	    {
+	      expanded_location loc = expand_location (DECL_SOURCE_LOCATION (node->decl));
+	      fprintf (f, "%s:%s no calls\n",
+		       loc.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
+	    }
+	  for (caller = node->callers; caller; caller = caller->next_caller)
+	    {
+	      if (!caller_tu)
+		caller_tu = DECL_CONTEXT (caller->caller->decl);
+	      else if (caller_tu
+		       && DECL_CONTEXT (caller->caller->decl) != caller_tu)
+		found = false;
+	    }
+	  if (found && caller_tu)
+	    {
+	      expanded_location loc1 = expand_location (DECL_SOURCE_LOCATION (node->decl));
+	      expanded_location loc2 = expand_location (DECL_SOURCE_LOCATION (node->callers->caller->decl));
+
+	      if (DECL_CONTEXT (node->decl) == caller_tu)
+		fprintf (f, "%s:%s can be made static\n",
+			 loc1.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)));
+	      else
+		{
+		  struct cgraph_edge *callee;
+		  bool calls_nonpublic_static_fn = false;
+		  /* Check if we can move node to the caller TU without
+		     moving anything else.  */
+		  for (callee = node->callees; callee; callee = callee->next_callee)
+		    {
+		      if (!TREE_PUBLIC (callee->callee->decl)
+			  && TREE_STATIC (callee->callee->decl))
+			calls_nonpublic_static_fn = true;
+		    }
+		  if (!calls_nonpublic_static_fn)
+		    fprintf (f, "%s:%s called only from %s\n",
+			     loc1.file, IDENTIFIER_POINTER (DECL_NAME (node->decl)),
+			     loc2.file);
+		}
+	    }
+	}
+      fclose (f);
+    }
+
   if (flag_ltrans)
     for (node = cgraph_nodes; node; node = node->next)
       {