On Mon, Jul 21, 2014 at 7:13 AM, Pengfei Yuan <0xcool...@gmail.com> wrote: > Hi, > > This patch tunes optimization options based on profile data: > * Disable PGO options if profile is not available or empty. > * Optimize for size if profile is available but empty.
Err ... these don't seem interesting cases to "optimize" for? Richard. > Here is an experiment on Firefox PGO build: > > CPU Intel Core i7-4770 > RAM 32 GB > OS Debian sid amd64 > Firefox source mozilla-central, changeset 4bafe35cfb65 > Compiler GCC 4.9.2 20140721 (prerelease) > > Result: > > Size of libxul.so | Octane benchmark score > PGO w/o this patch 67206232 32440.4 +/- 0.35% > PGO w/ this patch 66604312 32765.8 +/- 0.56% > > With this patch, the size of PGO-built libxul.so decreases by 0.9% and the > performance improves slightly. > > Regards, > > Yuan Pengfei > Peking University > > > gcc/ChangeLog: > > * coverage.c (coverage_check): New function. > * coverage.h (coverage_check): New function. > * toplev.c (profile_based_option_override): New function. > (process_options): Add profile based option tuning. > > > diff --git a/gcc/coverage.c b/gcc/coverage.c > index 4c06fa4..205bee5 100644 > --- a/gcc/coverage.c > +++ b/gcc/coverage.c > @@ -1128,6 +1128,75 @@ coverage_obj_finish (vec<constructor_elt, va_gc> *ctor) > varpool_finalize_decl (gcov_info_var); > } > > +/* Check the profile data file. > + Return -1 if the file is not available or corrupted, > + 0 if the file is available and all counters are zero, > + 1 otherwise. */ > + > +int > +coverage_check (const char *filename) > +{ > + int ret = 0; > + int len = strlen (filename); > + int prefix_len = 0; > + gcov_unsigned_t tag; > + char *data_filename; > + > + if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename)) > + profile_data_prefix = getpwd (); > + > + if (profile_data_prefix) > + prefix_len = strlen (profile_data_prefix); > + > + data_filename = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) > + + prefix_len + 2); > + > + if (profile_data_prefix) > + { > + memcpy (data_filename, profile_data_prefix, prefix_len); > + data_filename[prefix_len++] = '/'; > + } > + memcpy (data_filename + prefix_len, filename, len); > + strcpy (data_filename + prefix_len + len, GCOV_DATA_SUFFIX); > + > + if (!gcov_open (data_filename, 1)) > + return -1; > + if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC) > + || gcov_read_unsigned () != GCOV_VERSION) > + { > + gcov_close (); > + return -1; > + } > + gcov_read_unsigned (); > + > + while ((tag = gcov_read_unsigned ())) > + { > + gcov_unsigned_t length = gcov_read_unsigned (); > + gcov_position_t offset = gcov_position (); > + > + if (GCOV_TAG_IS_COUNTER (tag)) > + { > + unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); > + unsigned ix; > + > + for (ix = 0; ix != n_counts; ix++) > + if (gcov_read_counter ()) > + ret = 1; > + } > + gcov_sync (offset, length); > + > + if (gcov_is_error ()) > + { > + ret = -1; > + break; > + } > + } > + > + gcov_close (); > + > + return ret; > +} > + > /* Perform file-level initialization. Read in data file, generate name > of notes file. */ > > diff --git a/gcc/coverage.h b/gcc/coverage.h > index 81f87a6..51d1119 100644 > --- a/gcc/coverage.h > +++ b/gcc/coverage.h > @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see > > #include "gcov-io.h" > > +extern int coverage_check (const char *); > extern void coverage_init (const char *); > extern void coverage_finish (void); > > diff --git a/gcc/toplev.c b/gcc/toplev.c > index d646faf..b0c3906 100644 > --- a/gcc/toplev.c > +++ b/gcc/toplev.c > @@ -1222,6 +1222,77 @@ init_alignments (void) > align_functions_log = floor_log2 (align_functions * 2 - 1); > } > > +/* Override options based on profile. */ > + > +static void > +profile_based_option_override (void) > +{ > + int status; > + const char *name = aux_base_name; > + > + if (!flag_branch_probabilities) > + return; > + > + if (!name) > + { > + char *newname; > + if (!main_input_filename) > + return; > + newname = xstrdup (lbasename (main_input_filename)); > + strip_off_ending (newname, strlen (newname)); > + name = newname; > + } > + > + status = coverage_check (name); > + if (status > 0) > + return; > + > + /* Profile data file is valid and all profile counters are zero. > + Prefer optimizing code size. */ > + if (status == 0) > + { > + optimize = 2; > + optimize_size = 1; > + maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS, 1, > + param_values, global_options_set.x_param_values); > + > + /* Ignore coverage mismatch since all counters are zero. */ > + diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch, > + DK_IGNORED, UNKNOWN_LOCATION); > + } > + > + if (!flag_profile_use) > + return; > + > + /* Disable optimization options for PGO. */ > + if (!global_options_set.x_flag_profile_values) > + flag_profile_values = false; > + if (!global_options_set.x_flag_unroll_loops) > + flag_unroll_loops = false; > + if (!global_options_set.x_flag_peel_loops) > + flag_peel_loops = false; > + if (!global_options_set.x_flag_tracer) > + flag_tracer = false; > + if (!global_options_set.x_flag_value_profile_transformations) > + flag_value_profile_transformations = false; > + if (!global_options_set.x_flag_ipa_cp_clone) > + flag_ipa_cp_clone = false; > + if (!global_options_set.x_flag_predictive_commoning) > + flag_predictive_commoning = false; > + if (!global_options_set.x_flag_unswitch_loops) > + flag_unswitch_loops = false; > + if (!global_options_set.x_flag_gcse_after_reload) > + flag_gcse_after_reload = false; > + if (!global_options_set.x_flag_tree_loop_vectorize > + && !global_options_set.x_flag_tree_vectorize) > + flag_tree_loop_vectorize = false; > + if (!global_options_set.x_flag_tree_slp_vectorize > + && !global_options_set.x_flag_tree_vectorize) > + flag_tree_slp_vectorize = false; > + if (!global_options_set.x_flag_vect_cost_model) > + flag_vect_cost_model = VECT_COST_MODEL_CHEAP; > +} > + > /* Process the options that have been parsed. */ > static void > process_options (void) > @@ -1245,6 +1316,8 @@ process_options (void) > so we can correctly initialize debug output. */ > no_backend = lang_hooks.post_options (&main_input_filename); > > + profile_based_option_override (); > + > /* Some machines may reject certain combinations of options. */ > targetm.target_option.override ();