2008-01-25 Douglas Gregor <doug.gregor@gmail.com>
[official-gcc.git] / gcc / tree-profile.c
blob00fbd862ad9a6816599585197a51fbc3e4e7fab0
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
15 version.
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
20 for more details.
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. */
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "rtl.h"
34 #include "flags.h"
35 #include "output.h"
36 #include "regs.h"
37 #include "expr.h"
38 #include "function.h"
39 #include "toplev.h"
40 #include "coverage.h"
41 #include "tree.h"
42 #include "tree-flow.h"
43 #include "tree-dump.h"
44 #include "tree-pass.h"
45 #include "timevar.h"
46 #include "value-prof.h"
47 #include "ggc.h"
48 #include "cgraph.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. */
66 /* Add code:
67 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
68 static void* __gcov_indirect_call_callee; // actual callee addres
70 static void
71 tree_init_ic_make_global_vars (void)
73 tree gcov_type_ptr;
75 ptr_void = build_pointer_type (void_type_node);
77 ic_void_ptr_var
78 = build_decl (VAR_DECL,
79 get_identifier ("__gcov_indirect_call_callee"),
80 ptr_void);
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 ());
88 ic_gcov_type_ptr_var
89 = build_decl (VAR_DECL,
90 get_identifier ("__gcov_indirect_call_counters"),
91 gcov_type_ptr);
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);
99 static void
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;
105 tree gcov_type_ptr;
106 tree ic_profiler_fn_type;
107 tree average_profiler_fn_type;
109 if (!gcov_type_node)
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,
118 integer_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,
128 NULL_TREE);
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,
136 NULL_TREE);
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 *) */
144 ic_profiler_fn_type
145 = build_function_type_list (void_type_node,
146 gcov_type_ptr, gcov_type_node,
147 ptr_void,
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);
159 tree_ior_profiler_fn
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. */
169 static void
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 (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. */
193 static tree
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. */
206 static void
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;
212 tree call, val;
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. */
229 static void
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 = tree_coverage_counter_ref (tag, base), ref_ptr;
235 tree call, val;
237 ref_ptr = force_gimple_operand_bsi (&bsi,
238 build_addr (ref, current_function_decl),
239 true, NULL_TREE, true, BSI_SAME_STMT);
240 val = prepare_instrumented_value (&bsi, value);
241 call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val);
242 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
245 /* Output instructions as GIMPLE trees for code to find the most common value.
246 VALUE is the expression whose value is profiled. TAG is the tag of the
247 section for counters, BASE is offset of the counter position. */
249 static void
250 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
252 tree stmt = value->hvalue.stmt;
253 block_stmt_iterator bsi = bsi_for_stmt (stmt);
254 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
255 tree call, val;
257 ref_ptr = force_gimple_operand_bsi (&bsi,
258 build_addr (ref, current_function_decl),
259 true, NULL_TREE, true, BSI_SAME_STMT);
260 val = prepare_instrumented_value (&bsi, value);
261 call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val);
262 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
266 /* Output instructions as GIMPLE trees for code to find the most
267 common called function in indirect call.
268 VALUE is the call expression whose indirect callee is profiled.
269 TAG is the tag of the section for counters, BASE is offset of the
270 counter position. */
272 static void
273 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
275 tree tmp1, stmt1, stmt2, stmt3;
276 tree stmt = value->hvalue.stmt;
277 block_stmt_iterator bsi = bsi_for_stmt (stmt);
278 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
280 ref_ptr = force_gimple_operand_bsi (&bsi,
281 build_addr (ref, current_function_decl),
282 true, NULL_TREE, true, BSI_SAME_STMT);
284 /* Insert code:
286 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
287 __gcov_indirect_call_callee = (void *) indirect call argument;
290 tmp1 = create_tmp_var (ptr_void, "PROF");
291 stmt1 = build_gimple_modify_stmt (ic_gcov_type_ptr_var, ref_ptr);
292 stmt2 = build_gimple_modify_stmt (tmp1, unshare_expr (value->hvalue.value));
293 stmt3 = build_gimple_modify_stmt (ic_void_ptr_var, tmp1);
295 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
296 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
297 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
301 /* Output instructions as GIMPLE trees for code to find the most
302 common called function in indirect call. Insert instructions at the
303 beginning of every possible called function.
306 static void
307 tree_gen_ic_func_profiler (void)
309 struct cgraph_node * c_node = cgraph_node (current_function_decl);
310 block_stmt_iterator bsi;
311 edge e;
312 basic_block bb;
313 edge_iterator ei;
314 tree stmt1;
315 tree tree_uid, cur_func;
317 if (flag_unit_at_a_time)
319 if (!c_node->needed)
320 return;
323 tree_init_edge_profiler ();
325 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
327 bb = split_edge (e);
328 bsi = bsi_start (bb);
329 cur_func = force_gimple_operand_bsi (&bsi,
330 build_addr (current_function_decl,
331 current_function_decl),
332 true, NULL_TREE,
333 true, BSI_SAME_STMT);
334 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
335 stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4,
336 ic_gcov_type_ptr_var,
337 tree_uid,
338 cur_func,
339 ic_void_ptr_var);
340 bsi_insert_after (&bsi, stmt1, BSI_NEW_STMT);
344 /* Output instructions as GIMPLE trees for code to find the most common value
345 of a difference between two evaluations of an expression.
346 VALUE is the expression whose value is profiled. TAG is the tag of the
347 section for counters, BASE is offset of the counter position. */
349 static void
350 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
351 unsigned tag ATTRIBUTE_UNUSED,
352 unsigned base ATTRIBUTE_UNUSED)
354 /* FIXME implement this. */
355 #ifdef ENABLE_CHECKING
356 internal_error ("unimplemented functionality");
357 #endif
358 gcc_unreachable ();
361 /* Output instructions as GIMPLE trees to increment the average histogram
362 counter. VALUE is the expression whose value is profiled. TAG is the
363 tag of the section for counters, BASE is offset of the counter position. */
365 static void
366 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
368 tree stmt = value->hvalue.stmt;
369 block_stmt_iterator bsi = bsi_for_stmt (stmt);
370 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
371 tree call, val;
373 ref_ptr = force_gimple_operand_bsi (&bsi,
374 build_addr (ref, current_function_decl),
375 true, NULL_TREE,
376 true, BSI_SAME_STMT);
377 val = prepare_instrumented_value (&bsi, value);
378 call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val);
379 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
382 /* Output instructions as GIMPLE trees to increment the ior histogram
383 counter. VALUE is the expression whose value is profiled. TAG is the
384 tag of the section for counters, BASE is offset of the counter position. */
386 static void
387 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
389 tree stmt = value->hvalue.stmt;
390 block_stmt_iterator bsi = bsi_for_stmt (stmt);
391 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
392 tree call, val;
394 ref_ptr = force_gimple_operand_bsi (&bsi,
395 build_addr (ref, current_function_decl),
396 true, NULL_TREE, true, BSI_SAME_STMT);
397 val = prepare_instrumented_value (&bsi, value);
398 call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val);
399 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
402 /* Return 1 if tree-based profiling is in effect, else 0.
403 If it is, set up hooks for tree-based profiling.
404 Gate for pass_tree_profile. */
406 static bool
407 do_tree_profiling (void)
409 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
411 tree_register_profile_hooks ();
412 tree_register_value_prof_hooks ();
413 return true;
415 return false;
418 static unsigned int
419 tree_profiling (void)
421 /* Don't profile functions produced at destruction time, particularly
422 the gcov datastructure initializer. Don't profile if it has been
423 already instrumented either (when OpenMP expansion creates
424 child function from already instrumented body). */
425 if (cgraph_state == CGRAPH_STATE_FINISHED
426 || cfun->after_tree_profile)
427 return 0;
429 /* Re-set global shared temporary variable for edge-counters. */
430 gcov_type_tmp_var = NULL_TREE;
432 branch_prob ();
434 if (! flag_branch_probabilities
435 && flag_profile_values)
436 tree_gen_ic_func_profiler ();
438 if (flag_branch_probabilities
439 && flag_profile_values
440 && flag_value_profile_transformations)
441 value_profile_transformations ();
442 /* The above could hose dominator info. Currently there is
443 none coming in, this is a safety valve. It should be
444 easy to adjust it, if and when there is some. */
445 free_dominance_info (CDI_DOMINATORS);
446 free_dominance_info (CDI_POST_DOMINATORS);
447 cfun->after_tree_profile = 1;
448 return 0;
451 struct tree_opt_pass pass_tree_profile =
453 "tree_profile", /* name */
454 do_tree_profiling, /* gate */
455 tree_profiling, /* execute */
456 NULL, /* sub */
457 NULL, /* next */
458 0, /* static_pass_number */
459 TV_BRANCH_PROB, /* tv_id */
460 PROP_gimple_leh | PROP_cfg, /* properties_required */
461 PROP_gimple_leh | PROP_cfg, /* properties_provided */
462 0, /* properties_destroyed */
463 0, /* todo_flags_start */
464 TODO_verify_stmts | TODO_dump_func, /* todo_flags_finish */
465 0 /* letter */
468 struct profile_hooks tree_profile_hooks =
470 tree_init_edge_profiler, /* init_edge_profiler */
471 tree_gen_edge_profiler, /* gen_edge_profiler */
472 tree_gen_interval_profiler, /* gen_interval_profiler */
473 tree_gen_pow2_profiler, /* gen_pow2_profiler */
474 tree_gen_one_value_profiler, /* gen_one_value_profiler */
475 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
476 tree_gen_ic_profiler, /* gen_ic_profiler */
477 tree_gen_average_profiler, /* gen_average_profiler */
478 tree_gen_ior_profiler /* gen_ior_profiler */
481 #include "gt-tree-profile.h"