This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Instrument only selected files (PR gcov-profile/87442).
- From: Martin Liška <mliska at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jan Hubicka <hubicka at ucw dot cz>
- Date: Thu, 8 Nov 2018 14:42:40 +0100
- Subject: [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)