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
;
57 static GTY(()) tree ic_void_ptr_var
;
58 static GTY(()) tree ic_gcov_type_ptr_var
;
59 static GTY(()) tree ptr_void
;
61 /* Do initialization work for the edge profiler. */
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
65 static void* __gcov_indirect_call_callee; // actual callie addres
68 tree_init_ic_make_global_vars (void)
72 ptr_void
= build_pointer_type (void_type_node
);
75 = build_decl (VAR_DECL
,
76 get_identifier ("__gcov_indirect_call_callee"),
78 TREE_STATIC (ic_void_ptr_var
) = 1;
79 TREE_PUBLIC (ic_void_ptr_var
) = 0;
80 DECL_ARTIFICIAL (ic_void_ptr_var
) = 1;
81 DECL_INITIAL (ic_void_ptr_var
) = NULL
;
82 assemble_variable (ic_void_ptr_var
, 0, 0, 0);
84 gcov_type_ptr
= build_pointer_type (get_gcov_type ());
86 = build_decl (VAR_DECL
,
87 get_identifier ("__gcov_indirect_call_counters"),
89 TREE_STATIC (ic_gcov_type_ptr_var
) = 1;
90 TREE_PUBLIC (ic_gcov_type_ptr_var
) = 0;
91 DECL_ARTIFICIAL (ic_gcov_type_ptr_var
) = 1;
92 DECL_INITIAL (ic_gcov_type_ptr_var
) = NULL
;
93 assemble_variable (ic_gcov_type_ptr_var
, 0, 0, 0);
97 tree_init_edge_profiler (void)
99 tree interval_profiler_fn_type
;
100 tree pow2_profiler_fn_type
;
101 tree one_value_profiler_fn_type
;
103 tree ic_profiler_fn_type
;
107 gcov_type_node
= get_gcov_type ();
108 gcov_type_ptr
= build_pointer_type (gcov_type_node
);
110 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
111 interval_profiler_fn_type
112 = build_function_type_list (void_type_node
,
113 gcov_type_ptr
, gcov_type_node
,
115 unsigned_type_node
, NULL_TREE
);
116 tree_interval_profiler_fn
117 = build_fn_decl ("__gcov_interval_profiler",
118 interval_profiler_fn_type
);
120 /* void (*) (gcov_type *, gcov_type) */
121 pow2_profiler_fn_type
122 = build_function_type_list (void_type_node
,
123 gcov_type_ptr
, gcov_type_node
,
125 tree_pow2_profiler_fn
= build_fn_decl ("__gcov_pow2_profiler",
126 pow2_profiler_fn_type
);
128 /* void (*) (gcov_type *, gcov_type) */
129 one_value_profiler_fn_type
130 = build_function_type_list (void_type_node
,
131 gcov_type_ptr
, gcov_type_node
,
133 tree_one_value_profiler_fn
134 = build_fn_decl ("__gcov_one_value_profiler",
135 one_value_profiler_fn_type
);
137 tree_init_ic_make_global_vars ();
139 /* void (*) (gcov_type *, gcov_type, void *, void *) */
141 = build_function_type_list (void_type_node
,
142 gcov_type_ptr
, gcov_type_node
,
144 ptr_void
, NULL_TREE
);
145 tree_indirect_call_profiler_fn
146 = build_fn_decl ("__gcov_indirect_call_profiler",
147 ic_profiler_fn_type
);
151 /* Output instructions as GIMPLE trees to increment the edge
152 execution count, and insert them on E. We rely on
153 bsi_insert_on_edge to preserve the order. */
156 tree_gen_edge_profiler (int edgeno
, edge e
)
158 tree tmp1
= create_tmp_var (gcov_type_node
, "PROF");
159 tree tmp2
= create_tmp_var (gcov_type_node
, "PROF");
160 tree ref
= tree_coverage_counter_ref (GCOV_COUNTER_ARCS
, edgeno
);
161 tree stmt1
= build2 (GIMPLE_MODIFY_STMT
, gcov_type_node
, tmp1
, ref
);
162 tree stmt2
= build2 (GIMPLE_MODIFY_STMT
, gcov_type_node
, tmp2
,
163 build2 (PLUS_EXPR
, gcov_type_node
,
164 tmp1
, integer_one_node
));
165 tree stmt3
= build2 (GIMPLE_MODIFY_STMT
, gcov_type_node
, ref
, tmp2
);
166 bsi_insert_on_edge (e
, stmt1
);
167 bsi_insert_on_edge (e
, stmt2
);
168 bsi_insert_on_edge (e
, stmt3
);
171 /* Emits code to get VALUE to instrument at BSI, and returns the
172 variable containing the value. */
175 prepare_instrumented_value (block_stmt_iterator
*bsi
,
176 histogram_value value
)
178 tree val
= value
->hvalue
.value
;
179 return force_gimple_operand_bsi (bsi
, fold_convert (gcov_type_node
, val
),
183 /* Output instructions as GIMPLE trees to increment the interval histogram
184 counter. VALUE is the expression whose value is profiled. TAG is the
185 tag of the section for counters, BASE is offset of the counter position. */
188 tree_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
190 tree stmt
= value
->hvalue
.stmt
;
191 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
192 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
193 tree args
, call
, val
;
194 tree start
= build_int_cst_type (integer_type_node
, value
->hdata
.intvl
.int_start
);
195 tree steps
= build_int_cst_type (unsigned_type_node
, value
->hdata
.intvl
.steps
);
197 ref_ptr
= force_gimple_operand_bsi (&bsi
,
198 build_addr (ref
, current_function_decl
),
200 val
= prepare_instrumented_value (&bsi
, value
);
201 args
= tree_cons (NULL_TREE
, ref_ptr
,
202 tree_cons (NULL_TREE
, val
,
203 tree_cons (NULL_TREE
, start
,
204 tree_cons (NULL_TREE
, steps
,
206 call
= build_function_call_expr (tree_interval_profiler_fn
, args
);
207 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
210 /* Output instructions as GIMPLE trees to increment the power of two histogram
211 counter. VALUE is the expression whose value is profiled. TAG is the tag
212 of the section for counters, BASE is offset of the counter position. */
215 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
217 tree stmt
= value
->hvalue
.stmt
;
218 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
219 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
220 tree args
, call
, val
;
222 ref_ptr
= force_gimple_operand_bsi (&bsi
,
223 build_addr (ref
, current_function_decl
),
225 val
= prepare_instrumented_value (&bsi
, value
);
226 args
= tree_cons (NULL_TREE
, ref_ptr
,
227 tree_cons (NULL_TREE
, val
,
229 call
= build_function_call_expr (tree_pow2_profiler_fn
, args
);
230 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
233 /* Output instructions as GIMPLE trees for code to find the most common value.
234 VALUE is the expression whose value is profiled. TAG is the tag of the
235 section for counters, BASE is offset of the counter position. */
238 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
240 tree stmt
= value
->hvalue
.stmt
;
241 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
242 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
243 tree args
, call
, val
;
245 ref_ptr
= force_gimple_operand_bsi (&bsi
,
246 build_addr (ref
, current_function_decl
),
248 val
= prepare_instrumented_value (&bsi
, value
);
249 args
= tree_cons (NULL_TREE
, ref_ptr
,
250 tree_cons (NULL_TREE
, val
,
252 call
= build_function_call_expr (tree_one_value_profiler_fn
, args
);
253 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
257 /* Output instructions as GIMPLE trees for code to find the most
258 common called function in indirect call.
259 VALUE is the call expression whose indirect callie is profiled.
260 TAG is the tag of the section for counters, BASE is offset of the
264 tree_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
266 tree tmp1
, stmt1
, stmt2
, stmt3
;
267 tree stmt
= value
->hvalue
.stmt
;
268 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
269 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
271 ref_ptr
= force_gimple_operand_bsi (&bsi
,
272 build_addr (ref
, current_function_decl
),
277 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
278 __gcov_indirect_call_callee = (void *) indirect call argument;
281 tmp1
= create_tmp_var (ptr_void
, "PROF");
282 stmt1
= build2 (GIMPLE_MODIFY_STMT
,
283 build_pointer_type (get_gcov_type ()),
284 ic_gcov_type_ptr_var
, ref_ptr
);
285 stmt2
= build2 (GIMPLE_MODIFY_STMT
, ptr_void
, tmp1
,
286 unshare_expr (value
->hvalue
.value
));
287 stmt3
= build2 (GIMPLE_MODIFY_STMT
, ptr_void
,
288 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 begining 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 args
, 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 tree_uid
= build_int_cst (gcov_type_node
, c_node
->pid
);
329 args
= tree_cons (NULL_TREE
, ic_gcov_type_ptr_var
,
330 tree_cons (NULL_TREE
, tree_uid
,
331 tree_cons (NULL_TREE
, cur_func
,
332 tree_cons (NULL_TREE
,
335 stmt1
= build_function_call_expr (tree_indirect_call_profiler_fn
, args
);
336 bsi_insert_after (&bsi
, stmt1
, BSI_SAME_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 /* Return 1 if tree-based profiling is in effect, else 0.
358 If it is, set up hooks for tree-based profiling.
359 Gate for pass_tree_profile. */
362 do_tree_profiling (void)
364 if (profile_arc_flag
|| flag_test_coverage
|| flag_branch_probabilities
)
366 tree_register_profile_hooks ();
367 tree_register_value_prof_hooks ();
374 tree_profiling (void)
376 /* Don't profile functions produced at destruction time, particularly
377 the gcov datastructure initializer. */
378 if (cgraph_state
== CGRAPH_STATE_FINISHED
)
382 if (! flag_branch_probabilities
383 && flag_profile_values
)
384 tree_gen_ic_func_profiler ();
386 if (flag_branch_probabilities
387 && flag_profile_values
388 && flag_value_profile_transformations
)
389 value_profile_transformations ();
390 /* The above could hose dominator info. Currently there is
391 none coming in, this is a safety valve. It should be
392 easy to adjust it, if and when there is some. */
393 free_dominance_info (CDI_DOMINATORS
);
394 free_dominance_info (CDI_POST_DOMINATORS
);
398 struct tree_opt_pass pass_tree_profile
=
400 "tree_profile", /* name */
401 do_tree_profiling
, /* gate */
402 tree_profiling
, /* execute */
405 0, /* static_pass_number */
406 TV_BRANCH_PROB
, /* tv_id */
407 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
408 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
409 0, /* properties_destroyed */
410 0, /* todo_flags_start */
411 TODO_verify_stmts
, /* todo_flags_finish */
415 struct profile_hooks tree_profile_hooks
=
417 tree_init_edge_profiler
, /* init_edge_profiler */
418 tree_gen_edge_profiler
, /* gen_edge_profiler */
419 tree_gen_interval_profiler
, /* gen_interval_profiler */
420 tree_gen_pow2_profiler
, /* gen_pow2_profiler */
421 tree_gen_one_value_profiler
, /* gen_one_value_profiler */
422 tree_gen_const_delta_profiler
,/* gen_const_delta_profiler */
423 tree_gen_ic_profiler
, /* gen_ic_profiler */
426 #include "gt-tree-profile.h"