11debfc3dSmrg /* Calculate branch probabilities, and basic block execution counts.
2*8feb0f0bSmrg Copyright (C) 1990-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
41debfc3dSmrg based on some ideas from Dain Samples of UC Berkeley.
51debfc3dSmrg Further mangling by Bob Manson, Cygnus Support.
61debfc3dSmrg Converted to use trees by Dale Johannesen, Apple Computer.
71debfc3dSmrg
81debfc3dSmrg This file is part of GCC.
91debfc3dSmrg
101debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
111debfc3dSmrg the terms of the GNU General Public License as published by the Free
121debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
131debfc3dSmrg version.
141debfc3dSmrg
151debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
161debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
171debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
181debfc3dSmrg for more details.
191debfc3dSmrg
201debfc3dSmrg You should have received a copy of the GNU General Public License
211debfc3dSmrg along with GCC; see the file COPYING3. If not see
221debfc3dSmrg <http://www.gnu.org/licenses/>. */
231debfc3dSmrg
241debfc3dSmrg /* Generate basic block profile instrumentation and auxiliary files.
251debfc3dSmrg Tree-based version. See profile.c for overview. */
261debfc3dSmrg
271debfc3dSmrg #include "config.h"
281debfc3dSmrg #include "system.h"
291debfc3dSmrg #include "coretypes.h"
301debfc3dSmrg #include "memmodel.h"
311debfc3dSmrg #include "backend.h"
321debfc3dSmrg #include "target.h"
331debfc3dSmrg #include "tree.h"
341debfc3dSmrg #include "gimple.h"
351debfc3dSmrg #include "cfghooks.h"
361debfc3dSmrg #include "tree-pass.h"
371debfc3dSmrg #include "ssa.h"
381debfc3dSmrg #include "cgraph.h"
391debfc3dSmrg #include "coverage.h"
401debfc3dSmrg #include "diagnostic-core.h"
411debfc3dSmrg #include "fold-const.h"
421debfc3dSmrg #include "varasm.h"
431debfc3dSmrg #include "tree-nested.h"
441debfc3dSmrg #include "gimplify.h"
451debfc3dSmrg #include "gimple-iterator.h"
461debfc3dSmrg #include "gimplify-me.h"
471debfc3dSmrg #include "tree-cfg.h"
481debfc3dSmrg #include "tree-into-ssa.h"
491debfc3dSmrg #include "value-prof.h"
501debfc3dSmrg #include "profile.h"
511debfc3dSmrg #include "tree-cfgcleanup.h"
52a2dc1f3fSmrg #include "stringpool.h"
53a2dc1f3fSmrg #include "attribs.h"
54a2dc1f3fSmrg #include "tree-pretty-print.h"
55c0a68be4Smrg #include "langhooks.h"
56c0a68be4Smrg #include "stor-layout.h"
57c0a68be4Smrg #include "xregex.h"
581debfc3dSmrg
591debfc3dSmrg static GTY(()) tree gcov_type_node;
601debfc3dSmrg static GTY(()) tree tree_interval_profiler_fn;
611debfc3dSmrg static GTY(()) tree tree_pow2_profiler_fn;
62*8feb0f0bSmrg static GTY(()) tree tree_topn_values_profiler_fn;
631debfc3dSmrg static GTY(()) tree tree_indirect_call_profiler_fn;
641debfc3dSmrg static GTY(()) tree tree_average_profiler_fn;
651debfc3dSmrg static GTY(()) tree tree_ior_profiler_fn;
661debfc3dSmrg static GTY(()) tree tree_time_profiler_counter;
671debfc3dSmrg
681debfc3dSmrg
69c0a68be4Smrg static GTY(()) tree ic_tuple_var;
70c0a68be4Smrg static GTY(()) tree ic_tuple_counters_field;
71c0a68be4Smrg static GTY(()) tree ic_tuple_callee_field;
721debfc3dSmrg
731debfc3dSmrg /* Do initialization work for the edge profiler. */
741debfc3dSmrg
751debfc3dSmrg /* Add code:
76*8feb0f0bSmrg __thread gcov* __gcov_indirect_call.counters; // pointer to actual counter
77*8feb0f0bSmrg __thread void* __gcov_indirect_call.callee; // actual callee address
781debfc3dSmrg __thread int __gcov_function_counter; // time profiler function counter
791debfc3dSmrg */
801debfc3dSmrg static void
init_ic_make_global_vars(void)811debfc3dSmrg init_ic_make_global_vars (void)
821debfc3dSmrg {
831debfc3dSmrg tree gcov_type_ptr;
841debfc3dSmrg
851debfc3dSmrg gcov_type_ptr = build_pointer_type (get_gcov_type ());
861debfc3dSmrg
87c0a68be4Smrg tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
88c0a68be4Smrg
89c0a68be4Smrg /* callee */
90c0a68be4Smrg ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
91c0a68be4Smrg ptr_type_node);
92c0a68be4Smrg
93c0a68be4Smrg /* counters */
94c0a68be4Smrg ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
95c0a68be4Smrg NULL_TREE, gcov_type_ptr);
96c0a68be4Smrg DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field;
97c0a68be4Smrg
98c0a68be4Smrg finish_builtin_struct (tuple_type, "indirect_call_tuple",
99c0a68be4Smrg ic_tuple_counters_field, NULL_TREE);
100c0a68be4Smrg
101c0a68be4Smrg ic_tuple_var
1021debfc3dSmrg = build_decl (UNKNOWN_LOCATION, VAR_DECL,
103*8feb0f0bSmrg get_identifier ("__gcov_indirect_call"), tuple_type);
104c0a68be4Smrg TREE_PUBLIC (ic_tuple_var) = 1;
105c0a68be4Smrg DECL_ARTIFICIAL (ic_tuple_var) = 1;
106c0a68be4Smrg DECL_INITIAL (ic_tuple_var) = NULL;
107c0a68be4Smrg DECL_EXTERNAL (ic_tuple_var) = 1;
1081debfc3dSmrg if (targetm.have_tls)
109c0a68be4Smrg set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var));
1101debfc3dSmrg }
1111debfc3dSmrg
1121debfc3dSmrg /* Create the type and function decls for the interface with gcov. */
1131debfc3dSmrg
1141debfc3dSmrg void
gimple_init_gcov_profiler(void)1151debfc3dSmrg gimple_init_gcov_profiler (void)
1161debfc3dSmrg {
1171debfc3dSmrg tree interval_profiler_fn_type;
1181debfc3dSmrg tree pow2_profiler_fn_type;
119*8feb0f0bSmrg tree topn_values_profiler_fn_type;
1201debfc3dSmrg tree gcov_type_ptr;
1211debfc3dSmrg tree ic_profiler_fn_type;
1221debfc3dSmrg tree average_profiler_fn_type;
1231debfc3dSmrg const char *fn_name;
1241debfc3dSmrg
1251debfc3dSmrg if (!gcov_type_node)
1261debfc3dSmrg {
1271debfc3dSmrg const char *fn_suffix
1281debfc3dSmrg = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
1291debfc3dSmrg
1301debfc3dSmrg gcov_type_node = get_gcov_type ();
1311debfc3dSmrg gcov_type_ptr = build_pointer_type (gcov_type_node);
1321debfc3dSmrg
1331debfc3dSmrg /* void (*) (gcov_type *, gcov_type, int, unsigned) */
1341debfc3dSmrg interval_profiler_fn_type
1351debfc3dSmrg = build_function_type_list (void_type_node,
1361debfc3dSmrg gcov_type_ptr, gcov_type_node,
1371debfc3dSmrg integer_type_node,
1381debfc3dSmrg unsigned_type_node, NULL_TREE);
1391debfc3dSmrg fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
1401debfc3dSmrg tree_interval_profiler_fn = build_fn_decl (fn_name,
1411debfc3dSmrg interval_profiler_fn_type);
1421debfc3dSmrg free (CONST_CAST (char *, fn_name));
1431debfc3dSmrg TREE_NOTHROW (tree_interval_profiler_fn) = 1;
1441debfc3dSmrg DECL_ATTRIBUTES (tree_interval_profiler_fn)
1451debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
1461debfc3dSmrg DECL_ATTRIBUTES (tree_interval_profiler_fn));
1471debfc3dSmrg
1481debfc3dSmrg /* void (*) (gcov_type *, gcov_type) */
1491debfc3dSmrg pow2_profiler_fn_type
1501debfc3dSmrg = build_function_type_list (void_type_node,
1511debfc3dSmrg gcov_type_ptr, gcov_type_node,
1521debfc3dSmrg NULL_TREE);
1531debfc3dSmrg fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
1541debfc3dSmrg tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
1551debfc3dSmrg free (CONST_CAST (char *, fn_name));
1561debfc3dSmrg TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
1571debfc3dSmrg DECL_ATTRIBUTES (tree_pow2_profiler_fn)
1581debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
1591debfc3dSmrg DECL_ATTRIBUTES (tree_pow2_profiler_fn));
1601debfc3dSmrg
1611debfc3dSmrg /* void (*) (gcov_type *, gcov_type) */
162*8feb0f0bSmrg topn_values_profiler_fn_type
1631debfc3dSmrg = build_function_type_list (void_type_node,
1641debfc3dSmrg gcov_type_ptr, gcov_type_node,
1651debfc3dSmrg NULL_TREE);
166*8feb0f0bSmrg fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL);
167*8feb0f0bSmrg tree_topn_values_profiler_fn
168*8feb0f0bSmrg = build_fn_decl (fn_name, topn_values_profiler_fn_type);
1691debfc3dSmrg free (CONST_CAST (char *, fn_name));
170*8feb0f0bSmrg
171*8feb0f0bSmrg TREE_NOTHROW (tree_topn_values_profiler_fn) = 1;
172*8feb0f0bSmrg DECL_ATTRIBUTES (tree_topn_values_profiler_fn)
1731debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
174*8feb0f0bSmrg DECL_ATTRIBUTES (tree_topn_values_profiler_fn));
1751debfc3dSmrg
1761debfc3dSmrg init_ic_make_global_vars ();
1771debfc3dSmrg
1781debfc3dSmrg /* void (*) (gcov_type, void *) */
1791debfc3dSmrg ic_profiler_fn_type
1801debfc3dSmrg = build_function_type_list (void_type_node,
1811debfc3dSmrg gcov_type_node,
182c0a68be4Smrg ptr_type_node,
1831debfc3dSmrg NULL_TREE);
184*8feb0f0bSmrg fn_name = concat ("__gcov_indirect_call_profiler_v4", fn_suffix, NULL);
1851debfc3dSmrg tree_indirect_call_profiler_fn
186*8feb0f0bSmrg = build_fn_decl (fn_name, ic_profiler_fn_type);
187*8feb0f0bSmrg free (CONST_CAST (char *, fn_name));
1881debfc3dSmrg
1891debfc3dSmrg TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
1901debfc3dSmrg DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
1911debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
1921debfc3dSmrg DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
1931debfc3dSmrg
1941debfc3dSmrg tree_time_profiler_counter
1951debfc3dSmrg = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1961debfc3dSmrg get_identifier ("__gcov_time_profiler_counter"),
1971debfc3dSmrg get_gcov_type ());
1981debfc3dSmrg TREE_PUBLIC (tree_time_profiler_counter) = 1;
1991debfc3dSmrg DECL_EXTERNAL (tree_time_profiler_counter) = 1;
2001debfc3dSmrg TREE_STATIC (tree_time_profiler_counter) = 1;
2011debfc3dSmrg DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
2021debfc3dSmrg DECL_INITIAL (tree_time_profiler_counter) = NULL;
2031debfc3dSmrg
2041debfc3dSmrg /* void (*) (gcov_type *, gcov_type) */
2051debfc3dSmrg average_profiler_fn_type
2061debfc3dSmrg = build_function_type_list (void_type_node,
2071debfc3dSmrg gcov_type_ptr, gcov_type_node, NULL_TREE);
2081debfc3dSmrg fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
2091debfc3dSmrg tree_average_profiler_fn = build_fn_decl (fn_name,
2101debfc3dSmrg average_profiler_fn_type);
2111debfc3dSmrg free (CONST_CAST (char *, fn_name));
2121debfc3dSmrg TREE_NOTHROW (tree_average_profiler_fn) = 1;
2131debfc3dSmrg DECL_ATTRIBUTES (tree_average_profiler_fn)
2141debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
2151debfc3dSmrg DECL_ATTRIBUTES (tree_average_profiler_fn));
2161debfc3dSmrg fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
2171debfc3dSmrg tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
2181debfc3dSmrg free (CONST_CAST (char *, fn_name));
2191debfc3dSmrg TREE_NOTHROW (tree_ior_profiler_fn) = 1;
2201debfc3dSmrg DECL_ATTRIBUTES (tree_ior_profiler_fn)
2211debfc3dSmrg = tree_cons (get_identifier ("leaf"), NULL,
2221debfc3dSmrg DECL_ATTRIBUTES (tree_ior_profiler_fn));
2231debfc3dSmrg
2241debfc3dSmrg /* LTO streamer needs assembler names. Because we create these decls
2251debfc3dSmrg late, we need to initialize them by hand. */
2261debfc3dSmrg DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
2271debfc3dSmrg DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
228*8feb0f0bSmrg DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn);
2291debfc3dSmrg DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
2301debfc3dSmrg DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
2311debfc3dSmrg DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
2321debfc3dSmrg }
2331debfc3dSmrg }
2341debfc3dSmrg
2351debfc3dSmrg /* Output instructions as GIMPLE trees to increment the edge
2361debfc3dSmrg execution count, and insert them on E. We rely on
2371debfc3dSmrg gsi_insert_on_edge to preserve the order. */
2381debfc3dSmrg
2391debfc3dSmrg void
gimple_gen_edge_profiler(int edgeno,edge e)2401debfc3dSmrg gimple_gen_edge_profiler (int edgeno, edge e)
2411debfc3dSmrg {
2421debfc3dSmrg tree one;
2431debfc3dSmrg
2441debfc3dSmrg one = build_int_cst (gcov_type_node, 1);
2451debfc3dSmrg
2461debfc3dSmrg if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
2471debfc3dSmrg {
2481debfc3dSmrg /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
2491debfc3dSmrg tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
2501debfc3dSmrg tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
2511debfc3dSmrg ? BUILT_IN_ATOMIC_FETCH_ADD_8:
2521debfc3dSmrg BUILT_IN_ATOMIC_FETCH_ADD_4);
2531debfc3dSmrg gcall *stmt = gimple_build_call (f, 3, addr, one,
2541debfc3dSmrg build_int_cst (integer_type_node,
2551debfc3dSmrg MEMMODEL_RELAXED));
2561debfc3dSmrg gsi_insert_on_edge (e, stmt);
2571debfc3dSmrg }
2581debfc3dSmrg else
2591debfc3dSmrg {
2601debfc3dSmrg tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
2611debfc3dSmrg tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
2621debfc3dSmrg NULL, "PROF_edge_counter");
2631debfc3dSmrg gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
2641debfc3dSmrg gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
2651debfc3dSmrg NULL, "PROF_edge_counter");
2661debfc3dSmrg gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
2671debfc3dSmrg gimple_assign_lhs (stmt1), one);
2681debfc3dSmrg gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
2691debfc3dSmrg gimple_assign_lhs (stmt2));
2701debfc3dSmrg gsi_insert_on_edge (e, stmt1);
2711debfc3dSmrg gsi_insert_on_edge (e, stmt2);
2721debfc3dSmrg gsi_insert_on_edge (e, stmt3);
2731debfc3dSmrg }
2741debfc3dSmrg }
2751debfc3dSmrg
2761debfc3dSmrg /* Emits code to get VALUE to instrument at GSI, and returns the
2771debfc3dSmrg variable containing the value. */
2781debfc3dSmrg
2791debfc3dSmrg static tree
prepare_instrumented_value(gimple_stmt_iterator * gsi,histogram_value value)2801debfc3dSmrg prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
2811debfc3dSmrg {
2821debfc3dSmrg tree val = value->hvalue.value;
2831debfc3dSmrg if (POINTER_TYPE_P (TREE_TYPE (val)))
2841debfc3dSmrg val = fold_convert (build_nonstandard_integer_type
2851debfc3dSmrg (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
2861debfc3dSmrg return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
2871debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
2881debfc3dSmrg }
2891debfc3dSmrg
2901debfc3dSmrg /* Output instructions as GIMPLE trees to increment the interval histogram
2911debfc3dSmrg counter. VALUE is the expression whose value is profiled. TAG is the
2921debfc3dSmrg tag of the section for counters, BASE is offset of the counter position. */
2931debfc3dSmrg
2941debfc3dSmrg void
gimple_gen_interval_profiler(histogram_value value,unsigned tag)295*8feb0f0bSmrg gimple_gen_interval_profiler (histogram_value value, unsigned tag)
2961debfc3dSmrg {
2971debfc3dSmrg gimple *stmt = value->hvalue.stmt;
2981debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
299*8feb0f0bSmrg tree ref = tree_coverage_counter_ref (tag, 0), ref_ptr;
3001debfc3dSmrg gcall *call;
3011debfc3dSmrg tree val;
3021debfc3dSmrg tree start = build_int_cst_type (integer_type_node,
3031debfc3dSmrg value->hdata.intvl.int_start);
3041debfc3dSmrg tree steps = build_int_cst_type (unsigned_type_node,
3051debfc3dSmrg value->hdata.intvl.steps);
3061debfc3dSmrg
3071debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi,
3081debfc3dSmrg build_addr (ref),
3091debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
3101debfc3dSmrg val = prepare_instrumented_value (&gsi, value);
3111debfc3dSmrg call = gimple_build_call (tree_interval_profiler_fn, 4,
3121debfc3dSmrg ref_ptr, val, start, steps);
3131debfc3dSmrg gsi_insert_before (&gsi, call, GSI_NEW_STMT);
3141debfc3dSmrg }
3151debfc3dSmrg
3161debfc3dSmrg /* Output instructions as GIMPLE trees to increment the power of two histogram
3171debfc3dSmrg counter. VALUE is the expression whose value is profiled. TAG is the tag
318*8feb0f0bSmrg of the section for counters. */
3191debfc3dSmrg
3201debfc3dSmrg void
gimple_gen_pow2_profiler(histogram_value value,unsigned tag)321*8feb0f0bSmrg gimple_gen_pow2_profiler (histogram_value value, unsigned tag)
3221debfc3dSmrg {
3231debfc3dSmrg gimple *stmt = value->hvalue.stmt;
3241debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
325*8feb0f0bSmrg tree ref_ptr = tree_coverage_counter_addr (tag, 0);
3261debfc3dSmrg gcall *call;
3271debfc3dSmrg tree val;
3281debfc3dSmrg
3291debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
3301debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
3311debfc3dSmrg val = prepare_instrumented_value (&gsi, value);
3321debfc3dSmrg call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
3331debfc3dSmrg gsi_insert_before (&gsi, call, GSI_NEW_STMT);
3341debfc3dSmrg }
3351debfc3dSmrg
336*8feb0f0bSmrg /* Output instructions as GIMPLE trees for code to find the most N common
337*8feb0f0bSmrg values. VALUE is the expression whose value is profiled. TAG is the tag
338*8feb0f0bSmrg of the section for counters. */
3391debfc3dSmrg
3401debfc3dSmrg void
gimple_gen_topn_values_profiler(histogram_value value,unsigned tag)341*8feb0f0bSmrg gimple_gen_topn_values_profiler (histogram_value value, unsigned tag)
3421debfc3dSmrg {
3431debfc3dSmrg gimple *stmt = value->hvalue.stmt;
3441debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
345*8feb0f0bSmrg tree ref_ptr = tree_coverage_counter_addr (tag, 0);
3461debfc3dSmrg gcall *call;
3471debfc3dSmrg tree val;
3481debfc3dSmrg
3491debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
3501debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
3511debfc3dSmrg val = prepare_instrumented_value (&gsi, value);
352*8feb0f0bSmrg call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val);
3531debfc3dSmrg gsi_insert_before (&gsi, call, GSI_NEW_STMT);
3541debfc3dSmrg }
3551debfc3dSmrg
3561debfc3dSmrg
3571debfc3dSmrg /* Output instructions as GIMPLE trees for code to find the most
3581debfc3dSmrg common called function in indirect call.
3591debfc3dSmrg VALUE is the call expression whose indirect callee is profiled.
360*8feb0f0bSmrg TAG is the tag of the section for counters. */
3611debfc3dSmrg
3621debfc3dSmrg void
gimple_gen_ic_profiler(histogram_value value,unsigned tag)363*8feb0f0bSmrg gimple_gen_ic_profiler (histogram_value value, unsigned tag)
3641debfc3dSmrg {
3651debfc3dSmrg tree tmp1;
3661debfc3dSmrg gassign *stmt1, *stmt2, *stmt3;
3671debfc3dSmrg gimple *stmt = value->hvalue.stmt;
3681debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
369*8feb0f0bSmrg tree ref_ptr = tree_coverage_counter_addr (tag, 0);
3701debfc3dSmrg
3711debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
3721debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
3731debfc3dSmrg
3741debfc3dSmrg /* Insert code:
3751debfc3dSmrg
376c0a68be4Smrg stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
3771debfc3dSmrg stmt2: tmp1 = (void *) (indirect call argument value)
378c0a68be4Smrg stmt3: __gcov_indirect_call.callee = tmp1;
379a2dc1f3fSmrg
380a2dc1f3fSmrg Example:
381a2dc1f3fSmrg f_1 = foo;
382c0a68be4Smrg __gcov_indirect_call.counters = &__gcov4.main[0];
383a2dc1f3fSmrg PROF_9 = f_1;
384*8feb0f0bSmrg __gcov_indirect_call.callee = PROF_9;
385a2dc1f3fSmrg _4 = f_1 ();
3861debfc3dSmrg */
3871debfc3dSmrg
388c0a68be4Smrg tree gcov_type_ptr = build_pointer_type (get_gcov_type ());
389c0a68be4Smrg
390c0a68be4Smrg tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr,
391c0a68be4Smrg ic_tuple_var, ic_tuple_counters_field, NULL_TREE);
392c0a68be4Smrg
393c0a68be4Smrg stmt1 = gimple_build_assign (counter_ref, ref_ptr);
394c0a68be4Smrg tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
3951debfc3dSmrg stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
396c0a68be4Smrg tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
397c0a68be4Smrg ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
398c0a68be4Smrg stmt3 = gimple_build_assign (callee_ref, tmp1);
3991debfc3dSmrg
4001debfc3dSmrg gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
4011debfc3dSmrg gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
4021debfc3dSmrg gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
4031debfc3dSmrg }
4041debfc3dSmrg
4051debfc3dSmrg
4061debfc3dSmrg /* Output instructions as GIMPLE trees for code to find the most
4071debfc3dSmrg common called function in indirect call. Insert instructions at the
4081debfc3dSmrg beginning of every possible called function.
4091debfc3dSmrg */
4101debfc3dSmrg
4111debfc3dSmrg void
gimple_gen_ic_func_profiler(void)4121debfc3dSmrg gimple_gen_ic_func_profiler (void)
4131debfc3dSmrg {
4141debfc3dSmrg struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
4151debfc3dSmrg gcall *stmt1;
4161debfc3dSmrg tree tree_uid, cur_func, void0;
4171debfc3dSmrg
4181debfc3dSmrg if (c_node->only_called_directly_p ())
4191debfc3dSmrg return;
4201debfc3dSmrg
4211debfc3dSmrg gimple_init_gcov_profiler ();
4221debfc3dSmrg
423a2dc1f3fSmrg basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
424a2dc1f3fSmrg basic_block cond_bb = split_edge (single_succ_edge (entry));
425a2dc1f3fSmrg basic_block update_bb = split_edge (single_succ_edge (cond_bb));
426a2dc1f3fSmrg
427a2dc1f3fSmrg /* We need to do an extra split in order to not create an input
428a2dc1f3fSmrg for a possible PHI node. */
429a2dc1f3fSmrg split_edge (single_succ_edge (update_bb));
430a2dc1f3fSmrg
431a2dc1f3fSmrg edge true_edge = single_succ_edge (cond_bb);
432a2dc1f3fSmrg true_edge->flags = EDGE_TRUE_VALUE;
433a2dc1f3fSmrg
434a2dc1f3fSmrg profile_probability probability;
435a2dc1f3fSmrg if (DECL_VIRTUAL_P (current_function_decl))
436a2dc1f3fSmrg probability = profile_probability::very_likely ();
437a2dc1f3fSmrg else
438a2dc1f3fSmrg probability = profile_probability::unlikely ();
439a2dc1f3fSmrg
440a2dc1f3fSmrg true_edge->probability = probability;
441a2dc1f3fSmrg edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
442a2dc1f3fSmrg EDGE_FALSE_VALUE);
443a2dc1f3fSmrg e->probability = true_edge->probability.invert ();
444a2dc1f3fSmrg
4451debfc3dSmrg /* Insert code:
4461debfc3dSmrg
447*8feb0f0bSmrg if (__gcov_indirect_call.callee != NULL)
448c0a68be4Smrg __gcov_indirect_call_profiler_v3 (profile_id, ¤t_function_decl);
449a2dc1f3fSmrg
450c0a68be4Smrg The function __gcov_indirect_call_profiler_v3 is responsible for
451*8feb0f0bSmrg resetting __gcov_indirect_call.callee to NULL. */
452a2dc1f3fSmrg
453a2dc1f3fSmrg gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
454c0a68be4Smrg void0 = build_int_cst (ptr_type_node, 0);
455a2dc1f3fSmrg
456c0a68be4Smrg tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
457c0a68be4Smrg ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
458c0a68be4Smrg
459c0a68be4Smrg tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE,
460a2dc1f3fSmrg true, GSI_SAME_STMT);
461a2dc1f3fSmrg
462a2dc1f3fSmrg gcond *cond = gimple_build_cond (NE_EXPR, ref,
463a2dc1f3fSmrg void0, NULL, NULL);
464a2dc1f3fSmrg gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
465a2dc1f3fSmrg
466a2dc1f3fSmrg gsi = gsi_after_labels (update_bb);
4671debfc3dSmrg
4681debfc3dSmrg cur_func = force_gimple_operand_gsi (&gsi,
4691debfc3dSmrg build_addr (current_function_decl),
4701debfc3dSmrg true, NULL_TREE,
4711debfc3dSmrg true, GSI_SAME_STMT);
4721debfc3dSmrg tree_uid = build_int_cst
4731debfc3dSmrg (gcov_type_node,
4741debfc3dSmrg cgraph_node::get (current_function_decl)->profile_id);
4751debfc3dSmrg stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
4761debfc3dSmrg tree_uid, cur_func);
4771debfc3dSmrg gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
4781debfc3dSmrg }
4791debfc3dSmrg
4801debfc3dSmrg /* Output instructions as GIMPLE tree at the beginning for each function.
4811debfc3dSmrg TAG is the tag of the section for counters, BASE is offset of the
4821debfc3dSmrg counter position and GSI is the iterator we place the counter. */
4831debfc3dSmrg
4841debfc3dSmrg void
gimple_gen_time_profiler(unsigned tag)485*8feb0f0bSmrg gimple_gen_time_profiler (unsigned tag)
4861debfc3dSmrg {
4871debfc3dSmrg tree type = get_gcov_type ();
4881debfc3dSmrg basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
4891debfc3dSmrg basic_block cond_bb = split_edge (single_succ_edge (entry));
4901debfc3dSmrg basic_block update_bb = split_edge (single_succ_edge (cond_bb));
491a2dc1f3fSmrg
492a2dc1f3fSmrg /* We need to do an extra split in order to not create an input
493a2dc1f3fSmrg for a possible PHI node. */
4941debfc3dSmrg split_edge (single_succ_edge (update_bb));
4951debfc3dSmrg
4961debfc3dSmrg edge true_edge = single_succ_edge (cond_bb);
4971debfc3dSmrg true_edge->flags = EDGE_TRUE_VALUE;
498a2dc1f3fSmrg true_edge->probability = profile_probability::unlikely ();
4991debfc3dSmrg edge e
5001debfc3dSmrg = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
501a2dc1f3fSmrg e->probability = true_edge->probability.invert ();
5021debfc3dSmrg
5031debfc3dSmrg gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
504*8feb0f0bSmrg tree original_ref = tree_coverage_counter_ref (tag, 0);
5051debfc3dSmrg tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
5061debfc3dSmrg true, GSI_SAME_STMT);
5071debfc3dSmrg tree one = build_int_cst (type, 1);
5081debfc3dSmrg
5091debfc3dSmrg /* Emit: if (counters[0] != 0). */
5101debfc3dSmrg gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
5111debfc3dSmrg NULL, NULL);
5121debfc3dSmrg gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
5131debfc3dSmrg
5141debfc3dSmrg gsi = gsi_start_bb (update_bb);
5151debfc3dSmrg
5161debfc3dSmrg /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
5171debfc3dSmrg if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
5181debfc3dSmrg {
5191debfc3dSmrg tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
5201debfc3dSmrg "time_profiler_counter_ptr");
5211debfc3dSmrg tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
5221debfc3dSmrg tree_time_profiler_counter);
5231debfc3dSmrg gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
5241debfc3dSmrg gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
5251debfc3dSmrg tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
5261debfc3dSmrg ? BUILT_IN_ATOMIC_ADD_FETCH_8:
5271debfc3dSmrg BUILT_IN_ATOMIC_ADD_FETCH_4);
5281debfc3dSmrg gcall *stmt = gimple_build_call (f, 3, ptr, one,
5291debfc3dSmrg build_int_cst (integer_type_node,
5301debfc3dSmrg MEMMODEL_RELAXED));
5311debfc3dSmrg tree result_type = TREE_TYPE (TREE_TYPE (f));
5321debfc3dSmrg tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
5331debfc3dSmrg gimple_set_lhs (stmt, tmp);
5341debfc3dSmrg gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
5351debfc3dSmrg tmp = make_temp_ssa_name (type, NULL, "time_profile");
5361debfc3dSmrg assign = gimple_build_assign (tmp, NOP_EXPR,
5371debfc3dSmrg gimple_call_lhs (stmt));
5381debfc3dSmrg gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
5391debfc3dSmrg assign = gimple_build_assign (original_ref, tmp);
5401debfc3dSmrg gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
5411debfc3dSmrg }
5421debfc3dSmrg else
5431debfc3dSmrg {
5441debfc3dSmrg tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
5451debfc3dSmrg gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
5461debfc3dSmrg gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
5471debfc3dSmrg
5481debfc3dSmrg tmp = make_temp_ssa_name (type, NULL, "time_profile");
5491debfc3dSmrg assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
5501debfc3dSmrg one);
5511debfc3dSmrg gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
5521debfc3dSmrg assign = gimple_build_assign (original_ref, tmp);
5531debfc3dSmrg gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
5541debfc3dSmrg assign = gimple_build_assign (tree_time_profiler_counter, tmp);
5551debfc3dSmrg gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
5561debfc3dSmrg }
5571debfc3dSmrg }
5581debfc3dSmrg
5591debfc3dSmrg /* Output instructions as GIMPLE trees to increment the average histogram
5601debfc3dSmrg counter. VALUE is the expression whose value is profiled. TAG is the
5611debfc3dSmrg tag of the section for counters, BASE is offset of the counter position. */
5621debfc3dSmrg
5631debfc3dSmrg void
gimple_gen_average_profiler(histogram_value value,unsigned tag)564*8feb0f0bSmrg gimple_gen_average_profiler (histogram_value value, unsigned tag)
5651debfc3dSmrg {
5661debfc3dSmrg gimple *stmt = value->hvalue.stmt;
5671debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
568*8feb0f0bSmrg tree ref_ptr = tree_coverage_counter_addr (tag, 0);
5691debfc3dSmrg gcall *call;
5701debfc3dSmrg tree val;
5711debfc3dSmrg
5721debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
5731debfc3dSmrg true, NULL_TREE,
5741debfc3dSmrg true, GSI_SAME_STMT);
5751debfc3dSmrg val = prepare_instrumented_value (&gsi, value);
5761debfc3dSmrg call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
5771debfc3dSmrg gsi_insert_before (&gsi, call, GSI_NEW_STMT);
5781debfc3dSmrg }
5791debfc3dSmrg
5801debfc3dSmrg /* Output instructions as GIMPLE trees to increment the ior histogram
5811debfc3dSmrg counter. VALUE is the expression whose value is profiled. TAG is the
5821debfc3dSmrg tag of the section for counters, BASE is offset of the counter position. */
5831debfc3dSmrg
5841debfc3dSmrg void
gimple_gen_ior_profiler(histogram_value value,unsigned tag)585*8feb0f0bSmrg gimple_gen_ior_profiler (histogram_value value, unsigned tag)
5861debfc3dSmrg {
5871debfc3dSmrg gimple *stmt = value->hvalue.stmt;
5881debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
589*8feb0f0bSmrg tree ref_ptr = tree_coverage_counter_addr (tag, 0);
5901debfc3dSmrg gcall *call;
5911debfc3dSmrg tree val;
5921debfc3dSmrg
5931debfc3dSmrg ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
5941debfc3dSmrg true, NULL_TREE, true, GSI_SAME_STMT);
5951debfc3dSmrg val = prepare_instrumented_value (&gsi, value);
5961debfc3dSmrg call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
5971debfc3dSmrg gsi_insert_before (&gsi, call, GSI_NEW_STMT);
5981debfc3dSmrg }
5991debfc3dSmrg
600c0a68be4Smrg static vec<regex_t> profile_filter_files;
601c0a68be4Smrg static vec<regex_t> profile_exclude_files;
602c0a68be4Smrg
603c0a68be4Smrg /* Parse list of provided REGEX (separated with semi-collon) and
604c0a68be4Smrg create expressions (of type regex_t) and save them into V vector.
605c0a68be4Smrg If there is a regular expression parsing error, error message is
606c0a68be4Smrg printed for FLAG_NAME. */
607c0a68be4Smrg
608c0a68be4Smrg static void
parse_profile_filter(const char * regex,vec<regex_t> * v,const char * flag_name)609c0a68be4Smrg parse_profile_filter (const char *regex, vec<regex_t> *v,
610c0a68be4Smrg const char *flag_name)
611c0a68be4Smrg {
612c0a68be4Smrg v->create (4);
613c0a68be4Smrg if (regex != NULL)
614c0a68be4Smrg {
615c0a68be4Smrg char *str = xstrdup (regex);
616c0a68be4Smrg for (char *p = strtok (str, ";"); p != NULL; p = strtok (NULL, ";"))
617c0a68be4Smrg {
618c0a68be4Smrg regex_t r;
619c0a68be4Smrg if (regcomp (&r, p, REG_EXTENDED | REG_NOSUB) != 0)
620c0a68be4Smrg {
621c0a68be4Smrg error ("invalid regular expression %qs in %qs",
622c0a68be4Smrg p, flag_name);
623c0a68be4Smrg return;
624c0a68be4Smrg }
625c0a68be4Smrg
626c0a68be4Smrg v->safe_push (r);
627c0a68be4Smrg }
628c0a68be4Smrg }
629c0a68be4Smrg }
630c0a68be4Smrg
631c0a68be4Smrg /* Parse values of -fprofile-filter-files and -fprofile-exclude-files
632c0a68be4Smrg options. */
633c0a68be4Smrg
634c0a68be4Smrg static void
parse_profile_file_filtering()635c0a68be4Smrg parse_profile_file_filtering ()
636c0a68be4Smrg {
637c0a68be4Smrg parse_profile_filter (flag_profile_filter_files, &profile_filter_files,
638c0a68be4Smrg "-fprofile-filter-files");
639c0a68be4Smrg parse_profile_filter (flag_profile_exclude_files, &profile_exclude_files,
640c0a68be4Smrg "-fprofile-exclude-files");
641c0a68be4Smrg }
642c0a68be4Smrg
643c0a68be4Smrg /* Parse vectors of regular expressions. */
644c0a68be4Smrg
645c0a68be4Smrg static void
release_profile_file_filtering()646c0a68be4Smrg release_profile_file_filtering ()
647c0a68be4Smrg {
648c0a68be4Smrg profile_filter_files.release ();
649c0a68be4Smrg profile_exclude_files.release ();
650c0a68be4Smrg }
651c0a68be4Smrg
652c0a68be4Smrg /* Return true when FILENAME should be instrumented based on
653c0a68be4Smrg -fprofile-filter-files and -fprofile-exclude-files options. */
654c0a68be4Smrg
655c0a68be4Smrg static bool
include_source_file_for_profile(const char * filename)656c0a68be4Smrg include_source_file_for_profile (const char *filename)
657c0a68be4Smrg {
658c0a68be4Smrg /* First check whether file is included in flag_profile_exclude_files. */
659c0a68be4Smrg for (unsigned i = 0; i < profile_exclude_files.length (); i++)
660c0a68be4Smrg if (regexec (&profile_exclude_files[i],
661c0a68be4Smrg filename, 0, NULL, 0) == REG_NOERROR)
662c0a68be4Smrg return false;
663c0a68be4Smrg
664c0a68be4Smrg /* For non-empty flag_profile_filter_files include only files matching a
665c0a68be4Smrg regex in the flag. */
666c0a68be4Smrg if (profile_filter_files.is_empty ())
667c0a68be4Smrg return true;
668c0a68be4Smrg
669c0a68be4Smrg for (unsigned i = 0; i < profile_filter_files.length (); i++)
670c0a68be4Smrg if (regexec (&profile_filter_files[i], filename, 0, NULL, 0) == REG_NOERROR)
671c0a68be4Smrg return true;
672c0a68be4Smrg
673c0a68be4Smrg return false;
674c0a68be4Smrg }
675c0a68be4Smrg
6761debfc3dSmrg #ifndef HAVE_sync_compare_and_swapsi
6771debfc3dSmrg #define HAVE_sync_compare_and_swapsi 0
6781debfc3dSmrg #endif
6791debfc3dSmrg #ifndef HAVE_atomic_compare_and_swapsi
6801debfc3dSmrg #define HAVE_atomic_compare_and_swapsi 0
6811debfc3dSmrg #endif
6821debfc3dSmrg
6831debfc3dSmrg #ifndef HAVE_sync_compare_and_swapdi
6841debfc3dSmrg #define HAVE_sync_compare_and_swapdi 0
6851debfc3dSmrg #endif
6861debfc3dSmrg #ifndef HAVE_atomic_compare_and_swapdi
6871debfc3dSmrg #define HAVE_atomic_compare_and_swapdi 0
6881debfc3dSmrg #endif
6891debfc3dSmrg
6901debfc3dSmrg /* Profile all functions in the callgraph. */
6911debfc3dSmrg
6921debfc3dSmrg static unsigned int
tree_profiling(void)6931debfc3dSmrg tree_profiling (void)
6941debfc3dSmrg {
6951debfc3dSmrg struct cgraph_node *node;
6961debfc3dSmrg
6971debfc3dSmrg /* Verify whether we can utilize atomic update operations. */
6981debfc3dSmrg bool can_support_atomic = false;
6991debfc3dSmrg unsigned HOST_WIDE_INT gcov_type_size
7001debfc3dSmrg = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
7011debfc3dSmrg if (gcov_type_size == 4)
7021debfc3dSmrg can_support_atomic
7031debfc3dSmrg = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
7041debfc3dSmrg else if (gcov_type_size == 8)
7051debfc3dSmrg can_support_atomic
7061debfc3dSmrg = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
7071debfc3dSmrg
7081debfc3dSmrg if (flag_profile_update == PROFILE_UPDATE_ATOMIC
7091debfc3dSmrg && !can_support_atomic)
7101debfc3dSmrg {
7111debfc3dSmrg warning (0, "target does not support atomic profile update, "
7121debfc3dSmrg "single mode is selected");
7131debfc3dSmrg flag_profile_update = PROFILE_UPDATE_SINGLE;
7141debfc3dSmrg }
7151debfc3dSmrg else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
7161debfc3dSmrg flag_profile_update = can_support_atomic
7171debfc3dSmrg ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
7181debfc3dSmrg
7191debfc3dSmrg /* This is a small-ipa pass that gets called only once, from
7201debfc3dSmrg cgraphunit.c:ipa_passes(). */
7211debfc3dSmrg gcc_assert (symtab->state == IPA_SSA);
7221debfc3dSmrg
7231debfc3dSmrg init_node_map (true);
724c0a68be4Smrg parse_profile_file_filtering ();
7251debfc3dSmrg
7261debfc3dSmrg FOR_EACH_DEFINED_FUNCTION (node)
7271debfc3dSmrg {
728a2dc1f3fSmrg bool thunk = false;
729a2dc1f3fSmrg if (!gimple_has_body_p (node->decl) && !node->thunk.thunk_p)
7301debfc3dSmrg continue;
7311debfc3dSmrg
7321debfc3dSmrg /* Don't profile functions produced for builtin stuff. */
7331debfc3dSmrg if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
7341debfc3dSmrg continue;
7351debfc3dSmrg
7361debfc3dSmrg if (lookup_attribute ("no_profile_instrument_function",
7371debfc3dSmrg DECL_ATTRIBUTES (node->decl)))
7381debfc3dSmrg continue;
7391debfc3dSmrg /* Do not instrument extern inline functions when testing coverage.
7401debfc3dSmrg While this is not perfectly consistent (early inlined extern inlines
7411debfc3dSmrg will get acocunted), testsuite expects that. */
7421debfc3dSmrg if (DECL_EXTERNAL (node->decl)
7431debfc3dSmrg && flag_test_coverage)
7441debfc3dSmrg continue;
7451debfc3dSmrg
746c0a68be4Smrg const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl));
747c0a68be4Smrg if (!include_source_file_for_profile (file))
748c0a68be4Smrg continue;
749c0a68be4Smrg
750a2dc1f3fSmrg if (node->thunk.thunk_p)
751a2dc1f3fSmrg {
752a2dc1f3fSmrg /* We cannot expand variadic thunks to Gimple. */
753a2dc1f3fSmrg if (stdarg_p (TREE_TYPE (node->decl)))
754a2dc1f3fSmrg continue;
755a2dc1f3fSmrg thunk = true;
756a2dc1f3fSmrg /* When generate profile, expand thunk to gimple so it can be
757a2dc1f3fSmrg instrumented same way as other functions. */
758a2dc1f3fSmrg if (profile_arc_flag)
759a2dc1f3fSmrg node->expand_thunk (false, true);
760a2dc1f3fSmrg /* Read cgraph profile but keep function as thunk at profile-use
761a2dc1f3fSmrg time. */
762a2dc1f3fSmrg else
763a2dc1f3fSmrg {
764a2dc1f3fSmrg read_thunk_profile (node);
765a2dc1f3fSmrg continue;
766a2dc1f3fSmrg }
767a2dc1f3fSmrg }
768a2dc1f3fSmrg
7691debfc3dSmrg push_cfun (DECL_STRUCT_FUNCTION (node->decl));
7701debfc3dSmrg
771a2dc1f3fSmrg if (dump_file)
772a2dc1f3fSmrg dump_function_header (dump_file, cfun->decl, dump_flags);
773a2dc1f3fSmrg
7741debfc3dSmrg /* Local pure-const may imply need to fixup the cfg. */
775a2dc1f3fSmrg if (gimple_has_body_p (node->decl)
776a2dc1f3fSmrg && (execute_fixup_cfg () & TODO_cleanup_cfg))
7771debfc3dSmrg cleanup_tree_cfg ();
7781debfc3dSmrg
779a2dc1f3fSmrg branch_prob (thunk);
7801debfc3dSmrg
7811debfc3dSmrg if (! flag_branch_probabilities
7821debfc3dSmrg && flag_profile_values)
7831debfc3dSmrg gimple_gen_ic_func_profiler ();
7841debfc3dSmrg
7851debfc3dSmrg if (flag_branch_probabilities
786a2dc1f3fSmrg && !thunk
7871debfc3dSmrg && flag_profile_values
788*8feb0f0bSmrg && flag_value_profile_transformations
789*8feb0f0bSmrg && profile_status_for_fn (cfun) == PROFILE_READ)
7901debfc3dSmrg gimple_value_profile_transformations ();
7911debfc3dSmrg
7921debfc3dSmrg /* The above could hose dominator info. Currently there is
7931debfc3dSmrg none coming in, this is a safety valve. It should be
7941debfc3dSmrg easy to adjust it, if and when there is some. */
7951debfc3dSmrg free_dominance_info (CDI_DOMINATORS);
7961debfc3dSmrg free_dominance_info (CDI_POST_DOMINATORS);
7971debfc3dSmrg pop_cfun ();
7981debfc3dSmrg }
7991debfc3dSmrg
800c0a68be4Smrg release_profile_file_filtering ();
801c0a68be4Smrg
8021debfc3dSmrg /* Drop pure/const flags from instrumented functions. */
8031debfc3dSmrg if (profile_arc_flag || flag_test_coverage)
8041debfc3dSmrg FOR_EACH_DEFINED_FUNCTION (node)
8051debfc3dSmrg {
8061debfc3dSmrg if (!gimple_has_body_p (node->decl)
8071debfc3dSmrg || !(!node->clone_of
8081debfc3dSmrg || node->decl != node->clone_of->decl))
8091debfc3dSmrg continue;
8101debfc3dSmrg
8111debfc3dSmrg /* Don't profile functions produced for builtin stuff. */
8121debfc3dSmrg if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
8131debfc3dSmrg continue;
8141debfc3dSmrg
8151debfc3dSmrg node->set_const_flag (false, false);
8161debfc3dSmrg node->set_pure_flag (false, false);
8171debfc3dSmrg }
8181debfc3dSmrg
8191debfc3dSmrg /* Update call statements and rebuild the cgraph. */
8201debfc3dSmrg FOR_EACH_DEFINED_FUNCTION (node)
8211debfc3dSmrg {
8221debfc3dSmrg basic_block bb;
8231debfc3dSmrg
8241debfc3dSmrg if (!gimple_has_body_p (node->decl)
8251debfc3dSmrg || !(!node->clone_of
8261debfc3dSmrg || node->decl != node->clone_of->decl))
8271debfc3dSmrg continue;
8281debfc3dSmrg
8291debfc3dSmrg /* Don't profile functions produced for builtin stuff. */
8301debfc3dSmrg if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
8311debfc3dSmrg continue;
8321debfc3dSmrg
8331debfc3dSmrg push_cfun (DECL_STRUCT_FUNCTION (node->decl));
8341debfc3dSmrg
8351debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
8361debfc3dSmrg {
8371debfc3dSmrg gimple_stmt_iterator gsi;
8381debfc3dSmrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
8391debfc3dSmrg {
8401debfc3dSmrg gimple *stmt = gsi_stmt (gsi);
8411debfc3dSmrg if (is_gimple_call (stmt))
8421debfc3dSmrg update_stmt (stmt);
8431debfc3dSmrg }
8441debfc3dSmrg }
8451debfc3dSmrg
8461debfc3dSmrg /* re-merge split blocks. */
8471debfc3dSmrg cleanup_tree_cfg ();
8481debfc3dSmrg update_ssa (TODO_update_ssa);
8491debfc3dSmrg
8501debfc3dSmrg cgraph_edge::rebuild_edges ();
8511debfc3dSmrg
8521debfc3dSmrg pop_cfun ();
8531debfc3dSmrg }
8541debfc3dSmrg
8551debfc3dSmrg handle_missing_profiles ();
8561debfc3dSmrg
8571debfc3dSmrg del_node_map ();
8581debfc3dSmrg return 0;
8591debfc3dSmrg }
8601debfc3dSmrg
8611debfc3dSmrg namespace {
8621debfc3dSmrg
8631debfc3dSmrg const pass_data pass_data_ipa_tree_profile =
8641debfc3dSmrg {
8651debfc3dSmrg SIMPLE_IPA_PASS, /* type */
8661debfc3dSmrg "profile", /* name */
8671debfc3dSmrg OPTGROUP_NONE, /* optinfo_flags */
8681debfc3dSmrg TV_IPA_PROFILE, /* tv_id */
8691debfc3dSmrg 0, /* properties_required */
8701debfc3dSmrg 0, /* properties_provided */
8711debfc3dSmrg 0, /* properties_destroyed */
8721debfc3dSmrg 0, /* todo_flags_start */
8731debfc3dSmrg TODO_dump_symtab, /* todo_flags_finish */
8741debfc3dSmrg };
8751debfc3dSmrg
8761debfc3dSmrg class pass_ipa_tree_profile : public simple_ipa_opt_pass
8771debfc3dSmrg {
8781debfc3dSmrg public:
pass_ipa_tree_profile(gcc::context * ctxt)8791debfc3dSmrg pass_ipa_tree_profile (gcc::context *ctxt)
8801debfc3dSmrg : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
8811debfc3dSmrg {}
8821debfc3dSmrg
8831debfc3dSmrg /* opt_pass methods: */
8841debfc3dSmrg virtual bool gate (function *);
execute(function *)8851debfc3dSmrg virtual unsigned int execute (function *) { return tree_profiling (); }
8861debfc3dSmrg
8871debfc3dSmrg }; // class pass_ipa_tree_profile
8881debfc3dSmrg
8891debfc3dSmrg bool
gate(function *)8901debfc3dSmrg pass_ipa_tree_profile::gate (function *)
8911debfc3dSmrg {
8921debfc3dSmrg /* When profile instrumentation, use or test coverage shall be performed.
8931debfc3dSmrg But for AutoFDO, this there is no instrumentation, thus this pass is
894*8feb0f0bSmrg disabled. */
8951debfc3dSmrg return (!in_lto_p && !flag_auto_profile
8961debfc3dSmrg && (flag_branch_probabilities || flag_test_coverage
8971debfc3dSmrg || profile_arc_flag));
8981debfc3dSmrg }
8991debfc3dSmrg
9001debfc3dSmrg } // anon namespace
9011debfc3dSmrg
9021debfc3dSmrg simple_ipa_opt_pass *
make_pass_ipa_tree_profile(gcc::context * ctxt)9031debfc3dSmrg make_pass_ipa_tree_profile (gcc::context *ctxt)
9041debfc3dSmrg {
9051debfc3dSmrg return new pass_ipa_tree_profile (ctxt);
9061debfc3dSmrg }
9071debfc3dSmrg
9081debfc3dSmrg #include "gt-tree-profile.h"
909