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, 2007 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 3, 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 COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 /* Generate basic block profile instrumentation and auxiliary files.
26 Tree-based version. See profile.c for overview. */
30 #include "coretypes.h"
41 #include "tree-flow.h"
42 #include "tree-dump.h"
43 #include "tree-pass.h"
45 #include "value-prof.h"
48 static GTY(()) tree gcov_type_node
;
49 static GTY(()) tree tree_interval_profiler_fn
;
50 static GTY(()) tree tree_pow2_profiler_fn
;
51 static GTY(()) tree tree_one_value_profiler_fn
;
54 /* Do initialization work for the edge profiler. */
57 tree_init_edge_profiler (void)
59 tree interval_profiler_fn_type
;
60 tree pow2_profiler_fn_type
;
61 tree one_value_profiler_fn_type
;
66 gcov_type_node
= get_gcov_type ();
67 gcov_type_ptr
= build_pointer_type (gcov_type_node
);
69 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
70 interval_profiler_fn_type
71 = build_function_type_list (void_type_node
,
72 gcov_type_ptr
, gcov_type_node
,
74 unsigned_type_node
, NULL_TREE
);
75 tree_interval_profiler_fn
76 = build_fn_decl ("__gcov_interval_profiler",
77 interval_profiler_fn_type
);
79 /* void (*) (gcov_type *, gcov_type) */
81 = build_function_type_list (void_type_node
,
82 gcov_type_ptr
, gcov_type_node
,
84 tree_pow2_profiler_fn
= build_fn_decl ("__gcov_pow2_profiler",
85 pow2_profiler_fn_type
);
87 /* void (*) (gcov_type *, gcov_type) */
88 one_value_profiler_fn_type
89 = build_function_type_list (void_type_node
,
90 gcov_type_ptr
, gcov_type_node
,
92 tree_one_value_profiler_fn
93 = build_fn_decl ("__gcov_one_value_profiler",
94 one_value_profiler_fn_type
);
98 /* Output instructions as GIMPLE trees to increment the edge
99 execution count, and insert them on E. We rely on
100 bsi_insert_on_edge to preserve the order. */
103 tree_gen_edge_profiler (int edgeno
, edge e
)
105 tree tmp1
= create_tmp_var (gcov_type_node
, "PROF");
106 tree tmp2
= create_tmp_var (gcov_type_node
, "PROF");
107 tree ref
= tree_coverage_counter_ref (GCOV_COUNTER_ARCS
, edgeno
);
108 tree stmt1
= build2 (MODIFY_EXPR
, gcov_type_node
, tmp1
, ref
);
109 tree stmt2
= build2 (MODIFY_EXPR
, gcov_type_node
, tmp2
,
110 build2 (PLUS_EXPR
, gcov_type_node
,
111 tmp1
, integer_one_node
));
112 tree stmt3
= build2 (MODIFY_EXPR
, gcov_type_node
, ref
, tmp2
);
113 bsi_insert_on_edge (e
, stmt1
);
114 bsi_insert_on_edge (e
, stmt2
);
115 bsi_insert_on_edge (e
, stmt3
);
118 /* Emits code to get VALUE to instrument at BSI, and returns the
119 variable containing the value. */
122 prepare_instrumented_value (block_stmt_iterator
*bsi
,
123 histogram_value value
)
125 tree val
= value
->hvalue
.value
;
126 return force_gimple_operand_bsi (bsi
, fold_convert (gcov_type_node
, val
),
130 /* Output instructions as GIMPLE trees to increment the interval histogram
131 counter. VALUE is the expression whose value is profiled. TAG is the
132 tag of the section for counters, BASE is offset of the counter position. */
135 tree_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
137 tree stmt
= value
->hvalue
.stmt
;
138 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
139 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
140 tree args
, call
, val
;
141 tree start
= build_int_cst_type (integer_type_node
, value
->hdata
.intvl
.int_start
);
142 tree steps
= build_int_cst_type (unsigned_type_node
, value
->hdata
.intvl
.steps
);
144 ref_ptr
= force_gimple_operand_bsi (&bsi
,
145 build_addr (ref
, current_function_decl
),
147 val
= prepare_instrumented_value (&bsi
, value
);
148 args
= tree_cons (NULL_TREE
, ref_ptr
,
149 tree_cons (NULL_TREE
, val
,
150 tree_cons (NULL_TREE
, start
,
151 tree_cons (NULL_TREE
, steps
,
153 call
= build_function_call_expr (tree_interval_profiler_fn
, args
);
154 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
157 /* Output instructions as GIMPLE trees to increment the power of two histogram
158 counter. VALUE is the expression whose value is profiled. TAG is the tag
159 of the section for counters, BASE is offset of the counter position. */
162 tree_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
164 tree stmt
= value
->hvalue
.stmt
;
165 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
166 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
167 tree args
, call
, val
;
169 ref_ptr
= force_gimple_operand_bsi (&bsi
,
170 build_addr (ref
, current_function_decl
),
172 val
= prepare_instrumented_value (&bsi
, value
);
173 args
= tree_cons (NULL_TREE
, ref_ptr
,
174 tree_cons (NULL_TREE
, val
,
176 call
= build_function_call_expr (tree_pow2_profiler_fn
, args
);
177 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
180 /* Output instructions as GIMPLE trees for code to find the most common value.
181 VALUE is the expression whose value is profiled. TAG is the tag of the
182 section for counters, BASE is offset of the counter position. */
185 tree_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
187 tree stmt
= value
->hvalue
.stmt
;
188 block_stmt_iterator bsi
= bsi_for_stmt (stmt
);
189 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
190 tree args
, call
, val
;
192 ref_ptr
= force_gimple_operand_bsi (&bsi
,
193 build_addr (ref
, current_function_decl
),
195 val
= prepare_instrumented_value (&bsi
, value
);
196 args
= tree_cons (NULL_TREE
, ref_ptr
,
197 tree_cons (NULL_TREE
, val
,
199 call
= build_function_call_expr (tree_one_value_profiler_fn
, args
);
200 bsi_insert_before (&bsi
, call
, BSI_SAME_STMT
);
203 /* Output instructions as GIMPLE trees for code to find the most common value
204 of a difference between two evaluations of an expression.
205 VALUE is the expression whose value is profiled. TAG is the tag of the
206 section for counters, BASE is offset of the counter position. */
209 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED
,
210 unsigned tag ATTRIBUTE_UNUSED
,
211 unsigned base ATTRIBUTE_UNUSED
)
213 /* FIXME implement this. */
214 #ifdef ENABLE_CHECKING
215 internal_error ("unimplemented functionality");
220 /* Return 1 if tree-based profiling is in effect, else 0.
221 If it is, set up hooks for tree-based profiling.
222 Gate for pass_tree_profile. */
225 do_tree_profiling (void)
227 if (profile_arc_flag
|| flag_test_coverage
|| flag_branch_probabilities
)
229 tree_register_profile_hooks ();
230 tree_register_value_prof_hooks ();
237 tree_profiling (void)
240 if (flag_branch_probabilities
241 && flag_profile_values
242 && flag_value_profile_transformations
)
243 value_profile_transformations ();
244 /* The above could hose dominator info. Currently there is
245 none coming in, this is a safety valve. It should be
246 easy to adjust it, if and when there is some. */
247 free_dominance_info (CDI_DOMINATORS
);
248 free_dominance_info (CDI_POST_DOMINATORS
);
252 struct tree_opt_pass pass_tree_profile
=
254 "tree_profile", /* name */
255 do_tree_profiling
, /* gate */
256 tree_profiling
, /* execute */
259 0, /* static_pass_number */
260 TV_BRANCH_PROB
, /* tv_id */
261 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
262 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
263 0, /* properties_destroyed */
264 0, /* todo_flags_start */
265 TODO_verify_stmts
, /* todo_flags_finish */
269 /* Return 1 if tree-based profiling is in effect, else 0.
270 If it is, set up hooks for tree-based profiling.
271 Gate for pass_tree_profile. */
274 do_early_tree_profiling (void)
276 return (do_tree_profiling () && (!flag_unit_at_a_time
|| !optimize
));
279 struct tree_opt_pass pass_early_tree_profile
=
281 "early_tree_profile", /* name */
282 do_early_tree_profiling
, /* gate */
283 tree_profiling
, /* execute */
286 0, /* static_pass_number */
287 TV_BRANCH_PROB
, /* tv_id */
288 PROP_gimple_leh
| PROP_cfg
, /* properties_required */
289 PROP_gimple_leh
| PROP_cfg
, /* properties_provided */
290 0, /* properties_destroyed */
291 0, /* todo_flags_start */
292 TODO_verify_stmts
, /* todo_flags_finish */
296 struct profile_hooks tree_profile_hooks
=
298 tree_init_edge_profiler
, /* init_edge_profiler */
299 tree_gen_edge_profiler
, /* gen_edge_profiler */
300 tree_gen_interval_profiler
, /* gen_interval_profiler */
301 tree_gen_pow2_profiler
, /* gen_pow2_profiler */
302 tree_gen_one_value_profiler
, /* gen_one_value_profiler */
303 tree_gen_const_delta_profiler
/* gen_const_delta_profiler */
306 #include "gt-tree-profile.h"