On Fri, 30 Mar 2012, Richard Guenther wrote: > On Thu, 29 Mar 2012, Jan Hubicka wrote: > > > 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 ;)
Btw, the following is the last incarnation of the patch - I've stopped here for now. If you LTO bootstrap with it you can find *.callers files in the build tree (remember to use -O0 for added precision). Richard. Index: gcc/lto/lto.c =================================================================== --- gcc/lto/lto.c (revision 186007) +++ gcc/lto/lto.c (working copy) @@ -2721,6 +2721,70 @@ 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) + || DECL_PRESERVE_P (node->decl) + || resolution_used_from_other_file_p (node->resolution)) + continue; + + /* For now, until we walk references. */ + if (node->address_taken) + 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) {