PR ipa/64550
[official-gcc.git] / gcc / tree-profile.c
blobf57a247295a59db7e5f78faa10be1439144a751f
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 "hashtab.h"
33 #include "hash-set.h"
34 #include "vec.h"
35 #include "machmode.h"
36 #include "hard-reg-set.h"
37 #include "input.h"
38 #include "function.h"
39 #include "predict.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "basic-block.h"
43 #include "diagnostic-core.h"
44 #include "coverage.h"
45 #include "double-int.h"
46 #include "input.h"
47 #include "alias.h"
48 #include "symtab.h"
49 #include "wide-int.h"
50 #include "inchash.h"
51 #include "tree.h"
52 #include "fold-const.h"
53 #include "tree-ssa-alias.h"
54 #include "internal-fn.h"
55 #include "gimple-expr.h"
56 #include "is-a.h"
57 #include "gimple.h"
58 #include "varasm.h"
59 #include "tree-nested.h"
60 #include "gimplify.h"
61 #include "gimple-iterator.h"
62 #include "gimplify-me.h"
63 #include "gimple-ssa.h"
64 #include "hash-map.h"
65 #include "plugin-api.h"
66 #include "ipa-ref.h"
67 #include "cgraph.h"
68 #include "tree-cfg.h"
69 #include "stringpool.h"
70 #include "tree-ssanames.h"
71 #include "tree-into-ssa.h"
72 #include "tree-pass.h"
73 #include "value-prof.h"
74 #include "profile.h"
75 #include "target.h"
76 #include "tree-cfgcleanup.h"
77 #include "tree-nested.h"
78 #include "params.h"
80 static GTY(()) tree gcov_type_node;
81 static GTY(()) tree tree_interval_profiler_fn;
82 static GTY(()) tree tree_pow2_profiler_fn;
83 static GTY(()) tree tree_one_value_profiler_fn;
84 static GTY(()) tree tree_indirect_call_profiler_fn;
85 static GTY(()) tree tree_time_profiler_fn;
86 static GTY(()) tree tree_average_profiler_fn;
87 static GTY(()) tree tree_ior_profiler_fn;
90 static GTY(()) tree ic_void_ptr_var;
91 static GTY(()) tree ic_gcov_type_ptr_var;
92 static GTY(()) tree ptr_void;
94 /* Do initialization work for the edge profiler. */
96 /* Add code:
97 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
98 __thread void* __gcov_indirect_call_callee; // actual callee address
99 __thread int __gcov_function_counter; // time profiler function counter
101 static void
102 init_ic_make_global_vars (void)
104 tree gcov_type_ptr;
106 ptr_void = build_pointer_type (void_type_node);
108 /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
109 if (flag_lto)
111 ic_void_ptr_var
112 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
113 get_identifier ("__gcov_indirect_call_callee_ltopriv"),
114 ptr_void);
115 TREE_PUBLIC (ic_void_ptr_var) = 1;
116 DECL_COMMON (ic_void_ptr_var) = 1;
117 DECL_VISIBILITY (ic_void_ptr_var) = VISIBILITY_HIDDEN;
118 DECL_VISIBILITY_SPECIFIED (ic_void_ptr_var) = true;
120 else
122 ic_void_ptr_var
123 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
124 get_identifier (
125 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
126 "__gcov_indirect_call_topn_callee" :
127 "__gcov_indirect_call_callee")),
128 ptr_void);
129 TREE_PUBLIC (ic_void_ptr_var) = 1;
130 DECL_EXTERNAL (ic_void_ptr_var) = 1;
132 TREE_STATIC (ic_void_ptr_var) = 1;
133 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
134 DECL_INITIAL (ic_void_ptr_var) = NULL;
135 if (targetm.have_tls)
136 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
138 varpool_node::finalize_decl (ic_void_ptr_var);
140 gcov_type_ptr = build_pointer_type (get_gcov_type ());
141 /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
142 if (flag_lto)
144 ic_gcov_type_ptr_var
145 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
146 get_identifier ("__gcov_indirect_call_counters_ltopriv"),
147 gcov_type_ptr);
148 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
149 DECL_COMMON (ic_gcov_type_ptr_var) = 1;
150 DECL_VISIBILITY (ic_gcov_type_ptr_var) = VISIBILITY_HIDDEN;
151 DECL_VISIBILITY_SPECIFIED (ic_gcov_type_ptr_var) = true;
153 else
155 ic_gcov_type_ptr_var
156 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
157 get_identifier (
158 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
159 "__gcov_indirect_call_topn_counters" :
160 "__gcov_indirect_call_counters")),
161 gcov_type_ptr);
162 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
163 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
165 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
166 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
167 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
168 if (targetm.have_tls)
169 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
171 varpool_node::finalize_decl (ic_gcov_type_ptr_var);
174 /* Create the type and function decls for the interface with gcov. */
176 void
177 gimple_init_edge_profiler (void)
179 tree interval_profiler_fn_type;
180 tree pow2_profiler_fn_type;
181 tree one_value_profiler_fn_type;
182 tree gcov_type_ptr;
183 tree ic_profiler_fn_type;
184 tree average_profiler_fn_type;
185 tree time_profiler_fn_type;
187 if (!gcov_type_node)
189 gcov_type_node = get_gcov_type ();
190 gcov_type_ptr = build_pointer_type (gcov_type_node);
192 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
193 interval_profiler_fn_type
194 = build_function_type_list (void_type_node,
195 gcov_type_ptr, gcov_type_node,
196 integer_type_node,
197 unsigned_type_node, NULL_TREE);
198 tree_interval_profiler_fn
199 = build_fn_decl ("__gcov_interval_profiler",
200 interval_profiler_fn_type);
201 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
202 DECL_ATTRIBUTES (tree_interval_profiler_fn)
203 = tree_cons (get_identifier ("leaf"), NULL,
204 DECL_ATTRIBUTES (tree_interval_profiler_fn));
206 /* void (*) (gcov_type *, gcov_type) */
207 pow2_profiler_fn_type
208 = build_function_type_list (void_type_node,
209 gcov_type_ptr, gcov_type_node,
210 NULL_TREE);
211 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
212 pow2_profiler_fn_type);
213 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
214 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
215 = tree_cons (get_identifier ("leaf"), NULL,
216 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
218 /* void (*) (gcov_type *, gcov_type) */
219 one_value_profiler_fn_type
220 = build_function_type_list (void_type_node,
221 gcov_type_ptr, gcov_type_node,
222 NULL_TREE);
223 tree_one_value_profiler_fn
224 = build_fn_decl ("__gcov_one_value_profiler",
225 one_value_profiler_fn_type);
226 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
227 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
228 = tree_cons (get_identifier ("leaf"), NULL,
229 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
231 init_ic_make_global_vars ();
233 /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
234 if (flag_lto)
236 /* void (*) (gcov_type, void *) */
237 ic_profiler_fn_type
238 = build_function_type_list (void_type_node,
239 gcov_type_ptr, gcov_type_node,
240 ptr_void, ptr_void,
241 NULL_TREE);
242 tree_indirect_call_profiler_fn
243 = build_fn_decl ("__gcov_indirect_call_profiler",
244 ic_profiler_fn_type);
246 else
248 /* void (*) (gcov_type, void *) */
249 ic_profiler_fn_type
250 = build_function_type_list (void_type_node,
251 gcov_type_node,
252 ptr_void,
253 NULL_TREE);
254 tree_indirect_call_profiler_fn
255 = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
256 "__gcov_indirect_call_topn_profiler":
257 "__gcov_indirect_call_profiler_v2"),
258 ic_profiler_fn_type);
260 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
261 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
262 = tree_cons (get_identifier ("leaf"), NULL,
263 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
265 /* void (*) (gcov_type *, gcov_type, void *) */
266 time_profiler_fn_type
267 = build_function_type_list (void_type_node,
268 gcov_type_ptr, NULL_TREE);
269 tree_time_profiler_fn
270 = build_fn_decl ("__gcov_time_profiler",
271 time_profiler_fn_type);
272 TREE_NOTHROW (tree_time_profiler_fn) = 1;
273 DECL_ATTRIBUTES (tree_time_profiler_fn)
274 = tree_cons (get_identifier ("leaf"), NULL,
275 DECL_ATTRIBUTES (tree_time_profiler_fn));
277 /* void (*) (gcov_type *, gcov_type) */
278 average_profiler_fn_type
279 = build_function_type_list (void_type_node,
280 gcov_type_ptr, gcov_type_node, NULL_TREE);
281 tree_average_profiler_fn
282 = build_fn_decl ("__gcov_average_profiler",
283 average_profiler_fn_type);
284 TREE_NOTHROW (tree_average_profiler_fn) = 1;
285 DECL_ATTRIBUTES (tree_average_profiler_fn)
286 = tree_cons (get_identifier ("leaf"), NULL,
287 DECL_ATTRIBUTES (tree_average_profiler_fn));
288 tree_ior_profiler_fn
289 = build_fn_decl ("__gcov_ior_profiler",
290 average_profiler_fn_type);
291 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
292 DECL_ATTRIBUTES (tree_ior_profiler_fn)
293 = tree_cons (get_identifier ("leaf"), NULL,
294 DECL_ATTRIBUTES (tree_ior_profiler_fn));
296 /* LTO streamer needs assembler names. Because we create these decls
297 late, we need to initialize them by hand. */
298 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
299 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
300 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
301 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
302 DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
303 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
304 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
308 /* Output instructions as GIMPLE trees to increment the edge
309 execution count, and insert them on E. We rely on
310 gsi_insert_on_edge to preserve the order. */
312 void
313 gimple_gen_edge_profiler (int edgeno, edge e)
315 tree ref, one, gcov_type_tmp_var;
316 gassign *stmt1, *stmt2, *stmt3;
318 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
319 one = build_int_cst (gcov_type_node, 1);
320 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
321 NULL, "PROF_edge_counter");
322 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
323 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
324 NULL, "PROF_edge_counter");
325 stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
326 gimple_assign_lhs (stmt1), one);
327 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
328 gsi_insert_on_edge (e, stmt1);
329 gsi_insert_on_edge (e, stmt2);
330 gsi_insert_on_edge (e, stmt3);
333 /* Emits code to get VALUE to instrument at GSI, and returns the
334 variable containing the value. */
336 static tree
337 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
339 tree val = value->hvalue.value;
340 if (POINTER_TYPE_P (TREE_TYPE (val)))
341 val = fold_convert (build_nonstandard_integer_type
342 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
343 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
344 true, NULL_TREE, true, GSI_SAME_STMT);
347 /* Output instructions as GIMPLE trees to increment the interval histogram
348 counter. VALUE is the expression whose value is profiled. TAG is the
349 tag of the section for counters, BASE is offset of the counter position. */
351 void
352 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
354 gimple stmt = value->hvalue.stmt;
355 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
356 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
357 gcall *call;
358 tree val;
359 tree start = build_int_cst_type (integer_type_node,
360 value->hdata.intvl.int_start);
361 tree steps = build_int_cst_type (unsigned_type_node,
362 value->hdata.intvl.steps);
364 ref_ptr = force_gimple_operand_gsi (&gsi,
365 build_addr (ref, current_function_decl),
366 true, NULL_TREE, true, GSI_SAME_STMT);
367 val = prepare_instrumented_value (&gsi, value);
368 call = gimple_build_call (tree_interval_profiler_fn, 4,
369 ref_ptr, val, start, steps);
370 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
373 /* Output instructions as GIMPLE trees to increment the power of two histogram
374 counter. VALUE is the expression whose value is profiled. TAG is the tag
375 of the section for counters, BASE is offset of the counter position. */
377 void
378 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
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);
383 gcall *call;
384 tree val;
386 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
387 true, NULL_TREE, true, GSI_SAME_STMT);
388 val = prepare_instrumented_value (&gsi, value);
389 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
390 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
393 /* Output instructions as GIMPLE trees for code to find the most common value.
394 VALUE is the expression whose value is profiled. TAG is the tag of the
395 section for counters, BASE is offset of the counter position. */
397 void
398 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
400 gimple stmt = value->hvalue.stmt;
401 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
402 tree ref_ptr = tree_coverage_counter_addr (tag, base);
403 gcall *call;
404 tree val;
406 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
407 true, NULL_TREE, true, GSI_SAME_STMT);
408 val = prepare_instrumented_value (&gsi, value);
409 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
410 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
414 /* Output instructions as GIMPLE trees for code to find the most
415 common called function in indirect call.
416 VALUE is the call expression whose indirect callee is profiled.
417 TAG is the tag of the section for counters, BASE is offset of the
418 counter position. */
420 void
421 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
423 tree tmp1;
424 gassign *stmt1, *stmt2, *stmt3;
425 gimple stmt = value->hvalue.stmt;
426 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
427 tree ref_ptr = tree_coverage_counter_addr (tag, base);
429 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
430 tag == GCOV_COUNTER_V_INDIR) ||
431 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
432 tag == GCOV_COUNTER_ICALL_TOPNV))
433 return;
435 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
436 true, NULL_TREE, true, GSI_SAME_STMT);
438 /* Insert code:
440 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
441 stmt2: tmp1 = (void *) (indirect call argument value)
442 stmt3: __gcov_indirect_call_callee = tmp1;
445 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
446 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
447 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
448 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
450 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
451 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
452 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
456 /* Output instructions as GIMPLE trees for code to find the most
457 common called function in indirect call. Insert instructions at the
458 beginning of every possible called function.
461 void
462 gimple_gen_ic_func_profiler (void)
464 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
465 gimple_stmt_iterator gsi;
466 gcall *stmt1;
467 gassign *stmt2;
468 tree tree_uid, cur_func, void0;
470 if (c_node->only_called_directly_p ())
471 return;
473 gimple_init_edge_profiler ();
475 /* Insert code:
477 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
478 &current_function_decl)
480 gsi = gsi_after_labels (split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
482 cur_func = force_gimple_operand_gsi (&gsi,
483 build_addr (current_function_decl,
484 current_function_decl),
485 true, NULL_TREE,
486 true, GSI_SAME_STMT);
487 tree_uid = build_int_cst
488 (gcov_type_node, cgraph_node::get (current_function_decl)->profile_id);
489 /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
490 if (flag_lto)
492 tree counter_ptr, ptr_var;
493 counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
494 true, NULL_TREE, true,
495 GSI_SAME_STMT);
496 ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
497 true, NULL_TREE, true,
498 GSI_SAME_STMT);
500 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
501 counter_ptr, tree_uid, cur_func, ptr_var);
503 else
505 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
506 tree_uid, cur_func);
508 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
510 /* Set __gcov_indirect_call_callee to 0,
511 so that calls from other modules won't get misattributed
512 to the last caller of the current callee. */
513 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
514 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
515 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
518 /* Output instructions as GIMPLE tree at the beginning for each function.
519 TAG is the tag of the section for counters, BASE is offset of the
520 counter position and GSI is the iterator we place the counter. */
522 void
523 gimple_gen_time_profiler (unsigned tag, unsigned base,
524 gimple_stmt_iterator &gsi)
526 tree ref_ptr = tree_coverage_counter_addr (tag, base);
527 gcall *call;
529 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
530 true, NULL_TREE, true, GSI_SAME_STMT);
531 call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
532 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
535 /* Output instructions as GIMPLE trees for code to find the most common value
536 of a difference between two evaluations of an expression.
537 VALUE is the expression whose value is profiled. TAG is the tag of the
538 section for counters, BASE is offset of the counter position. */
540 void
541 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
542 unsigned tag ATTRIBUTE_UNUSED,
543 unsigned base ATTRIBUTE_UNUSED)
545 /* FIXME implement this. */
546 #ifdef ENABLE_CHECKING
547 internal_error ("unimplemented functionality");
548 #endif
549 gcc_unreachable ();
552 /* Output instructions as GIMPLE trees to increment the average histogram
553 counter. VALUE is the expression whose value is profiled. TAG is the
554 tag of the section for counters, BASE is offset of the counter position. */
556 void
557 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
559 gimple stmt = value->hvalue.stmt;
560 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
561 tree ref_ptr = tree_coverage_counter_addr (tag, base);
562 gcall *call;
563 tree val;
565 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
566 true, NULL_TREE,
567 true, GSI_SAME_STMT);
568 val = prepare_instrumented_value (&gsi, value);
569 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
570 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
573 /* Output instructions as GIMPLE trees to increment the ior histogram
574 counter. VALUE is the expression whose value is profiled. TAG is the
575 tag of the section for counters, BASE is offset of the counter position. */
577 void
578 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
580 gimple stmt = value->hvalue.stmt;
581 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
582 tree ref_ptr = tree_coverage_counter_addr (tag, base);
583 gcall *call;
584 tree val;
586 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
587 true, NULL_TREE, true, GSI_SAME_STMT);
588 val = prepare_instrumented_value (&gsi, value);
589 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
590 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
593 /* Profile all functions in the callgraph. */
595 static unsigned int
596 tree_profiling (void)
598 struct cgraph_node *node;
600 /* This is a small-ipa pass that gets called only once, from
601 cgraphunit.c:ipa_passes(). */
602 gcc_assert (symtab->state == IPA_SSA);
604 init_node_map (true);
606 FOR_EACH_DEFINED_FUNCTION (node)
608 if (!gimple_has_body_p (node->decl))
609 continue;
611 /* Don't profile functions produced for builtin stuff. */
612 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
613 continue;
615 /* Do not instrument extern inline functions when testing coverage.
616 While this is not perfectly consistent (early inlined extern inlines
617 will get acocunted), testsuite expects that. */
618 if (DECL_EXTERNAL (node->decl)
619 && flag_test_coverage)
620 continue;
622 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
624 /* Local pure-const may imply need to fixup the cfg. */
625 if (execute_fixup_cfg () & TODO_cleanup_cfg)
626 cleanup_tree_cfg ();
628 branch_prob ();
630 if (! flag_branch_probabilities
631 && flag_profile_values)
632 gimple_gen_ic_func_profiler ();
634 if (flag_branch_probabilities
635 && flag_profile_values
636 && flag_value_profile_transformations)
637 gimple_value_profile_transformations ();
639 /* The above could hose dominator info. Currently there is
640 none coming in, this is a safety valve. It should be
641 easy to adjust it, if and when there is some. */
642 free_dominance_info (CDI_DOMINATORS);
643 free_dominance_info (CDI_POST_DOMINATORS);
644 pop_cfun ();
647 /* Drop pure/const flags from instrumented functions. */
648 FOR_EACH_DEFINED_FUNCTION (node)
650 if (!gimple_has_body_p (node->decl)
651 || !(!node->clone_of
652 || node->decl != node->clone_of->decl))
653 continue;
655 /* Don't profile functions produced for builtin stuff. */
656 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
657 continue;
659 node->set_const_flag (false, false);
660 node->set_pure_flag (false, false);
663 /* Update call statements and rebuild the cgraph. */
664 FOR_EACH_DEFINED_FUNCTION (node)
666 basic_block bb;
668 if (!gimple_has_body_p (node->decl)
669 || !(!node->clone_of
670 || node->decl != node->clone_of->decl))
671 continue;
673 /* Don't profile functions produced for builtin stuff. */
674 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
675 continue;
677 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
679 FOR_EACH_BB_FN (bb, cfun)
681 gimple_stmt_iterator gsi;
682 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
684 gimple stmt = gsi_stmt (gsi);
685 if (is_gimple_call (stmt))
686 update_stmt (stmt);
690 /* re-merge split blocks. */
691 cleanup_tree_cfg ();
692 update_ssa (TODO_update_ssa);
694 cgraph_edge::rebuild_edges ();
696 pop_cfun ();
699 handle_missing_profiles ();
701 del_node_map ();
702 return 0;
705 namespace {
707 const pass_data pass_data_ipa_tree_profile =
709 SIMPLE_IPA_PASS, /* type */
710 "profile", /* name */
711 OPTGROUP_NONE, /* optinfo_flags */
712 TV_IPA_PROFILE, /* tv_id */
713 0, /* properties_required */
714 0, /* properties_provided */
715 0, /* properties_destroyed */
716 0, /* todo_flags_start */
717 0, /* todo_flags_finish */
720 class pass_ipa_tree_profile : public simple_ipa_opt_pass
722 public:
723 pass_ipa_tree_profile (gcc::context *ctxt)
724 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
727 /* opt_pass methods: */
728 virtual bool gate (function *);
729 virtual unsigned int execute (function *) { return tree_profiling (); }
731 }; // class pass_ipa_tree_profile
733 bool
734 pass_ipa_tree_profile::gate (function *)
736 /* When profile instrumentation, use or test coverage shall be performed.
737 But for AutoFDO, this there is no instrumentation, thus this pass is
738 diabled. */
739 return (!in_lto_p && !flag_auto_profile
740 && (flag_branch_probabilities || flag_test_coverage
741 || profile_arc_flag));
744 } // anon namespace
746 simple_ipa_opt_pass *
747 make_pass_ipa_tree_profile (gcc::context *ctxt)
749 return new pass_ipa_tree_profile (ctxt);
752 #include "gt-tree-profile.h"