+2016-08-10 Martin Liska <mliska@suse.cz>
+
+ Cherry picked (and modified) from google-4_7 branch
+ 2012-12-26 Rong Xu <xur@google.com>
+ * common.opt (fprofile-update): Add new flag.
+ * coretypes.h: Define enum profile_update.
+ * doc/invoke.texi: Document -fprofile-update.
+ * gcov-io.h: Declare GCOV_TYPE_ATOMIC_FETCH_ADD and
+ GCOV_TYPE_ATOMIC_FETCH_ADD_FN.
+ * tree-profile.c (gimple_init_edge_profiler): Generate
+ also atomic profiler update.
+ (gimple_gen_edge_profiler): Likewise.
+
2016-08-10 David Malcolm <dmalcolm@redhat.com>
* toplev.c (finalize): Set aux_info_file, asm_out_file, and
Common Report Var(flag_profile_correction)
Enable correction of flow inconsistent profile data input.
+fprofile-update=
+Common Joined RejectNegative Enum(profile_update) Var(flag_profile_update) Init(PROFILE_UPDATE_SINGLE)
+-fprofile-update=[single|atomic] Set the profile update method.
+
+Enum
+Name(profile_update) Type(enum profile_update) UnknownError(unknown profile update method %qs)
+
+EnumValue
+Enum(profile_update) String(single) Value(PROFILE_UPDATE_SINGLE)
+
+EnumValue
+Enum(profile_update) String(atomic) Value(PROFILE_UPDATE_ATOMIC)
+
fprofile-generate
Common
Enable common options for generating profile info for profile feedback directed optimizations.
OFFLOAD_ABI_ILP32
};
+/* Types of profile update methods. */
+enum profile_update {
+ PROFILE_UPDATE_SINGLE,
+ PROFILE_UPDATE_ATOMIC
+};
+
/* Types of unwind/exception handling info that can be generated. */
enum unwind_info_type
To optimize the program based on the collected profile information, use
@option{-fprofile-use}. @xref{Optimize Options}, for more information.
+@item -fprofile-update=@var{method}
+@opindex fprofile-update
+
+Alter the update method for an application instrumented for profile
+feedback based optimization. The @var{method} argument should be one of
+@samp{single} or @samp{atomic}. The first one is useful for single-threaded
+applications, while the second one prevents profile corruption by emitting
+thread-safe code.
+
+@strong{Warning:} When an application does not properly join all threads
+(or creates an detached thread), a profile file can be still corrupted.
+
@item -fsanitize=address
@opindex fsanitize=address
Enable AddressSanitizer, a fast memory error detector.
#ifndef GCC_GCOV_IO_H
#define GCC_GCOV_IO_H
+#if LONG_LONG_TYPE_SIZE > 32
+#define GCOV_TYPE_ATOMIC_FETCH_ADD_FN __atomic_fetch_add_8
+#define GCOV_TYPE_ATOMIC_FETCH_ADD BUILT_IN_ATOMIC_FETCH_ADD_8
+#else
+#define GCOV_TYPE_ATOMIC_FETCH_ADD_FN __atomic_fetch_add_4
+#define GCOV_TYPE_ATOMIC_FETCH_ADD BUILT_IN_ATOMIC_FETCH_ADD_4
+#endif
+
#ifndef IN_LIBGCOV
/* About the host */
+2016-08-10 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/gcov/gcov-threads-1.C: New test.
+
2016-08-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
PR target/71873
--- /dev/null
+/* { dg-options "-fprofile-arcs -ftest-coverage -pthread -fprofile-update=atomic" } */
+/* { dg-do run { target native } } */
+
+#include <stdint.h>
+#include <pthread.h>
+#include <assert.h>
+
+#define NR 5
+
+pthread_mutex_t cndMs[NR];
+static void *ContentionNoDeadlock_thread(void *start)
+{
+ for (uint32_t k = 0; k < 100000; ++k) /* count(500005) */
+ {
+ int starti = *(int*)start; /* count(500000) */
+ for (uint32_t i = starti; i < NR; ++i)
+ pthread_mutex_lock (&cndMs[i]);
+ for (int32_t i = NR - 1; i >= starti; --i)
+ pthread_mutex_unlock (&cndMs[i]);
+ }
+}
+int main(int argc, char **argv) {
+ for (unsigned i = 0; i < NR; i++)
+ cndMs[i] = PTHREAD_MUTEX_INITIALIZER;
+
+ pthread_t t[NR];
+ int ids[NR];
+
+ for (int i = 0; i < NR; i++)
+ {
+ ids[i] = i;
+ int r = pthread_create (&t[i], NULL, ContentionNoDeadlock_thread, &ids[i]);
+ assert (r == 0); /* count(5) */
+ }
+
+ int ret;
+ for (int i = 0; i < NR; i++)
+ {
+ int r = pthread_join (t[i], (void**)&ret);
+ assert (r == 0); /* count(5) */
+ }
+
+ return 0; /* count(1) */
+}
+
+/* { dg-final { run-gcov gcov-threads-1.C } } */
tree ic_profiler_fn_type;
tree average_profiler_fn_type;
tree time_profiler_fn_type;
+ const char *profiler_fn_name;
if (!gcov_type_node)
{
gcov_type_node,
ptr_void,
NULL_TREE);
+ profiler_fn_name = "__gcov_indirect_call_profiler_v2";
+ if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
+ profiler_fn_name = "__gcov_indirect_call_topn_profiler";
+
tree_indirect_call_profiler_fn
- = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
- "__gcov_indirect_call_topn_profiler":
- "__gcov_indirect_call_profiler_v2"),
- ic_profiler_fn_type);
+ = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
void
gimple_gen_edge_profiler (int edgeno, edge e)
{
- tree ref, one, gcov_type_tmp_var;
- gassign *stmt1, *stmt2, *stmt3;
+ tree one;
- ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
one = build_int_cst (gcov_type_node, 1);
- gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
- NULL, "PROF_edge_counter");
- stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
- gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
- NULL, "PROF_edge_counter");
- stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
- gimple_assign_lhs (stmt1), one);
- stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
- gsi_insert_on_edge (e, stmt1);
- gsi_insert_on_edge (e, stmt2);
- gsi_insert_on_edge (e, stmt3);
+
+ if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
+ {
+ /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
+ tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
+ gcall *stmt
+ = gimple_build_call (builtin_decl_explicit (GCOV_TYPE_ATOMIC_FETCH_ADD),
+ 3, addr, one,
+ build_int_cst (integer_type_node,
+ MEMMODEL_RELAXED));
+ gsi_insert_on_edge (e, stmt);
+ }
+ else
+ {
+ tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
+ tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
+ NULL, "PROF_edge_counter");
+ gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
+ gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
+ NULL, "PROF_edge_counter");
+ gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
+ gimple_assign_lhs (stmt1), one);
+ gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
+ gimple_assign_lhs (stmt2));
+ gsi_insert_on_edge (e, stmt1);
+ gsi_insert_on_edge (e, stmt2);
+ gsi_insert_on_edge (e, stmt3);
+ }
}
/* Emits code to get VALUE to instrument at GSI, and returns the