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
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 2, 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 COPYING. If not, write to the Free
24 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
27 /* Generate basic block profile instrumentation and auxiliary files.
28 Tree-based version. See profile.c for overview. */
32 #include "coretypes.h"
43 #include "tree-flow.h"
44 #include "tree-dump.h"
45 #include "tree-pass.h"
47 #include "value-prof.h"
51 static GTY(()) tree gcov_type_node;
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 addres
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 tmp1 = create_tmp_var (gcov_type_node, "PROF");
173 tree tmp2 = create_tmp_var (gcov_type_node, "PROF");
174 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
175 tree one = build_int_cst (gcov_type_node, 1);
176 tree stmt1 = build_gimple_modify_stmt (tmp1, ref);
177 tree stmt2 = build_gimple_modify_stmt (tmp2,
178 build2 (PLUS_EXPR, gcov_type_node,
180 tree stmt3 = build_gimple_modify_stmt (ref, tmp2);
181 bsi_insert_on_edge (e, stmt1);
182 bsi_insert_on_edge (e, stmt2);
183 bsi_insert_on_edge (e, stmt3);
186 /* Emits code to get VALUE to instrument at BSI, and returns the
187 variable containing the value. */
190 prepare_instrumented_value (block_stmt_iterator *bsi,
191 histogram_value value)
193 tree val = value->hvalue.value;
194 return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
195 true, NULL_TREE, true, BSI_SAME_STMT);
198 /* Output instructions as GIMPLE trees to increment the interval histogram
199 counter. VALUE is the expression whose value is profiled. TAG is the
200 tag of the section for counters, BASE is offset of the counter position. */
203 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
205 tree stmt = value->hvalue.stmt;
206 block_stmt_iterator bsi = bsi_for_stmt (stmt);
207 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
209 tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start);
210 tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps);
212 ref_ptr = force_gimple_operand_bsi (&bsi,
213 build_addr (ref, current_function_decl),
214 true, NULL_TREE, true, BSI_SAME_STMT);
215 val = prepare_instrumented_value (&bsi, value);
216 call = build_call_expr (tree_interval_profiler_fn, 4,
217 ref_ptr, val, start, steps);
218 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
221 /* Output instructions as GIMPLE trees to increment the power of two histogram
222 counter. VALUE is the expression whose value is profiled. TAG is the tag
223 of the section for counters, BASE is offset of the counter position. */
226 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
228 tree stmt = value->hvalue.stmt;
229 block_stmt_iterator bsi = bsi_for_stmt (stmt);
230 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
233 ref_ptr = force_gimple_operand_bsi (&bsi,
234 build_addr (ref, current_function_decl),
235 true, NULL_TREE, true, BSI_SAME_STMT);
236 val = prepare_instrumented_value (&bsi, value);
237 call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val);
238 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
241 /* Output instructions as GIMPLE trees for code to find the most common value.
242 VALUE is the expression whose value is profiled. TAG is the tag of the
243 section for counters, BASE is offset of the counter position. */
246 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
248 tree stmt = value->hvalue.stmt;
249 block_stmt_iterator bsi = bsi_for_stmt (stmt);
250 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
253 ref_ptr = force_gimple_operand_bsi (&bsi,
254 build_addr (ref, current_function_decl),
255 true, NULL_TREE, true, BSI_SAME_STMT);
256 val = prepare_instrumented_value (&bsi, value);
257 call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val);
258 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
262 /* Output instructions as GIMPLE trees for code to find the most
263 common called function in indirect call.
264 VALUE is the call expression whose indirect callee is profiled.
265 TAG is the tag of the section for counters, BASE is offset of the
269 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
271 tree tmp1, stmt1, stmt2, stmt3;
272 tree stmt = value->hvalue.stmt;
273 block_stmt_iterator bsi = bsi_for_stmt (stmt);
274 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
276 ref_ptr = force_gimple_operand_bsi (&bsi,
277 build_addr (ref, current_function_decl),
278 true, NULL_TREE, true, BSI_SAME_STMT);
282 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
283 __gcov_indirect_call_callee = (void *) indirect call argument;
286 tmp1 = create_tmp_var (ptr_void, "PROF");
287 stmt1 = build_gimple_modify_stmt (ic_gcov_type_ptr_var, ref_ptr);
288 stmt2 = build_gimple_modify_stmt (tmp1, unshare_expr (value->hvalue.value));
289 stmt3 = build_gimple_modify_stmt (ic_void_ptr_var, tmp1);
291 bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
292 bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
293 bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
297 /* Output instructions as GIMPLE trees for code to find the most
298 common called function in indirect call. Insert instructions at the
299 beginning of every possible called function.
303 tree_gen_ic_func_profiler (void)
305 struct cgraph_node * c_node = cgraph_node (current_function_decl);
306 block_stmt_iterator bsi;
311 tree tree_uid, cur_func;
313 if (flag_unit_at_a_time)
319 tree_init_edge_profiler ();
321 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
324 bsi = bsi_start (bb);
325 cur_func = force_gimple_operand_bsi (&bsi,
326 build_addr (current_function_decl,
327 current_function_decl),
329 true, BSI_SAME_STMT);
330 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
331 stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4,
332 ic_gcov_type_ptr_var,
336 bsi_insert_after (&bsi, stmt1, BSI_NEW_STMT);
340 /* Output instructions as GIMPLE trees for code to find the most common value
341 of a difference between two evaluations of an expression.
342 VALUE is the expression whose value is profiled. TAG is the tag of the
343 section for counters, BASE is offset of the counter position. */
346 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
347 unsigned tag ATTRIBUTE_UNUSED,
348 unsigned base ATTRIBUTE_UNUSED)
350 /* FIXME implement this. */
351 #ifdef ENABLE_CHECKING
352 internal_error ("unimplemented functionality");
357 /* Output instructions as GIMPLE trees to increment the average histogram
358 counter. VALUE is the expression whose value is profiled. TAG is the
359 tag of the section for counters, BASE is offset of the counter position. */
362 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
364 tree stmt = value->hvalue.stmt;
365 block_stmt_iterator bsi = bsi_for_stmt (stmt);
366 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
369 ref_ptr = force_gimple_operand_bsi (&bsi,
370 build_addr (ref, current_function_decl),
372 true, BSI_SAME_STMT);
373 val = prepare_instrumented_value (&bsi, value);
374 call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val);
375 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
378 /* Output instructions as GIMPLE trees to increment the ior histogram
379 counter. VALUE is the expression whose value is profiled. TAG is the
380 tag of the section for counters, BASE is offset of the counter position. */
383 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
385 tree stmt = value->hvalue.stmt;
386 block_stmt_iterator bsi = bsi_for_stmt (stmt);
387 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
390 ref_ptr = force_gimple_operand_bsi (&bsi,
391 build_addr (ref, current_function_decl),
392 true, NULL_TREE, true, BSI_SAME_STMT);
393 val = prepare_instrumented_value (&bsi, value);
394 call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val);
395 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
398 /* Return 1 if tree-based profiling is in effect, else 0.
399 If it is, set up hooks for tree-based profiling.
400 Gate for pass_tree_profile. */
403 do_tree_profiling (void)
405 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
407 tree_register_profile_hooks ();
408 tree_register_value_prof_hooks ();
415 tree_profiling (void)
417 /* Don't profile functions produced at destruction time, particularly
418 the gcov datastructure initializer. */
419 if (cgraph_state == CGRAPH_STATE_FINISHED)
423 if (! flag_branch_probabilities
424 && flag_profile_values)
425 tree_gen_ic_func_profiler ();
427 if (flag_branch_probabilities
428 && flag_profile_values
429 && flag_value_profile_transformations)
430 value_profile_transformations ();
431 /* The above could hose dominator info. Currently there is
432 none coming in, this is a safety valve. It should be
433 easy to adjust it, if and when there is some. */
434 free_dominance_info (CDI_DOMINATORS);
435 free_dominance_info (CDI_POST_DOMINATORS);
439 struct tree_opt_pass pass_tree_profile =
441 "tree_profile", /* name */
442 do_tree_profiling, /* gate */
443 tree_profiling, /* execute */
446 0, /* static_pass_number */
447 TV_BRANCH_PROB, /* tv_id */
448 PROP_gimple_leh | PROP_cfg, /* properties_required */
449 PROP_gimple_leh | PROP_cfg, /* properties_provided */
450 0, /* properties_destroyed */
451 0, /* todo_flags_start */
452 TODO_verify_stmts | TODO_dump_func, /* todo_flags_finish */
456 struct profile_hooks tree_profile_hooks =
458 tree_init_edge_profiler, /* init_edge_profiler */
459 tree_gen_edge_profiler, /* gen_edge_profiler */
460 tree_gen_interval_profiler, /* gen_interval_profiler */
461 tree_gen_pow2_profiler, /* gen_pow2_profiler */
462 tree_gen_one_value_profiler, /* gen_one_value_profiler */
463 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
464 tree_gen_ic_profiler, /* gen_ic_profiler */
465 tree_gen_average_profiler, /* gen_average_profiler */
466 tree_gen_ior_profiler /* gen_ior_profiler */
469 #include "gt-tree-profile.h"