2005-05-11 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / tree-profile.c
blob2c91fc3859fa20d5d1c8e829a60f7b7e867cc80e
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, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, 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 = 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. */
122 static tree
123 prepare_instrumented_value (block_stmt_iterator *bsi,
124 histogram_value value)
126 tree val = value->hvalue.tree.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.tree.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),
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.tree.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),
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.tree.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),
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 (flag_tree_based_profiling
229 && (profile_arc_flag || flag_test_coverage || flag_branch_probabilities))
231 tree_register_profile_hooks ();
232 tree_register_value_prof_hooks ();
233 return true;
235 return false;
238 /* Return the file on which profile dump output goes, if any. */
240 static FILE *tree_profile_dump_file (void) {
241 return dump_file;
244 static void
245 tree_profiling (void)
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);
259 struct tree_opt_pass pass_tree_profile =
261 "tree_profile", /* name */
262 do_tree_profiling, /* gate */
263 tree_profiling, /* execute */
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 */
272 TODO_verify_stmts, /* todo_flags_finish */
273 0 /* letter */
276 struct profile_hooks tree_profile_hooks =
278 tree_init_edge_profiler, /* init_edge_profiler */
279 tree_gen_edge_profiler, /* gen_edge_profiler */
280 tree_gen_interval_profiler, /* gen_interval_profiler */
281 tree_gen_pow2_profiler, /* gen_pow2_profiler */
282 tree_gen_one_value_profiler, /* gen_one_value_profiler */
283 tree_gen_const_delta_profiler,/* gen_const_delta_profiler */
284 tree_profile_dump_file /* profile_dump_file */
287 #include "gt-tree-profile.h"