]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gcov: Add TARGET_GCOV_TYPE_SIZE target hook
authorSebastian Huber <sebastian.huber@embedded-brains.de>
Mon, 9 Aug 2021 07:06:14 +0000 (09:06 +0200)
committerSebastian Huber <sebastian.huber@embedded-brains.de>
Mon, 16 Aug 2021 13:34:25 +0000 (15:34 +0200)
If -fprofile-update=atomic is used, then the target must provide atomic
operations for the counters of the type returned by get_gcov_type().
This is a 64-bit type for targets which have a 64-bit long long type.
On 32-bit targets this could be an issue since they may not provide
64-bit atomic operations.  Allow targets to override the default type
size with the new TARGET_GCOV_TYPE_SIZE target hook.

If a 32-bit gcov type size is used, then there is currently a warning in
libgcov-driver.c in a dead code block due to
sizeof (counter) == sizeof (gcov_unsigned_t):

libgcc/libgcov-driver.c: In function 'dump_counter':
libgcc/libgcov-driver.c:401:46: warning: right shift count >= width of type [-Wshift-count-overflow]
  401 |     dump_unsigned ((gcov_unsigned_t)(counter >> 32), dump_fn, arg);
      |                                              ^~

gcc/c-family/

* c-cppbuiltin.c (c_cpp_builtins): Define
__LIBGCC_GCOV_TYPE_SIZE if flag_building_libgcc is true.

gcc/

* config/sparc/rtemself.h (SPARC_GCOV_TYPE_SIZE): Define.
* config/sparc/sparc.c (sparc_gcov_type_size): New.
(TARGET_GCOV_TYPE_SIZE): Redefine if SPARC_GCOV_TYPE_SIZE is defined.
* coverage.c (get_gcov_type): Use targetm.gcov_type_size().
* doc/tm.texi (TARGET_GCOV_TYPE_SIZE): Add hook under "Misc".
* doc/tm.texi.in: Regenerate.
* target.def (gcov_type_size): New target hook.
* targhooks.c (default_gcov_type_size): New.
* targhooks.h (default_gcov_type_size): Declare.
* tree-profile.c (gimple_gen_edge_profiler): Use precision of
gcov_type_node.
(gimple_gen_time_profiler): Likewise.

libgcc/

* libgcov.h (gcov_type): Define using __LIBGCC_GCOV_TYPE_SIZE.
(gcov_type_unsigned): Likewise.

gcc/c-family/c-cppbuiltin.c
gcc/config/sparc/rtemself.h
gcc/config/sparc/sparc.c
gcc/coverage.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-profile.c
libgcc/libgcov.h

index f79f939bd10f025bf9cad2a015dd0fa67af0d103..3fa62bc4fe7696bad109fd5f5bfd442579d2a518 100644 (file)
@@ -1450,6 +1450,8 @@ c_cpp_builtins (cpp_reader *pfile)
       /* For libgcov.  */
       builtin_define_with_int_value ("__LIBGCC_VTABLE_USES_DESCRIPTORS__",
                                     TARGET_VTABLE_USES_DESCRIPTORS);
+      builtin_define_with_int_value ("__LIBGCC_GCOV_TYPE_SIZE",
+                                    targetm.gcov_type_size());
     }
 
   /* For use in assembly language.  */
index fa972af640cc8f6c733bd3f46f48c4991c2a6eb3..d64ce9012daf95dfb54e50b5d14674a67c364c73 100644 (file)
@@ -40,3 +40,5 @@
 
 /* Use the default */
 #undef LINK_GCC_C_SEQUENCE_SPEC
+
+#define SPARC_GCOV_TYPE_SIZE 32
index 04fc80f0ee62a95064057f862cdb1e9dfdc2d4d4..06f41d7bb53f6d588a0d4c1a47da73e6c6c08423 100644 (file)
@@ -944,6 +944,17 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_ZERO_CALL_USED_REGS
 #define TARGET_ZERO_CALL_USED_REGS sparc_zero_call_used_regs
 
+#ifdef SPARC_GCOV_TYPE_SIZE
+static HOST_WIDE_INT
+sparc_gcov_type_size (void)
+{
+  return SPARC_GCOV_TYPE_SIZE;
+}
+
+#undef TARGET_GCOV_TYPE_SIZE
+#define TARGET_GCOV_TYPE_SIZE sparc_gcov_type_size
+#endif
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return the memory reference contained in X if any, zero otherwise.  */
index ac9a9fdad228271f121b3068519f7662bbd7e323..10d7f8366cb547f06a00af5c11c8d7fe4532353b 100644 (file)
@@ -146,7 +146,7 @@ tree
 get_gcov_type (void)
 {
   scalar_int_mode mode
-    = smallest_int_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32);
+    = smallest_int_mode_for_size (targetm.gcov_type_size ());
   return lang_hooks.types.type_for_mode (mode, false);
 }
 
index a30fdcbbf3d680c12dcb6a97af90dd018732de4a..f68f42638a112bed8396fd634bd3fd3c44ce848a 100644 (file)
@@ -12588,3 +12588,14 @@ Return an RTX representing @var{tagged_pointer} with its tag set to zero.
 Store the result in @var{target} if convenient.
 The default clears the top byte of the original pointer.
 @end deftypefn
+
+@deftypefn {Target Hook} HOST_WIDE_INT TARGET_GCOV_TYPE_SIZE (void)
+Returns the gcov type size in bits.  This type is used for example for
+counters incremented by profiling and code-coverage events.  The default
+value is 64, if the type size of long long is greater than 32, otherwise the
+default value is 32.  A 64-bit type is recommended to avoid overflows of the
+counters.  If the @option{-fprofile-update=atomic} is used, then the
+counters are incremented using atomic operations.  Targets not supporting
+64-bit atomic operations may override the default value and request a 32-bit
+type.
+@end deftypefn
index 611fc500ac86c9621849f94a9e4b3a8d6e64e631..fdf16b901c537e6a02f630a80a2213d2dcb6d5d6 100644 (file)
@@ -8180,3 +8180,5 @@ maintainer is familiar with.
 @hook TARGET_MEMTAG_EXTRACT_TAG
 
 @hook TARGET_MEMTAG_UNTAGGED_POINTER
+
+@hook TARGET_GCOV_TYPE_SIZE
index 7676d5e626e372f00b537a4053ed1919d5f00f17..28a34f1d51b5abb41c537b9cd327ca59f1f9260f 100644 (file)
@@ -7104,6 +7104,18 @@ DEFHOOK
  void, (void),
  NULL)
 
+DEFHOOK
+(gcov_type_size,
+ "Returns the gcov type size in bits.  This type is used for example for\n\
+counters incremented by profiling and code-coverage events.  The default\n\
+value is 64, if the type size of long long is greater than 32, otherwise the\n\
+default value is 32.  A 64-bit type is recommended to avoid overflows of the\n\
+counters.  If the @option{-fprofile-update=atomic} is used, then the\n\
+counters are incremented using atomic operations.  Targets not supporting\n\
+64-bit atomic operations may override the default value and request a 32-bit\n\
+type.",
+ HOST_WIDE_INT, (void), default_gcov_type_size)
+
 /* Close the 'struct gcc_target' definition.  */
 HOOK_VECTOR_END (C90_EMPTY_HACK)
 
index eb5190910dcf7d0acd09bba282fb5ce87887b163..c9b5208853dbc15706a65d1eb335e28e0564325e 100644 (file)
@@ -2654,4 +2654,11 @@ default_memtag_untagged_pointer (rtx tagged_pointer, rtx target)
   return untagged_base;
 }
 
+/* The default implementation of TARGET_GCOV_TYPE_SIZE.  */
+HOST_WIDE_INT
+default_gcov_type_size (void)
+{
+  return TYPE_PRECISION (long_long_integer_type_node) > 32 ? 64 : 32;
+}
+
 #include "gt-targhooks.h"
index f92e102c450c23288cc79ed41c0d64cbf87826a4..92d51992e625c2497aa8496b1e2e3d916e5706fd 100644 (file)
@@ -302,4 +302,6 @@ extern rtx default_memtag_set_tag (rtx, rtx, rtx);
 extern rtx default_memtag_extract_tag (rtx, rtx);
 extern rtx default_memtag_untagged_pointer (rtx, rtx);
 
+extern HOST_WIDE_INT default_gcov_type_size (void);
+
 #endif /* GCC_TARGHOOKS_H */
index 5a74cc96e1323f4684e09b4c8b34076088cd0d30..cf46912631cb3fa5bd252b6cc8baebbc4eb55112 100644 (file)
@@ -250,7 +250,7 @@ gimple_gen_edge_profiler (int edgeno, edge e)
     {
       /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
       tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
-      tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
+      tree f = builtin_decl_explicit (TYPE_PRECISION (gcov_type_node) > 32
                                      ? BUILT_IN_ATOMIC_FETCH_ADD_8:
                                      BUILT_IN_ATOMIC_FETCH_ADD_4);
       gcall *stmt = gimple_build_call (f, 3, addr, one,
@@ -525,7 +525,7 @@ gimple_gen_time_profiler (unsigned tag)
                          tree_time_profiler_counter);
       gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
       gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
-      tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
+      tree f = builtin_decl_explicit (TYPE_PRECISION (gcov_type_node) > 32
                                      ? BUILT_IN_ATOMIC_ADD_FETCH_8:
                                      BUILT_IN_ATOMIC_ADD_FETCH_4);
       gcall *stmt = gimple_build_call (f, 3, ptr, one,
index 9c537253293f02b4b514a64a8bb84318ef70e934..f6354a7a070580656da9f2a550d240647cecba3e 100644 (file)
@@ -52,7 +52,7 @@
 #if __CHAR_BIT__ == 8
 typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI)));
 typedef unsigned gcov_position_t __attribute__ ((mode (SI)));
-#if LONG_LONG_TYPE_SIZE > 32
+#if __LIBGCC_GCOV_TYPE_SIZE > 32
 typedef signed gcov_type __attribute__ ((mode (DI)));
 typedef unsigned gcov_type_unsigned __attribute__ ((mode (DI)));
 #else
@@ -63,7 +63,7 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI)));
 #if __CHAR_BIT__ == 16
 typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI)));
 typedef unsigned gcov_position_t __attribute__ ((mode (HI)));
-#if LONG_LONG_TYPE_SIZE > 32
+#if __LIBGCC_GCOV_TYPE_SIZE > 32
 typedef signed gcov_type __attribute__ ((mode (SI)));
 typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI)));
 #else
@@ -73,7 +73,7 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI)));
 #else
 typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI)));
 typedef unsigned gcov_position_t __attribute__ ((mode (QI)));
-#if LONG_LONG_TYPE_SIZE > 32
+#if __LIBGCC_GCOV_TYPE_SIZE > 32
 typedef signed gcov_type __attribute__ ((mode (HI)));
 typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI)));
 #else