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
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"
42 #include "tree-flow.h"
43 #include "tree-dump.h"
44 #include "tree-pass.h"
46 #include "value-prof.h"
50 static GTY(()) tree gcov_type_node;
51 static GTY(()) tree gcov_type_tmp_var;
52 static GTY(()) tree tree_interval_profiler_fn;
53 static GTY(()) tree tree_pow2_profiler_fn;
54 static GTY(()) tree tree_one_value_profiler_fn;
55 static GTY(()) tree tree_indirect_call_profiler_fn;
56 static GTY(()) tree tree_average_profiler_fn;
57 static GTY(()) tree tree_ior_profiler_fn;
60 static GTY(()) tree ic_void_ptr_var;
61 static GTY(()) tree ic_gcov_type_ptr_var;
62 static GTY(()) tree ptr_void;
64 /* Do initialization work for the edge profiler. */
67 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
68 static void* __gcov_indirect_call_callee; // actual callee address
71 tree_init_ic_make_global_vars (void)
75 ptr_void = build_pointer_type (void_type_node);
78 = build_decl (VAR_DECL,
79 get_identifier ("__gcov_indirect_call_callee"),
81 TREE_STATIC (ic_void_ptr_var) = 1;
82 TREE_PUBLIC (ic_void_ptr_var) = 0;
83 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
84 DECL_INITIAL (ic_void_ptr_var) = NULL;
85 assemble_variable (ic_void_ptr_var, 0, 0, 0);
87 gcov_type_ptr = build_pointer_type (get_gcov_type ());
89 = build_decl (VAR_DECL,
90 get_identifier ("__gcov_indirect_call_counters"),
92 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
93 TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
94 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
95 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
96 assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
100 tree_init_edge_profiler (void)
102 tree interval_profiler_fn_type;
103 tree pow2_profiler_fn_type;
104 tree one_value_profiler_fn_type;
106 tree ic_profiler_fn_type;
107 tree average_profiler_fn_type;
111 gcov_type_node = get_gcov_type ();
112 gcov_type_ptr = build_pointer_type (gcov_type_node);
114 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
115 interval_profiler_fn_type
116 = build_function_type_list (void_type_node,
117 gcov_type_ptr, gcov_type_node,
119 unsigned_type_node, NULL_TREE);
120 tree_interval_profiler_fn
121 = build_fn_decl ("__gcov_interval_profiler",
122 interval_profiler_fn_type);
124 /* void (*) (gcov_type *, gcov_type) */
125 pow2_profiler_fn_type
126 = build_function_type_list (void_type_node,
127 gcov_type_ptr, gcov_type_node,
129 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
130 pow2_profiler_fn_type);
132 /* void (*) (gcov_type *, gcov_type) */
133 one_value_profiler_fn_type
134 = build_function_type_list (void_type_node,
135 gcov_type_ptr, gcov_type_node,
137 tree_one_value_profiler_fn
138 = build_fn_decl ("__gcov_one_value_profiler",
139 one_value_profiler_fn_type);
141 tree_init_ic_make_global_vars ();
143 /* void (*) (gcov_type *, gcov_type, void *, void *) */
145 = build_function_type_list (void_type_node,
146 gcov_type_ptr, gcov_type_node,
148 ptr_void, NULL_TREE);
149 tree_indirect_call_profiler_fn
150 = build_fn_decl ("__gcov_indirect_call_profiler",
151 ic_profiler_fn_type);
152 /* void (*) (gcov_type *, gcov_type) */
153 average_profiler_fn_type
154 = build_function_type_list (void_type_node,
155 gcov_type_ptr, gcov_type_node, NULL_TREE);
156 tree_average_profiler_fn
157 = build_fn_decl ("__gcov_average_profiler",
158 average_profiler_fn_type);
160 = build_fn_decl ("__gcov_ior_profiler",
161 average_profiler_fn_type);
165 /* Output instructions as GIMPLE trees to increment the edge
166 execution count, and insert them on E. We rely on
167 bsi_insert_on_edge to preserve the order. */
170 tree_gen_edge_profiler (int edgeno, edge e)
172 tree ref, one, stmt1, stmt2, stmt3;
174 /* We share one temporary variable declaration per function. This
175 gets re-set in tree_profiling. */
176 if (gcov_type_tmp_var == NULL_TREE)
177 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
178 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
179 one = build_int_cst (gcov_type_node, 1);
180 stmt1 = build_gimple_modify_stmt (gcov_type_tmp_var, ref);
181 stmt2 = build_gimple_modify_stmt (gcov_type_tmp_var,
182 build2 (PLUS_EXPR, gcov_type_node,
183 gcov_type_tmp_var, one));
184 stmt3 = build_gimple_modify_stmt (unshare_expr (ref), gcov_type_tmp_var);
185 bsi_insert_on_edge (e, stmt1);
186 bsi_insert_on_edge (e, stmt2);
187 bsi_insert_on_edge (e, stmt3);
190 /* Emits code to get VALUE to instrument at BSI, and returns the
191 variable containing the value. */
194 prepare_instrumented_value (block_stmt_iterator *bsi,
195 histogram_value value)
197 tree val = value->hvalue.value;
198 return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
199 true, NULL_TREE, true, BSI_SAME_STMT);
202 /* Output instructions as GIMPLE trees to increment the interval histogram
203 counter. VALUE is the expression whose value is profiled. TAG is the
204 tag of the section for counters, BASE is offset of the counter position. */
207 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
209 tree stmt = value->hvalue.stmt;
210 block_stmt_iterator bsi = bsi_for_stmt (stmt);
211 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
213 tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start);
214 tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps);
216 ref_ptr = force_gimple_operand_bsi (&bsi,
217 build_addr (ref, current_function_decl),
218 true, NULL_TREE, true, BSI_SAME_STMT);
219 val = prepare_instrumented_value (&bsi, value);
220 call = build_call_expr (tree_interval_profiler_fn, 4,
221 ref_ptr, val, start, steps);
222 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
225 /* Output instructions as GIMPLE trees to increment the power of two histogram
226 counter. VALUE is the expression whose value is profiled. TAG is the tag
227 of the section for counters, BASE is offset of the counter position. */
230 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
232 tree stmt = value->hvalue.stmt;
233 block_stmt_iterator bsi = bsi_for_stmt (stmt);
234 tree ref_ptr = tree_coverage_counter_addr (tag, base);
237 ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
238 true, NULL_TREE, true, BSI_SAME_STMT);
239 val = prepare_instrumented_value (&bsi, value);
240 call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val);
241 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
244 /* Output instructions as GIMPLE trees for code to find the most common value.
245 VALUE is the expression whose value is profiled. TAG is the tag of the
246 section for counters, BASE is offset of the counter position. */
249 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
251 tree stmt = value->hvalue.stmt;
252 block_stmt_iterator bsi = bsi_for_stmt (stmt);
253 tree ref_ptr = tree_coverage_counter_addr (tag, base);
256 ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
257 true, NULL_TREE, true, BSI_SAME_STMT);
258 val = prepare_instrumented_value (&bsi, value);
259 call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val);
260 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
264 /* Output instructions as GIMPLE trees for code to find the most
265 common called function in indirect call.
266 VALUE is the call expression whose indirect callee is profiled.
267 TAG is the tag of the section for counters, BASE is offset of the
271 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
273 tree tmp1, stmt1, stmt2, stmt3;
274 tree stmt = value->hvalue.stmt;
275 block_stmt_iterator bsi = bsi_for_stmt (stmt);
276 tree ref_ptr = tree_coverage_counter_addr (tag, base);
278 ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
279 true, NULL_TREE, true, BSI_SAME_STMT);
283 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
284 __gcov_indirect_call_callee = (void *) indirect call argument;
287 tmp1 = create_tmp_var (ptr_void, "PROF");
288 stmt1 = build_gimple_modify_stmt (ic_gcov_type_ptr_var, ref_ptr);
289 stmt2 = build_gimple_modify_stmt (tmp1, unshare_expr (value->hvalue.value));
290 stmt3 = build_gimple_modify_stmt (ic_void_ptr_var, tmp1);
292 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
293 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
294 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
298 /* Output instructions as GIMPLE trees for code to find the most
299 common called function in indirect call. Insert instructions at the
300 beginning of every possible called function.
304 tree_gen_ic_func_profiler (void)
306 struct cgraph_node * c_node = cgraph_node (current_function_decl);
307 block_stmt_iterator bsi;
312 tree tree_uid, cur_func;
317 tree_init_edge_profiler ();
319 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
324 bsi = bsi_start (bb);
326 cur_func = force_gimple_operand_bsi (&bsi,
327 build_addr (current_function_decl,
328 current_function_decl),
330 true, BSI_SAME_STMT);
331 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
332 stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4,
333 ic_gcov_type_ptr_var,
337 bsi_insert_after (&bsi, stmt1, BSI_NEW_STMT);
339 gcc_assert (EDGE_COUNT (bb->succs) == 1);
340 bb = split_edge (EDGE_I (bb->succs, 0));
341 bsi = bsi_start (bb);
342 /* Set __gcov_indirect_call_callee to 0,
343 so that calls from other modules won't get misattributed
344 to the last caller of the current callee. */
345 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
346 stmt2 = build_gimple_modify_stmt (ic_void_ptr_var, void0);
347 bsi_insert_after (&bsi, stmt2, BSI_NEW_STMT);
351 /* Output instructions as GIMPLE trees for code to find the most common value
352 of a difference between two evaluations of an expression.
353 VALUE is the expression whose value is profiled. TAG is the tag of the
354 section for counters, BASE is offset of the counter position. */
357 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
358 unsigned tag ATTRIBUTE_UNUSED,
359 unsigned base ATTRIBUTE_UNUSED)
361 /* FIXME implement this. */
362 #ifdef ENABLE_CHECKING
363 internal_error ("unimplemented functionality");
368 /* Output instructions as GIMPLE trees to increment the average histogram
369 counter. VALUE is the expression whose value is profiled. TAG is the
370 tag of the section for counters, BASE is offset of the counter position. */
373 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
375 tree stmt = value->hvalue.stmt;
376 block_stmt_iterator bsi = bsi_for_stmt (stmt);
377 tree ref_ptr = tree_coverage_counter_addr (tag, base);
380 ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
382 true, BSI_SAME_STMT);
383 val = prepare_instrumented_value (&bsi, value);
384 call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val);
385 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
388 /* Output instructions as GIMPLE trees to increment the ior histogram
389 counter. VALUE is the expression whose value is profiled. TAG is the
390 tag of the section for counters, BASE is offset of the counter position. */
393 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
395 tree stmt = value->hvalue.stmt;
396 block_stmt_iterator bsi = bsi_for_stmt (stmt);
397 tree ref_ptr = tree_coverage_counter_addr (tag, base);
400 ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
401 true, NULL_TREE, true, BSI_SAME_STMT);
402 val = prepare_instrumented_value (&bsi, value);
403 call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val);
404 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
407 /* Return 1 if tree-based profiling is in effect, else 0.
408 If it is, set up hooks for tree-based profiling.
409 Gate for pass_tree_profile. */
412 do_tree_profiling (void)
414 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
416 tree_register_profile_hooks ();
417 tree_register_value_prof_hooks ();
424 tree_profiling (void)
426 /* Don't profile functions produced at destruction time, particularly
427 the gcov datastructure initializer. Don't profile if it has been
428 already instrumented either (when OpenMP expansion creates
429 child function from already instrumented body). */
430 if (cgraph_state == CGRAPH_STATE_FINISHED
431 || cfun->after_tree_profile)
434 /* Re-set global shared temporary variable for edge-counters. */
435 gcov_type_tmp_var = NULL_TREE;
439 if (! flag_branch_probabilities
440 && flag_profile_values)
441 tree_gen_ic_func_profiler ();
443 if (flag_branch_probabilities
444 && flag_profile_values
445 && flag_value_profile_transformations)
446 value_profile_transformations ();
447 /* The above could hose dominator info. Currently there is
448 none coming in, this is a safety valve. It should be
449 easy to adjust it, if and when there is some. */
450 free_dominance_info (CDI_DOMINATORS);
451 free_dominance_info (CDI_POST_DOMINATORS);
452 cfun->after_tree_profile = 1;
456 struct gimple_opt_pass pass_tree_profile =
460 "tree_profile", /* name */
461 do_tree_profiling, /* gate */
462 tree_profiling, /* execute */
465 0, /* static_pass_number */
466 TV_BRANCH_PROB, /* tv_id */
467 PROP_gimple_leh | PROP_cfg, /* properties_required */
468 PROP_gimple_leh | PROP_cfg, /* properties_provided */
469 0, /* properties_destroyed */
470 0, /* todo_flags_start */
471 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */
475 struct profile_hooks tree_profile_hooks =
477 tree_init_edge_profiler, /* init_edge_profiler */
478 tree_gen_edge_profiler, /* gen_edge_profiler */
479 tree_gen_interval_profiler, /* gen_interval_profiler */
480 tree_gen_pow2_profiler, /* gen_pow2_profiler */
481 tree_gen_one_value_profiler, /* gen_one_value_profiler */
482 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
483 tree_gen_ic_profiler, /* gen_ic_profiler */
484 tree_gen_average_profiler, /* gen_average_profiler */
485 tree_gen_ior_profiler /* gen_ior_profiler */
488 #include "gt-tree-profile.h"