]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-profile.c
Update copyright years.
[thirdparty/gcc.git] / gcc / tree-profile.c
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.
7
8 This file is part of GCC.
9
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.
14
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.
19
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/>. */
23
24 /* Generate basic block profile instrumentation and auxiliary files.
25 Tree-based version. See profile.c for overview. */
26
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"
52
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;
61
62
63 static GTY(()) tree ic_void_ptr_var;
64 static GTY(()) tree ic_gcov_type_ptr_var;
65 static GTY(()) tree ptr_void;
66
67 /* Do initialization work for the edge profiler. */
68
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
73 */
74 static void
75 init_ic_make_global_vars (void)
76 {
77 tree gcov_type_ptr;
78
79 ptr_void = build_pointer_type (void_type_node);
80
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));
95
96 varpool_node::finalize_decl (ic_void_ptr_var);
97
98 gcov_type_ptr = build_pointer_type (get_gcov_type ());
99
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));
114
115 varpool_node::finalize_decl (ic_gcov_type_ptr_var);
116 }
117
118 /* Create the type and function decls for the interface with gcov. */
119
120 void
121 gimple_init_edge_profiler (void)
122 {
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
131 if (!gcov_type_node)
132 {
133 gcov_type_node = get_gcov_type ();
134 gcov_type_ptr = build_pointer_type (gcov_type_node);
135
136 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
137 interval_profiler_fn_type
138 = build_function_type_list (void_type_node,
139 gcov_type_ptr, gcov_type_node,
140 integer_type_node,
141 unsigned_type_node, NULL_TREE);
142 tree_interval_profiler_fn
143 = build_fn_decl ("__gcov_interval_profiler",
144 interval_profiler_fn_type);
145 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
146 DECL_ATTRIBUTES (tree_interval_profiler_fn)
147 = tree_cons (get_identifier ("leaf"), NULL,
148 DECL_ATTRIBUTES (tree_interval_profiler_fn));
149
150 /* void (*) (gcov_type *, gcov_type) */
151 pow2_profiler_fn_type
152 = build_function_type_list (void_type_node,
153 gcov_type_ptr, gcov_type_node,
154 NULL_TREE);
155 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
156 pow2_profiler_fn_type);
157 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
158 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
159 = tree_cons (get_identifier ("leaf"), NULL,
160 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
161
162 /* void (*) (gcov_type *, gcov_type) */
163 one_value_profiler_fn_type
164 = build_function_type_list (void_type_node,
165 gcov_type_ptr, gcov_type_node,
166 NULL_TREE);
167 tree_one_value_profiler_fn
168 = build_fn_decl ("__gcov_one_value_profiler",
169 one_value_profiler_fn_type);
170 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
171 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
172 = tree_cons (get_identifier ("leaf"), NULL,
173 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
174
175 init_ic_make_global_vars ();
176
177 /* void (*) (gcov_type, void *) */
178 ic_profiler_fn_type
179 = build_function_type_list (void_type_node,
180 gcov_type_node,
181 ptr_void,
182 NULL_TREE);
183 tree_indirect_call_profiler_fn
184 = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
185 "__gcov_indirect_call_topn_profiler":
186 "__gcov_indirect_call_profiler_v2"),
187 ic_profiler_fn_type);
188
189 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
190 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
191 = tree_cons (get_identifier ("leaf"), NULL,
192 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
193
194 /* void (*) (gcov_type *, gcov_type, void *) */
195 time_profiler_fn_type
196 = build_function_type_list (void_type_node,
197 gcov_type_ptr, NULL_TREE);
198 tree_time_profiler_fn
199 = build_fn_decl ("__gcov_time_profiler",
200 time_profiler_fn_type);
201 TREE_NOTHROW (tree_time_profiler_fn) = 1;
202 DECL_ATTRIBUTES (tree_time_profiler_fn)
203 = tree_cons (get_identifier ("leaf"), NULL,
204 DECL_ATTRIBUTES (tree_time_profiler_fn));
205
206 /* void (*) (gcov_type *, gcov_type) */
207 average_profiler_fn_type
208 = build_function_type_list (void_type_node,
209 gcov_type_ptr, gcov_type_node, NULL_TREE);
210 tree_average_profiler_fn
211 = build_fn_decl ("__gcov_average_profiler",
212 average_profiler_fn_type);
213 TREE_NOTHROW (tree_average_profiler_fn) = 1;
214 DECL_ATTRIBUTES (tree_average_profiler_fn)
215 = tree_cons (get_identifier ("leaf"), NULL,
216 DECL_ATTRIBUTES (tree_average_profiler_fn));
217 tree_ior_profiler_fn
218 = build_fn_decl ("__gcov_ior_profiler",
219 average_profiler_fn_type);
220 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
221 DECL_ATTRIBUTES (tree_ior_profiler_fn)
222 = tree_cons (get_identifier ("leaf"), NULL,
223 DECL_ATTRIBUTES (tree_ior_profiler_fn));
224
225 /* LTO streamer needs assembler names. Because we create these decls
226 late, we need to initialize them by hand. */
227 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
228 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
229 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
230 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
231 DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
232 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
233 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
234 }
235 }
236
237 /* Output instructions as GIMPLE trees to increment the edge
238 execution count, and insert them on E. We rely on
239 gsi_insert_on_edge to preserve the order. */
240
241 void
242 gimple_gen_edge_profiler (int edgeno, edge e)
243 {
244 tree ref, one, gcov_type_tmp_var;
245 gassign *stmt1, *stmt2, *stmt3;
246
247 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
248 one = build_int_cst (gcov_type_node, 1);
249 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
250 NULL, "PROF_edge_counter");
251 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
252 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
253 NULL, "PROF_edge_counter");
254 stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
255 gimple_assign_lhs (stmt1), one);
256 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
257 gsi_insert_on_edge (e, stmt1);
258 gsi_insert_on_edge (e, stmt2);
259 gsi_insert_on_edge (e, stmt3);
260 }
261
262 /* Emits code to get VALUE to instrument at GSI, and returns the
263 variable containing the value. */
264
265 static tree
266 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
267 {
268 tree val = value->hvalue.value;
269 if (POINTER_TYPE_P (TREE_TYPE (val)))
270 val = fold_convert (build_nonstandard_integer_type
271 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
272 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
273 true, NULL_TREE, true, GSI_SAME_STMT);
274 }
275
276 /* Output instructions as GIMPLE trees to increment the interval histogram
277 counter. VALUE is the expression whose value is profiled. TAG is the
278 tag of the section for counters, BASE is offset of the counter position. */
279
280 void
281 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
282 {
283 gimple *stmt = value->hvalue.stmt;
284 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
285 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
286 gcall *call;
287 tree val;
288 tree start = build_int_cst_type (integer_type_node,
289 value->hdata.intvl.int_start);
290 tree steps = build_int_cst_type (unsigned_type_node,
291 value->hdata.intvl.steps);
292
293 ref_ptr = force_gimple_operand_gsi (&gsi,
294 build_addr (ref),
295 true, NULL_TREE, true, GSI_SAME_STMT);
296 val = prepare_instrumented_value (&gsi, value);
297 call = gimple_build_call (tree_interval_profiler_fn, 4,
298 ref_ptr, val, start, steps);
299 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
300 }
301
302 /* Output instructions as GIMPLE trees to increment the power of two histogram
303 counter. VALUE is the expression whose value is profiled. TAG is the tag
304 of the section for counters, BASE is offset of the counter position. */
305
306 void
307 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
308 {
309 gimple *stmt = value->hvalue.stmt;
310 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
311 tree ref_ptr = tree_coverage_counter_addr (tag, base);
312 gcall *call;
313 tree val;
314
315 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
316 true, NULL_TREE, true, GSI_SAME_STMT);
317 val = prepare_instrumented_value (&gsi, value);
318 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
319 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
320 }
321
322 /* Output instructions as GIMPLE trees for code to find the most common value.
323 VALUE is the expression whose value is profiled. TAG is the tag of the
324 section for counters, BASE is offset of the counter position. */
325
326 void
327 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
328 {
329 gimple *stmt = value->hvalue.stmt;
330 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
331 tree ref_ptr = tree_coverage_counter_addr (tag, base);
332 gcall *call;
333 tree val;
334
335 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
336 true, NULL_TREE, true, GSI_SAME_STMT);
337 val = prepare_instrumented_value (&gsi, value);
338 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
339 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
340 }
341
342
343 /* Output instructions as GIMPLE trees for code to find the most
344 common called function in indirect call.
345 VALUE is the call expression whose indirect callee is profiled.
346 TAG is the tag of the section for counters, BASE is offset of the
347 counter position. */
348
349 void
350 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
351 {
352 tree tmp1;
353 gassign *stmt1, *stmt2, *stmt3;
354 gimple *stmt = value->hvalue.stmt;
355 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
356 tree ref_ptr = tree_coverage_counter_addr (tag, base);
357
358 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
359 tag == GCOV_COUNTER_V_INDIR) ||
360 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
361 tag == GCOV_COUNTER_ICALL_TOPNV))
362 return;
363
364 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
365 true, NULL_TREE, true, GSI_SAME_STMT);
366
367 /* Insert code:
368
369 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
370 stmt2: tmp1 = (void *) (indirect call argument value)
371 stmt3: __gcov_indirect_call_callee = tmp1;
372 */
373
374 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
375 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
376 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
377 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
378
379 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
380 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
381 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
382 }
383
384
385 /* Output instructions as GIMPLE trees for code to find the most
386 common called function in indirect call. Insert instructions at the
387 beginning of every possible called function.
388 */
389
390 void
391 gimple_gen_ic_func_profiler (void)
392 {
393 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
394 gimple_stmt_iterator gsi;
395 gcall *stmt1;
396 gassign *stmt2;
397 tree tree_uid, cur_func, void0;
398
399 if (c_node->only_called_directly_p ())
400 return;
401
402 gimple_init_edge_profiler ();
403
404 /* Insert code:
405
406 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
407 &current_function_decl)
408 */
409 gsi = gsi_after_labels (split_edge (single_succ_edge
410 (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
411
412 cur_func = force_gimple_operand_gsi (&gsi,
413 build_addr (current_function_decl),
414 true, NULL_TREE,
415 true, GSI_SAME_STMT);
416 tree_uid = build_int_cst
417 (gcov_type_node,
418 cgraph_node::get (current_function_decl)->profile_id);
419 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
420 tree_uid, cur_func);
421 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
422
423 /* Set __gcov_indirect_call_callee to 0,
424 so that calls from other modules won't get misattributed
425 to the last caller of the current callee. */
426 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
427 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
428 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
429 }
430
431 /* Output instructions as GIMPLE tree at the beginning for each function.
432 TAG is the tag of the section for counters, BASE is offset of the
433 counter position and GSI is the iterator we place the counter. */
434
435 void
436 gimple_gen_time_profiler (unsigned tag, unsigned base,
437 gimple_stmt_iterator &gsi)
438 {
439 tree ref_ptr = tree_coverage_counter_addr (tag, base);
440 gcall *call;
441
442 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
443 true, NULL_TREE, true, GSI_SAME_STMT);
444 call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
445 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
446 }
447
448 /* Output instructions as GIMPLE trees for code to find the most common value
449 of a difference between two evaluations of an expression.
450 VALUE is the expression whose value is profiled. TAG is the tag of the
451 section for counters, BASE is offset of the counter position. */
452
453 void
454 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
455 unsigned tag ATTRIBUTE_UNUSED,
456 unsigned base ATTRIBUTE_UNUSED)
457 {
458 /* FIXME implement this. */
459 if (flag_checking)
460 internal_error ("unimplemented functionality");
461 gcc_unreachable ();
462 }
463
464 /* Output instructions as GIMPLE trees to increment the average histogram
465 counter. VALUE is the expression whose value is profiled. TAG is the
466 tag of the section for counters, BASE is offset of the counter position. */
467
468 void
469 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
470 {
471 gimple *stmt = value->hvalue.stmt;
472 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
473 tree ref_ptr = tree_coverage_counter_addr (tag, base);
474 gcall *call;
475 tree val;
476
477 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
478 true, NULL_TREE,
479 true, GSI_SAME_STMT);
480 val = prepare_instrumented_value (&gsi, value);
481 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
482 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
483 }
484
485 /* Output instructions as GIMPLE trees to increment the ior histogram
486 counter. VALUE is the expression whose value is profiled. TAG is the
487 tag of the section for counters, BASE is offset of the counter position. */
488
489 void
490 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
491 {
492 gimple *stmt = value->hvalue.stmt;
493 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
494 tree ref_ptr = tree_coverage_counter_addr (tag, base);
495 gcall *call;
496 tree val;
497
498 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
499 true, NULL_TREE, true, GSI_SAME_STMT);
500 val = prepare_instrumented_value (&gsi, value);
501 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
502 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
503 }
504
505 /* Profile all functions in the callgraph. */
506
507 static unsigned int
508 tree_profiling (void)
509 {
510 struct cgraph_node *node;
511
512 /* This is a small-ipa pass that gets called only once, from
513 cgraphunit.c:ipa_passes(). */
514 gcc_assert (symtab->state == IPA_SSA);
515
516 init_node_map (true);
517
518 FOR_EACH_DEFINED_FUNCTION (node)
519 {
520 if (!gimple_has_body_p (node->decl))
521 continue;
522
523 /* Don't profile functions produced for builtin stuff. */
524 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
525 continue;
526
527 /* Do not instrument extern inline functions when testing coverage.
528 While this is not perfectly consistent (early inlined extern inlines
529 will get acocunted), testsuite expects that. */
530 if (DECL_EXTERNAL (node->decl)
531 && flag_test_coverage)
532 continue;
533
534 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
535
536 /* Local pure-const may imply need to fixup the cfg. */
537 if (execute_fixup_cfg () & TODO_cleanup_cfg)
538 cleanup_tree_cfg ();
539
540 branch_prob ();
541
542 if (! flag_branch_probabilities
543 && flag_profile_values)
544 gimple_gen_ic_func_profiler ();
545
546 if (flag_branch_probabilities
547 && flag_profile_values
548 && flag_value_profile_transformations)
549 gimple_value_profile_transformations ();
550
551 /* The above could hose dominator info. Currently there is
552 none coming in, this is a safety valve. It should be
553 easy to adjust it, if and when there is some. */
554 free_dominance_info (CDI_DOMINATORS);
555 free_dominance_info (CDI_POST_DOMINATORS);
556 pop_cfun ();
557 }
558
559 /* Drop pure/const flags from instrumented functions. */
560 if (profile_arc_flag || flag_test_coverage)
561 FOR_EACH_DEFINED_FUNCTION (node)
562 {
563 if (!gimple_has_body_p (node->decl)
564 || !(!node->clone_of
565 || node->decl != node->clone_of->decl))
566 continue;
567
568 /* Don't profile functions produced for builtin stuff. */
569 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
570 continue;
571
572 node->set_const_flag (false, false);
573 node->set_pure_flag (false, false);
574 }
575
576 /* Update call statements and rebuild the cgraph. */
577 FOR_EACH_DEFINED_FUNCTION (node)
578 {
579 basic_block bb;
580
581 if (!gimple_has_body_p (node->decl)
582 || !(!node->clone_of
583 || node->decl != node->clone_of->decl))
584 continue;
585
586 /* Don't profile functions produced for builtin stuff. */
587 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
588 continue;
589
590 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
591
592 FOR_EACH_BB_FN (bb, cfun)
593 {
594 gimple_stmt_iterator gsi;
595 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
596 {
597 gimple *stmt = gsi_stmt (gsi);
598 if (is_gimple_call (stmt))
599 update_stmt (stmt);
600 }
601 }
602
603 /* re-merge split blocks. */
604 cleanup_tree_cfg ();
605 update_ssa (TODO_update_ssa);
606
607 cgraph_edge::rebuild_edges ();
608
609 pop_cfun ();
610 }
611
612 handle_missing_profiles ();
613
614 del_node_map ();
615 return 0;
616 }
617
618 namespace {
619
620 const pass_data pass_data_ipa_tree_profile =
621 {
622 SIMPLE_IPA_PASS, /* type */
623 "profile", /* name */
624 OPTGROUP_NONE, /* optinfo_flags */
625 TV_IPA_PROFILE, /* tv_id */
626 0, /* properties_required */
627 0, /* properties_provided */
628 0, /* properties_destroyed */
629 0, /* todo_flags_start */
630 TODO_dump_symtab, /* todo_flags_finish */
631 };
632
633 class pass_ipa_tree_profile : public simple_ipa_opt_pass
634 {
635 public:
636 pass_ipa_tree_profile (gcc::context *ctxt)
637 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
638 {}
639
640 /* opt_pass methods: */
641 virtual bool gate (function *);
642 virtual unsigned int execute (function *) { return tree_profiling (); }
643
644 }; // class pass_ipa_tree_profile
645
646 bool
647 pass_ipa_tree_profile::gate (function *)
648 {
649 /* When profile instrumentation, use or test coverage shall be performed.
650 But for AutoFDO, this there is no instrumentation, thus this pass is
651 diabled. */
652 return (!in_lto_p && !flag_auto_profile
653 && (flag_branch_probabilities || flag_test_coverage
654 || profile_arc_flag));
655 }
656
657 } // anon namespace
658
659 simple_ipa_opt_pass *
660 make_pass_ipa_tree_profile (gcc::context *ctxt)
661 {
662 return new pass_ipa_tree_profile (ctxt);
663 }
664
665 #include "gt-tree-profile.h"