From 14e19b82c1e67ead60c3095ac23347317298904b Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 19 Oct 2020 17:40:00 +0200 Subject: [PATCH] gcov-profile: use static pool for TOPN first gcc/ChangeLog: PR gcov-profile/97461 * gcov-io.h (GCOV_PREALLOCATED_KVP): Pre-allocate 64 static counters. libgcc/ChangeLog: PR gcov-profile/97461 * libgcov.h (gcov_counter_add): Use first static counters as it should help to have malloc wrappers set up. gcc/testsuite/ChangeLog: PR gcov-profile/97461 * gcc.dg/tree-prof/pr97461.c: New test. --- gcc/gcov-io.h | 2 +- gcc/testsuite/gcc.dg/tree-prof/pr97461.c | 58 ++++++++++++++++++++++++ libgcc/libgcov.h | 24 +++------- 3 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-prof/pr97461.c diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index 4dba01c78ce..4e95c7c82ee 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -293,7 +293,7 @@ GCOV_COUNTERS #define GCOV_TOPN_MAXIMUM_TRACKED_VALUES 32 /* Number of pre-allocated gcov_kvp structures. */ -#define GCOV_PREALLOCATED_KVP 16 +#define GCOV_PREALLOCATED_KVP 64 /* Convert a counter index to a tag. */ #define GCOV_TAG_FOR_COUNTER(COUNT) \ diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr97461.c b/gcc/testsuite/gcc.dg/tree-prof/pr97461.c new file mode 100644 index 00000000000..8d21a3ef421 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/pr97461.c @@ -0,0 +1,58 @@ +/* PR gcov-profile/97461 */ +/* { dg-options "-O2 -ldl" } */ + +#define _GNU_SOURCE + +#include +#include +#include + +static int malloc_depth = 0; + +static char memory[128* 1024]; +static size_t memory_p = 0; + +void f1(void) {} +void f2(void) {} + +typedef void (*fun_t)(void); +static const fun_t funs[2] = { f1, f2, }; + +static void * malloc_impl(size_t size) { + void * r = &memory[memory_p]; + memory_p += size; + + // force TOPN profile + funs[size % 2](); + return r; +} + +// Override default malloc, check it it get s called recursively +void * malloc(size_t size) { + // Must not be called recursively. Malloc implementation does not support it. + if (malloc_depth != 0) __builtin_trap(); + + ++malloc_depth; + void * r = malloc_impl(size); + --malloc_depth; + return r; +} + +// Called from gcov +void *calloc(size_t nmemb, size_t size) { + // Must not be called recursively. Malloc implementation does not support it. + if (malloc_depth != 0) __builtin_trap(); + + ++malloc_depth; + void * r = malloc_impl(size * nmemb); + memset(r, 0, size * nmemb); + --malloc_depth; + return r; +} + +void free(void *ptr){} + +int main() { + void * p = malloc(8); + return p != 0 ? 0 : 1; +} diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h index 8be5bebcac0..e70cf63b414 100644 --- a/libgcc/libgcov.h +++ b/libgcc/libgcov.h @@ -404,22 +404,16 @@ gcov_counter_add (gcov_type *counter, gcov_type value, *counter += value; } -/* Allocate gcov_kvp from heap. If we are recursively called, then allocate - it from a list of pre-allocated pool. */ +/* Allocate gcov_kvp from statically pre-allocated pool, + or use heap otherwise. */ static inline struct gcov_kvp * allocate_gcov_kvp (void) { struct gcov_kvp *new_node = NULL; - static -#if defined(HAVE_CC_TLS) -__thread -#endif - volatile unsigned in_recursion ATTRIBUTE_UNUSED = 0; - #if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn) - if (__builtin_expect (in_recursion, 0)) + if (__gcov_kvp_pool_index < GCOV_PREALLOCATED_KVP) { unsigned index; #if GCOV_SUPPORTS_ATOMIC @@ -430,17 +424,11 @@ __thread #endif if (index < GCOV_PREALLOCATED_KVP) new_node = &__gcov_kvp_pool[index]; - else - /* Do not crash in the situation. */ - return NULL; } - else #endif - { - in_recursion = 1; - new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp)); - in_recursion = 0; - } + + if (new_node == NULL) + new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp)); return new_node; }