Import gcc-4.4.1
[dragonfly.git] / contrib / gcc-4.4 / gcc / tree-profile.c
blob4467668a8858632e7af13b0f5081987d1d38bfb9
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 address
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 /* New call was added, make goto call edges if neccesary. */
167 static void
168 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
170 gimple stmt = gsi_stmt (gsi);
172 if (!stmt_can_make_abnormal_goto (stmt))
173 return;
174 if (!gsi_end_p (gsi))
175 split_block (gimple_bb (stmt), stmt);
176 make_abnormal_goto_edges (gimple_bb (stmt), true);
179 /* Output instructions as GIMPLE trees to increment the edge
180 execution count, and insert them on E. We rely on
181 gsi_insert_on_edge to preserve the order. */
183 static void
184 tree_gen_edge_profiler (int edgeno, edge e)
186 tree ref, one;
187 gimple stmt1, stmt2, stmt3;
189 /* We share one temporary variable declaration per function. This
190 gets re-set in tree_profiling. */
191 if (gcov_type_tmp_var == NULL_TREE)
192 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
193 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
194 one = build_int_cst (gcov_type_node, 1);
195 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
196 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
197 gcov_type_tmp_var, one);
198 stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
199 gsi_insert_on_edge (e, stmt1);
200 gsi_insert_on_edge (e, stmt2);
201 gsi_insert_on_edge (e, stmt3);
204 /* Emits code to get VALUE to instrument at GSI, and returns the
205 variable containing the value. */
207 static tree
208 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
210 tree val = value->hvalue.value;
211 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
212 true, NULL_TREE, true, GSI_SAME_STMT);
215 /* Output instructions as GIMPLE trees to increment the interval histogram
216 counter. VALUE is the expression whose value is profiled. TAG is the
217 tag of the section for counters, BASE is offset of the counter position. */
219 static void
220 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
222 gimple stmt = value->hvalue.stmt;
223 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
224 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
225 gimple call;
226 tree val;
227 tree start = build_int_cst_type (integer_type_node,
228 value->hdata.intvl.int_start);
229 tree steps = build_int_cst_type (unsigned_type_node,
230 value->hdata.intvl.steps);
232 ref_ptr = force_gimple_operand_gsi (&gsi,
233 build_addr (ref, current_function_decl),
234 true, NULL_TREE, true, GSI_SAME_STMT);
235 val = prepare_instrumented_value (&gsi, value);
236 call = gimple_build_call (tree_interval_profiler_fn, 4,
237 ref_ptr, val, start, steps);
238 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
239 add_abnormal_goto_call_edges (gsi);
242 /* Output instructions as GIMPLE trees to increment the power of two histogram
243 counter. VALUE is the expression whose value is profiled. TAG is the tag
244 of the section for counters, BASE is offset of the counter position. */
246 static void
247 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
249 gimple stmt = value->hvalue.stmt;
250 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
251 tree ref_ptr = tree_coverage_counter_addr (tag, base);
252 gimple call;
253 tree val;
255 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
256 true, NULL_TREE, true, GSI_SAME_STMT);
257 val = prepare_instrumented_value (&gsi, value);
258 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
259 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
260 add_abnormal_goto_call_edges (gsi);
263 /* Output instructions as GIMPLE trees for code to find the most common value.
264 VALUE is the expression whose value is profiled. TAG is the tag of the
265 section for counters, BASE is offset of the counter position. */
267 static void
268 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
270 gimple stmt = value->hvalue.stmt;
271 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
272 tree ref_ptr = tree_coverage_counter_addr (tag, base);
273 gimple call;
274 tree val;
276 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
277 true, NULL_TREE, true, GSI_SAME_STMT);
278 val = prepare_instrumented_value (&gsi, value);
279 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
280 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
281 add_abnormal_goto_call_edges (gsi);
285 /* Output instructions as GIMPLE trees for code to find the most
286 common called function in indirect call.
287 VALUE is the call expression whose indirect callee is profiled.
288 TAG is the tag of the section for counters, BASE is offset of the
289 counter position. */
291 static void
292 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
294 tree tmp1;
295 gimple stmt1, stmt2, stmt3;
296 gimple stmt = value->hvalue.stmt;
297 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
298 tree ref_ptr = tree_coverage_counter_addr (tag, base);
300 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
301 true, NULL_TREE, true, GSI_SAME_STMT);
303 /* Insert code:
305 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
306 __gcov_indirect_call_callee = (void *) indirect call argument;
309 tmp1 = create_tmp_var (ptr_void, "PROF");
310 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
311 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
312 stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
314 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
315 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
316 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
320 /* Output instructions as GIMPLE trees for code to find the most
321 common called function in indirect call. Insert instructions at the
322 beginning of every possible called function.
325 static void
326 tree_gen_ic_func_profiler (void)
328 struct cgraph_node * c_node = cgraph_node (current_function_decl);
329 gimple_stmt_iterator gsi;
330 edge e;
331 basic_block bb;
332 edge_iterator ei;
333 gimple stmt1, stmt2;
334 tree tree_uid, cur_func;
336 if (!c_node->needed)
337 return;
339 tree_init_edge_profiler ();
341 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
343 tree void0;
345 bb = split_edge (e);
346 gsi = gsi_start_bb (bb);
348 cur_func = force_gimple_operand_gsi (&gsi,
349 build_addr (current_function_decl,
350 current_function_decl),
351 true, NULL_TREE,
352 true, GSI_SAME_STMT);
353 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
354 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
355 ic_gcov_type_ptr_var,
356 tree_uid,
357 cur_func,
358 ic_void_ptr_var);
359 gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
360 gcc_assert (EDGE_COUNT (bb->succs) == 1);
361 bb = split_edge (EDGE_I (bb->succs, 0));
362 add_abnormal_goto_call_edges (gsi);
364 gsi = gsi_start_bb (bb);
365 /* Set __gcov_indirect_call_callee to 0,
366 so that calls from other modules won't get misattributed
367 to the last caller of the current callee. */
368 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
369 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
370 gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
374 /* Output instructions as GIMPLE trees for code to find the most common value
375 of a difference between two evaluations of an expression.
376 VALUE is the expression whose value is profiled. TAG is the tag of the
377 section for counters, BASE is offset of the counter position. */
379 static void
380 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
381 unsigned tag ATTRIBUTE_UNUSED,
382 unsigned base ATTRIBUTE_UNUSED)
384 /* FIXME implement this. */
385 #ifdef ENABLE_CHECKING
386 internal_error ("unimplemented functionality");
387 #endif
388 gcc_unreachable ();
391 /* Output instructions as GIMPLE trees to increment the average 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_average_profiler (histogram_value value, unsigned tag, unsigned base)
398 gimple stmt = value->hvalue.stmt;
399 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
400 tree ref_ptr = tree_coverage_counter_addr (tag, base);
401 gimple call;
402 tree val;
404 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
405 true, NULL_TREE,
406 true, GSI_SAME_STMT);
407 val = prepare_instrumented_value (&gsi, value);
408 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
409 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
410 add_abnormal_goto_call_edges (gsi);
413 /* Output instructions as GIMPLE trees to increment the ior histogram
414 counter. VALUE is the expression whose value is profiled. TAG is the
415 tag of the section for counters, BASE is offset of the counter position. */
417 static void
418 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
420 gimple stmt = value->hvalue.stmt;
421 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
422 tree ref_ptr = tree_coverage_counter_addr (tag, base);
423 gimple call;
424 tree val;
426 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
427 true, NULL_TREE, true, GSI_SAME_STMT);
428 val = prepare_instrumented_value (&gsi, value);
429 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
430 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
431 add_abnormal_goto_call_edges (gsi);
434 /* Return 1 if tree-based profiling is in effect, else 0.
435 If it is, set up hooks for tree-based profiling.
436 Gate for pass_tree_profile. */
438 static bool
439 do_tree_profiling (void)
441 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
443 tree_register_profile_hooks ();
444 gimple_register_value_prof_hooks ();
445 return true;
447 return false;
450 static unsigned int
451 tree_profiling (void)
453 /* Don't profile functions produced at destruction time, particularly
454 the gcov datastructure initializer. Don't profile if it has been
455 already instrumented either (when OpenMP expansion creates
456 child function from already instrumented body). */
457 if (cgraph_state == CGRAPH_STATE_FINISHED
458 || cfun->after_tree_profile)
459 return 0;
461 /* Re-set global shared temporary variable for edge-counters. */
462 gcov_type_tmp_var = NULL_TREE;
464 branch_prob ();
466 if (! flag_branch_probabilities
467 && flag_profile_values)
468 tree_gen_ic_func_profiler ();
470 if (flag_branch_probabilities
471 && flag_profile_values
472 && flag_value_profile_transformations)
473 value_profile_transformations ();
474 /* The above could hose dominator info. Currently there is
475 none coming in, this is a safety valve. It should be
476 easy to adjust it, if and when there is some. */
477 free_dominance_info (CDI_DOMINATORS);
478 free_dominance_info (CDI_POST_DOMINATORS);
479 cfun->after_tree_profile = 1;
480 return 0;
483 struct gimple_opt_pass pass_tree_profile =
486 GIMPLE_PASS,
487 "tree_profile", /* name */
488 do_tree_profiling, /* gate */
489 tree_profiling, /* execute */
490 NULL, /* sub */
491 NULL, /* next */
492 0, /* static_pass_number */
493 TV_BRANCH_PROB, /* tv_id */
494 PROP_gimple_leh | PROP_cfg, /* properties_required */
495 PROP_gimple_leh | PROP_cfg, /* properties_provided */
496 0, /* properties_destroyed */
497 0, /* todo_flags_start */
498 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */
502 struct profile_hooks tree_profile_hooks =
504 tree_init_edge_profiler, /* init_edge_profiler */
505 tree_gen_edge_profiler, /* gen_edge_profiler */
506 tree_gen_interval_profiler, /* gen_interval_profiler */
507 tree_gen_pow2_profiler, /* gen_pow2_profiler */
508 tree_gen_one_value_profiler, /* gen_one_value_profiler */
509 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
510 tree_gen_ic_profiler, /* gen_ic_profiler */
511 tree_gen_average_profiler, /* gen_average_profiler */
512 tree_gen_ior_profiler /* gen_ior_profiler */
515 #include "gt-tree-profile.h"