gcc/ChangeLog:
[official-gcc.git] / gcc / tree-profile.c
blobbd7556a074a77331919dc3709803806802a18b84
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 Free Software Foundation, Inc.
4 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5 based on some ideas from Dain Samples of UC Berkeley.
6 Further mangling by Bob Manson, Cygnus Support.
7 Converted to use trees by Dale Johannesen, Apple Computer.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING. If not, write to the Free
23 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301, USA. */
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 tree_interval_profiler_fn;
52 static GTY(()) tree tree_pow2_profiler_fn;
53 static GTY(()) tree tree_one_value_profiler_fn;
54 static GTY(()) tree tree_indirect_call_profiler_fn;
55 static GTY(()) tree tree_average_profiler_fn;
56 static GTY(()) tree tree_ior_profiler_fn;
59 static GTY(()) tree ic_void_ptr_var;
60 static GTY(()) tree ic_gcov_type_ptr_var;
61 static GTY(()) tree ptr_void;
63 /* Do initialization work for the edge profiler. */
65 /* Add code:
66 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
67 static void* __gcov_indirect_call_callee; // actual callee addres
69 static void
70 tree_init_ic_make_global_vars (void)
72 tree gcov_type_ptr;
74 ptr_void = build_pointer_type (void_type_node);
76 ic_void_ptr_var
77 = build_decl (VAR_DECL,
78 get_identifier ("__gcov_indirect_call_callee"),
79 ptr_void);
80 TREE_STATIC (ic_void_ptr_var) = 1;
81 TREE_PUBLIC (ic_void_ptr_var) = 0;
82 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
83 DECL_INITIAL (ic_void_ptr_var) = NULL;
84 assemble_variable (ic_void_ptr_var, 0, 0, 0);
86 gcov_type_ptr = build_pointer_type (get_gcov_type ());
87 ic_gcov_type_ptr_var
88 = build_decl (VAR_DECL,
89 get_identifier ("__gcov_indirect_call_counters"),
90 gcov_type_ptr);
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 assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
98 static void
99 tree_init_edge_profiler (void)
101 tree interval_profiler_fn_type;
102 tree pow2_profiler_fn_type;
103 tree one_value_profiler_fn_type;
104 tree gcov_type_ptr;
105 tree ic_profiler_fn_type;
106 tree average_profiler_fn_type;
108 if (!gcov_type_node)
110 gcov_type_node = get_gcov_type ();
111 gcov_type_ptr = build_pointer_type (gcov_type_node);
113 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
114 interval_profiler_fn_type
115 = build_function_type_list (void_type_node,
116 gcov_type_ptr, gcov_type_node,
117 integer_type_node,
118 unsigned_type_node, NULL_TREE);
119 tree_interval_profiler_fn
120 = build_fn_decl ("__gcov_interval_profiler",
121 interval_profiler_fn_type);
123 /* void (*) (gcov_type *, gcov_type) */
124 pow2_profiler_fn_type
125 = build_function_type_list (void_type_node,
126 gcov_type_ptr, gcov_type_node,
127 NULL_TREE);
128 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
129 pow2_profiler_fn_type);
131 /* void (*) (gcov_type *, gcov_type) */
132 one_value_profiler_fn_type
133 = build_function_type_list (void_type_node,
134 gcov_type_ptr, gcov_type_node,
135 NULL_TREE);
136 tree_one_value_profiler_fn
137 = build_fn_decl ("__gcov_one_value_profiler",
138 one_value_profiler_fn_type);
140 tree_init_ic_make_global_vars ();
142 /* void (*) (gcov_type *, gcov_type, void *, void *) */
143 ic_profiler_fn_type
144 = build_function_type_list (void_type_node,
145 gcov_type_ptr, gcov_type_node,
146 ptr_void,
147 ptr_void, NULL_TREE);
148 tree_indirect_call_profiler_fn
149 = build_fn_decl ("__gcov_indirect_call_profiler",
150 ic_profiler_fn_type);
151 /* void (*) (gcov_type *, gcov_type) */
152 average_profiler_fn_type
153 = build_function_type_list (void_type_node,
154 gcov_type_ptr, gcov_type_node, NULL_TREE);
155 tree_average_profiler_fn
156 = build_fn_decl ("__gcov_average_profiler",
157 average_profiler_fn_type);
158 tree_ior_profiler_fn
159 = build_fn_decl ("__gcov_ior_profiler",
160 average_profiler_fn_type);
164 /* Output instructions as GIMPLE trees to increment the edge
165 execution count, and insert them on E. We rely on
166 bsi_insert_on_edge to preserve the order. */
168 static void
169 tree_gen_edge_profiler (int edgeno, edge e)
171 tree tmp1 = create_tmp_var (gcov_type_node, "PROF");
172 tree tmp2 = create_tmp_var (gcov_type_node, "PROF");
173 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
174 tree stmt1 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, tmp1, ref);
175 tree stmt2 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, tmp2,
176 build2 (PLUS_EXPR, gcov_type_node,
177 tmp1, integer_one_node));
178 tree stmt3 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, ref, tmp2);
179 bsi_insert_on_edge (e, stmt1);
180 bsi_insert_on_edge (e, stmt2);
181 bsi_insert_on_edge (e, stmt3);
184 /* Emits code to get VALUE to instrument at BSI, and returns the
185 variable containing the value. */
187 static tree
188 prepare_instrumented_value (block_stmt_iterator *bsi,
189 histogram_value value)
191 tree val = value->hvalue.value;
192 return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
193 true, NULL_TREE);
196 /* Output instructions as GIMPLE trees to increment the interval histogram
197 counter. VALUE is the expression whose value is profiled. TAG is the
198 tag of the section for counters, BASE is offset of the counter position. */
200 static void
201 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
203 tree stmt = value->hvalue.stmt;
204 block_stmt_iterator bsi = bsi_for_stmt (stmt);
205 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
206 tree args, call, val;
207 tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start);
208 tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps);
210 ref_ptr = force_gimple_operand_bsi (&bsi,
211 build_addr (ref, current_function_decl),
212 true, NULL_TREE);
213 val = prepare_instrumented_value (&bsi, value);
214 args = tree_cons (NULL_TREE, ref_ptr,
215 tree_cons (NULL_TREE, val,
216 tree_cons (NULL_TREE, start,
217 tree_cons (NULL_TREE, steps,
218 NULL_TREE))));
219 call = build_function_call_expr (tree_interval_profiler_fn, args);
220 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
223 /* Output instructions as GIMPLE trees to increment the power of two histogram
224 counter. VALUE is the expression whose value is profiled. TAG is the tag
225 of the section for counters, BASE is offset of the counter position. */
227 static void
228 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
230 tree stmt = value->hvalue.stmt;
231 block_stmt_iterator bsi = bsi_for_stmt (stmt);
232 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
233 tree args, call, val;
235 ref_ptr = force_gimple_operand_bsi (&bsi,
236 build_addr (ref, current_function_decl),
237 true, NULL_TREE);
238 val = prepare_instrumented_value (&bsi, value);
239 args = tree_cons (NULL_TREE, ref_ptr,
240 tree_cons (NULL_TREE, val,
241 NULL_TREE));
242 call = build_function_call_expr (tree_pow2_profiler_fn, args);
243 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
246 /* Output instructions as GIMPLE trees for code to find the most common value.
247 VALUE is the expression whose value is profiled. TAG is the tag of the
248 section for counters, BASE is offset of the counter position. */
250 static void
251 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
253 tree stmt = value->hvalue.stmt;
254 block_stmt_iterator bsi = bsi_for_stmt (stmt);
255 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
256 tree args, call, val;
258 ref_ptr = force_gimple_operand_bsi (&bsi,
259 build_addr (ref, current_function_decl),
260 true, NULL_TREE);
261 val = prepare_instrumented_value (&bsi, value);
262 args = tree_cons (NULL_TREE, ref_ptr,
263 tree_cons (NULL_TREE, val,
264 NULL_TREE));
265 call = build_function_call_expr (tree_one_value_profiler_fn, args);
266 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
270 /* Output instructions as GIMPLE trees for code to find the most
271 common called function in indirect call.
272 VALUE is the call expression whose indirect callee is profiled.
273 TAG is the tag of the section for counters, BASE is offset of the
274 counter position. */
276 static void
277 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
279 tree tmp1, stmt1, stmt2, stmt3;
280 tree stmt = value->hvalue.stmt;
281 block_stmt_iterator bsi = bsi_for_stmt (stmt);
282 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
284 ref_ptr = force_gimple_operand_bsi (&bsi,
285 build_addr (ref, current_function_decl),
286 true, NULL_TREE);
288 /* Insert code:
290 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
291 __gcov_indirect_call_callee = (void *) indirect call argument;
294 tmp1 = create_tmp_var (ptr_void, "PROF");
295 stmt1 = build2 (GIMPLE_MODIFY_STMT,
296 build_pointer_type (get_gcov_type ()),
297 ic_gcov_type_ptr_var, ref_ptr);
298 stmt2 = build2 (GIMPLE_MODIFY_STMT, ptr_void, tmp1,
299 unshare_expr (value->hvalue.value));
300 stmt3 = build2 (GIMPLE_MODIFY_STMT, ptr_void,
301 ic_void_ptr_var, tmp1);
303 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
304 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
305 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
309 /* Output instructions as GIMPLE trees for code to find the most
310 common called function in indirect call. Insert instructions at the
311 beginning of every possible called function.
314 static void
315 tree_gen_ic_func_profiler (void)
317 struct cgraph_node * c_node = cgraph_node (current_function_decl);
318 block_stmt_iterator bsi;
319 edge e;
320 basic_block bb;
321 edge_iterator ei;
322 tree stmt1;
323 tree args, tree_uid, cur_func;
325 if (flag_unit_at_a_time)
327 if (!c_node->needed)
328 return;
331 tree_init_edge_profiler ();
333 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
335 bb = split_edge (e);
336 bsi = bsi_start (bb);
337 cur_func = force_gimple_operand_bsi (&bsi,
338 build_addr (current_function_decl,
339 current_function_decl),
340 true, NULL_TREE);
341 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
342 args = tree_cons (NULL_TREE, ic_gcov_type_ptr_var,
343 tree_cons (NULL_TREE, tree_uid,
344 tree_cons (NULL_TREE, cur_func,
345 tree_cons (NULL_TREE,
346 ic_void_ptr_var,
347 NULL_TREE))));
348 stmt1 = build_function_call_expr (tree_indirect_call_profiler_fn, args);
349 bsi_insert_after (&bsi, stmt1, BSI_SAME_STMT);
353 /* Output instructions as GIMPLE trees for code to find the most common value
354 of a difference between two evaluations of an expression.
355 VALUE is the expression whose value is profiled. TAG is the tag of the
356 section for counters, BASE is offset of the counter position. */
358 static void
359 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
360 unsigned tag ATTRIBUTE_UNUSED,
361 unsigned base ATTRIBUTE_UNUSED)
363 /* FIXME implement this. */
364 #ifdef ENABLE_CHECKING
365 internal_error ("unimplemented functionality");
366 #endif
367 gcc_unreachable ();
370 /* Output instructions as GIMPLE trees to increment the average histogram
371 counter. VALUE is the expression whose value is profiled. TAG is the
372 tag of the section for counters, BASE is offset of the counter position. */
374 static void
375 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
377 tree stmt = value->hvalue.stmt;
378 block_stmt_iterator bsi = bsi_for_stmt (stmt);
379 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
380 tree args, call, val;
382 ref_ptr = force_gimple_operand_bsi (&bsi,
383 build_addr (ref, current_function_decl),
384 true, NULL_TREE);
385 val = prepare_instrumented_value (&bsi, value);
386 args = tree_cons (NULL_TREE, ref_ptr, tree_cons (NULL_TREE, val, NULL_TREE));
387 call = build_function_call_expr (tree_average_profiler_fn, args);
388 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
391 /* Output instructions as GIMPLE trees to increment the ior histogram
392 counter. VALUE is the expression whose value is profiled. TAG is the
393 tag of the section for counters, BASE is offset of the counter position. */
395 static void
396 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
398 tree stmt = value->hvalue.stmt;
399 block_stmt_iterator bsi = bsi_for_stmt (stmt);
400 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
401 tree args, call, val;
403 ref_ptr = force_gimple_operand_bsi (&bsi,
404 build_addr (ref, current_function_decl),
405 true, NULL_TREE);
406 val = prepare_instrumented_value (&bsi, value);
407 args = tree_cons (NULL_TREE, ref_ptr, tree_cons (NULL_TREE, val, NULL_TREE));
408 call = build_function_call_expr (tree_ior_profiler_fn, args);
409 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
412 /* Return 1 if tree-based profiling is in effect, else 0.
413 If it is, set up hooks for tree-based profiling.
414 Gate for pass_tree_profile. */
416 static bool
417 do_tree_profiling (void)
419 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
421 tree_register_profile_hooks ();
422 tree_register_value_prof_hooks ();
423 return true;
425 return false;
428 static unsigned int
429 tree_profiling (void)
431 /* Don't profile functions produced at destruction time, particularly
432 the gcov datastructure initializer. */
433 if (cgraph_state == CGRAPH_STATE_FINISHED)
434 return 0;
435 branch_prob ();
437 if (! flag_branch_probabilities
438 && flag_profile_values)
439 tree_gen_ic_func_profiler ();
441 if (flag_branch_probabilities
442 && flag_profile_values
443 && flag_value_profile_transformations)
444 value_profile_transformations ();
445 /* The above could hose dominator info. Currently there is
446 none coming in, this is a safety valve. It should be
447 easy to adjust it, if and when there is some. */
448 free_dominance_info (CDI_DOMINATORS);
449 free_dominance_info (CDI_POST_DOMINATORS);
450 return 0;
453 struct tree_opt_pass pass_tree_profile =
455 "tree_profile", /* name */
456 do_tree_profiling, /* gate */
457 tree_profiling, /* execute */
458 NULL, /* sub */
459 NULL, /* next */
460 0, /* static_pass_number */
461 TV_BRANCH_PROB, /* tv_id */
462 PROP_gimple_leh | PROP_cfg, /* properties_required */
463 PROP_gimple_leh | PROP_cfg, /* properties_provided */
464 0, /* properties_destroyed */
465 0, /* todo_flags_start */
466 TODO_verify_stmts | TODO_dump_func, /* todo_flags_finish */
467 0 /* letter */
470 struct profile_hooks tree_profile_hooks =
472 tree_init_edge_profiler, /* init_edge_profiler */
473 tree_gen_edge_profiler, /* gen_edge_profiler */
474 tree_gen_interval_profiler, /* gen_interval_profiler */
475 tree_gen_pow2_profiler, /* gen_pow2_profiler */
476 tree_gen_one_value_profiler, /* gen_one_value_profiler */
477 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
478 tree_gen_ic_profiler, /* gen_ic_profiler */
479 tree_gen_average_profiler, /* gen_average_profiler */
480 tree_gen_ior_profiler /* gen_ior_profiler */
483 #include "gt-tree-profile.h"