2016-09-25 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / gcc / tree-profile.c
blob69b48e59be412a98c33699621432915b12b4c190
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990-2016 Free Software Foundation, Inc.
3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
4 based on some ideas from Dain Samples of UC Berkeley.
5 Further mangling by Bob Manson, Cygnus Support.
6 Converted to use trees by Dale Johannesen, Apple Computer.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 /* Generate basic block profile instrumentation and auxiliary files.
25 Tree-based version. See profile.c for overview. */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "backend.h"
31 #include "target.h"
32 #include "tree.h"
33 #include "gimple.h"
34 #include "cfghooks.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "cgraph.h"
38 #include "coverage.h"
39 #include "diagnostic-core.h"
40 #include "fold-const.h"
41 #include "varasm.h"
42 #include "tree-nested.h"
43 #include "gimplify.h"
44 #include "gimple-iterator.h"
45 #include "gimplify-me.h"
46 #include "tree-cfg.h"
47 #include "tree-into-ssa.h"
48 #include "value-prof.h"
49 #include "profile.h"
50 #include "tree-cfgcleanup.h"
51 #include "params.h"
53 static GTY(()) tree gcov_type_node;
54 static GTY(()) tree tree_interval_profiler_fn;
55 static GTY(()) tree tree_pow2_profiler_fn;
56 static GTY(()) tree tree_one_value_profiler_fn;
57 static GTY(()) tree tree_indirect_call_profiler_fn;
58 static GTY(()) tree tree_time_profiler_fn;
59 static GTY(()) tree tree_average_profiler_fn;
60 static GTY(()) tree tree_ior_profiler_fn;
63 static GTY(()) tree ic_void_ptr_var;
64 static GTY(()) tree ic_gcov_type_ptr_var;
65 static GTY(()) tree ptr_void;
67 /* Do initialization work for the edge profiler. */
69 /* Add code:
70 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
71 __thread void* __gcov_indirect_call_callee; // actual callee address
72 __thread int __gcov_function_counter; // time profiler function counter
74 static void
75 init_ic_make_global_vars (void)
77 tree gcov_type_ptr;
79 ptr_void = build_pointer_type (void_type_node);
81 ic_void_ptr_var
82 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
83 get_identifier (
84 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
85 "__gcov_indirect_call_topn_callee" :
86 "__gcov_indirect_call_callee")),
87 ptr_void);
88 TREE_PUBLIC (ic_void_ptr_var) = 1;
89 DECL_EXTERNAL (ic_void_ptr_var) = 1;
90 TREE_STATIC (ic_void_ptr_var) = 1;
91 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
92 DECL_INITIAL (ic_void_ptr_var) = NULL;
93 if (targetm.have_tls)
94 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
96 varpool_node::finalize_decl (ic_void_ptr_var);
98 gcov_type_ptr = build_pointer_type (get_gcov_type ());
100 ic_gcov_type_ptr_var
101 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
102 get_identifier (
103 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
104 "__gcov_indirect_call_topn_counters" :
105 "__gcov_indirect_call_counters")),
106 gcov_type_ptr);
107 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
108 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
109 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
110 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
111 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
112 if (targetm.have_tls)
113 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
115 varpool_node::finalize_decl (ic_gcov_type_ptr_var);
118 /* Create the type and function decls for the interface with gcov. */
120 void
121 gimple_init_edge_profiler (void)
123 tree interval_profiler_fn_type;
124 tree pow2_profiler_fn_type;
125 tree one_value_profiler_fn_type;
126 tree gcov_type_ptr;
127 tree ic_profiler_fn_type;
128 tree average_profiler_fn_type;
129 tree time_profiler_fn_type;
130 const char *profiler_fn_name;
131 const char *fn_name;
133 if (!gcov_type_node)
135 const char *fn_suffix
136 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
138 gcov_type_node = get_gcov_type ();
139 gcov_type_ptr = build_pointer_type (gcov_type_node);
141 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
142 interval_profiler_fn_type
143 = build_function_type_list (void_type_node,
144 gcov_type_ptr, gcov_type_node,
145 integer_type_node,
146 unsigned_type_node, NULL_TREE);
147 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
148 tree_interval_profiler_fn = build_fn_decl (fn_name,
149 interval_profiler_fn_type);
150 free (CONST_CAST (char *, fn_name));
151 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
152 DECL_ATTRIBUTES (tree_interval_profiler_fn)
153 = tree_cons (get_identifier ("leaf"), NULL,
154 DECL_ATTRIBUTES (tree_interval_profiler_fn));
156 /* void (*) (gcov_type *, gcov_type) */
157 pow2_profiler_fn_type
158 = build_function_type_list (void_type_node,
159 gcov_type_ptr, gcov_type_node,
160 NULL_TREE);
161 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
162 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
163 free (CONST_CAST (char *, fn_name));
164 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
165 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
166 = tree_cons (get_identifier ("leaf"), NULL,
167 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
169 /* void (*) (gcov_type *, gcov_type) */
170 one_value_profiler_fn_type
171 = build_function_type_list (void_type_node,
172 gcov_type_ptr, gcov_type_node,
173 NULL_TREE);
174 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
175 tree_one_value_profiler_fn = build_fn_decl (fn_name,
176 one_value_profiler_fn_type);
177 free (CONST_CAST (char *, fn_name));
178 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
179 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
180 = tree_cons (get_identifier ("leaf"), NULL,
181 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
183 init_ic_make_global_vars ();
185 /* void (*) (gcov_type, void *) */
186 ic_profiler_fn_type
187 = build_function_type_list (void_type_node,
188 gcov_type_node,
189 ptr_void,
190 NULL_TREE);
191 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
192 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
193 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
195 tree_indirect_call_profiler_fn
196 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
198 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
199 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
200 = tree_cons (get_identifier ("leaf"), NULL,
201 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
203 /* void (*) (gcov_type *, gcov_type, void *) */
204 time_profiler_fn_type
205 = build_function_type_list (void_type_node,
206 gcov_type_ptr, NULL_TREE);
207 fn_name = concat ("__gcov_time_profiler", fn_suffix, NULL);
208 tree_time_profiler_fn = build_fn_decl (fn_name, time_profiler_fn_type);
209 free (CONST_CAST (char *, fn_name));
210 TREE_NOTHROW (tree_time_profiler_fn) = 1;
211 DECL_ATTRIBUTES (tree_time_profiler_fn)
212 = tree_cons (get_identifier ("leaf"), NULL,
213 DECL_ATTRIBUTES (tree_time_profiler_fn));
215 /* void (*) (gcov_type *, gcov_type) */
216 average_profiler_fn_type
217 = build_function_type_list (void_type_node,
218 gcov_type_ptr, gcov_type_node, NULL_TREE);
219 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
220 tree_average_profiler_fn = build_fn_decl (fn_name,
221 average_profiler_fn_type);
222 free (CONST_CAST (char *, fn_name));
223 TREE_NOTHROW (tree_average_profiler_fn) = 1;
224 DECL_ATTRIBUTES (tree_average_profiler_fn)
225 = tree_cons (get_identifier ("leaf"), NULL,
226 DECL_ATTRIBUTES (tree_average_profiler_fn));
227 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
228 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
229 free (CONST_CAST (char *, fn_name));
230 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
231 DECL_ATTRIBUTES (tree_ior_profiler_fn)
232 = tree_cons (get_identifier ("leaf"), NULL,
233 DECL_ATTRIBUTES (tree_ior_profiler_fn));
235 /* LTO streamer needs assembler names. Because we create these decls
236 late, we need to initialize them by hand. */
237 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
238 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
239 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
240 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
241 DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
242 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
243 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
247 /* Output instructions as GIMPLE trees to increment the edge
248 execution count, and insert them on E. We rely on
249 gsi_insert_on_edge to preserve the order. */
251 void
252 gimple_gen_edge_profiler (int edgeno, edge e)
254 tree one;
256 one = build_int_cst (gcov_type_node, 1);
258 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
260 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
261 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
262 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
263 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
264 BUILT_IN_ATOMIC_FETCH_ADD_4);
265 gcall *stmt = gimple_build_call (f, 3, addr, one,
266 build_int_cst (integer_type_node,
267 MEMMODEL_RELAXED));
268 gsi_insert_on_edge (e, stmt);
270 else
272 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
273 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
274 NULL, "PROF_edge_counter");
275 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
276 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
277 NULL, "PROF_edge_counter");
278 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
279 gimple_assign_lhs (stmt1), one);
280 gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
281 gimple_assign_lhs (stmt2));
282 gsi_insert_on_edge (e, stmt1);
283 gsi_insert_on_edge (e, stmt2);
284 gsi_insert_on_edge (e, stmt3);
288 /* Emits code to get VALUE to instrument at GSI, and returns the
289 variable containing the value. */
291 static tree
292 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
294 tree val = value->hvalue.value;
295 if (POINTER_TYPE_P (TREE_TYPE (val)))
296 val = fold_convert (build_nonstandard_integer_type
297 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
298 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
299 true, NULL_TREE, true, GSI_SAME_STMT);
302 /* Output instructions as GIMPLE trees to increment the interval histogram
303 counter. VALUE is the expression whose value is profiled. TAG is the
304 tag of the section for counters, BASE is offset of the counter position. */
306 void
307 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
309 gimple *stmt = value->hvalue.stmt;
310 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
311 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
312 gcall *call;
313 tree val;
314 tree start = build_int_cst_type (integer_type_node,
315 value->hdata.intvl.int_start);
316 tree steps = build_int_cst_type (unsigned_type_node,
317 value->hdata.intvl.steps);
319 ref_ptr = force_gimple_operand_gsi (&gsi,
320 build_addr (ref),
321 true, NULL_TREE, true, GSI_SAME_STMT);
322 val = prepare_instrumented_value (&gsi, value);
323 call = gimple_build_call (tree_interval_profiler_fn, 4,
324 ref_ptr, val, start, steps);
325 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
328 /* Output instructions as GIMPLE trees to increment the power of two histogram
329 counter. VALUE is the expression whose value is profiled. TAG is the tag
330 of the section for counters, BASE is offset of the counter position. */
332 void
333 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
335 gimple *stmt = value->hvalue.stmt;
336 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
337 tree ref_ptr = tree_coverage_counter_addr (tag, base);
338 gcall *call;
339 tree val;
341 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
342 true, NULL_TREE, true, GSI_SAME_STMT);
343 val = prepare_instrumented_value (&gsi, value);
344 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
345 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
348 /* Output instructions as GIMPLE trees for code to find the most common value.
349 VALUE is the expression whose value is profiled. TAG is the tag of the
350 section for counters, BASE is offset of the counter position. */
352 void
353 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
355 gimple *stmt = value->hvalue.stmt;
356 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
357 tree ref_ptr = tree_coverage_counter_addr (tag, base);
358 gcall *call;
359 tree val;
361 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
362 true, NULL_TREE, true, GSI_SAME_STMT);
363 val = prepare_instrumented_value (&gsi, value);
364 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
365 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
369 /* Output instructions as GIMPLE trees for code to find the most
370 common called function in indirect call.
371 VALUE is the call expression whose indirect callee is profiled.
372 TAG is the tag of the section for counters, BASE is offset of the
373 counter position. */
375 void
376 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
378 tree tmp1;
379 gassign *stmt1, *stmt2, *stmt3;
380 gimple *stmt = value->hvalue.stmt;
381 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
382 tree ref_ptr = tree_coverage_counter_addr (tag, base);
384 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
385 tag == GCOV_COUNTER_V_INDIR) ||
386 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
387 tag == GCOV_COUNTER_ICALL_TOPNV))
388 return;
390 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
391 true, NULL_TREE, true, GSI_SAME_STMT);
393 /* Insert code:
395 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
396 stmt2: tmp1 = (void *) (indirect call argument value)
397 stmt3: __gcov_indirect_call_callee = tmp1;
400 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
401 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
402 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
403 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
405 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
406 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
407 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
411 /* Output instructions as GIMPLE trees for code to find the most
412 common called function in indirect call. Insert instructions at the
413 beginning of every possible called function.
416 void
417 gimple_gen_ic_func_profiler (void)
419 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
420 gimple_stmt_iterator gsi;
421 gcall *stmt1;
422 gassign *stmt2;
423 tree tree_uid, cur_func, void0;
425 if (c_node->only_called_directly_p ())
426 return;
428 gimple_init_edge_profiler ();
430 /* Insert code:
432 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
433 &current_function_decl)
435 gsi = gsi_after_labels (split_edge (single_succ_edge
436 (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
438 cur_func = force_gimple_operand_gsi (&gsi,
439 build_addr (current_function_decl),
440 true, NULL_TREE,
441 true, GSI_SAME_STMT);
442 tree_uid = build_int_cst
443 (gcov_type_node,
444 cgraph_node::get (current_function_decl)->profile_id);
445 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
446 tree_uid, cur_func);
447 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
449 /* Set __gcov_indirect_call_callee to 0,
450 so that calls from other modules won't get misattributed
451 to the last caller of the current callee. */
452 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
453 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
454 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
457 /* Output instructions as GIMPLE tree at the beginning for each function.
458 TAG is the tag of the section for counters, BASE is offset of the
459 counter position and GSI is the iterator we place the counter. */
461 void
462 gimple_gen_time_profiler (unsigned tag, unsigned base,
463 gimple_stmt_iterator &gsi)
465 tree ref_ptr = tree_coverage_counter_addr (tag, base);
466 gcall *call;
468 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
469 true, NULL_TREE, true, GSI_SAME_STMT);
470 call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
471 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
474 /* Output instructions as GIMPLE trees for code to find the most common value
475 of a difference between two evaluations of an expression.
476 VALUE is the expression whose value is profiled. TAG is the tag of the
477 section for counters, BASE is offset of the counter position. */
479 void
480 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
481 unsigned tag ATTRIBUTE_UNUSED,
482 unsigned base ATTRIBUTE_UNUSED)
484 /* FIXME implement this. */
485 if (flag_checking)
486 internal_error ("unimplemented functionality");
487 gcc_unreachable ();
490 /* Output instructions as GIMPLE trees to increment the average histogram
491 counter. VALUE is the expression whose value is profiled. TAG is the
492 tag of the section for counters, BASE is offset of the counter position. */
494 void
495 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
497 gimple *stmt = value->hvalue.stmt;
498 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
499 tree ref_ptr = tree_coverage_counter_addr (tag, base);
500 gcall *call;
501 tree val;
503 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
504 true, NULL_TREE,
505 true, GSI_SAME_STMT);
506 val = prepare_instrumented_value (&gsi, value);
507 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
508 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
511 /* Output instructions as GIMPLE trees to increment the ior histogram
512 counter. VALUE is the expression whose value is profiled. TAG is the
513 tag of the section for counters, BASE is offset of the counter position. */
515 void
516 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
518 gimple *stmt = value->hvalue.stmt;
519 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
520 tree ref_ptr = tree_coverage_counter_addr (tag, base);
521 gcall *call;
522 tree val;
524 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
525 true, NULL_TREE, true, GSI_SAME_STMT);
526 val = prepare_instrumented_value (&gsi, value);
527 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
528 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
531 #ifndef HAVE_sync_compare_and_swapsi
532 #define HAVE_sync_compare_and_swapsi 0
533 #endif
534 #ifndef HAVE_atomic_compare_and_swapsi
535 #define HAVE_atomic_compare_and_swapsi 0
536 #endif
538 #ifndef HAVE_sync_compare_and_swapdi
539 #define HAVE_sync_compare_and_swapdi 0
540 #endif
541 #ifndef HAVE_atomic_compare_and_swapdi
542 #define HAVE_atomic_compare_and_swapdi 0
543 #endif
545 /* Profile all functions in the callgraph. */
547 static unsigned int
548 tree_profiling (void)
550 struct cgraph_node *node;
552 /* Verify whether we can utilize atomic update operations. */
553 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
555 bool can_support = false;
556 unsigned HOST_WIDE_INT gcov_type_size
557 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
558 if (gcov_type_size == 4)
559 can_support
560 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
561 else if (gcov_type_size == 8)
562 can_support
563 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
565 if (!can_support)
567 warning (0, "target does not support atomic profile update, "
568 "single mode is selected");
569 flag_profile_update = PROFILE_UPDATE_SINGLE;
573 /* This is a small-ipa pass that gets called only once, from
574 cgraphunit.c:ipa_passes(). */
575 gcc_assert (symtab->state == IPA_SSA);
577 init_node_map (true);
579 FOR_EACH_DEFINED_FUNCTION (node)
581 if (!gimple_has_body_p (node->decl))
582 continue;
584 /* Don't profile functions produced for builtin stuff. */
585 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
586 continue;
588 if (lookup_attribute ("no_profile_instrument_function",
589 DECL_ATTRIBUTES (node->decl)))
590 continue;
591 /* Do not instrument extern inline functions when testing coverage.
592 While this is not perfectly consistent (early inlined extern inlines
593 will get acocunted), testsuite expects that. */
594 if (DECL_EXTERNAL (node->decl)
595 && flag_test_coverage)
596 continue;
598 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
600 /* Local pure-const may imply need to fixup the cfg. */
601 if (execute_fixup_cfg () & TODO_cleanup_cfg)
602 cleanup_tree_cfg ();
604 branch_prob ();
606 if (! flag_branch_probabilities
607 && flag_profile_values)
608 gimple_gen_ic_func_profiler ();
610 if (flag_branch_probabilities
611 && flag_profile_values
612 && flag_value_profile_transformations)
613 gimple_value_profile_transformations ();
615 /* The above could hose dominator info. Currently there is
616 none coming in, this is a safety valve. It should be
617 easy to adjust it, if and when there is some. */
618 free_dominance_info (CDI_DOMINATORS);
619 free_dominance_info (CDI_POST_DOMINATORS);
620 pop_cfun ();
623 /* Drop pure/const flags from instrumented functions. */
624 if (profile_arc_flag || flag_test_coverage)
625 FOR_EACH_DEFINED_FUNCTION (node)
627 if (!gimple_has_body_p (node->decl)
628 || !(!node->clone_of
629 || node->decl != node->clone_of->decl))
630 continue;
632 /* Don't profile functions produced for builtin stuff. */
633 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
634 continue;
636 node->set_const_flag (false, false);
637 node->set_pure_flag (false, false);
640 /* Update call statements and rebuild the cgraph. */
641 FOR_EACH_DEFINED_FUNCTION (node)
643 basic_block bb;
645 if (!gimple_has_body_p (node->decl)
646 || !(!node->clone_of
647 || node->decl != node->clone_of->decl))
648 continue;
650 /* Don't profile functions produced for builtin stuff. */
651 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
652 continue;
654 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
656 FOR_EACH_BB_FN (bb, cfun)
658 gimple_stmt_iterator gsi;
659 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
661 gimple *stmt = gsi_stmt (gsi);
662 if (is_gimple_call (stmt))
663 update_stmt (stmt);
667 /* re-merge split blocks. */
668 cleanup_tree_cfg ();
669 update_ssa (TODO_update_ssa);
671 cgraph_edge::rebuild_edges ();
673 pop_cfun ();
676 handle_missing_profiles ();
678 del_node_map ();
679 return 0;
682 namespace {
684 const pass_data pass_data_ipa_tree_profile =
686 SIMPLE_IPA_PASS, /* type */
687 "profile", /* name */
688 OPTGROUP_NONE, /* optinfo_flags */
689 TV_IPA_PROFILE, /* tv_id */
690 0, /* properties_required */
691 0, /* properties_provided */
692 0, /* properties_destroyed */
693 0, /* todo_flags_start */
694 TODO_dump_symtab, /* todo_flags_finish */
697 class pass_ipa_tree_profile : public simple_ipa_opt_pass
699 public:
700 pass_ipa_tree_profile (gcc::context *ctxt)
701 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
704 /* opt_pass methods: */
705 virtual bool gate (function *);
706 virtual unsigned int execute (function *) { return tree_profiling (); }
708 }; // class pass_ipa_tree_profile
710 bool
711 pass_ipa_tree_profile::gate (function *)
713 /* When profile instrumentation, use or test coverage shall be performed.
714 But for AutoFDO, this there is no instrumentation, thus this pass is
715 diabled. */
716 return (!in_lto_p && !flag_auto_profile
717 && (flag_branch_probabilities || flag_test_coverage
718 || profile_arc_flag));
721 } // anon namespace
723 simple_ipa_opt_pass *
724 make_pass_ipa_tree_profile (gcc::context *ctxt)
726 return new pass_ipa_tree_profile (ctxt);
729 #include "gt-tree-profile.h"