]> gcc.gnu.org Git - gcc.git/blame - gcc/tree-profile.c
cgraph.c (cgraph_clone_edge): New UPDATE_ORIGINAL argument.
[gcc.git] / gcc / tree-profile.c
CommitLineData
6de9cd9a
DN
1/* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
5f996627 3 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6de9cd9a
DN
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.
8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
13Software Foundation; either version 2, or (at your option) any later
14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
22along with GCC; see the file COPYING. If not, write to the Free
366ccddb
KC
23Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2402110-1301, USA. */
6de9cd9a
DN
25
26/* Generate basic block profile instrumentation and auxiliary files.
1f1e8527 27 Tree-based version. See profile.c for overview. */
6de9cd9a
DN
28
29#include "config.h"
30#include "system.h"
31#include "coretypes.h"
32#include "tm.h"
33#include "rtl.h"
34#include "flags.h"
35#include "output.h"
36#include "regs.h"
37#include "expr.h"
38#include "function.h"
39#include "toplev.h"
40#include "coverage.h"
41#include "tree.h"
42#include "tree-flow.h"
43#include "tree-dump.h"
44#include "tree-pass.h"
45#include "timevar.h"
46#include "value-prof.h"
9885da8e 47#include "ggc.h"
6de9cd9a 48
9885da8e
ZD
49static GTY(()) tree gcov_type_node;
50static GTY(()) tree tree_interval_profiler_fn;
51static GTY(()) tree tree_pow2_profiler_fn;
52static GTY(()) tree tree_one_value_profiler_fn;
6de9cd9a 53\f
f3df9541
AK
54
55/* Do initialization work for the edge profiler. */
56
57static void
58tree_init_edge_profiler (void)
59{
9885da8e
ZD
60 tree interval_profiler_fn_type;
61 tree pow2_profiler_fn_type;
62 tree one_value_profiler_fn_type;
63 tree gcov_type_ptr;
64
65 if (!gcov_type_node)
66 {
67 gcov_type_node = get_gcov_type ();
68 gcov_type_ptr = build_pointer_type (gcov_type_node);
69
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,
74 integer_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);
79
80 /* void (*) (gcov_type *, gcov_type) */
81 pow2_profiler_fn_type
82 = build_function_type_list (void_type_node,
83 gcov_type_ptr, gcov_type_node,
84 NULL_TREE);
85 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
86 pow2_profiler_fn_type);
87
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,
92 NULL_TREE);
93 tree_one_value_profiler_fn
94 = build_fn_decl ("__gcov_one_value_profiler",
95 one_value_profiler_fn_type);
96 }
f3df9541
AK
97}
98
6de9cd9a
DN
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. */
102
103static void
104tree_gen_edge_profiler (int edgeno, edge e)
105{
070e3969
RS
106 tree tmp1 = create_tmp_var (gcov_type_node, "PROF");
107 tree tmp2 = create_tmp_var (gcov_type_node, "PROF");
6de9cd9a 108 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
070e3969
RS
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,
6de9cd9a 112 tmp1, integer_one_node));
070e3969 113 tree stmt3 = build (MODIFY_EXPR, gcov_type_node, ref, tmp2);
6de9cd9a
DN
114 bsi_insert_on_edge (e, stmt1);
115 bsi_insert_on_edge (e, stmt2);
116 bsi_insert_on_edge (e, stmt3);
117}
118
9885da8e
ZD
119/* Emits code to get VALUE to instrument at BSI, and returns the
120 variable containing the value. */
121
122static tree
123prepare_instrumented_value (block_stmt_iterator *bsi,
124 histogram_value value)
125{
126 tree val = value->hvalue.tree.value;
127 return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
128 true, NULL_TREE);
129}
130
6de9cd9a
DN
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. */
134
135static void
1f1e8527 136tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
6de9cd9a 137{
1f1e8527
DJ
138 tree stmt = value->hvalue.tree.stmt;
139 block_stmt_iterator bsi = bsi_for_stmt (stmt);
9885da8e
ZD
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);
144
145 ref_ptr = force_gimple_operand_bsi (&bsi,
bde6c65d 146 build_addr (ref, current_function_decl),
9885da8e
ZD
147 true, NULL_TREE);
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,
153 NULL_TREE))));
154 call = build_function_call_expr (tree_interval_profiler_fn, args);
155 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
6de9cd9a
DN
156}
157
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. */
161
162static void
1f1e8527 163tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
6de9cd9a 164{
1f1e8527
DJ
165 tree stmt = value->hvalue.tree.stmt;
166 block_stmt_iterator bsi = bsi_for_stmt (stmt);
9885da8e
ZD
167 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
168 tree args, call, val;
169
170 ref_ptr = force_gimple_operand_bsi (&bsi,
bde6c65d 171 build_addr (ref, current_function_decl),
9885da8e
ZD
172 true, NULL_TREE);
173 val = prepare_instrumented_value (&bsi, value);
174 args = tree_cons (NULL_TREE, ref_ptr,
175 tree_cons (NULL_TREE, val,
176 NULL_TREE));
177 call = build_function_call_expr (tree_pow2_profiler_fn, args);
178 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
6de9cd9a
DN
179}
180
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. */
184
185static void
1f1e8527 186tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
6de9cd9a 187{
1f1e8527
DJ
188 tree stmt = value->hvalue.tree.stmt;
189 block_stmt_iterator bsi = bsi_for_stmt (stmt);
9885da8e
ZD
190 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
191 tree args, call, val;
192
193 ref_ptr = force_gimple_operand_bsi (&bsi,
bde6c65d 194 build_addr (ref, current_function_decl),
9885da8e
ZD
195 true, NULL_TREE);
196 val = prepare_instrumented_value (&bsi, value);
197 args = tree_cons (NULL_TREE, ref_ptr,
198 tree_cons (NULL_TREE, val,
199 NULL_TREE));
200 call = build_function_call_expr (tree_one_value_profiler_fn, args);
201 bsi_insert_before (&bsi, call, BSI_SAME_STMT);
6de9cd9a
DN
202}
203
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. */
208
209static void
6d9901e7 210tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
6de9cd9a
DN
211 unsigned tag ATTRIBUTE_UNUSED,
212 unsigned base ATTRIBUTE_UNUSED)
213{
214 /* FIXME implement this. */
1e128c5f
GB
215#ifdef ENABLE_CHECKING
216 internal_error ("unimplemented functionality");
217#endif
218 gcc_unreachable ();
6de9cd9a
DN
219}
220
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. */
224
1f1e8527
DJ
225static bool
226do_tree_profiling (void)
878f99d2 227{
bbd236a1
JH
228 if (flag_tree_based_profiling
229 && (profile_arc_flag || flag_test_coverage || flag_branch_probabilities))
6de9cd9a
DN
230 {
231 tree_register_profile_hooks ();
232 tree_register_value_prof_hooks ();
bbd236a1 233 return true;
6de9cd9a 234 }
bbd236a1 235 return false;
6de9cd9a
DN
236}
237
238/* Return the file on which profile dump output goes, if any. */
239
240static FILE *tree_profile_dump_file (void) {
241 return dump_file;
242}
243
1f1e8527
DJ
244static void
245tree_profiling (void)
246{
247 branch_prob ();
248 if (flag_branch_probabilities
249 && flag_profile_values
250 && flag_value_profile_transformations)
251 value_profile_transformations ();
252 /* The above could hose dominator info. Currently there is
253 none coming in, this is a safety valve. It should be
254 easy to adjust it, if and when there is some. */
255 free_dominance_info (CDI_DOMINATORS);
256 free_dominance_info (CDI_POST_DOMINATORS);
257}
258
6de9cd9a
DN
259struct tree_opt_pass pass_tree_profile =
260{
261 "tree_profile", /* name */
262 do_tree_profiling, /* gate */
1f1e8527 263 tree_profiling, /* execute */
6de9cd9a
DN
264 NULL, /* sub */
265 NULL, /* next */
266 0, /* static_pass_number */
267 TV_BRANCH_PROB, /* tv_id */
268 PROP_gimple_leh | PROP_cfg, /* properties_required */
269 PROP_gimple_leh | PROP_cfg, /* properties_provided */
270 0, /* properties_destroyed */
271 0, /* todo_flags_start */
9f8628ba
PB
272 TODO_verify_stmts, /* todo_flags_finish */
273 0 /* letter */
6de9cd9a
DN
274};
275
d63db217
JH
276/* Return 1 if tree-based profiling is in effect, else 0.
277 If it is, set up hooks for tree-based profiling.
278 Gate for pass_tree_profile. */
279
280static bool
281do_early_tree_profiling (void)
282{
283 return (do_tree_profiling () && (!flag_unit_at_a_time || !optimize));
284}
285
286struct tree_opt_pass pass_early_tree_profile =
287{
288 "early_tree_profile", /* name */
289 do_early_tree_profiling, /* gate */
290 tree_profiling, /* execute */
291 NULL, /* sub */
292 NULL, /* next */
293 0, /* static_pass_number */
294 TV_BRANCH_PROB, /* tv_id */
295 PROP_gimple_leh | PROP_cfg, /* properties_required */
296 PROP_gimple_leh | PROP_cfg, /* properties_provided */
297 0, /* properties_destroyed */
298 0, /* todo_flags_start */
299 TODO_verify_stmts, /* todo_flags_finish */
300 0 /* letter */
301};
302
6de9cd9a
DN
303struct profile_hooks tree_profile_hooks =
304{
f3df9541 305 tree_init_edge_profiler, /* init_edge_profiler */
6de9cd9a
DN
306 tree_gen_edge_profiler, /* gen_edge_profiler */
307 tree_gen_interval_profiler, /* gen_interval_profiler */
308 tree_gen_pow2_profiler, /* gen_pow2_profiler */
309 tree_gen_one_value_profiler, /* gen_one_value_profiler */
310 tree_gen_const_delta_profiler,/* gen_const_delta_profiler */
311 tree_profile_dump_file /* profile_dump_file */
312};
9885da8e
ZD
313
314#include "gt-tree-profile.h"
This page took 0.761562 seconds and 5 git commands to generate.