2006-08-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
[official-gcc.git] / gcc / tree-profile.c
blobfe42309ccc7d3e0f171ddce2e43ae07eabc80782
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
14 version.
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
19 for more details.
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
24 02110-1301, USA. */
26 /* Generate basic block profile instrumentation and auxiliary files.
27 Tree-based version. See profile.c for overview. */
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"
47 #include "ggc.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. */
57 static void
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;
63 tree gcov_type_ptr;
65 if (!gcov_type_node)
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,
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);
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);
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);
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. */
103 static void
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 = build2 (MODIFY_EXPR, gcov_type_node, tmp1, ref);
110 tree stmt2 = build2 (MODIFY_EXPR, gcov_type_node, tmp2,
111 build2 (PLUS_EXPR, gcov_type_node,
112 tmp1, integer_one_node));
113 tree stmt3 = build2 (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. */
122 static tree
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),
128 true, NULL_TREE);
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. */
135 static void
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),
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);
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. */
162 static void
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),
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);
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. */
185 static void
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),
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);
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. */
209 static void
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");
217 #endif
218 gcc_unreachable ();
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. */
225 static bool
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 ();
232 return true;
234 return false;
237 static unsigned int
238 tree_profiling (void)
240 branch_prob ();
241 if (flag_branch_probabilities
242 && flag_profile_values
243 && flag_value_profile_transformations)
244 value_profile_transformations ();
245 /* The above could hose dominator info. Currently there is
246 none coming in, this is a safety valve. It should be
247 easy to adjust it, if and when there is some. */
248 free_dominance_info (CDI_DOMINATORS);
249 free_dominance_info (CDI_POST_DOMINATORS);
250 return 0;
253 struct tree_opt_pass pass_tree_profile =
255 "tree_profile", /* name */
256 do_tree_profiling, /* gate */
257 tree_profiling, /* execute */
258 NULL, /* sub */
259 NULL, /* next */
260 0, /* static_pass_number */
261 TV_BRANCH_PROB, /* tv_id */
262 PROP_gimple_leh | PROP_cfg, /* properties_required */
263 PROP_gimple_leh | PROP_cfg, /* properties_provided */
264 0, /* properties_destroyed */
265 0, /* todo_flags_start */
266 TODO_verify_stmts, /* todo_flags_finish */
267 0 /* letter */
270 /* Return 1 if tree-based profiling is in effect, else 0.
271 If it is, set up hooks for tree-based profiling.
272 Gate for pass_tree_profile. */
274 static bool
275 do_early_tree_profiling (void)
277 return (do_tree_profiling () && (!flag_unit_at_a_time || !optimize));
280 struct tree_opt_pass pass_early_tree_profile =
282 "early_tree_profile", /* name */
283 do_early_tree_profiling, /* gate */
284 tree_profiling, /* execute */
285 NULL, /* sub */
286 NULL, /* next */
287 0, /* static_pass_number */
288 TV_BRANCH_PROB, /* tv_id */
289 PROP_gimple_leh | PROP_cfg, /* properties_required */
290 PROP_gimple_leh | PROP_cfg, /* properties_provided */
291 0, /* properties_destroyed */
292 0, /* todo_flags_start */
293 TODO_verify_stmts, /* todo_flags_finish */
294 0 /* letter */
297 struct profile_hooks tree_profile_hooks =
299 tree_init_edge_profiler, /* init_edge_profiler */
300 tree_gen_edge_profiler, /* gen_edge_profiler */
301 tree_gen_interval_profiler, /* gen_interval_profiler */
302 tree_gen_pow2_profiler, /* gen_pow2_profiler */
303 tree_gen_one_value_profiler, /* gen_one_value_profiler */
304 tree_gen_const_delta_profiler /* gen_const_delta_profiler */
307 #include "gt-tree-profile.h"