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

Message ID cb8407ca-1eb9-c656-7512-c48c3aaf1eb6@suse.cz
State New
Headers show
Series
  • Instrument only selected files (PR gcov-profile/87442).
Related show

Commit Message

Martin Liška Nov. 8, 2018, 1:42 p.m.
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

Comments

Jeff Law Nov. 9, 2018, 10 p.m. | #1
On 11/8/18 6:42 AM, Martin Liška wrote:
> 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.
Extra credit if we could also do this on a function level.  I've
certainly talked to developers that want finer grained control over what
gets instrumented and what doesn't.  This is probably enough to help
them, but I'm sure they'll want more :-)


OK.
jeff
Martin Liška Nov. 10, 2018, 8:56 a.m. | #2
On 11/9/18 11:00 PM, Jeff Law wrote:
> On 11/8/18 6:42 AM, Martin Liška wrote:
>> 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.
> Extra credit if we could also do this on a function level.  I've
> certainly talked to developers that want finer grained control over what
> gets instrumented and what doesn't.  This is probably enough to help
> them, but I'm sure they'll want more :-)

Hi.

We do have support for that: no_profile_instrument_function attribute ;)

Martin

> 
> 
> OK.
> jeff
>
Martin Liška Nov. 12, 2018, 7:56 a.m. | #3
On 11/9/18 11:00 PM, Jeff Law wrote:
> On 11/8/18 6:42 AM, Martin Liška wrote:
>> 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.
> Extra credit if we could also do this on a function level.  I've
> certainly talked to developers that want finer grained control over what
> gets instrumented and what doesn't.  This is probably enough to help
> them, but I'm sure they'll want more :-)
> 
> 
> OK.
> jeff
> 

Hi.

May I consider this Jeff as approval of the patch?

Thanks,
Martin
Jeff Law Nov. 12, 2018, 3:36 p.m. | #4
On 11/12/18 12:56 AM, Martin Liška wrote:
> On 11/9/18 11:00 PM, Jeff Law wrote:
>> On 11/8/18 6:42 AM, Martin Liška wrote:
>>> 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.
>> Extra credit if we could also do this on a function level.  I've
>> certainly talked to developers that want finer grained control over what
>> gets instrumented and what doesn't.  This is probably enough to help
>> them, but I'm sure they'll want more :-)
>>
>>
>> OK.
>> jeff
>>
> 
> Hi.
> 
> May I consider this Jeff as approval of the patch?
Yes.  SOrry I wasn't explicit about that.
jeff

Patch

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)