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