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
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
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
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 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. */
66 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
67 static void* __gcov_indirect_call_callee; // actual callee addres
70 tree_init_ic_make_global_vars (void)
74 ptr_void
= build_pointer_type (void_type_node
);
77 = build_decl (VAR_DECL
,
78 get_identifier ("__gcov_indirect_call_callee"),
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 ());
88 = build_decl (VAR_DECL
,
89 get_identifier ("__gcov_indirect_call_counters"),
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);
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
;
105 tree ic_profiler_fn_type
;
106 tree average_profiler_fn_type
;
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
,
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
,
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
,
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 *) */
144 = build_function_type_list (void_type_node
,
145 gcov_type_ptr
, gcov_type_node
,
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
);
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. */
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. */
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
),
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. */
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
;
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
),
213 val
= prepare_instrumented_value (&bsi
, value
);
214 call
= build_call_expr (tree_interval_profiler_fn
, 4,
215 ref_ptr
, val
, start
, steps
);
216 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
219 /* Output instructions as GIMPLE trees to increment the power of two histogram
220 counter. VALUE is the expression whose value is profiled. TAG is the tag
221 of the section for counters, BASE is offset of the counter position. */
224 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
226 tree stmt
= value
->hvalue
.stmt
;
227 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
228 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
231 ref_ptr
= force_gimple_operand_bsi (&bsi
,
232 build_addr (ref
, current_function_decl
),
234 val
= prepare_instrumented_value (&bsi
, value
);
235 call
= build_call_expr (tree_pow2_profiler_fn
, 2, ref_ptr
, val
);
236 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
239 /* Output instructions as GIMPLE trees for code to find the most common value.
240 VALUE is the expression whose value is profiled. TAG is the tag of the
241 section for counters, BASE is offset of the counter position. */
244 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
246 tree stmt
= value
->hvalue
.stmt
;
247 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
248 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
251 ref_ptr
= force_gimple_operand_bsi (&bsi
,
252 build_addr (ref
, current_function_decl
),
254 val
= prepare_instrumented_value (&bsi
, value
);
255 call
= build_call_expr (tree_one_value_profiler_fn
, 2, ref_ptr
, val
);
256 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
260 /* Output instructions as GIMPLE trees for code to find the most
261 common called function in indirect call.
262 VALUE is the call expression whose indirect callee is profiled.
263 TAG is the tag of the section for counters, BASE is offset of the
267 tree_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
269 tree tmp1
, stmt1
, stmt2
, stmt3
;
270 tree stmt
= value
->hvalue
.stmt
;
271 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
272 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
274 ref_ptr
= force_gimple_operand_bsi (&bsi
,
275 build_addr (ref
, current_function_decl
),
280 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
281 __gcov_indirect_call_callee = (void *) indirect call argument;
284 tmp1
= create_tmp_var (ptr_void
, "PROF");
285 stmt1
= build2 (GIMPLE_MODIFY_STMT
,
286 build_pointer_type (get_gcov_type ()),
287 ic_gcov_type_ptr_var
, ref_ptr
);
288 stmt2
= build2 (GIMPLE_MODIFY_STMT
, ptr_void
, tmp1
,
289 unshare_expr (value
->hvalue
.value
));
290 stmt3
= build2 (GIMPLE_MODIFY_STMT
, ptr_void
,
291 ic_void_ptr_var
, tmp1
);
293 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
294 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
295 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
299 /* Output instructions as GIMPLE trees for code to find the most
300 common called function in indirect call. Insert instructions at the
301 beginning of every possible called function.
305 tree_gen_ic_func_profiler (void)
307 struct cgraph_node
* c_node
= cgraph_node (current_function_decl
);
308 block_stmt_iterator bsi
;
313 tree tree_uid
, cur_func
;
315 if (flag_unit_at_a_time
)
321 tree_init_edge_profiler ();
323 FOR_EACH_EDGE (e
, ei
, ENTRY_BLOCK_PTR
->succs
)
326 bsi
= bsi_start (bb
);
327 cur_func
= force_gimple_operand_bsi (&bsi
,
328 build_addr (current_function_decl
,
329 current_function_decl
),
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_SAME_STMT
);
341 /* Output instructions as GIMPLE trees for code to find the most common value
342 of a difference between two evaluations of an expression.
343 VALUE is the expression whose value is profiled. TAG is the tag of the
344 section for counters, BASE is offset of the counter position. */
347 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED
,
348 unsigned tag ATTRIBUTE_UNUSED
,
349 unsigned base ATTRIBUTE_UNUSED
)
351 /* FIXME implement this. */
352 #ifdef ENABLE_CHECKING
353 internal_error ("unimplemented functionality");
358 /* Output instructions as GIMPLE trees to increment the average histogram
359 counter. VALUE is the expression whose value is profiled. TAG is the
360 tag of the section for counters, BASE is offset of the counter position. */
363 tree_gen_average_profiler (histogram_value value
, unsigned tag
, unsigned base
)
365 tree stmt
= value
->hvalue
.stmt
;
366 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
367 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
370 ref_ptr
= force_gimple_operand_bsi (&bsi
,
371 build_addr (ref
, current_function_decl
),
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
),
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"