gcov: Add gen_counter_update()

Move the counter update to the new gen_counter_update() helper function.  Use
it in gimple_gen_edge_profiler() and gimple_gen_time_profiler().  The resulting
gimple instructions should be identical with the exception of the removed
unshare_expr() call.  The unshare_expr() call was used in
gimple_gen_edge_profiler().

gcc/ChangeLog:

	* tree-profile.cc (gen_assign_counter_update): New.
	(gen_counter_update): Likewise.
	(gimple_gen_edge_profiler): Use gen_counter_update().
	(gimple_gen_time_profiler): Likewise.
This commit is contained in:
Sebastian Huber 2023-10-21 15:52:15 +02:00
parent 3ef8882adc
commit a350a74d61

View file

@ -235,47 +235,78 @@ gimple_init_gcov_profiler (void)
}
}
/* Output instructions as GIMPLE trees to increment the edge
execution count, and insert them on E. We rely on
gsi_insert_on_edge to preserve the order. */
/* If RESULT is not null, then output instructions as GIMPLE trees to assign
the updated counter from CALL of FUNC to RESULT. Insert the CALL and the
optional assignment instructions to GSI. Use NAME for temporary values. */
void
gimple_gen_edge_profiler (int edgeno, edge e)
static inline void
gen_assign_counter_update (gimple_stmt_iterator *gsi, gcall *call, tree func,
tree result, const char *name)
{
tree one;
if (result)
{
tree result_type = TREE_TYPE (TREE_TYPE (func));
tree tmp = make_temp_ssa_name (result_type, NULL, name);
gimple_set_lhs (call, tmp);
gsi_insert_after (gsi, call, GSI_NEW_STMT);
gassign *assign = gimple_build_assign (result, tmp);
gsi_insert_after (gsi, assign, GSI_NEW_STMT);
}
else
gsi_insert_after (gsi, call, GSI_NEW_STMT);
}
one = build_int_cst (gcov_type_node, 1);
/* Output instructions as GIMPLE trees to increment the COUNTER. If RESULT is
not null, then assign the updated counter value to RESULT. Insert the
instructions to GSI. Use NAME for temporary values. */
static inline void
gen_counter_update (gimple_stmt_iterator *gsi, tree counter, tree result,
const char *name)
{
tree type = gcov_type_node;
tree addr = build_fold_addr_expr (counter);
tree one = build_int_cst (type, 1);
tree relaxed = build_int_cst (integer_type_node, MEMMODEL_RELAXED);
if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
{
/* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
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,
build_int_cst (integer_type_node,
MEMMODEL_RELAXED));
gsi_insert_on_edge (e, stmt);
tree f = builtin_decl_explicit (TYPE_PRECISION (type) > 32
? BUILT_IN_ATOMIC_ADD_FETCH_8:
BUILT_IN_ATOMIC_ADD_FETCH_4);
gcall *call = gimple_build_call (f, 3, addr, one, relaxed);
gen_assign_counter_update (gsi, call, f, result, name);
}
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);
tree tmp1 = make_temp_ssa_name (type, NULL, name);
gassign *assign1 = gimple_build_assign (tmp1, counter);
gsi_insert_after (gsi, assign1, GSI_NEW_STMT);
tree tmp2 = make_temp_ssa_name (type, NULL, name);
gassign *assign2 = gimple_build_assign (tmp2, PLUS_EXPR, tmp1, one);
gsi_insert_after (gsi, assign2, GSI_NEW_STMT);
gassign *assign3 = gimple_build_assign (counter, tmp2);
gsi_insert_after (gsi, assign3, GSI_NEW_STMT);
if (result)
{
gassign *assign4 = gimple_build_assign (result, tmp2);
gsi_insert_after (gsi, assign4, GSI_NEW_STMT);
}
}
}
/* Output instructions as GIMPLE trees to increment the edge
execution count, and insert them on E. */
void
gimple_gen_edge_profiler (int edgeno, edge e)
{
gimple_stmt_iterator gsi = gsi_last (PENDING_STMT (e));
tree counter = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
gen_counter_update (&gsi, counter, NULL_TREE, "PROF_edge_counter");
}
/* Emits code to get VALUE to instrument at GSI, and returns the
variable containing the value. */
@ -507,56 +538,16 @@ gimple_gen_time_profiler (unsigned tag)
tree original_ref = tree_coverage_counter_ref (tag, 0);
tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
true, GSI_SAME_STMT);
tree one = build_int_cst (type, 1);
/* Emit: if (counters[0] != 0). */
gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
NULL, NULL);
gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
gsi = gsi_start_bb (update_bb);
/* Emit: counters[0] = ++__gcov_time_profiler_counter. */
if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
{
tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
"PROF_time_profiler_counter_ptr");
tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
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 (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,
build_int_cst (integer_type_node,
MEMMODEL_RELAXED));
tree result_type = TREE_TYPE (TREE_TYPE (f));
tree tmp = make_temp_ssa_name (result_type, NULL, "PROF_time_profile");
gimple_set_lhs (stmt, tmp);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
tmp = make_temp_ssa_name (type, NULL, "PROF_time_profile");
assign = gimple_build_assign (tmp, NOP_EXPR,
gimple_call_lhs (stmt));
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (original_ref, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
}
else
{
tree tmp = make_temp_ssa_name (type, NULL, "PROF_time_profile");
gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
tmp = make_temp_ssa_name (type, NULL, "PROF_time_profile");
assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
one);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (original_ref, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (tree_time_profiler_counter, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
}
gsi = gsi_start_bb (update_bb);
gen_counter_update (&gsi, tree_time_profiler_counter, original_ref,
"PROF_time_profile");
}
/* Output instructions as GIMPLE trees to increment the average histogram