This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Instrument only selected files (PR gcov-profile/87442).


Hi.

The patch is about possibility to filter which files are instrumented. The usage
is explained in the PR.

Patch can bootstrap and survives regression tests on x86_64-linux-gnu.

Ready for trunk?
Thanks,
Martin

gcc/ChangeLog:

2018-11-08  Martin Liska  <mliska@suse.cz>

	PR gcov-profile/87442
	* common.opt: Add -fprofile-filter-files and -fprofile-exclude-files
	options.
	* doc/invoke.texi: Document them.
	* tree-profile.c (parse_profile_filter): New.
	(parse_profile_file_filtering): Likewise.
	(release_profile_file_filtering): Likewise.
	(include_source_file_for_profile): Likewise.
	(tree_profiling): Filter source files based on the
	newly added options.

gcc/testsuite/ChangeLog:

2018-11-08  Martin Liska  <mliska@suse.cz>

	PR gcov-profile/87442
	* gcc.dg/profile-filtering-1.c: New test.
	* gcc.dg/profile-filtering-2.c: New test.
---
 gcc/common.opt                             |  8 +++
 gcc/doc/invoke.texi                        | 19 +++++
 gcc/testsuite/gcc.dg/profile-filtering-1.c | 37 ++++++++++
 gcc/testsuite/gcc.dg/profile-filtering-2.c | 37 ++++++++++
 gcc/tree-profile.c                         | 84 ++++++++++++++++++++++
 5 files changed, 185 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/profile-filtering-1.c
 create mode 100644 gcc/testsuite/gcc.dg/profile-filtering-2.c


diff --git a/gcc/common.opt b/gcc/common.opt
index 5a5d33205a4..6494011cd6e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2067,6 +2067,14 @@ fprofile-update=
 Common Joined RejectNegative Enum(profile_update) Var(flag_profile_update) Init(PROFILE_UPDATE_SINGLE)
 -fprofile-update=[single|atomic|prefer-atomic]	Set the profile update method.
 
+fprofile-filter-files=
+Common Joined RejectNegative Var(flag_profile_filter_files)
+Instrument only functions from files where names match any regular expression (separated by a semi-colon).
+
+fprofile-exclude-files=
+Common Joined RejectNegative Var(flag_profile_exclude_files)
+Instrument only functions from files where names do not match all the regular expressions (separated by a semi-colon).
+
 Enum
 Name(profile_update) Type(enum profile_update) UnknownError(unknown profile update method %qs)
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 849bb76dc25..c2f29dbd522 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -483,6 +483,7 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-p  -pg  -fprofile-arcs  --coverage  -ftest-coverage @gol
 -fprofile-abs-path @gol
 -fprofile-dir=@var{path}  -fprofile-generate  -fprofile-generate=@var{path} @gol
+-fprofile-update=@var{method}  -fprofile-filter-files=@var{regex}  -fprofile-exclude-files=@var{regex} @gol
 -fsanitize=@var{style}  -fsanitize-recover  -fsanitize-recover=@var{style} @gol
 -fasan-shadow-offset=@var{number}  -fsanitize-sections=@var{s1},@var{s2},... @gol
 -fsanitize-undefined-trap-on-error  -fbounds-check @gol
@@ -11808,6 +11809,24 @@ when supported by a target, or to @samp{single} otherwise.  The GCC driver
 automatically selects @samp{prefer-atomic} when @option{-pthread}
 is present in the command line.
 
+@item -fprofile-filter-files=@var{regex}
+@opindex fprofile-filter-files
+
+Instrument only functions from files where names match
+any regular expression (separated by a semi-colon).
+
+For example, @option{-fprofile-filter-files=main.c;module.*.c} will instrument
+only @file{main.c} and all C files starting with 'module'.
+
+@item -fprofile-exclude-files=@var{regex}
+@opindex fprofile-exclude-files
+
+Instrument only functions from files where names do not match
+all the regular expressions (separated by a semi-colon).
+
+For example, @option{-fprofile-exclude-files=/usr/*} will prevent instrumentation
+of all files that are located in @file{/usr/} folder.
+
 @item -fsanitize=address
 @opindex fsanitize=address
 Enable AddressSanitizer, a fast memory error detector.
diff --git a/gcc/testsuite/gcc.dg/profile-filtering-1.c b/gcc/testsuite/gcc.dg/profile-filtering-1.c
new file mode 100644
index 00000000000..f123e24b2a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/profile-filtering-1.c
@@ -0,0 +1,37 @@
+/* { dg-require-profiling "-fprofile-generate" } */
+/* { dg-options "-O2 -fprofile-generate -fprofile-filter-files=.\*filtering-1.c -fdump-tree-optimized" } */
+
+extern void abort (void);
+
+int *p1;
+int *p2;
+int *p3;
+
+int ga = 100;
+
+int
+sub (int i, int j)
+{
+  int k;
+  int l;
+  int m;
+  int n;
+  p1 = &k;
+  p2 = &l;
+  p3 = &m;
+  k = 20;
+  l = 30;
+  m = 40;
+  n = i / j;
+  return n + ga;
+}
+
+int
+main(void)
+{
+  if (sub (99, 33) != 103)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "PROF_edge" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/profile-filtering-2.c b/gcc/testsuite/gcc.dg/profile-filtering-2.c
new file mode 100644
index 00000000000..98bd3aea00f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/profile-filtering-2.c
@@ -0,0 +1,37 @@
+/* { dg-require-profiling "-fprofile-generate" } */
+/* { dg-options "-O2 -fprofile-generate -fprofile-filter-files=.\*filtering-1.c -fprofile-exclude-files=.\* -fdump-tree-optimized" } */
+
+extern void abort (void);
+
+int *p1;
+int *p2;
+int *p3;
+
+int ga = 100;
+
+int
+sub (int i, int j)
+{
+  int k;
+  int l;
+  int m;
+  int n;
+  p1 = &k;
+  p2 = &l;
+  p3 = &m;
+  k = 20;
+  l = 30;
+  m = 40;
+  n = i / j;
+  return n + ga;
+}
+
+int
+main(void)
+{
+  if (sub (99, 33) != 103)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "PROF_edge" "optimized" } } */
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index d8f2a3b1ba4..48204423eaf 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "langhooks.h"
 #include "stor-layout.h"
+#include "xregex.h"
 
 static GTY(()) tree gcov_type_node;
 static GTY(()) tree tree_interval_profiler_fn;
@@ -610,6 +611,82 @@ gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
 }
 
+static vec<regex_t> profile_filter_files;
+static vec<regex_t> profile_exclude_files;
+
+/* Parse list of provided REGEX (separated with semi-collon) and
+   create expressions (of type regex_t) and save them into V vector.
+   If there is a regular expression parsing error, error message is
+   printed for FLAG_NAME.  */
+
+static void
+parse_profile_filter (const char *regex, vec<regex_t> *v,
+		      const char *flag_name)
+{
+  v->create (4);
+  if (regex != NULL)
+    {
+      char *str = xstrdup (regex);
+      for (char *p = strtok (str, ";"); p != NULL; p = strtok (NULL, ";"))
+	{
+	  regex_t r;
+	  if (regcomp (&r, p, REG_EXTENDED | REG_NOSUB) != 0)
+	    {
+	      error ("invalid regular expression '%s' in %<%s%>",
+		     p, flag_name);
+	      return;
+	    }
+
+	  v->safe_push (r);
+	}
+    }
+}
+
+/* Parse values of -fprofile-filter-files and -fprofile-exclude-files
+   options.  */
+
+static void
+parse_profile_file_filtering ()
+{
+  parse_profile_filter (flag_profile_filter_files, &profile_filter_files,
+			"-fprofile-filter-files");
+  parse_profile_filter (flag_profile_exclude_files, &profile_exclude_files,
+			"-fprofile-exclude-files");
+}
+
+/* Parse vectors of regular expressions.  */
+
+static void
+release_profile_file_filtering ()
+{
+  profile_filter_files.release ();
+  profile_exclude_files.release ();
+}
+
+/* Return true when FILENAME should be instrumented based on
+   -fprofile-filter-files and -fprofile-exclude-files options.  */
+
+static bool
+include_source_file_for_profile (const char *filename)
+{
+  /* First check whether file is included in flag_profile_exclude_files.  */
+  for (unsigned i = 0; i < profile_exclude_files.length (); i++)
+    if (regexec (&profile_exclude_files[i],
+		 filename, 0, NULL, 0) == REG_NOERROR)
+      return false;
+
+  /* For non-empty flag_profile_filter_files include only files matching a
+     regex in the flag.  */
+  if (profile_filter_files.is_empty ())
+    return true;
+
+  for (unsigned i = 0; i < profile_filter_files.length (); i++)
+    if (regexec (&profile_filter_files[i], filename, 0, NULL, 0) == REG_NOERROR)
+      return true;
+
+  return false;
+}
+
 #ifndef HAVE_sync_compare_and_swapsi
 #define HAVE_sync_compare_and_swapsi 0
 #endif
@@ -658,6 +735,7 @@ tree_profiling (void)
   gcc_assert (symtab->state == IPA_SSA);
 
   init_node_map (true);
+  parse_profile_file_filtering ();
 
   FOR_EACH_DEFINED_FUNCTION (node)
     {
@@ -678,6 +756,10 @@ tree_profiling (void)
 	  && flag_test_coverage)
 	continue;
 
+      const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl));
+      if (!include_source_file_for_profile (file))
+	continue;
+
       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 
       if (dump_file)
@@ -706,6 +788,8 @@ tree_profiling (void)
       pop_cfun ();
     }
 
+  release_profile_file_filtering ();
+
   /* Drop pure/const flags from instrumented functions.  */
   if (profile_arc_flag || flag_test_coverage)
     FOR_EACH_DEFINED_FUNCTION (node)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]