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"
49 static GTY(()) tree gcov_type_node
;
50 static GTY(()) tree tree_interval_profiler_fn
;
51 static GTY(()) tree tree_pow2_profiler_fn
;
52 static GTY(()) tree tree_one_value_profiler_fn
;
55 /* Do initialization work for the edge profiler. */
58 tree_init_edge_profiler (void)
60 tree interval_profiler_fn_type
;
61 tree pow2_profiler_fn_type
;
62 tree one_value_profiler_fn_type
;
67 gcov_type_node
= get_gcov_type ();
68 gcov_type_ptr
= build_pointer_type (gcov_type_node
);
70 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
71 interval_profiler_fn_type
72 = build_function_type_list (void_type_node
,
73 gcov_type_ptr
, gcov_type_node
,
75 unsigned_type_node
, NULL_TREE
);
76 tree_interval_profiler_fn
77 = build_fn_decl ("__gcov_interval_profiler",
78 interval_profiler_fn_type
);
80 /* void (*) (gcov_type *, gcov_type) */
82 = build_function_type_list (void_type_node
,
83 gcov_type_ptr
, gcov_type_node
,
85 tree_pow2_profiler_fn
= build_fn_decl ("__gcov_pow2_profiler",
86 pow2_profiler_fn_type
);
88 /* void (*) (gcov_type *, gcov_type) */
89 one_value_profiler_fn_type
90 = build_function_type_list (void_type_node
,
91 gcov_type_ptr
, gcov_type_node
,
93 tree_one_value_profiler_fn
94 = build_fn_decl ("__gcov_one_value_profiler",
95 one_value_profiler_fn_type
);
99 /* Output instructions as GIMPLE trees to increment the edge
100 execution count, and insert them on E. We rely on
101 bsi_insert_on_edge to preserve the order. */
104 tree_gen_edge_profiler (int edgeno
, edge e
)
106 tree tmp1
= create_tmp_var (gcov_type_node
, "PROF");
107 tree tmp2
= create_tmp_var (gcov_type_node
, "PROF");
108 tree ref
= tree_coverage_counter_ref (GCOV_COUNTER_ARCS
, edgeno
);
109 tree stmt1
= build (MODIFY_EXPR
, gcov_type_node
, tmp1
, ref
);
110 tree stmt2
= build (MODIFY_EXPR
, gcov_type_node
, tmp2
,
111 build (PLUS_EXPR
, gcov_type_node
,
112 tmp1
, integer_one_node
));
113 tree stmt3
= build (MODIFY_EXPR
, gcov_type_node
, ref
, tmp2
);
114 bsi_insert_on_edge (e
, stmt1
);
115 bsi_insert_on_edge (e
, stmt2
);
116 bsi_insert_on_edge (e
, stmt3
);
119 /* Emits code to get VALUE to instrument at BSI, and returns the
120 variable containing the value. */
123 prepare_instrumented_value (block_stmt_iterator
*bsi
,
124 histogram_value value
)
126 tree val
= value
->hvalue
.value
;
127 return force_gimple_operand_bsi (bsi
, fold_convert (gcov_type_node
, val
),
131 /* Output instructions as GIMPLE trees to increment the interval histogram
132 counter. VALUE is the expression whose value is profiled. TAG is the
133 tag of the section for counters, BASE is offset of the counter position. */
136 tree_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
138 tree stmt
= value
->hvalue
.stmt
;
139 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
140 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
141 tree args
, call
, val
;
142 tree start
= build_int_cst_type (integer_type_node
, value
->hdata
.intvl
.int_start
);
143 tree steps
= build_int_cst_type (unsigned_type_node
, value
->hdata
.intvl
.steps
);
145 ref_ptr
= force_gimple_operand_bsi (&bsi
,
146 build_addr (ref
, current_function_decl
),
148 val
= prepare_instrumented_value (&bsi
, value
);
149 args
= tree_cons (NULL_TREE
, ref_ptr
,
150 tree_cons (NULL_TREE
, val
,
151 tree_cons (NULL_TREE
, start
,
152 tree_cons (NULL_TREE
, steps
,
154 call
= build_function_call_expr (tree_interval_profiler_fn
, args
);
155 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
158 /* Output instructions as GIMPLE trees to increment the power of two histogram
159 counter. VALUE is the expression whose value is profiled. TAG is the tag
160 of the section for counters, BASE is offset of the counter position. */
163 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
165 tree stmt
= value
->hvalue
.stmt
;
166 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
167 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
168 tree args
, call
, val
;
170 ref_ptr
= force_gimple_operand_bsi (&bsi
,
171 build_addr (ref
, current_function_decl
),
173 val
= prepare_instrumented_value (&bsi
, value
);
174 args
= tree_cons (NULL_TREE
, ref_ptr
,
175 tree_cons (NULL_TREE
, val
,
177 call
= build_function_call_expr (tree_pow2_profiler_fn
, args
);
178 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
181 /* Output instructions as GIMPLE trees for code to find the most common value.
182 VALUE is the expression whose value is profiled. TAG is the tag of the
183 section for counters, BASE is offset of the counter position. */
186 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
188 tree stmt
= value
->hvalue
.stmt
;
189 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
190 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
191 tree args
, call
, val
;
193 ref_ptr
= force_gimple_operand_bsi (&bsi
,
194 build_addr (ref
, current_function_decl
),
196 val
= prepare_instrumented_value (&bsi
, value
);
197 args
= tree_cons (NULL_TREE
, ref_ptr
,
198 tree_cons (NULL_TREE
, val
,
200 call
= build_function_call_expr (tree_one_value_profiler_fn
, args
);
201 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
204 /* Output instructions as GIMPLE trees for code to find the most common value
205 of a difference between two evaluations of an expression.
206 VALUE is the expression whose value is profiled. TAG is the tag of the
207 section for counters, BASE is offset of the counter position. */
210 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED
,
211 unsigned tag ATTRIBUTE_UNUSED
,
212 unsigned base ATTRIBUTE_UNUSED
)
214 /* FIXME implement this. */
215 #ifdef ENABLE_CHECKING
216 internal_error ("unimplemented functionality");
221 /* Return 1 if tree-based profiling is in effect, else 0.
222 If it is, set up hooks for tree-based profiling.
223 Gate for pass_tree_profile. */
226 do_tree_profiling (void)
228 if (profile_arc_flag
|| flag_test_coverage
|| flag_branch_probabilities
)
230 tree_register_profile_hooks ();
231 tree_register_value_prof_hooks ();
237 /* Return the file on which profile dump output goes, if any. */
239 static FILE *tree_profile_dump_file (void) {
244 tree_profiling (void)
247 if (flag_branch_probabilities
248 && flag_profile_values
249 && flag_value_profile_transformations
)
250 value_profile_transformations ();
251 /* The above could hose dominator info. Currently there is
252 none coming in, this is a safety valve. It should be
253 easy to adjust it, if and when there is some. */
254 free_dominance_info (CDI_DOMINATORS
);
255 free_dominance_info (CDI_POST_DOMINATORS
);
258 struct tree_opt_pass pass_tree_profile
=
260 "tree_profile", /* name */
261 do_tree_profiling
, /* gate */
262 tree_profiling
, /* execute */
265 0, /* static_pass_number */
266 TV_BRANCH_PROB
, /* tv_id */
267 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
268 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
269 0, /* properties_destroyed */
270 0, /* todo_flags_start */
271 TODO_verify_stmts
, /* todo_flags_finish */
275 /* Return 1 if tree-based profiling is in effect, else 0.
276 If it is, set up hooks for tree-based profiling.
277 Gate for pass_tree_profile. */
280 do_early_tree_profiling (void)
282 return (do_tree_profiling () && (!flag_unit_at_a_time
|| !optimize
));
285 struct tree_opt_pass pass_early_tree_profile
=
287 "early_tree_profile", /* name */
288 do_early_tree_profiling
, /* gate */
289 tree_profiling
, /* execute */
292 0, /* static_pass_number */
293 TV_BRANCH_PROB
, /* tv_id */
294 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
295 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
296 0, /* properties_destroyed */
297 0, /* todo_flags_start */
298 TODO_verify_stmts
, /* todo_flags_finish */
302 struct profile_hooks tree_profile_hooks
=
304 tree_init_edge_profiler
, /* init_edge_profiler */
305 tree_gen_edge_profiler
, /* gen_edge_profiler */
306 tree_gen_interval_profiler
, /* gen_interval_profiler */
307 tree_gen_pow2_profiler
, /* gen_pow2_profiler */
308 tree_gen_one_value_profiler
, /* gen_one_value_profiler */
309 tree_gen_const_delta_profiler
,/* gen_const_delta_profiler */
310 tree_profile_dump_file
/* profile_dump_file */
313 #include "gt-tree-profile.h"