1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
4 Free Software Foundation, Inc.
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6 based on some ideas from Dain Samples of UC Berkeley.
7 Further mangling by Bob Manson, Cygnus Support.
8 Converted to use trees by Dale Johannesen, Apple Computer.
10 This file is part of GCC.
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3. If not see
24 <http://www.gnu.org/licenses/>. */
26 /* Generate basic block profile instrumentation and auxiliary files.
27 Tree-based version. See profile.c for overview. */
31 #include "coretypes.h"
40 #include "tree-flow.h"
41 #include "tree-dump.h"
42 #include "tree-pass.h"
44 #include "value-prof.h"
47 static GTY(()) tree gcov_type_node;
48 static GTY(()) tree gcov_type_tmp_var;
49 static GTY(()) tree tree_interval_profiler_fn;
50 static GTY(()) tree tree_pow2_profiler_fn;
51 static GTY(()) tree tree_one_value_profiler_fn;
52 static GTY(()) tree tree_indirect_call_profiler_fn;
53 static GTY(()) tree tree_average_profiler_fn;
54 static GTY(()) tree tree_ior_profiler_fn;
57 static GTY(()) tree ic_void_ptr_var;
58 static GTY(()) tree ic_gcov_type_ptr_var;
59 static GTY(()) tree ptr_void;
61 /* Do initialization work for the edge profiler. */
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
65 static void* __gcov_indirect_call_callee; // actual callee address
68 tree_init_ic_make_global_vars (void)
72 ptr_void = build_pointer_type (void_type_node);
75 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
76 get_identifier ("__gcov_indirect_call_callee"),
78 TREE_STATIC (ic_void_ptr_var) = 1;
79 TREE_PUBLIC (ic_void_ptr_var) = 0;
80 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
81 DECL_INITIAL (ic_void_ptr_var) = NULL;
82 DECL_TLS_MODEL (ic_void_ptr_var) = decl_default_tls_model (ic_void_ptr_var);
83 varpool_finalize_decl (ic_void_ptr_var);
84 varpool_mark_needed_node (varpool_node (ic_void_ptr_var));
86 gcov_type_ptr = build_pointer_type (get_gcov_type ());
88 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
89 get_identifier ("__gcov_indirect_call_counters"),
91 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
92 TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
93 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
94 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
95 DECL_TLS_MODEL (ic_gcov_type_ptr_var) = decl_default_tls_model (ic_gcov_type_ptr_var);
96 varpool_finalize_decl (ic_gcov_type_ptr_var);
97 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var));
101 tree_init_edge_profiler (void)
103 tree interval_profiler_fn_type;
104 tree pow2_profiler_fn_type;
105 tree one_value_profiler_fn_type;
107 tree ic_profiler_fn_type;
108 tree average_profiler_fn_type;
112 gcov_type_node = get_gcov_type ();
113 gcov_type_ptr = build_pointer_type (gcov_type_node);
115 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
116 interval_profiler_fn_type
117 = build_function_type_list (void_type_node,
118 gcov_type_ptr, gcov_type_node,
120 unsigned_type_node, NULL_TREE);
121 tree_interval_profiler_fn
122 = build_fn_decl ("__gcov_interval_profiler",
123 interval_profiler_fn_type);
125 /* void (*) (gcov_type *, gcov_type) */
126 pow2_profiler_fn_type
127 = build_function_type_list (void_type_node,
128 gcov_type_ptr, gcov_type_node,
130 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
131 pow2_profiler_fn_type);
133 /* void (*) (gcov_type *, gcov_type) */
134 one_value_profiler_fn_type
135 = build_function_type_list (void_type_node,
136 gcov_type_ptr, gcov_type_node,
138 tree_one_value_profiler_fn
139 = build_fn_decl ("__gcov_one_value_profiler",
140 one_value_profiler_fn_type);
142 tree_init_ic_make_global_vars ();
144 /* void (*) (gcov_type *, gcov_type, void *, void *) */
146 = build_function_type_list (void_type_node,
147 gcov_type_ptr, gcov_type_node,
149 ptr_void, NULL_TREE);
150 tree_indirect_call_profiler_fn
151 = build_fn_decl ("__gcov_indirect_call_profiler",
152 ic_profiler_fn_type);
153 /* void (*) (gcov_type *, gcov_type) */
154 average_profiler_fn_type
155 = build_function_type_list (void_type_node,
156 gcov_type_ptr, gcov_type_node, NULL_TREE);
157 tree_average_profiler_fn
158 = build_fn_decl ("__gcov_average_profiler",
159 average_profiler_fn_type);
161 = build_fn_decl ("__gcov_ior_profiler",
162 average_profiler_fn_type);
163 /* LTO streamer needs assembler names. Because we create these decls
164 late, we need to initialize them by hand. */
165 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
166 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
167 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
168 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
169 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
170 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
174 /* New call was added, make goto call edges if neccesary. */
177 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
179 gimple stmt = gsi_stmt (gsi);
181 if (!stmt_can_make_abnormal_goto (stmt))
183 if (!gsi_end_p (gsi))
184 split_block (gimple_bb (stmt), stmt);
185 make_abnormal_goto_edges (gimple_bb (stmt), true);
188 /* Output instructions as GIMPLE trees to increment the edge
189 execution count, and insert them on E. We rely on
190 gsi_insert_on_edge to preserve the order. */
193 tree_gen_edge_profiler (int edgeno, edge e)
196 gimple stmt1, stmt2, stmt3;
198 /* We share one temporary variable declaration per function. This
199 gets re-set in tree_profiling. */
200 if (gcov_type_tmp_var == NULL_TREE)
201 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
202 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
203 one = build_int_cst (gcov_type_node, 1);
204 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
205 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
206 gcov_type_tmp_var, one);
207 stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
208 gsi_insert_on_edge (e, stmt1);
209 gsi_insert_on_edge (e, stmt2);
210 gsi_insert_on_edge (e, stmt3);
213 /* Emits code to get VALUE to instrument at GSI, and returns the
214 variable containing the value. */
217 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
219 tree val = value->hvalue.value;
220 if (POINTER_TYPE_P (TREE_TYPE (val)))
221 val = fold_convert (sizetype, val);
222 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
223 true, NULL_TREE, true, GSI_SAME_STMT);
226 /* Output instructions as GIMPLE trees to increment the interval histogram
227 counter. VALUE is the expression whose value is profiled. TAG is the
228 tag of the section for counters, BASE is offset of the counter position. */
231 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
233 gimple stmt = value->hvalue.stmt;
234 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
235 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
238 tree start = build_int_cst_type (integer_type_node,
239 value->hdata.intvl.int_start);
240 tree steps = build_int_cst_type (unsigned_type_node,
241 value->hdata.intvl.steps);
243 ref_ptr = force_gimple_operand_gsi (&gsi,
244 build_addr (ref, current_function_decl),
245 true, NULL_TREE, true, GSI_SAME_STMT);
246 val = prepare_instrumented_value (&gsi, value);
247 call = gimple_build_call (tree_interval_profiler_fn, 4,
248 ref_ptr, val, start, steps);
249 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
250 add_abnormal_goto_call_edges (gsi);
253 /* Output instructions as GIMPLE trees to increment the power of two histogram
254 counter. VALUE is the expression whose value is profiled. TAG is the tag
255 of the section for counters, BASE is offset of the counter position. */
258 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
260 gimple stmt = value->hvalue.stmt;
261 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
262 tree ref_ptr = tree_coverage_counter_addr (tag, base);
266 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
267 true, NULL_TREE, true, GSI_SAME_STMT);
268 val = prepare_instrumented_value (&gsi, value);
269 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
270 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
271 add_abnormal_goto_call_edges (gsi);
274 /* Output instructions as GIMPLE trees for code to find the most common value.
275 VALUE is the expression whose value is profiled. TAG is the tag of the
276 section for counters, BASE is offset of the counter position. */
279 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
281 gimple stmt = value->hvalue.stmt;
282 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
283 tree ref_ptr = tree_coverage_counter_addr (tag, base);
287 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
288 true, NULL_TREE, true, GSI_SAME_STMT);
289 val = prepare_instrumented_value (&gsi, value);
290 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
291 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
292 add_abnormal_goto_call_edges (gsi);
296 /* Output instructions as GIMPLE trees for code to find the most
297 common called function in indirect call.
298 VALUE is the call expression whose indirect callee is profiled.
299 TAG is the tag of the section for counters, BASE is offset of the
303 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
306 gimple stmt1, stmt2, stmt3;
307 gimple stmt = value->hvalue.stmt;
308 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
309 tree ref_ptr = tree_coverage_counter_addr (tag, base);
311 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
312 true, NULL_TREE, true, GSI_SAME_STMT);
316 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
317 __gcov_indirect_call_callee = (void *) indirect call argument;
320 tmp1 = create_tmp_var (ptr_void, "PROF");
321 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
322 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
323 stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
325 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
326 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
327 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
331 /* Output instructions as GIMPLE trees for code to find the most
332 common called function in indirect call. Insert instructions at the
333 beginning of every possible called function.
337 tree_gen_ic_func_profiler (void)
339 struct cgraph_node * c_node = cgraph_node (current_function_decl);
340 gimple_stmt_iterator gsi;
345 tree tree_uid, cur_func;
347 if (cgraph_only_called_directly_p (c_node))
350 tree_init_edge_profiler ();
352 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
357 gsi = gsi_start_bb (bb);
359 cur_func = force_gimple_operand_gsi (&gsi,
360 build_addr (current_function_decl,
361 current_function_decl),
363 true, GSI_SAME_STMT);
364 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
365 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
366 ic_gcov_type_ptr_var,
370 gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
371 gcc_assert (EDGE_COUNT (bb->succs) == 1);
372 bb = split_edge (EDGE_I (bb->succs, 0));
373 add_abnormal_goto_call_edges (gsi);
375 gsi = gsi_start_bb (bb);
376 /* Set __gcov_indirect_call_callee to 0,
377 so that calls from other modules won't get misattributed
378 to the last caller of the current callee. */
379 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
380 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
381 gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
385 /* Output instructions as GIMPLE trees for code to find the most common value
386 of a difference between two evaluations of an expression.
387 VALUE is the expression whose value is profiled. TAG is the tag of the
388 section for counters, BASE is offset of the counter position. */
391 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
392 unsigned tag ATTRIBUTE_UNUSED,
393 unsigned base ATTRIBUTE_UNUSED)
395 /* FIXME implement this. */
396 #ifdef ENABLE_CHECKING
397 internal_error ("unimplemented functionality");
402 /* Output instructions as GIMPLE trees to increment the average histogram
403 counter. VALUE is the expression whose value is profiled. TAG is the
404 tag of the section for counters, BASE is offset of the counter position. */
407 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
409 gimple stmt = value->hvalue.stmt;
410 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
411 tree ref_ptr = tree_coverage_counter_addr (tag, base);
415 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
417 true, GSI_SAME_STMT);
418 val = prepare_instrumented_value (&gsi, value);
419 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
420 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
421 add_abnormal_goto_call_edges (gsi);
424 /* Output instructions as GIMPLE trees to increment the ior histogram
425 counter. VALUE is the expression whose value is profiled. TAG is the
426 tag of the section for counters, BASE is offset of the counter position. */
429 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
431 gimple stmt = value->hvalue.stmt;
432 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
433 tree ref_ptr = tree_coverage_counter_addr (tag, base);
437 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
438 true, NULL_TREE, true, GSI_SAME_STMT);
439 val = prepare_instrumented_value (&gsi, value);
440 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
441 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
442 add_abnormal_goto_call_edges (gsi);
445 /* Return 1 if tree-based profiling is in effect, else 0.
446 If it is, set up hooks for tree-based profiling.
447 Gate for pass_tree_profile. */
450 do_tree_profiling (void)
452 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
454 tree_register_profile_hooks ();
455 gimple_register_value_prof_hooks ();
462 tree_profiling (void)
464 /* Don't profile functions produced at destruction time, particularly
465 the gcov datastructure initializer. Don't profile if it has been
466 already instrumented either (when OpenMP expansion creates
467 child function from already instrumented body). */
468 if (cgraph_state == CGRAPH_STATE_FINISHED
469 || cfun->after_tree_profile)
472 /* Re-set global shared temporary variable for edge-counters. */
473 gcov_type_tmp_var = NULL_TREE;
477 if (! flag_branch_probabilities
478 && flag_profile_values)
479 tree_gen_ic_func_profiler ();
481 if (flag_branch_probabilities
482 && flag_profile_values
483 && flag_value_profile_transformations)
484 value_profile_transformations ();
485 /* The above could hose dominator info. Currently there is
486 none coming in, this is a safety valve. It should be
487 easy to adjust it, if and when there is some. */
488 free_dominance_info (CDI_DOMINATORS);
489 free_dominance_info (CDI_POST_DOMINATORS);
490 cfun->after_tree_profile = 1;
494 struct gimple_opt_pass pass_tree_profile =
498 "tree_profile", /* name */
499 do_tree_profiling, /* gate */
500 tree_profiling, /* execute */
503 0, /* static_pass_number */
504 TV_BRANCH_PROB, /* tv_id */
505 PROP_gimple_leh | PROP_cfg, /* properties_required */
506 0, /* properties_provided */
507 0, /* properties_destroyed */
508 0, /* todo_flags_start */
509 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */
513 struct profile_hooks tree_profile_hooks =
515 tree_init_edge_profiler, /* init_edge_profiler */
516 tree_gen_edge_profiler, /* gen_edge_profiler */
517 tree_gen_interval_profiler, /* gen_interval_profiler */
518 tree_gen_pow2_profiler, /* gen_pow2_profiler */
519 tree_gen_one_value_profiler, /* gen_one_value_profiler */
520 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
521 tree_gen_ic_profiler, /* gen_ic_profiler */
522 tree_gen_average_profiler, /* gen_average_profiler */
523 tree_gen_ior_profiler /* gen_ior_profiler */
526 #include "gt-tree-profile.h"