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
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 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. */
67 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
68 static void* __gcov_indirect_call_callee; // actual callee address
71 tree_init_ic_make_global_vars (void)
75 ptr_void
= build_pointer_type (void_type_node
);
78 = build_decl (UNKNOWN_LOCATION
, 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 (UNKNOWN_LOCATION
, 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 /* New call was added, make goto call edges if neccesary. */
168 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi
)
170 gimple stmt
= gsi_stmt (gsi
);
172 if (!stmt_can_make_abnormal_goto (stmt
))
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. */
184 tree_gen_edge_profiler (int edgeno
, edge e
)
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. */
208 prepare_instrumented_value (gimple_stmt_iterator
*gsi
, histogram_value value
)
210 tree val
= value
->hvalue
.value
;
211 if (POINTER_TYPE_P (TREE_TYPE (val
)))
212 val
= fold_convert (sizetype
, val
);
213 return force_gimple_operand_gsi (gsi
, fold_convert (gcov_type_node
, val
),
214 true, NULL_TREE
, true, GSI_SAME_STMT
);
217 /* Output instructions as GIMPLE trees to increment the interval histogram
218 counter. VALUE is the expression whose value is profiled. TAG is the
219 tag of the section for counters, BASE is offset of the counter position. */
222 tree_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
224 gimple stmt
= value
->hvalue
.stmt
;
225 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
226 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
229 tree start
= build_int_cst_type (integer_type_node
,
230 value
->hdata
.intvl
.int_start
);
231 tree steps
= build_int_cst_type (unsigned_type_node
,
232 value
->hdata
.intvl
.steps
);
234 ref_ptr
= force_gimple_operand_gsi (&gsi
,
235 build_addr (ref
, current_function_decl
),
236 true, NULL_TREE
, true, GSI_SAME_STMT
);
237 val
= prepare_instrumented_value (&gsi
, value
);
238 call
= gimple_build_call (tree_interval_profiler_fn
, 4,
239 ref_ptr
, val
, start
, steps
);
240 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
241 add_abnormal_goto_call_edges (gsi
);
244 /* Output instructions as GIMPLE trees to increment the power of two histogram
245 counter. VALUE is the expression whose value is profiled. TAG is the tag
246 of the section for counters, BASE is offset of the counter position. */
249 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
251 gimple stmt
= value
->hvalue
.stmt
;
252 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
253 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
257 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
258 true, NULL_TREE
, true, GSI_SAME_STMT
);
259 val
= prepare_instrumented_value (&gsi
, value
);
260 call
= gimple_build_call (tree_pow2_profiler_fn
, 2, ref_ptr
, val
);
261 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
262 add_abnormal_goto_call_edges (gsi
);
265 /* Output instructions as GIMPLE trees for code to find the most common value.
266 VALUE is the expression whose value is profiled. TAG is the tag of the
267 section for counters, BASE is offset of the counter position. */
270 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
272 gimple stmt
= value
->hvalue
.stmt
;
273 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
274 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
278 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
279 true, NULL_TREE
, true, GSI_SAME_STMT
);
280 val
= prepare_instrumented_value (&gsi
, value
);
281 call
= gimple_build_call (tree_one_value_profiler_fn
, 2, ref_ptr
, val
);
282 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
283 add_abnormal_goto_call_edges (gsi
);
287 /* Output instructions as GIMPLE trees for code to find the most
288 common called function in indirect call.
289 VALUE is the call expression whose indirect callee is profiled.
290 TAG is the tag of the section for counters, BASE is offset of the
294 tree_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
297 gimple stmt1
, stmt2
, stmt3
;
298 gimple stmt
= value
->hvalue
.stmt
;
299 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
300 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
302 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
303 true, NULL_TREE
, true, GSI_SAME_STMT
);
307 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
308 __gcov_indirect_call_callee = (void *) indirect call argument;
311 tmp1
= create_tmp_var (ptr_void
, "PROF");
312 stmt1
= gimple_build_assign (ic_gcov_type_ptr_var
, ref_ptr
);
313 stmt2
= gimple_build_assign (tmp1
, unshare_expr (value
->hvalue
.value
));
314 stmt3
= gimple_build_assign (ic_void_ptr_var
, tmp1
);
316 gsi_insert_before (&gsi
, stmt1
, GSI_SAME_STMT
);
317 gsi_insert_before (&gsi
, stmt2
, GSI_SAME_STMT
);
318 gsi_insert_before (&gsi
, stmt3
, GSI_SAME_STMT
);
322 /* Output instructions as GIMPLE trees for code to find the most
323 common called function in indirect call. Insert instructions at the
324 beginning of every possible called function.
328 tree_gen_ic_func_profiler (void)
330 struct cgraph_node
* c_node
= cgraph_node (current_function_decl
);
331 gimple_stmt_iterator gsi
;
336 tree tree_uid
, cur_func
;
341 tree_init_edge_profiler ();
343 FOR_EACH_EDGE (e
, ei
, ENTRY_BLOCK_PTR
->succs
)
348 gsi
= gsi_start_bb (bb
);
350 cur_func
= force_gimple_operand_gsi (&gsi
,
351 build_addr (current_function_decl
,
352 current_function_decl
),
354 true, GSI_SAME_STMT
);
355 tree_uid
= build_int_cst (gcov_type_node
, c_node
->pid
);
356 stmt1
= gimple_build_call (tree_indirect_call_profiler_fn
, 4,
357 ic_gcov_type_ptr_var
,
361 gsi_insert_after (&gsi
, stmt1
, GSI_NEW_STMT
);
362 gcc_assert (EDGE_COUNT (bb
->succs
) == 1);
363 bb
= split_edge (EDGE_I (bb
->succs
, 0));
364 add_abnormal_goto_call_edges (gsi
);
366 gsi
= gsi_start_bb (bb
);
367 /* Set __gcov_indirect_call_callee to 0,
368 so that calls from other modules won't get misattributed
369 to the last caller of the current callee. */
370 void0
= build_int_cst (build_pointer_type (void_type_node
), 0);
371 stmt2
= gimple_build_assign (ic_void_ptr_var
, void0
);
372 gsi_insert_after (&gsi
, stmt2
, GSI_NEW_STMT
);
376 /* Output instructions as GIMPLE trees for code to find the most common value
377 of a difference between two evaluations of an expression.
378 VALUE is the expression whose value is profiled. TAG is the tag of the
379 section for counters, BASE is offset of the counter position. */
382 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED
,
383 unsigned tag ATTRIBUTE_UNUSED
,
384 unsigned base ATTRIBUTE_UNUSED
)
386 /* FIXME implement this. */
387 #ifdef ENABLE_CHECKING
388 internal_error ("unimplemented functionality");
393 /* Output instructions as GIMPLE trees to increment the average histogram
394 counter. VALUE is the expression whose value is profiled. TAG is the
395 tag of the section for counters, BASE is offset of the counter position. */
398 tree_gen_average_profiler (histogram_value value
, unsigned tag
, unsigned base
)
400 gimple stmt
= value
->hvalue
.stmt
;
401 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
402 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
406 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
408 true, GSI_SAME_STMT
);
409 val
= prepare_instrumented_value (&gsi
, value
);
410 call
= gimple_build_call (tree_average_profiler_fn
, 2, ref_ptr
, val
);
411 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
412 add_abnormal_goto_call_edges (gsi
);
415 /* Output instructions as GIMPLE trees to increment the ior histogram
416 counter. VALUE is the expression whose value is profiled. TAG is the
417 tag of the section for counters, BASE is offset of the counter position. */
420 tree_gen_ior_profiler (histogram_value value
, unsigned tag
, unsigned base
)
422 gimple stmt
= value
->hvalue
.stmt
;
423 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
424 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
428 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
429 true, NULL_TREE
, true, GSI_SAME_STMT
);
430 val
= prepare_instrumented_value (&gsi
, value
);
431 call
= gimple_build_call (tree_ior_profiler_fn
, 2, ref_ptr
, val
);
432 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
433 add_abnormal_goto_call_edges (gsi
);
436 /* Return 1 if tree-based profiling is in effect, else 0.
437 If it is, set up hooks for tree-based profiling.
438 Gate for pass_tree_profile. */
441 do_tree_profiling (void)
443 if (profile_arc_flag
|| flag_test_coverage
|| flag_branch_probabilities
)
445 tree_register_profile_hooks ();
446 gimple_register_value_prof_hooks ();
453 tree_profiling (void)
455 /* Don't profile functions produced at destruction time, particularly
456 the gcov datastructure initializer. Don't profile if it has been
457 already instrumented either (when OpenMP expansion creates
458 child function from already instrumented body). */
459 if (cgraph_state
== CGRAPH_STATE_FINISHED
460 || cfun
->after_tree_profile
)
463 /* Re-set global shared temporary variable for edge-counters. */
464 gcov_type_tmp_var
= NULL_TREE
;
468 if (! flag_branch_probabilities
469 && flag_profile_values
)
470 tree_gen_ic_func_profiler ();
472 if (flag_branch_probabilities
473 && flag_profile_values
474 && flag_value_profile_transformations
)
475 value_profile_transformations ();
476 /* The above could hose dominator info. Currently there is
477 none coming in, this is a safety valve. It should be
478 easy to adjust it, if and when there is some. */
479 free_dominance_info (CDI_DOMINATORS
);
480 free_dominance_info (CDI_POST_DOMINATORS
);
481 cfun
->after_tree_profile
= 1;
485 struct gimple_opt_pass pass_tree_profile
=
489 "tree_profile", /* name */
490 do_tree_profiling
, /* gate */
491 tree_profiling
, /* execute */
494 0, /* static_pass_number */
495 TV_BRANCH_PROB
, /* tv_id */
496 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
497 0, /* properties_provided */
498 0, /* properties_destroyed */
499 0, /* todo_flags_start */
500 TODO_verify_stmts
| TODO_dump_func
/* todo_flags_finish */
504 struct profile_hooks tree_profile_hooks
=
506 tree_init_edge_profiler
, /* init_edge_profiler */
507 tree_gen_edge_profiler
, /* gen_edge_profiler */
508 tree_gen_interval_profiler
, /* gen_interval_profiler */
509 tree_gen_pow2_profiler
, /* gen_pow2_profiler */
510 tree_gen_one_value_profiler
, /* gen_one_value_profiler */
511 tree_gen_const_delta_profiler
, /* gen_const_delta_profiler */
512 tree_gen_ic_profiler
, /* gen_ic_profiler */
513 tree_gen_average_profiler
, /* gen_average_profiler */
514 tree_gen_ior_profiler
/* gen_ior_profiler */
517 #include "gt-tree-profile.h"