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
OSDebian sid amd64
Firefox sourcemozilla-central, changeset 4bafe35cfb65
Compiler GCC 4.9.2 20140721 (prerelease)
Result:
Size of libxul.so | Octane benchmark score
PGO w/o this patch67206232 32440.4 +/- 0.35%
PGO w/ this patch66604312 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 (vecconstructor_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