This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, 4.9/4.10] Profile based option tuning
- From: Pengfei Yuan <0xcoolypf at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 21 Jul 2014 13:13:55 +0800
- Subject: [PATCH, 4.9/4.10] Profile based option tuning
- Authentication-results: sourceware.org; auth=none
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.
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 ();