gcov: Add -fprofile-info-section support
authorSebastian Huber <sebastian.huber@embedded-brains.de>
Fri, 13 Nov 2020 16:47:40 +0000 (17:47 +0100)
committerMartin Liska <mliska@suse.cz>
Mon, 16 Nov 2020 11:52:14 +0000 (12:52 +0100)
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
gcc/coverage.c
gcc/doc/invoke.texi
gcc/opts.c
gcc/testsuite/gcc.dg/profile-info-section.c [new file with mode: 0644]

index 9552ceb..fe39b3d 100644 (file)
@@ -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.
index 7711412..d299e48 100644 (file)
@@ -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;
 }
index 6ce67e6..310c3f7 100644 (file)
@@ -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
 
index ac9972d..5777491 100644 (file)
@@ -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 (file)
index 0000000..c27fe17
--- /dev/null
@@ -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" } } */