/* Calculate branch probabilities, and basic block execution counts.
- Copyright (C) 1990-2013 Free Software Foundation, Inc.
+ Copyright (C) 1990-2015 Free Software Foundation, Inc.
Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
based on some ideas from Dain Samples of UC Berkeley.
Further mangling by Bob Manson, Cygnus Support.
#include "coretypes.h"
#include "tm.h"
#include "flags.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
#include "function.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
#include "basic-block.h"
#include "diagnostic-core.h"
#include "coverage.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
#include "tree.h"
+#include "fold-const.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
#include "gimple.h"
+#include "varasm.h"
+#include "tree-nested.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "gimple-ssa.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
#include "cgraph.h"
#include "tree-cfg.h"
+#include "stringpool.h"
#include "tree-ssanames.h"
#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "target.h"
#include "tree-cfgcleanup.h"
#include "tree-nested.h"
+#include "params.h"
static GTY(()) tree gcov_type_node;
static GTY(()) tree tree_interval_profiler_fn;
ptr_void = build_pointer_type (void_type_node);
- /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
- if (flag_lto)
- {
- ic_void_ptr_var
- = build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_callee_ltopriv"),
- ptr_void);
- TREE_PUBLIC (ic_void_ptr_var) = 1;
- DECL_COMMON (ic_void_ptr_var) = 1;
- DECL_VISIBILITY (ic_void_ptr_var) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (ic_void_ptr_var) = true;
- }
- else
- {
- ic_void_ptr_var
- = build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_callee"),
- ptr_void);
- TREE_PUBLIC (ic_void_ptr_var) = 1;
- DECL_EXTERNAL (ic_void_ptr_var) = 1;
- }
+ ic_void_ptr_var
+ = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (
+ (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ "__gcov_indirect_call_topn_callee" :
+ "__gcov_indirect_call_callee")),
+ ptr_void);
+ TREE_PUBLIC (ic_void_ptr_var) = 1;
+ DECL_EXTERNAL (ic_void_ptr_var) = 1;
TREE_STATIC (ic_void_ptr_var) = 1;
DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
DECL_INITIAL (ic_void_ptr_var) = NULL;
if (targetm.have_tls)
- DECL_TLS_MODEL (ic_void_ptr_var) =
- decl_default_tls_model (ic_void_ptr_var);
+ set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
- varpool_finalize_decl (ic_void_ptr_var);
+ varpool_node::finalize_decl (ic_void_ptr_var);
gcov_type_ptr = build_pointer_type (get_gcov_type ());
- /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
- if (flag_lto)
- {
- ic_gcov_type_ptr_var
- = build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_counters_ltopriv"),
- gcov_type_ptr);
- TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
- DECL_COMMON (ic_gcov_type_ptr_var) = 1;
- DECL_VISIBILITY (ic_gcov_type_ptr_var) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (ic_gcov_type_ptr_var) = true;
- }
- else
- {
- ic_gcov_type_ptr_var
- = build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_counters"),
- gcov_type_ptr);
- TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
- DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
- }
+
+ ic_gcov_type_ptr_var
+ = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (
+ (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ "__gcov_indirect_call_topn_counters" :
+ "__gcov_indirect_call_counters")),
+ gcov_type_ptr);
+ TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
+ DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
TREE_STATIC (ic_gcov_type_ptr_var) = 1;
DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
if (targetm.have_tls)
- DECL_TLS_MODEL (ic_gcov_type_ptr_var) =
- decl_default_tls_model (ic_gcov_type_ptr_var);
+ set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
- varpool_finalize_decl (ic_gcov_type_ptr_var);
+ varpool_node::finalize_decl (ic_gcov_type_ptr_var);
}
/* Create the type and function decls for the interface with gcov. */
init_ic_make_global_vars ();
- /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
- if (flag_lto)
- {
- /* void (*) (gcov_type, void *) */
- ic_profiler_fn_type
- = build_function_type_list (void_type_node,
- gcov_type_ptr, gcov_type_node,
- ptr_void, ptr_void,
- NULL_TREE);
- tree_indirect_call_profiler_fn
- = build_fn_decl ("__gcov_indirect_call_profiler",
- ic_profiler_fn_type);
- }
- else
- {
- /* void (*) (gcov_type, void *) */
- ic_profiler_fn_type
- = build_function_type_list (void_type_node,
- gcov_type_node,
- ptr_void,
- NULL_TREE);
- tree_indirect_call_profiler_fn
- = build_fn_decl ("__gcov_indirect_call_profiler_v2",
- ic_profiler_fn_type);
- }
+ /* void (*) (gcov_type, void *) */
+ ic_profiler_fn_type
+ = build_function_type_list (void_type_node,
+ gcov_type_node,
+ ptr_void,
+ NULL_TREE);
+ 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);
+
TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
gimple_gen_edge_profiler (int edgeno, edge e)
{
tree ref, one, gcov_type_tmp_var;
- gimple stmt1, stmt2, stmt3;
+ gassign *stmt1, *stmt2, *stmt3;
ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
one = build_int_cst (gcov_type_node, 1);
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_with_ops (PLUS_EXPR, gcov_type_tmp_var,
- gimple_assign_lhs (stmt1), one);
+ 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);
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
- gimple call;
+ gcall *call;
tree val;
tree start = build_int_cst_type (integer_type_node,
value->hdata.intvl.int_start);
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gimple call;
+ gcall *call;
tree val;
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gimple call;
+ gcall *call;
tree val;
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
{
tree tmp1;
- gimple stmt1, stmt2, stmt3;
+ gassign *stmt1, *stmt2, *stmt3;
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
+ if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
+ tag == GCOV_COUNTER_V_INDIR) ||
+ (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
+ tag == GCOV_COUNTER_ICALL_TOPNV))
+ return;
+
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
void
gimple_gen_ic_func_profiler (void)
{
- struct cgraph_node * c_node = cgraph_get_node (current_function_decl);
+ struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
gimple_stmt_iterator gsi;
- gimple stmt1, stmt2;
+ gcall *stmt1;
+ gassign *stmt2;
tree tree_uid, cur_func, void0;
- if (cgraph_only_called_directly_p (c_node))
+ if (c_node->only_called_directly_p ())
return;
gimple_init_edge_profiler ();
stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
¤t_function_decl)
*/
- gsi = gsi_after_labels (split_edge (single_succ_edge (ENTRY_BLOCK_PTR)));
+ gsi = gsi_after_labels (split_edge (single_succ_edge
+ (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
cur_func = force_gimple_operand_gsi (&gsi,
build_addr (current_function_decl,
true, NULL_TREE,
true, GSI_SAME_STMT);
tree_uid = build_int_cst
- (gcov_type_node, cgraph_get_node (current_function_decl)->profile_id);
- /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
- if (flag_lto)
- {
- tree counter_ptr, ptr_var;
- counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
- true, NULL_TREE, true,
- GSI_SAME_STMT);
- ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
- true, NULL_TREE, true,
- GSI_SAME_STMT);
-
- stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
- counter_ptr, tree_uid, cur_func, ptr_var);
- }
- else
- {
- stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
- tree_uid, cur_func);
- }
+ (gcov_type_node,
+ cgraph_node::get (current_function_decl)->profile_id);
+ stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
+ tree_uid, cur_func);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
/* Set __gcov_indirect_call_callee to 0,
gimple_stmt_iterator &gsi)
{
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gimple call;
+ gcall *call;
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gimple call;
+ gcall *call;
tree val;
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
gimple stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gimple call;
+ gcall *call;
tree val;
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
/* This is a small-ipa pass that gets called only once, from
cgraphunit.c:ipa_passes(). */
- gcc_assert (cgraph_state == CGRAPH_STATE_IPA_SSA);
+ gcc_assert (symtab->state == IPA_SSA);
init_node_map (true);
if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
continue;
+ /* Do not instrument extern inline functions when testing coverage.
+ While this is not perfectly consistent (early inlined extern inlines
+ will get acocunted), testsuite expects that. */
+ if (DECL_EXTERNAL (node->decl)
+ && flag_test_coverage)
+ continue;
+
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
/* Local pure-const may imply need to fixup the cfg. */
if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
continue;
- cgraph_set_const_flag (node, false, false);
- cgraph_set_pure_flag (node, false, false);
+ node->set_const_flag (false, false);
+ node->set_pure_flag (false, false);
}
/* Update call statements and rebuild the cgraph. */
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
cleanup_tree_cfg ();
update_ssa (TODO_update_ssa);
- rebuild_cgraph_edges ();
+ cgraph_edge::rebuild_edges ();
pop_cfun ();
}
return 0;
}
-/* When profile instrumentation, use or test coverage shall be performed. */
-
-static bool
-gate_tree_profile_ipa (void)
-{
- return (!in_lto_p
- && (flag_branch_probabilities || flag_test_coverage
- || profile_arc_flag));
-}
-
namespace {
const pass_data pass_data_ipa_tree_profile =
SIMPLE_IPA_PASS, /* type */
"profile", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
TV_IPA_PROFILE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
{}
/* opt_pass methods: */
- bool gate () { return gate_tree_profile_ipa (); }
- unsigned int execute () { return tree_profiling (); }
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *) { return tree_profiling (); }
}; // class pass_ipa_tree_profile
+bool
+pass_ipa_tree_profile::gate (function *)
+{
+ /* When profile instrumentation, use or test coverage shall be performed.
+ But for AutoFDO, this there is no instrumentation, thus this pass is
+ diabled. */
+ return (!in_lto_p && !flag_auto_profile
+ && (flag_branch_probabilities || flag_test_coverage
+ || profile_arc_flag));
+}
+
} // anon namespace
simple_ipa_opt_pass *