Hi!

As was pointed out in previous thread (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg00723.html), sometimes PGO-built binaries can actually introduce performance regressions. We could identify affected object files and disable PGO for them by simply removing corresponding .gcda file.
My previous patch was incomplete and had two major drawbacks:

* It disabled unrelated options (e.g. -frename-registers) and PGO-related options, set up by user explicitly, if corresponding .gcda file is not found. * As Markus pointed out, in many cases we actually don't want to disable PGO-related options even if .gcda file is missing.

This patch tries to solve these issues in the following way:

* Introduce new -fprofile-use-partial switch.
* If -fprofile-use-partial is ON, try to find corresponding .gcda file in the very early stage during compiler invoking (actually, when common command line options are parsed). If .gcda file exists, enable PGO-related optimizations and emit warning otherwise. I believe this should not break existing code.

Regtested and bootstrapped on x86_64-unknown-linux-gnu.

Does the patch look sensible?

Thanks,
-Maxim
gcc/ChangeLog:

2015-10-27  Maxim Ostapenko  <m.ostape...@partner.samsung.com>

	* common.opt (profile_file_name): New variable.
	(fprofile-use-partial): Likewise.
	(fprofile-use-partial=): Likewise.
	* opts.c: Include gcov-io.h.
	(common_handle_option): Defer enabling PGO-related optimizations until
	we know if corresponding .gcda file exists.
	(maybe_setup_aux_base_name): New function.
	(setup_coverage_filename): Likewise.
	(enable_fdo_optimizations): Move up in source file.
	(finish_options): Call maybe_setup_aux_base_name and setup coverage
	filename. Enable PGO-related optimizations if corresponding .gcda file
	exists if -fprofile-use-partial is used.  If -fprofile-use is used,
	enable PGO-related optimizations without any other conditions.
	* coverage.c (coverage_init): Adjust to use profile_file_name.

diff --git a/gcc/common.opt b/gcc/common.opt
index 12ca0d6..fb04201 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -198,6 +198,9 @@ const char *main_input_basename
 Variable
 int main_input_baselength
 
+Variable
+char *profile_file_name
+
 ; Which options have been printed by --help.
 Variable
 char *help_printed
@@ -1861,6 +1864,14 @@ fprofile-use=
 Common Joined RejectNegative
 Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
 
+fprofile-use-partial
+Common Var(flag_profile_use_partial)
+Enable common options for performing profile feedback directed optimizations.
+
+fprofile-use-partial=
+Common Joined RejectNegative
+Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
+
 fprofile-values
 Common Report Var(flag_profile_values)
 Insert code to profile values of expressions.
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 4e08e5f..461dd48 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1184,7 +1184,7 @@ void
 coverage_init (const char *filename)
 {
   int len = strlen (filename);
-  int prefix_len = 0;
+  da_file_name = profile_file_name;
 
   /* Since coverage_init is invoked very early, before the pass
      manager, we need to set up the dumping explicitly. This is
@@ -1193,24 +1193,6 @@ coverage_init (const char *filename)
     g->get_passes ()->get_pass_profile ()->static_pass_number;
   g->get_dumps ()->dump_start (profile_pass_num, NULL);
 
-  if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
-    profile_data_prefix = getpwd ();
-
-  if (profile_data_prefix)
-    prefix_len = strlen (profile_data_prefix);
-
-  /* Name of da file.  */
-  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
-			  + prefix_len + 2);
-
-  if (profile_data_prefix)
-    {
-      memcpy (da_file_name, profile_data_prefix, prefix_len);
-      da_file_name[prefix_len++] = '/';
-    }
-  memcpy (da_file_name + prefix_len, filename, len);
-  strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
-
   bbg_file_stamp = local_tick;
   
   if (flag_auto_profile)
diff --git a/gcc/opts.c b/gcc/opts.c
index 9a3fbb3..2e0cfa4 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "opts-diagnostic.h"
 #include "insn-attr-common.h"
 #include "common/common-target.h"
+#include "gcov-io.h"
 
 static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
 
@@ -660,6 +661,97 @@ default_options_optimization (struct gcc_options *opts,
 			 lang_mask, handlers, loc, dc);
 }
 
+/* Enable FDO-related flags.  */
+
+static void
+enable_fdo_optimizations (struct gcc_options *opts,
+			  struct gcc_options *opts_set,
+			  int value)
+{
+  if (!opts_set->x_flag_branch_probabilities)
+    opts->x_flag_branch_probabilities = value;
+  if (!opts_set->x_flag_profile_values)
+    opts->x_flag_profile_values = value;
+  if (!opts_set->x_flag_unroll_loops)
+    opts->x_flag_unroll_loops = value;
+  if (!opts_set->x_flag_peel_loops)
+    opts->x_flag_peel_loops = value;
+  if (!opts_set->x_flag_tracer)
+    opts->x_flag_tracer = value;
+  if (!opts_set->x_flag_value_profile_transformations)
+    opts->x_flag_value_profile_transformations = value;
+  if (!opts_set->x_flag_inline_functions)
+    opts->x_flag_inline_functions = value;
+  if (!opts_set->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp = value;
+  if (!opts_set->x_flag_ipa_cp_clone
+      && value && opts->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp_clone = value;
+  if (!opts_set->x_flag_ipa_cp_alignment
+      && value && opts->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp_alignment = value;
+  if (!opts_set->x_flag_predictive_commoning)
+    opts->x_flag_predictive_commoning = value;
+  if (!opts_set->x_flag_unswitch_loops)
+    opts->x_flag_unswitch_loops = value;
+  if (!opts_set->x_flag_gcse_after_reload)
+    opts->x_flag_gcse_after_reload = value;
+  if (!opts_set->x_flag_tree_loop_vectorize
+      && !opts_set->x_flag_tree_vectorize)
+    opts->x_flag_tree_loop_vectorize = value;
+  if (!opts_set->x_flag_tree_slp_vectorize
+      && !opts_set->x_flag_tree_vectorize)
+    opts->x_flag_tree_slp_vectorize = value;
+  if (!opts_set->x_flag_vect_cost_model)
+    opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
+  if (!opts_set->x_flag_tree_loop_distribute_patterns)
+    opts->x_flag_tree_loop_distribute_patterns = value;
+}
+
+static void
+maybe_setup_aux_base_name ()
+{
+  /* Set aux_base_name if not already set.  */
+  if (aux_base_name)
+    return;
+  else if (main_input_filename)
+    {
+      char *name = xstrdup (lbasename (main_input_filename));
+      strip_off_ending (name, strlen (name));
+      aux_base_name = name;
+    }
+  else
+    aux_base_name = "gccaux";
+}
+
+static char *
+setup_coverage_filename (const char *basename, struct gcc_options *opts)
+{
+  int len = strlen (basename);
+  int prefix_len = 0;
+  const char *data_prefix = opts->x_profile_data_prefix;
+
+  if (!opts->x_profile_data_prefix && !IS_ABSOLUTE_PATH (basename))
+    data_prefix = getpwd ();
+
+  if (data_prefix)
+    prefix_len = strlen (data_prefix);
+
+  /* Name of da file.  */
+  char *da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
+				+ prefix_len + 2);
+
+  if (data_prefix)
+    {
+      memcpy (da_file_name, data_prefix, prefix_len);
+      da_file_name[prefix_len++] = '/';
+    }
+  memcpy (da_file_name + prefix_len, basename, len);
+  strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
+  return da_file_name;
+}
+
+
 /* After all options at LOC have been read into OPTS and OPTS_SET,
    finalize settings of those options and diagnose incompatible
    combinations.  */
@@ -949,6 +1041,28 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
       opts->x_flag_aggressive_loop_optimizations = 0;
       opts->x_flag_strict_overflow = 0;
     }
+
+  maybe_setup_aux_base_name ();
+  opts->x_profile_file_name = setup_coverage_filename (aux_base_name, opts);
+  if (opts->x_flag_profile_use || opts->x_flag_profile_use_partial)
+    {
+      /* Warn only -fprofile-use-partial switch is enabled and corresponding
+         .gcda doesn't exist.  */
+      if (opts->x_flag_profile_use_partial
+	  && access (opts->x_profile_file_name, F_OK))
+	fprintf (stderr, "%s not found!\n", opts->x_profile_file_name);
+      else
+       {
+	 enable_fdo_optimizations (opts, opts_set, true);
+	 if (!opts_set->x_flag_profile_reorder_functions)
+	   opts->x_flag_profile_reorder_functions = true;
+	   /* Indirect call profiling should do all useful transformations
+	      speculative devirtualization does.  */
+	 if (!opts_set->x_flag_devirtualize_speculatively
+	     && opts->x_flag_value_profile_transformations)
+	   opts->x_flag_devirtualize_speculatively = false;
+      }
+    }
 }
 
 #define LEFT_COLUMN	27
@@ -1368,53 +1482,6 @@ print_specific_help (unsigned int include_flags,
 		       opts->x_help_columns, opts, lang_mask);
 }
 
-/* Enable FDO-related flags.  */
-
-static void
-enable_fdo_optimizations (struct gcc_options *opts,
-			  struct gcc_options *opts_set,
-			  int value)
-{
-  if (!opts_set->x_flag_branch_probabilities)
-    opts->x_flag_branch_probabilities = value;
-  if (!opts_set->x_flag_profile_values)
-    opts->x_flag_profile_values = value;
-  if (!opts_set->x_flag_unroll_loops)
-    opts->x_flag_unroll_loops = value;
-  if (!opts_set->x_flag_peel_loops)
-    opts->x_flag_peel_loops = value;
-  if (!opts_set->x_flag_tracer)
-    opts->x_flag_tracer = value;
-  if (!opts_set->x_flag_value_profile_transformations)
-    opts->x_flag_value_profile_transformations = value;
-  if (!opts_set->x_flag_inline_functions)
-    opts->x_flag_inline_functions = value;
-  if (!opts_set->x_flag_ipa_cp)
-    opts->x_flag_ipa_cp = value;
-  if (!opts_set->x_flag_ipa_cp_clone
-      && value && opts->x_flag_ipa_cp)
-    opts->x_flag_ipa_cp_clone = value;
-  if (!opts_set->x_flag_ipa_cp_alignment
-      && value && opts->x_flag_ipa_cp)
-    opts->x_flag_ipa_cp_alignment = value;
-  if (!opts_set->x_flag_predictive_commoning)
-    opts->x_flag_predictive_commoning = value;
-  if (!opts_set->x_flag_unswitch_loops)
-    opts->x_flag_unswitch_loops = value;
-  if (!opts_set->x_flag_gcse_after_reload)
-    opts->x_flag_gcse_after_reload = value;
-  if (!opts_set->x_flag_tree_loop_vectorize
-      && !opts_set->x_flag_tree_vectorize)
-    opts->x_flag_tree_loop_vectorize = value;
-  if (!opts_set->x_flag_tree_slp_vectorize
-      && !opts_set->x_flag_tree_vectorize)
-    opts->x_flag_tree_slp_vectorize = value;
-  if (!opts_set->x_flag_vect_cost_model)
-    opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
-  if (!opts_set->x_flag_tree_loop_distribute_patterns)
-    opts->x_flag_tree_loop_distribute_patterns = value;
-}
-
 /* Handle target- and language-independent options.  Return zero to
    generate an "unknown option" message.  Only options that need
    extra handling need to be listed here; if you simply want
@@ -1923,15 +1990,12 @@ common_handle_option (struct gcc_options *opts,
       opts->x_flag_profile_use = true;
       value = true;
       /* No break here - do -fprofile-use processing. */
+    case OPT_fprofile_use_partial_:
+      opts->x_flag_profile_use_partial = true;
     case OPT_fprofile_use:
-      enable_fdo_optimizations (opts, opts_set, value);
-      if (!opts_set->x_flag_profile_reorder_functions)
-	  opts->x_flag_profile_reorder_functions = value;
-	/* Indirect call profiling should do all useful transformations
-	   speculative devirtualization does.  */
-      if (!opts_set->x_flag_devirtualize_speculatively
-	  && opts->x_flag_value_profile_transformations)
-	opts->x_flag_devirtualize_speculatively = false;
+    case OPT_fprofile_use_partial:
+      /* Deferred until we know if we really need to enable PGO - related
+         optimizations.  */
       break;
 
     case OPT_fauto_profile_:

Reply via email to