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 3, 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 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. */
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 one
= build_int_cst (gcov_type_node
, 1);
175 tree stmt1
= build_gimple_modify_stmt (tmp1
, ref
);
176 tree stmt2
= build_gimple_modify_stmt (tmp2
,
177 build2 (PLUS_EXPR
, gcov_type_node
,
179 tree stmt3
= build_gimple_modify_stmt (ref
, tmp2
);
180 bsi_insert_on_edge (e
, stmt1
);
181 bsi_insert_on_edge (e
, stmt2
);
182 bsi_insert_on_edge (e
, stmt3
);
185 /* Emits code to get VALUE to instrument at BSI, and returns the
186 variable containing the value. */
189 prepare_instrumented_value (block_stmt_iterator
*bsi
,
190 histogram_value value
)
192 tree val
= value
->hvalue
.value
;
193 return force_gimple_operand_bsi (bsi
, fold_convert (gcov_type_node
, val
),
194 true, NULL_TREE
, true, BSI_SAME_STMT
);
197 /* Output instructions as GIMPLE trees to increment the interval histogram
198 counter. VALUE is the expression whose value is profiled. TAG is the
199 tag of the section for counters, BASE is offset of the counter position. */
202 tree_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
204 tree stmt
= value
->hvalue
.stmt
;
205 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
206 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
208 tree start
= build_int_cst_type (integer_type_node
, value
->hdata
.intvl
.int_start
);
209 tree steps
= build_int_cst_type (unsigned_type_node
, value
->hdata
.intvl
.steps
);
211 ref_ptr
= force_gimple_operand_bsi (&bsi
,
212 build_addr (ref
, current_function_decl
),
213 true, NULL_TREE
, true, BSI_SAME_STMT
);
214 val
= prepare_instrumented_value (&bsi
, value
);
215 call
= build_call_expr (tree_interval_profiler_fn
, 4,
216 ref_ptr
, val
, start
, steps
);
217 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
220 /* Output instructions as GIMPLE trees to increment the power of two histogram
221 counter. VALUE is the expression whose value is profiled. TAG is the tag
222 of the section for counters, BASE is offset of the counter position. */
225 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
227 tree stmt
= value
->hvalue
.stmt
;
228 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
229 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
232 ref_ptr
= force_gimple_operand_bsi (&bsi
,
233 build_addr (ref
, current_function_decl
),
234 true, NULL_TREE
, true, BSI_SAME_STMT
);
235 val
= prepare_instrumented_value (&bsi
, value
);
236 call
= build_call_expr (tree_pow2_profiler_fn
, 2, ref_ptr
, val
);
237 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
240 /* Output instructions as GIMPLE trees for code to find the most common value.
241 VALUE is the expression whose value is profiled. TAG is the tag of the
242 section for counters, BASE is offset of the counter position. */
245 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
247 tree stmt
= value
->hvalue
.stmt
;
248 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
249 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
252 ref_ptr
= force_gimple_operand_bsi (&bsi
,
253 build_addr (ref
, current_function_decl
),
254 true, NULL_TREE
, true, BSI_SAME_STMT
);
255 val
= prepare_instrumented_value (&bsi
, value
);
256 call
= build_call_expr (tree_one_value_profiler_fn
, 2, ref_ptr
, val
);
257 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
261 /* Output instructions as GIMPLE trees for code to find the most
262 common called function in indirect call.
263 VALUE is the call expression whose indirect callee is profiled.
264 TAG is the tag of the section for counters, BASE is offset of the
268 tree_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
270 tree tmp1
, stmt1
, stmt2
, stmt3
;
271 tree stmt
= value
->hvalue
.stmt
;
272 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
273 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
275 ref_ptr
= force_gimple_operand_bsi (&bsi
,
276 build_addr (ref
, current_function_decl
),
277 true, NULL_TREE
, true, BSI_SAME_STMT
);
281 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
282 __gcov_indirect_call_callee = (void *) indirect call argument;
285 tmp1
= create_tmp_var (ptr_void
, "PROF");
286 stmt1
= build_gimple_modify_stmt (ic_gcov_type_ptr_var
, ref_ptr
);
287 stmt2
= build_gimple_modify_stmt (tmp1
, unshare_expr (value
->hvalue
.value
));
288 stmt3
= build_gimple_modify_stmt (ic_void_ptr_var
, tmp1
);
290 bsi_insert_before (&bsi
, stmt1
, BSI_SAME_STMT
);
291 bsi_insert_before (&bsi
, stmt2
, BSI_SAME_STMT
);
292 bsi_insert_before (&bsi
, stmt3
, BSI_SAME_STMT
);
296 /* Output instructions as GIMPLE trees for code to find the most
297 common called function in indirect call. Insert instructions at the
298 beginning of every possible called function.
302 tree_gen_ic_func_profiler (void)
304 struct cgraph_node
* c_node
= cgraph_node (current_function_decl
);
305 block_stmt_iterator bsi
;
310 tree tree_uid
, cur_func
;
312 if (flag_unit_at_a_time
)
318 tree_init_edge_profiler ();
320 FOR_EACH_EDGE (e
, ei
, ENTRY_BLOCK_PTR
->succs
)
323 bsi
= bsi_start (bb
);
324 cur_func
= force_gimple_operand_bsi (&bsi
,
325 build_addr (current_function_decl
,
326 current_function_decl
),
328 true, BSI_SAME_STMT
);
329 tree_uid
= build_int_cst (gcov_type_node
, c_node
->pid
);
330 stmt1
= build_call_expr (tree_indirect_call_profiler_fn
, 4,
331 ic_gcov_type_ptr_var
,
335 bsi_insert_after (&bsi
, stmt1
, BSI_NEW_STMT
);
339 /* Output instructions as GIMPLE trees for code to find the most common value
340 of a difference between two evaluations of an expression.
341 VALUE is the expression whose value is profiled. TAG is the tag of the
342 section for counters, BASE is offset of the counter position. */
345 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED
,
346 unsigned tag ATTRIBUTE_UNUSED
,
347 unsigned base ATTRIBUTE_UNUSED
)
349 /* FIXME implement this. */
350 #ifdef ENABLE_CHECKING
351 internal_error ("unimplemented functionality");
356 /* Output instructions as GIMPLE trees to increment the average histogram
357 counter. VALUE is the expression whose value is profiled. TAG is the
358 tag of the section for counters, BASE is offset of the counter position. */
361 tree_gen_average_profiler (histogram_value value
, unsigned tag
, unsigned base
)
363 tree stmt
= value
->hvalue
.stmt
;
364 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
365 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
368 ref_ptr
= force_gimple_operand_bsi (&bsi
,
369 build_addr (ref
, current_function_decl
),
371 true, BSI_SAME_STMT
);
372 val
= prepare_instrumented_value (&bsi
, value
);
373 call
= build_call_expr (tree_average_profiler_fn
, 2, ref_ptr
, val
);
374 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
377 /* Output instructions as GIMPLE trees to increment the ior histogram
378 counter. VALUE is the expression whose value is profiled. TAG is the
379 tag of the section for counters, BASE is offset of the counter position. */
382 tree_gen_ior_profiler (histogram_value value
, unsigned tag
, unsigned base
)
384 tree stmt
= value
->hvalue
.stmt
;
385 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
386 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
389 ref_ptr
= force_gimple_operand_bsi (&bsi
,
390 build_addr (ref
, current_function_decl
),
391 true, NULL_TREE
, true, BSI_SAME_STMT
);
392 val
= prepare_instrumented_value (&bsi
, value
);
393 call
= build_call_expr (tree_ior_profiler_fn
, 2, ref_ptr
, val
);
394 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
397 /* Return 1 if tree-based profiling is in effect, else 0.
398 If it is, set up hooks for tree-based profiling.
399 Gate for pass_tree_profile. */
402 do_tree_profiling (void)
404 if (profile_arc_flag
|| flag_test_coverage
|| flag_branch_probabilities
)
406 tree_register_profile_hooks ();
407 tree_register_value_prof_hooks ();
414 tree_profiling (void)
416 /* Don't profile functions produced at destruction time, particularly
417 the gcov datastructure initializer. */
418 if (cgraph_state
== CGRAPH_STATE_FINISHED
)
422 if (! flag_branch_probabilities
423 && flag_profile_values
)
424 tree_gen_ic_func_profiler ();
426 if (flag_branch_probabilities
427 && flag_profile_values
428 && flag_value_profile_transformations
)
429 value_profile_transformations ();
430 /* The above could hose dominator info. Currently there is
431 none coming in, this is a safety valve. It should be
432 easy to adjust it, if and when there is some. */
433 free_dominance_info (CDI_DOMINATORS
);
434 free_dominance_info (CDI_POST_DOMINATORS
);
438 struct tree_opt_pass pass_tree_profile
=
440 "tree_profile", /* name */
441 do_tree_profiling
, /* gate */
442 tree_profiling
, /* execute */
445 0, /* static_pass_number */
446 TV_BRANCH_PROB
, /* tv_id */
447 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
448 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
449 0, /* properties_destroyed */
450 0, /* todo_flags_start */
451 TODO_verify_stmts
| TODO_dump_func
, /* todo_flags_finish */
455 struct profile_hooks tree_profile_hooks
=
457 tree_init_edge_profiler
, /* init_edge_profiler */
458 tree_gen_edge_profiler
, /* gen_edge_profiler */
459 tree_gen_interval_profiler
, /* gen_interval_profiler */
460 tree_gen_pow2_profiler
, /* gen_pow2_profiler */
461 tree_gen_one_value_profiler
, /* gen_one_value_profiler */
462 tree_gen_const_delta_profiler
, /* gen_const_delta_profiler */
463 tree_gen_ic_profiler
, /* gen_ic_profiler */
464 tree_gen_average_profiler
, /* gen_average_profiler */
465 tree_gen_ior_profiler
/* gen_ior_profiler */
468 #include "gt-tree-profile.h"