From 27f7fb79d27bd4a4a7f04d4970c06e9050a6564e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 13 Nov 2020 17:47:40 +0100 Subject: [PATCH] gcov: Add -fprofile-info-section support Register the profile information in the specified section instead of using a constructor/destructor. A pointer to the profile information generated by -fprofile-arcs or -ftest-coverage is placed in the specified section for each translation unit. This option disables the profile information registration through a constructor and it disables the profile information processing through a destructor. I am not sure how I can test this option. One approach would be to assemble a test file, then scan it and check that a .gcov_info section is present and no __gcov_init() and __gcov_exit() calls are present. Is there an example for this in the test suite? gcc/ * common.opt (fprofile-info-section): New. * coverage.c (build_gcov_info_var_registration): New. (coverage_obj_init): Evaluate profile_info_section and use build_gcov_info_var_registration(). * doc/invoke.texi (fprofile-info-section): Document. * opts.c (common_handle_option): Process fprofile-info-section option. gcc/testsuite/ChangeLog: * gcc.dg/profile-info-section.c: New test. --- gcc/common.opt | 8 ++++++ gcc/coverage.c | 28 ++++++++++++++++++-- gcc/doc/invoke.texi | 29 +++++++++++++++++++++ gcc/opts.c | 4 +++ gcc/testsuite/gcc.dg/profile-info-section.c | 20 ++++++++++++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/profile-info-section.c diff --git a/gcc/common.opt b/gcc/common.opt index 9552cebe0d6..fe39b3dee9f 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2272,6 +2272,14 @@ fprofile-generate= Common Joined RejectNegative Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=. +fprofile-info-section +Common RejectNegative +Register the profile information in the .gcov_info section instead of using a constructor/destructor. + +fprofile-info-section= +Common Joined RejectNegative Var(profile_info_section) +Register the profile information in the specified section instead of using a constructor/destructor. + fprofile-partial-training Common Report Var(flag_profile_partial_training) Optimization Do not assume that functions never executed during the train run are cold. diff --git a/gcc/coverage.c b/gcc/coverage.c index 7711412c3be..d299e48d591 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -1097,6 +1097,25 @@ build_gcov_exit_decl (void) cgraph_build_static_cdtor ('D', dtor, priority); } +/* Generate the pointer to the gcov_info_var in a dedicated section. */ + +static void +build_gcov_info_var_registration (tree gcov_info_type) +{ + tree var = build_decl (BUILTINS_LOCATION, + VAR_DECL, NULL_TREE, + build_pointer_type (gcov_info_type)); + TREE_STATIC (var) = 1; + TREE_READONLY (var) = 1; + char name_buf[32]; + ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 2); + DECL_NAME (var) = get_identifier (name_buf); + get_section (profile_info_section, SECTION_UNNAMED, NULL); + set_decl_section_name (var, profile_info_section); + DECL_INITIAL (var) = build_fold_addr_expr (gcov_info_var); + varpool_node::finalize_decl (var); +} + /* Create the gcov_info types and object. Generate the constructor function to call __gcov_init. Does not generate the initializer for the object. Returns TRUE if coverage data is being emitted. */ @@ -1151,8 +1170,13 @@ coverage_obj_init (void) ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0); DECL_NAME (gcov_info_var) = get_identifier (name_buf); - build_init_ctor (gcov_info_type); - build_gcov_exit_decl (); + if (profile_info_section) + build_gcov_info_var_registration (gcov_info_type); + else + { + build_init_ctor (gcov_info_type); + build_gcov_exit_decl (); + } return true; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6ce67e6edab..310c3f72a3f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -566,6 +566,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-info-section -fprofile-info-section=@var{name} @gol -fprofile-note=@var{path} -fprofile-prefix-path=@var{path} @gol -fprofile-update=@var{method} -fprofile-filter-files=@var{regex} @gol -fprofile-exclude-files=@var{regex} @gol @@ -14237,6 +14238,34 @@ the profile feedback data files. See @option{-fprofile-dir}. To optimize the program based on the collected profile information, use @option{-fprofile-use}. @xref{Optimize Options}, for more information. +@item -fprofile-info-section +@itemx -fprofile-info-section=@var{name} +@opindex fprofile-info-section + +Register the profile information in the specified section instead of using a +constructor/destructor. The section name is @var{name} if it is specified, +otherwise the section name defaults to @code{.gcov_info}. A pointer to the +profile information generated by @option{-fprofile-arcs} or +@option{-ftest-coverage} is placed in the specified section for each +translation unit. This option disables the profile information registration +through a constructor and it disables the profile information processing +through a destructor. This option is not intended to be used in hosted +environments such as GNU/Linux. It targets systems with limited resources +which do not support constructors and destructors. The linker could collect +the input sections in a continuous memory block and define start and end +symbols. The runtime support could dump the profiling information registered +in this linker set during program termination to a serial line for example. A +GNU linker script example which defines a linker output section follows: + +@smallexample + .gcov_info : + @{ + PROVIDE (__gcov_info_start = .); + KEEP (*(.gcov_info)) + PROVIDE (__gcov_info_end = .); + @} +@end smallexample + @item -fprofile-note=@var{path} @opindex fprofile-note diff --git a/gcc/opts.c b/gcc/opts.c index ac9972d9c38..57774916a09 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -2596,6 +2596,10 @@ common_handle_option (struct gcc_options *opts, SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value); break; + case OPT_fprofile_info_section: + opts->x_profile_info_section = ".gcov_info"; + break; + case OPT_fpatchable_function_entry_: { char *patch_area_arg = xstrdup (arg); diff --git a/gcc/testsuite/gcc.dg/profile-info-section.c b/gcc/testsuite/gcc.dg/profile-info-section.c new file mode 100644 index 00000000000..c27fe17084e --- /dev/null +++ b/gcc/testsuite/gcc.dg/profile-info-section.c @@ -0,0 +1,20 @@ +/* { dg-options "-fprofile-arcs -fprofile-info-section -fdump-tree-optimized" } */ + +int foo() +{ + return 0; +} + +int bar() +{ + return 1; +} + +int main () +{ + return foo (); +} + +/* { dg-final { scan-tree-dump-not "__gcov_init" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__gcov_exit" "optimized" } } */ +/* { dg-final { scan-assembler "\.gcov_info" } } */