gcc/ada/
[official-gcc.git] / gcc / tree-profile.c
blobe22e29449c9aaa50e278bcadf9c74af1d03e0797
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990-2015 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 "tm.h"
31 #include "flags.h"
32 #include "hard-reg-set.h"
33 #include "function.h"
34 #include "predict.h"
35 #include "dominance.h"
36 #include "cfg.h"
37 #include "basic-block.h"
38 #include "diagnostic-core.h"
39 #include "coverage.h"
40 #include "alias.h"
41 #include "symtab.h"
42 #include "tree.h"
43 #include "fold-const.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-expr.h"
47 #include "gimple.h"
48 #include "varasm.h"
49 #include "tree-nested.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-ssa.h"
54 #include "plugin-api.h"
55 #include "ipa-ref.h"
56 #include "cgraph.h"
57 #include "tree-cfg.h"
58 #include "stringpool.h"
59 #include "tree-ssanames.h"
60 #include "tree-into-ssa.h"
61 #include "tree-pass.h"
62 #include "value-prof.h"
63 #include "profile.h"
64 #include "target.h"
65 #include "tree-cfgcleanup.h"
66 #include "tree-nested.h"
67 #include "params.h"
69 static GTY(()) tree gcov_type_node;
70 static GTY(()) tree tree_interval_profiler_fn;
71 static GTY(()) tree tree_pow2_profiler_fn;
72 static GTY(()) tree tree_one_value_profiler_fn;
73 static GTY(()) tree tree_indirect_call_profiler_fn;
74 static GTY(()) tree tree_time_profiler_fn;
75 static GTY(()) tree tree_average_profiler_fn;
76 static GTY(()) tree tree_ior_profiler_fn;
79 static GTY(()) tree ic_void_ptr_var;
80 static GTY(()) tree ic_gcov_type_ptr_var;
81 static GTY(()) tree ptr_void;
83 /* Do initialization work for the edge profiler. */
85 /* Add code:
86 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
87 __thread void* __gcov_indirect_call_callee; // actual callee address
88 __thread int __gcov_function_counter; // time profiler function counter
90 static void
91 init_ic_make_global_vars (void)
93 tree gcov_type_ptr;
95 ptr_void = build_pointer_type (void_type_node);
97 ic_void_ptr_var
98 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
99 get_identifier (
100 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
101 "__gcov_indirect_call_topn_callee" :
102 "__gcov_indirect_call_callee")),
103 ptr_void);
104 TREE_PUBLIC (ic_void_ptr_var) = 1;
105 DECL_EXTERNAL (ic_void_ptr_var) = 1;
106 TREE_STATIC (ic_void_ptr_var) = 1;
107 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
108 DECL_INITIAL (ic_void_ptr_var) = NULL;
109 if (targetm.have_tls)
110 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
112 varpool_node::finalize_decl (ic_void_ptr_var);
114 gcov_type_ptr = build_pointer_type (get_gcov_type ());
116 ic_gcov_type_ptr_var
117 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
118 get_identifier (
119 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
120 "__gcov_indirect_call_topn_counters" :
121 "__gcov_indirect_call_counters")),
122 gcov_type_ptr);
123 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
124 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
125 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
126 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
127 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
128 if (targetm.have_tls)
129 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
131 varpool_node::finalize_decl (ic_gcov_type_ptr_var);
134 /* Create the type and function decls for the interface with gcov. */
136 void
137 gimple_init_edge_profiler (void)
139 tree interval_profiler_fn_type;
140 tree pow2_profiler_fn_type;
141 tree one_value_profiler_fn_type;
142 tree gcov_type_ptr;
143 tree ic_profiler_fn_type;
144 tree average_profiler_fn_type;
145 tree time_profiler_fn_type;
147 if (!gcov_type_node)
149 gcov_type_node = get_gcov_type ();
150 gcov_type_ptr = build_pointer_type (gcov_type_node);
152 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
153 interval_profiler_fn_type
154 = build_function_type_list (void_type_node,
155 gcov_type_ptr, gcov_type_node,
156 integer_type_node,
157 unsigned_type_node, NULL_TREE);
158 tree_interval_profiler_fn
159 = build_fn_decl ("__gcov_interval_profiler",
160 interval_profiler_fn_type);
161 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
162 DECL_ATTRIBUTES (tree_interval_profiler_fn)
163 = tree_cons (get_identifier ("leaf"), NULL,
164 DECL_ATTRIBUTES (tree_interval_profiler_fn));
166 /* void (*) (gcov_type *, gcov_type) */
167 pow2_profiler_fn_type
168 = build_function_type_list (void_type_node,
169 gcov_type_ptr, gcov_type_node,
170 NULL_TREE);
171 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
172 pow2_profiler_fn_type);
173 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
174 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
175 = tree_cons (get_identifier ("leaf"), NULL,
176 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
178 /* void (*) (gcov_type *, gcov_type) */
179 one_value_profiler_fn_type
180 = build_function_type_list (void_type_node,
181 gcov_type_ptr, gcov_type_node,
182 NULL_TREE);
183 tree_one_value_profiler_fn
184 = build_fn_decl ("__gcov_one_value_profiler",
185 one_value_profiler_fn_type);
186 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
187 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
188 = tree_cons (get_identifier ("leaf"), NULL,
189 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
191 init_ic_make_global_vars ();
193 /* void (*) (gcov_type, void *) */
194 ic_profiler_fn_type
195 = build_function_type_list (void_type_node,
196 gcov_type_node,
197 ptr_void,
198 NULL_TREE);
199 tree_indirect_call_profiler_fn
200 = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
201 "__gcov_indirect_call_topn_profiler":
202 "__gcov_indirect_call_profiler_v2"),
203 ic_profiler_fn_type);
205 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
206 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
207 = tree_cons (get_identifier ("leaf"), NULL,
208 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
210 /* void (*) (gcov_type *, gcov_type, void *) */
211 time_profiler_fn_type
212 = build_function_type_list (void_type_node,
213 gcov_type_ptr, NULL_TREE);
214 tree_time_profiler_fn
215 = build_fn_decl ("__gcov_time_profiler",
216 time_profiler_fn_type);
217 TREE_NOTHROW (tree_time_profiler_fn) = 1;
218 DECL_ATTRIBUTES (tree_time_profiler_fn)
219 = tree_cons (get_identifier ("leaf"), NULL,
220 DECL_ATTRIBUTES (tree_time_profiler_fn));
222 /* void (*) (gcov_type *, gcov_type) */
223 average_profiler_fn_type
224 = build_function_type_list (void_type_node,
225 gcov_type_ptr, gcov_type_node, NULL_TREE);
226 tree_average_profiler_fn
227 = build_fn_decl ("__gcov_average_profiler",
228 average_profiler_fn_type);
229 TREE_NOTHROW (tree_average_profiler_fn) = 1;
230 DECL_ATTRIBUTES (tree_average_profiler_fn)
231 = tree_cons (get_identifier ("leaf"), NULL,
232 DECL_ATTRIBUTES (tree_average_profiler_fn));
233 tree_ior_profiler_fn
234 = build_fn_decl ("__gcov_ior_profiler",
235 average_profiler_fn_type);
236 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
237 DECL_ATTRIBUTES (tree_ior_profiler_fn)
238 = tree_cons (get_identifier ("leaf"), NULL,
239 DECL_ATTRIBUTES (tree_ior_profiler_fn));
241 /* LTO streamer needs assembler names. Because we create these decls
242 late, we need to initialize them by hand. */
243 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
244 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
245 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
246 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
247 DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
248 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
249 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
253 /* Output instructions as GIMPLE trees to increment the edge
254 execution count, and insert them on E. We rely on
255 gsi_insert_on_edge to preserve the order. */
257 void
258 gimple_gen_edge_profiler (int edgeno, edge e)
260 tree ref, one, gcov_type_tmp_var;
261 gassign *stmt1, *stmt2, *stmt3;
263 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
264 one = build_int_cst (gcov_type_node, 1);
265 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
266 NULL, "PROF_edge_counter");
267 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
268 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
269 NULL, "PROF_edge_counter");
270 stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
271 gimple_assign_lhs (stmt1), one);
272 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
273 gsi_insert_on_edge (e, stmt1);
274 gsi_insert_on_edge (e, stmt2);
275 gsi_insert_on_edge (e, stmt3);
278 /* Emits code to get VALUE to instrument at GSI, and returns the
279 variable containing the value. */
281 static tree
282 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
284 tree val = value->hvalue.value;
285 if (POINTER_TYPE_P (TREE_TYPE (val)))
286 val = fold_convert (build_nonstandard_integer_type
287 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
288 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
289 true, NULL_TREE, true, GSI_SAME_STMT);
292 /* Output instructions as GIMPLE trees to increment the interval histogram
293 counter. VALUE is the expression whose value is profiled. TAG is the
294 tag of the section for counters, BASE is offset of the counter position. */
296 void
297 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
299 gimple stmt = value->hvalue.stmt;
300 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
301 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
302 gcall *call;
303 tree val;
304 tree start = build_int_cst_type (integer_type_node,
305 value->hdata.intvl.int_start);
306 tree steps = build_int_cst_type (unsigned_type_node,
307 value->hdata.intvl.steps);
309 ref_ptr = force_gimple_operand_gsi (&gsi,
310 build_addr (ref, current_function_decl),
311 true, NULL_TREE, true, GSI_SAME_STMT);
312 val = prepare_instrumented_value (&gsi, value);
313 call = gimple_build_call (tree_interval_profiler_fn, 4,
314 ref_ptr, val, start, steps);
315 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
318 /* Output instructions as GIMPLE trees to increment the power of two histogram
319 counter. VALUE is the expression whose value is profiled. TAG is the tag
320 of the section for counters, BASE is offset of the counter position. */
322 void
323 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
325 gimple stmt = value->hvalue.stmt;
326 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
327 tree ref_ptr = tree_coverage_counter_addr (tag, base);
328 gcall *call;
329 tree val;
331 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
332 true, NULL_TREE, true, GSI_SAME_STMT);
333 val = prepare_instrumented_value (&gsi, value);
334 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
335 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
338 /* Output instructions as GIMPLE trees for code to find the most common value.
339 VALUE is the expression whose value is profiled. TAG is the tag of the
340 section for counters, BASE is offset of the counter position. */
342 void
343 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
345 gimple stmt = value->hvalue.stmt;
346 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
347 tree ref_ptr = tree_coverage_counter_addr (tag, base);
348 gcall *call;
349 tree val;
351 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
352 true, NULL_TREE, true, GSI_SAME_STMT);
353 val = prepare_instrumented_value (&gsi, value);
354 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
355 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
359 /* Output instructions as GIMPLE trees for code to find the most
360 common called function in indirect call.
361 VALUE is the call expression whose indirect callee is profiled.
362 TAG is the tag of the section for counters, BASE is offset of the
363 counter position. */
365 void
366 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
368 tree tmp1;
369 gassign *stmt1, *stmt2, *stmt3;
370 gimple stmt = value->hvalue.stmt;
371 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
372 tree ref_ptr = tree_coverage_counter_addr (tag, base);
374 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
375 tag == GCOV_COUNTER_V_INDIR) ||
376 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
377 tag == GCOV_COUNTER_ICALL_TOPNV))
378 return;
380 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
381 true, NULL_TREE, true, GSI_SAME_STMT);
383 /* Insert code:
385 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
386 stmt2: tmp1 = (void *) (indirect call argument value)
387 stmt3: __gcov_indirect_call_callee = tmp1;
390 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
391 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
392 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
393 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
395 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
396 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
397 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
401 /* Output instructions as GIMPLE trees for code to find the most
402 common called function in indirect call. Insert instructions at the
403 beginning of every possible called function.
406 void
407 gimple_gen_ic_func_profiler (void)
409 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
410 gimple_stmt_iterator gsi;
411 gcall *stmt1;
412 gassign *stmt2;
413 tree tree_uid, cur_func, void0;
415 if (c_node->only_called_directly_p ())
416 return;
418 gimple_init_edge_profiler ();
420 /* Insert code:
422 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
423 &current_function_decl)
425 gsi = gsi_after_labels (split_edge (single_succ_edge
426 (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
428 cur_func = force_gimple_operand_gsi (&gsi,
429 build_addr (current_function_decl,
430 current_function_decl),
431 true, NULL_TREE,
432 true, GSI_SAME_STMT);
433 tree_uid = build_int_cst
434 (gcov_type_node,
435 cgraph_node::get (current_function_decl)->profile_id);
436 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
437 tree_uid, cur_func);
438 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
440 /* Set __gcov_indirect_call_callee to 0,
441 so that calls from other modules won't get misattributed
442 to the last caller of the current callee. */
443 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
444 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
445 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
448 /* Output instructions as GIMPLE tree at the beginning for each function.
449 TAG is the tag of the section for counters, BASE is offset of the
450 counter position and GSI is the iterator we place the counter. */
452 void
453 gimple_gen_time_profiler (unsigned tag, unsigned base,
454 gimple_stmt_iterator &gsi)
456 tree ref_ptr = tree_coverage_counter_addr (tag, base);
457 gcall *call;
459 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
460 true, NULL_TREE, true, GSI_SAME_STMT);
461 call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
462 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
465 /* Output instructions as GIMPLE trees for code to find the most common value
466 of a difference between two evaluations of an expression.
467 VALUE is the expression whose value is profiled. TAG is the tag of the
468 section for counters, BASE is offset of the counter position. */
470 void
471 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
472 unsigned tag ATTRIBUTE_UNUSED,
473 unsigned base ATTRIBUTE_UNUSED)
475 /* FIXME implement this. */
476 #ifdef ENABLE_CHECKING
477 internal_error ("unimplemented functionality");
478 #endif
479 gcc_unreachable ();
482 /* Output instructions as GIMPLE trees to increment the average histogram
483 counter. VALUE is the expression whose value is profiled. TAG is the
484 tag of the section for counters, BASE is offset of the counter position. */
486 void
487 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
489 gimple stmt = value->hvalue.stmt;
490 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
491 tree ref_ptr = tree_coverage_counter_addr (tag, base);
492 gcall *call;
493 tree val;
495 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
496 true, NULL_TREE,
497 true, GSI_SAME_STMT);
498 val = prepare_instrumented_value (&gsi, value);
499 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
500 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
503 /* Output instructions as GIMPLE trees to increment the ior histogram
504 counter. VALUE is the expression whose value is profiled. TAG is the
505 tag of the section for counters, BASE is offset of the counter position. */
507 void
508 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
510 gimple stmt = value->hvalue.stmt;
511 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
512 tree ref_ptr = tree_coverage_counter_addr (tag, base);
513 gcall *call;
514 tree val;
516 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
517 true, NULL_TREE, true, GSI_SAME_STMT);
518 val = prepare_instrumented_value (&gsi, value);
519 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
520 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
523 /* Profile all functions in the callgraph. */
525 static unsigned int
526 tree_profiling (void)
528 struct cgraph_node *node;
530 /* This is a small-ipa pass that gets called only once, from
531 cgraphunit.c:ipa_passes(). */
532 gcc_assert (symtab->state == IPA_SSA);
534 init_node_map (true);
536 FOR_EACH_DEFINED_FUNCTION (node)
538 if (!gimple_has_body_p (node->decl))
539 continue;
541 /* Don't profile functions produced for builtin stuff. */
542 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
543 continue;
545 /* Do not instrument extern inline functions when testing coverage.
546 While this is not perfectly consistent (early inlined extern inlines
547 will get acocunted), testsuite expects that. */
548 if (DECL_EXTERNAL (node->decl)
549 && flag_test_coverage)
550 continue;
552 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
554 /* Local pure-const may imply need to fixup the cfg. */
555 if (execute_fixup_cfg () & TODO_cleanup_cfg)
556 cleanup_tree_cfg ();
558 branch_prob ();
560 if (! flag_branch_probabilities
561 && flag_profile_values)
562 gimple_gen_ic_func_profiler ();
564 if (flag_branch_probabilities
565 && flag_profile_values
566 && flag_value_profile_transformations)
567 gimple_value_profile_transformations ();
569 /* The above could hose dominator info. Currently there is
570 none coming in, this is a safety valve. It should be
571 easy to adjust it, if and when there is some. */
572 free_dominance_info (CDI_DOMINATORS);
573 free_dominance_info (CDI_POST_DOMINATORS);
574 pop_cfun ();
577 /* Drop pure/const flags from instrumented functions. */
578 FOR_EACH_DEFINED_FUNCTION (node)
580 if (!gimple_has_body_p (node->decl)
581 || !(!node->clone_of
582 || node->decl != node->clone_of->decl))
583 continue;
585 /* Don't profile functions produced for builtin stuff. */
586 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
587 continue;
589 node->set_const_flag (false, false);
590 node->set_pure_flag (false, false);
593 /* Update call statements and rebuild the cgraph. */
594 FOR_EACH_DEFINED_FUNCTION (node)
596 basic_block bb;
598 if (!gimple_has_body_p (node->decl)
599 || !(!node->clone_of
600 || node->decl != node->clone_of->decl))
601 continue;
603 /* Don't profile functions produced for builtin stuff. */
604 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
605 continue;
607 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
609 FOR_EACH_BB_FN (bb, cfun)
611 gimple_stmt_iterator gsi;
612 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
614 gimple stmt = gsi_stmt (gsi);
615 if (is_gimple_call (stmt))
616 update_stmt (stmt);
620 /* re-merge split blocks. */
621 cleanup_tree_cfg ();
622 update_ssa (TODO_update_ssa);
624 cgraph_edge::rebuild_edges ();
626 pop_cfun ();
629 handle_missing_profiles ();
631 del_node_map ();
632 return 0;
635 namespace {
637 const pass_data pass_data_ipa_tree_profile =
639 SIMPLE_IPA_PASS, /* type */
640 "profile", /* name */
641 OPTGROUP_NONE, /* optinfo_flags */
642 TV_IPA_PROFILE, /* tv_id */
643 0, /* properties_required */
644 0, /* properties_provided */
645 0, /* properties_destroyed */
646 0, /* todo_flags_start */
647 0, /* todo_flags_finish */
650 class pass_ipa_tree_profile : public simple_ipa_opt_pass
652 public:
653 pass_ipa_tree_profile (gcc::context *ctxt)
654 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
657 /* opt_pass methods: */
658 virtual bool gate (function *);
659 virtual unsigned int execute (function *) { return tree_profiling (); }
661 }; // class pass_ipa_tree_profile
663 bool
664 pass_ipa_tree_profile::gate (function *)
666 /* When profile instrumentation, use or test coverage shall be performed.
667 But for AutoFDO, this there is no instrumentation, thus this pass is
668 diabled. */
669 return (!in_lto_p && !flag_auto_profile
670 && (flag_branch_probabilities || flag_test_coverage
671 || profile_arc_flag));
674 } // anon namespace
676 simple_ipa_opt_pass *
677 make_pass_ipa_tree_profile (gcc::context *ctxt)
679 return new pass_ipa_tree_profile (ctxt);
682 #include "gt-tree-profile.h"