Message ID | Pine.LNX.4.64.1203291225510.5416@jbgna.fhfr.qr |
---|---|
State | New |
Headers | show |
> > 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
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.
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) {