From patchwork Thu Nov 8 13:42:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 994887 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-489366-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="JAME64w1"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42rPcH096wz9s7T for ; Fri, 9 Nov 2018 00:42:54 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=JEX93+BjaA3b9COOU08+UXeqRF9nqGUCFexMBiscD606JLyH6T /6Gr1LMtikl85tHr7ImOo+GxMNUP2cUqTg9pR0f7PcCvupA83etYM95PL3jjH16O /0fb/NSvc+x9dDxjBY0aqfOaV8QUw0B5PLxEz03pjxytczY7x1CsguH7s= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=9IrxV92CXw79pJVHpjdQLmbWHu8=; b=JAME64w1tFEE773/1LMs KzewXF5id/U/6yaxVovq6ivCc4MK8O6DEkSMmjDvl8hsuRT5hGn7dqBegnNq7k/1 KU2+ziyIeCaA9tXAn7L8SC1VkjvhpLoNb1So3krpj/f+DcbPu9JcG4mkoBVKBO3L H8BlTfqG6imjhbSAGF+GZqQ= Received: (qmail 72252 invoked by alias); 8 Nov 2018 13:42:47 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 72217 invoked by uid 89); 8 Nov 2018 13:42:45 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=Instrument X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 08 Nov 2018 13:42:43 +0000 Received: from relay1.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 92912B03A; Thu, 8 Nov 2018 13:42:41 +0000 (UTC) From: =?utf-8?q?Martin_Li=C5=A1ka?= Subject: [PATCH] Instrument only selected files (PR gcov-profile/87442). To: gcc-patches@gcc.gnu.org Cc: Jan Hubicka Message-ID: Date: Thu, 8 Nov 2018 14:42:40 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 X-IsSubscribed: yes 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 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 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 profile_filter_files; +static vec 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 *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)