This patch improves the LIPO support in AutoFDO to make it more robust. Bootstrapped and passed regression test and benchmark tests.
Ok for google 4_7 branch? Thanks, Dehao http://codereview.appspot.com/8624045 Index: gcc/opts.h =================================================================== --- gcc/opts.h (revision 198362) +++ gcc/opts.h (working copy) @@ -409,6 +409,6 @@ extern void set_struct_debug_option (struct gcc_op const char *value); extern bool opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value, unsigned int lang_mask); -extern void write_opts_to_asm (void); +extern void write_lipo_info_to_asm (void); extern void pattern_match_function_attributes (tree); #endif Index: gcc/c-family/c-opts.c =================================================================== --- gcc/c-family/c-opts.c (revision 198362) +++ gcc/c-family/c-opts.c (working copy) @@ -1157,8 +1157,6 @@ c_common_parse_file (void) for (;;) { c_finish_options (); - if (flag_record_gcc_switches_in_elf && i == 0) - write_opts_to_asm (); pch_init (); set_lipo_c_parsing_context (parse_in, i, verbose); push_file_scope (); Index: gcc/toplev.c =================================================================== --- gcc/toplev.c (revision 198362) +++ gcc/toplev.c (working copy) @@ -1961,6 +1961,8 @@ do_compile (void) timevar_stop (TV_PHASE_SETUP); compile_file (); + if (flag_record_lipo_info_in_elf) + write_lipo_info_to_asm (); } else { Index: gcc/coverage.c =================================================================== --- gcc/coverage.c (revision 198362) +++ gcc/coverage.c (working copy) @@ -376,7 +376,7 @@ has_incompatible_cg_opts (bool *cg_opts1, bool *cg /* Returns true if the command-line arguments stored in the given module-infos are incompatible. */ -static bool +bool incompatible_cl_args (struct gcov_module_info* mod_info1, struct gcov_module_info* mod_info2) { @@ -2866,7 +2866,7 @@ coverage_init (const char *filename, const char* s strcat (main_input_file_name, source_name); } - if (flag_branch_probabilities) + if (flag_branch_probabilities && !flag_auto_profile) read_counts_file (da_file_name, 0); /* Reads at most one auxiliary GCDA file since we don't support merging */ @@ -3109,16 +3109,32 @@ coverage_has_asm_stmt (void) /* Write command line options to the .note section. */ void -write_opts_to_asm (void) +write_lipo_info_to_asm (void) { size_t i; cpp_dir *quote_paths, *bracket_paths, *pdir; struct str_list *pdef, *pinc; int num_quote_paths = 0; int num_bracket_paths = 0; + unsigned lang; get_include_chains ("e_paths, &bracket_paths); + /* Write lang, ggc_memory to ASM section. */ + switch_to_section (get_section (".gnu.switches.text.lipo_info", + SECTION_DEBUG, NULL)); + if (!strcmp (lang_hooks.name, "GNU C")) + lang = GCOV_MODULE_C_LANG; + else if (!strcmp (lang_hooks.name, "GNU C++")) + lang = GCOV_MODULE_CPP_LANG; + else + lang = GCOV_MODULE_UNKNOWN_LANG; + if (has_asm_statement) + lang |= GCOV_MODULE_ASM_STMTS; + dw2_asm_output_nstring (in_fnames[0], (size_t)-1, NULL); + dw2_asm_output_data_uleb128 (lang, NULL); + dw2_asm_output_data_uleb128 (ggc_total_memory, NULL); + /* Write quote_paths to ASM section. */ switch_to_section (get_section (".gnu.switches.text.quote_paths", SECTION_DEBUG, NULL)); Index: gcc/coverage.h =================================================================== --- gcc/coverage.h (revision 198362) +++ gcc/coverage.h (working copy) @@ -87,6 +87,9 @@ extern tree get_const_string_type (void); /* Mark this module as containing asm statements. */ extern void coverage_has_asm_stmt (void); +extern bool incompatible_cl_args (struct gcov_module_info *, + struct gcov_module_info *); + /* Defined in tree-profile.c. */ extern void tree_init_instrumentation_sampling (void); extern void tree_init_dyn_ipa_parameters (void); Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 198362) +++ gcc/common.opt (working copy) @@ -1822,8 +1822,8 @@ Record gcc command line switches in the object fil ; divide the command line options into several categories. And the ; section is not mergable so that linker can save gcc switches for ; each module. -frecord-gcc-switches-in-elf -Common Report Var(flag_record_gcc_switches_in_elf) +frecord-lipo-info-in-elf +Common Report Var(flag_record_lipo_info_in_elf) Record the compiler optimizations in a .gnu.switches.text section. freg-struct-return Index: gcc/auto-profile.c =================================================================== --- gcc/auto-profile.c (revision 198362) +++ gcc/auto-profile.c (working copy) @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "tree-flow.h" #include "value-prof.h" +#include "coverage.h" #include "auto-profile.h" /* The following routines implements AutoFDO optimization. @@ -143,7 +144,8 @@ struct afdo_module char *name; int ident; unsigned exported; - unsigned has_asm; + unsigned lang; + unsigned ggc_memory; unsigned num_aux_modules; unsigned num_quote_paths; unsigned num_bracket_paths; @@ -283,7 +285,8 @@ afdo_stack_hash (const void *stack) const char *file = afdo_get_filename (p->file); const char *func = afdo_get_bfd_name (p->func); h = iterative_hash (file, strlen (file), h); - h = iterative_hash (func, strlen (func), h); + if (func) + h = iterative_hash (func, strlen (func), h); h = iterative_hash (&p->line, sizeof (p->line), h); if (i == 0) h = iterative_hash (&p->discr, sizeof (p->discr), h); @@ -326,8 +329,11 @@ afdo_stack_eq (const void *p, const void *q) { const struct gcov_callsite_pos *p1 = s1->stack + i; const struct gcov_callsite_pos *p2 = s2->stack + i; + const char *func1 = afdo_get_bfd_name (p1->func); + const char *func2 = afdo_get_bfd_name (p2->func); + if (strcmp (afdo_get_filename (p1->file), afdo_get_filename (p2->file)) - || strcmp (afdo_get_bfd_name (p1->func), afdo_get_bfd_name (p2->func)) + || (func1 != NULL && func2 != NULL && strcmp (func1, func2)) || p1->line != p2->line || (i== 0 && p1->discr != p2->discr)) return 0; } @@ -460,6 +466,8 @@ afdo_add_module (struct gcov_module_info **module_ (*module_info)->ident = module->ident; (*module_info)->is_primary = is_primary; (*module_info)->flags = is_primary ? module->exported : 1; + (*module_info)->lang = module->lang; + (*module_info)->ggc_memory = module->ggc_memory; (*module_info)->source_filename = module->name; (*module_info)->num_quote_paths = module->num_quote_paths; (*module_info)->num_bracket_paths = module->num_bracket_paths; @@ -502,8 +510,37 @@ read_aux_modules (void) inform (0, "aux module %s cannot be found.", module.name); continue; } - afdo_add_module (&module_infos[curr_module++], aux_entry, false); - add_input_filename (module.name); + if ((aux_entry->lang & GCOV_MODULE_LANG_MASK) != + (entry->lang & GCOV_MODULE_LANG_MASK)) + { + inform (0, "Not importing %s: source language" + " different from primary module's source language", + aux_entry->name); + continue; + } + if ((aux_entry->lang & GCOV_MODULE_ASM_STMTS) + && flag_ripa_disallow_asm_modules) + { + if (flag_opt_info >= OPT_INFO_MIN) + inform (0, "Not importing %s: contains " + "assembler statements", aux_entry->name); + continue; + } + afdo_add_module (&module_infos[curr_module], aux_entry, false); + if (incompatible_cl_args (module_infos[0], module_infos[curr_module])) + { + if (flag_opt_info >= OPT_INFO_MIN) + inform (0, "Not importing %s: command-line" + " arguments not compatible with primary module", + aux_entry->name); + free (module_infos[curr_module]); + continue; + } + else + { + curr_module ++; + add_input_filename (module.name); + } } } @@ -1238,8 +1275,8 @@ read_profile (void) modules[i].ident = i + 1; /* exported flag. */ modules[i].exported = gcov_read_unsigned (); - /* has_asm flag. */ - modules[i].has_asm = gcov_read_unsigned (); + modules[i].lang = gcov_read_unsigned (); + modules[i].ggc_memory = gcov_read_unsigned (); /* aux_module and 5 options. */ modules[i].num_aux_modules = gcov_read_unsigned (); modules[i].num_quote_paths = gcov_read_unsigned (); @@ -1856,6 +1893,13 @@ auto_profile (void) pop_cfun (); } + cgraph_pre_profiling_inlining_done = true; + cgraph_process_module_scope_statics (); + /* Now perform link to allow cross module inlining. */ + cgraph_do_link (); + varpool_do_link (); + cgraph_unify_type_alias_sets (); + return TODO_rebuild_cgraph_edges; }