OSDN Git Service

* gcc.c (getenv_spec_function): New function.
[pf3gnuchains/gcc-fork.git] / gcc / tree-profile.c
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.
8
9 This file is part of GCC.
10
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.
15
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.
20
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.  */
25
26 /* Generate basic block profile instrumentation and auxiliary files.
27    Tree-based version.  See profile.c for overview.  */
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"
47 #include "ggc.h"
48 #include "cgraph.h"
49
50 static GTY(()) tree gcov_type_node;
51 static GTY(()) tree tree_interval_profiler_fn;
52 static GTY(()) tree tree_pow2_profiler_fn;
53 static GTY(()) tree tree_one_value_profiler_fn;
54 static GTY(()) tree tree_indirect_call_profiler_fn;
55 static GTY(()) tree tree_average_profiler_fn;
56 static GTY(()) tree tree_ior_profiler_fn;
57 \f
58
59 static GTY(()) tree ic_void_ptr_var;
60 static GTY(()) tree ic_gcov_type_ptr_var;
61 static GTY(()) tree ptr_void;
62
63 /* Do initialization work for the edge profiler.  */
64
65 /* Add code:
66    static gcov* __gcov_indirect_call_counters; // pointer to actual counter
67    static void* __gcov_indirect_call_callee; // actual callee addres
68 */
69 static void
70 tree_init_ic_make_global_vars (void)
71 {
72   tree  gcov_type_ptr;
73
74   ptr_void = build_pointer_type (void_type_node);
75   
76   ic_void_ptr_var 
77     = build_decl (VAR_DECL, 
78                   get_identifier ("__gcov_indirect_call_callee"), 
79                   ptr_void);
80   TREE_STATIC (ic_void_ptr_var) = 1;
81   TREE_PUBLIC (ic_void_ptr_var) = 0;
82   DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
83   DECL_INITIAL (ic_void_ptr_var) = NULL;
84   assemble_variable (ic_void_ptr_var, 0, 0, 0);
85
86   gcov_type_ptr = build_pointer_type (get_gcov_type ());
87   ic_gcov_type_ptr_var 
88     = build_decl (VAR_DECL, 
89                   get_identifier ("__gcov_indirect_call_counters"), 
90                   gcov_type_ptr);
91   TREE_STATIC (ic_gcov_type_ptr_var) = 1;
92   TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
93   DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
94   DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
95   assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
96 }
97
98 static void
99 tree_init_edge_profiler (void)
100 {
101   tree interval_profiler_fn_type;
102   tree pow2_profiler_fn_type;
103   tree one_value_profiler_fn_type;
104   tree gcov_type_ptr;
105   tree ic_profiler_fn_type;
106   tree average_profiler_fn_type;
107
108   if (!gcov_type_node)
109     {
110       gcov_type_node = get_gcov_type ();
111       gcov_type_ptr = build_pointer_type (gcov_type_node);
112
113       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
114       interval_profiler_fn_type
115               = build_function_type_list (void_type_node,
116                                           gcov_type_ptr, gcov_type_node,
117                                           integer_type_node,
118                                           unsigned_type_node, NULL_TREE);
119       tree_interval_profiler_fn
120               = build_fn_decl ("__gcov_interval_profiler",
121                                      interval_profiler_fn_type);
122
123       /* void (*) (gcov_type *, gcov_type)  */
124       pow2_profiler_fn_type
125               = build_function_type_list (void_type_node,
126                                           gcov_type_ptr, gcov_type_node,
127                                           NULL_TREE);
128       tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
129                                                    pow2_profiler_fn_type);
130
131       /* void (*) (gcov_type *, gcov_type)  */
132       one_value_profiler_fn_type
133               = build_function_type_list (void_type_node,
134                                           gcov_type_ptr, gcov_type_node,
135                                           NULL_TREE);
136       tree_one_value_profiler_fn
137               = build_fn_decl ("__gcov_one_value_profiler",
138                                      one_value_profiler_fn_type);
139
140       tree_init_ic_make_global_vars ();
141       
142       /* void (*) (gcov_type *, gcov_type, void *, void *)  */
143       ic_profiler_fn_type
144                = build_function_type_list (void_type_node,
145                                           gcov_type_ptr, gcov_type_node,
146                                           ptr_void,
147                                           ptr_void, NULL_TREE);
148       tree_indirect_call_profiler_fn
149               = build_fn_decl ("__gcov_indirect_call_profiler",
150                                      ic_profiler_fn_type);
151       /* void (*) (gcov_type *, gcov_type)  */
152       average_profiler_fn_type
153               = build_function_type_list (void_type_node,
154                                           gcov_type_ptr, gcov_type_node, NULL_TREE);
155       tree_average_profiler_fn
156               = build_fn_decl ("__gcov_average_profiler",
157                                      average_profiler_fn_type);
158       tree_ior_profiler_fn
159               = build_fn_decl ("__gcov_ior_profiler",
160                                      average_profiler_fn_type);
161     }
162 }
163
164 /* Output instructions as GIMPLE trees to increment the edge 
165    execution count, and insert them on E.  We rely on 
166    bsi_insert_on_edge to preserve the order.  */
167
168 static void
169 tree_gen_edge_profiler (int edgeno, edge e)
170 {
171   tree tmp1 = create_tmp_var (gcov_type_node, "PROF");
172   tree tmp2 = create_tmp_var (gcov_type_node, "PROF");
173   tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
174   tree stmt1 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, tmp1, ref);
175   tree stmt2 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, tmp2,
176                        build2 (PLUS_EXPR, gcov_type_node, 
177                               tmp1, integer_one_node));
178   tree stmt3 = build2 (GIMPLE_MODIFY_STMT, gcov_type_node, ref, tmp2);
179   bsi_insert_on_edge (e, stmt1);
180   bsi_insert_on_edge (e, stmt2);
181   bsi_insert_on_edge (e, stmt3);
182 }
183
184 /* Emits code to get VALUE to instrument at BSI, and returns the
185    variable containing the value.  */
186
187 static tree
188 prepare_instrumented_value (block_stmt_iterator *bsi,
189                             histogram_value value)
190 {
191   tree val = value->hvalue.value;
192   return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
193                                    true, NULL_TREE);
194 }
195
196 /* Output instructions as GIMPLE trees to increment the interval histogram 
197    counter.  VALUE is the expression whose value is profiled.  TAG is the 
198    tag of the section for counters, BASE is offset of the counter position.  */
199
200 static void
201 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
202 {
203   tree stmt = value->hvalue.stmt;
204   block_stmt_iterator bsi = bsi_for_stmt (stmt);
205   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
206   tree call, val;
207   tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start);
208   tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps);
209   
210   ref_ptr = force_gimple_operand_bsi (&bsi,
211                                       build_addr (ref, current_function_decl),
212                                       true, NULL_TREE);
213   val = prepare_instrumented_value (&bsi, value);
214   call = build_call_expr (tree_interval_profiler_fn, 4,
215                           ref_ptr, val, start, steps);
216   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
217 }
218
219 /* Output instructions as GIMPLE trees to increment the power of two histogram 
220    counter.  VALUE is the expression whose value is profiled.  TAG is the tag 
221    of the section for counters, BASE is offset of the counter position.  */
222
223 static void
224 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
225 {
226   tree stmt = value->hvalue.stmt;
227   block_stmt_iterator bsi = bsi_for_stmt (stmt);
228   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
229   tree call, val;
230   
231   ref_ptr = force_gimple_operand_bsi (&bsi,
232                                       build_addr (ref, current_function_decl),
233                                       true, NULL_TREE);
234   val = prepare_instrumented_value (&bsi, value);
235   call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val);
236   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
237 }
238
239 /* Output instructions as GIMPLE trees for code to find the most common value.
240    VALUE is the expression whose value is profiled.  TAG is the tag of the
241    section for counters, BASE is offset of the counter position.  */
242
243 static void
244 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
245 {
246   tree stmt = value->hvalue.stmt;
247   block_stmt_iterator bsi = bsi_for_stmt (stmt);
248   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
249   tree call, val;
250   
251   ref_ptr = force_gimple_operand_bsi (&bsi,
252                                       build_addr (ref, current_function_decl),
253                                       true, NULL_TREE);
254   val = prepare_instrumented_value (&bsi, value);
255   call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val);
256   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
257 }
258
259
260 /* Output instructions as GIMPLE trees for code to find the most
261    common called function in indirect call.  
262    VALUE is the call expression whose indirect callee is profiled.
263    TAG is the tag of the section for counters, BASE is offset of the
264    counter position.  */
265
266 static void
267 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
268 {
269   tree tmp1, stmt1, stmt2, stmt3;
270   tree stmt = value->hvalue.stmt;
271   block_stmt_iterator bsi = bsi_for_stmt (stmt);
272   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
273
274   ref_ptr = force_gimple_operand_bsi (&bsi,
275                                       build_addr (ref, current_function_decl),
276                                       true, NULL_TREE);
277
278   /* Insert code:
279     
280     __gcov_indirect_call_counters = get_relevant_counter_ptr (); 
281     __gcov_indirect_call_callee = (void *) indirect call argument;
282    */
283
284   tmp1 = create_tmp_var (ptr_void, "PROF");
285   stmt1 = build2 (GIMPLE_MODIFY_STMT, 
286                   build_pointer_type (get_gcov_type ()), 
287                   ic_gcov_type_ptr_var, ref_ptr);
288   stmt2 = build2 (GIMPLE_MODIFY_STMT, ptr_void, tmp1, 
289                   unshare_expr (value->hvalue.value));
290   stmt3 = build2 (GIMPLE_MODIFY_STMT, ptr_void, 
291                   ic_void_ptr_var, tmp1);
292
293   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
294   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
295   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
296 }
297
298
299 /* Output instructions as GIMPLE trees for code to find the most
300    common called function in indirect call. Insert instructions at the
301    beginning of every possible called function.
302   */
303
304 static void
305 tree_gen_ic_func_profiler (void)
306 {
307   struct cgraph_node * c_node = cgraph_node (current_function_decl);
308   block_stmt_iterator bsi;
309   edge e;
310   basic_block bb;
311   edge_iterator ei;
312   tree stmt1;
313   tree tree_uid, cur_func;
314
315   if (flag_unit_at_a_time)
316     {
317       if (!c_node->needed)
318         return;
319     }
320   
321   tree_init_edge_profiler ();
322   
323   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
324     {
325       bb = split_edge (e);
326       bsi = bsi_start (bb);
327       cur_func = force_gimple_operand_bsi (&bsi,
328                                            build_addr (current_function_decl, 
329                                                        current_function_decl),
330                                            true, NULL_TREE);
331       tree_uid = build_int_cst (gcov_type_node, c_node->pid);
332       stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4,
333                                ic_gcov_type_ptr_var,
334                                tree_uid,
335                                cur_func,
336                                ic_void_ptr_var);
337       bsi_insert_after (&bsi, stmt1, BSI_SAME_STMT);
338     }
339 }
340
341 /* Output instructions as GIMPLE trees for code to find the most common value 
342    of a difference between two evaluations of an expression.
343    VALUE is the expression whose value is profiled.  TAG is the tag of the
344    section for counters, BASE is offset of the counter position.  */
345
346 static void
347 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, 
348                                 unsigned tag ATTRIBUTE_UNUSED,
349                                 unsigned base ATTRIBUTE_UNUSED)
350 {
351   /* FIXME implement this.  */
352 #ifdef ENABLE_CHECKING
353   internal_error ("unimplemented functionality");
354 #endif
355   gcc_unreachable ();
356 }
357
358 /* Output instructions as GIMPLE trees to increment the average histogram 
359    counter.  VALUE is the expression whose value is profiled.  TAG is the 
360    tag of the section for counters, BASE is offset of the counter position.  */
361
362 static void
363 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
364 {
365   tree stmt = value->hvalue.stmt;
366   block_stmt_iterator bsi = bsi_for_stmt (stmt);
367   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
368   tree call, val;
369   
370   ref_ptr = force_gimple_operand_bsi (&bsi,
371                                       build_addr (ref, current_function_decl),
372                                       true, NULL_TREE);
373   val = prepare_instrumented_value (&bsi, value);
374   call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val);
375   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
376 }
377
378 /* Output instructions as GIMPLE trees to increment the ior histogram 
379    counter.  VALUE is the expression whose value is profiled.  TAG is the 
380    tag of the section for counters, BASE is offset of the counter position.  */
381
382 static void
383 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
384 {
385   tree stmt = value->hvalue.stmt;
386   block_stmt_iterator bsi = bsi_for_stmt (stmt);
387   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
388   tree call, val;
389   
390   ref_ptr = force_gimple_operand_bsi (&bsi,
391                                       build_addr (ref, current_function_decl),
392                                       true, NULL_TREE);
393   val = prepare_instrumented_value (&bsi, value);
394   call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val);
395   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
396 }
397
398 /* Return 1 if tree-based profiling is in effect, else 0.
399    If it is, set up hooks for tree-based profiling.
400    Gate for pass_tree_profile.  */
401
402 static bool
403 do_tree_profiling (void)
404 {
405   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
406     {
407       tree_register_profile_hooks ();
408       tree_register_value_prof_hooks ();
409       return true;
410     }
411   return false;
412 }
413
414 static unsigned int
415 tree_profiling (void)
416 {
417   /* Don't profile functions produced at destruction time, particularly
418      the gcov datastructure initializer.  */
419   if (cgraph_state == CGRAPH_STATE_FINISHED)
420     return 0;
421   branch_prob ();
422
423   if (! flag_branch_probabilities 
424       && flag_profile_values)
425     tree_gen_ic_func_profiler ();
426
427   if (flag_branch_probabilities
428       && flag_profile_values
429       && flag_value_profile_transformations)
430     value_profile_transformations ();
431   /* The above could hose dominator info.  Currently there is
432      none coming in, this is a safety valve.  It should be
433      easy to adjust it, if and when there is some.  */
434   free_dominance_info (CDI_DOMINATORS);
435   free_dominance_info (CDI_POST_DOMINATORS);
436   return 0;
437 }
438
439 struct tree_opt_pass pass_tree_profile = 
440 {
441   "tree_profile",                       /* name */
442   do_tree_profiling,                    /* gate */
443   tree_profiling,                       /* execute */
444   NULL,                                 /* sub */
445   NULL,                                 /* next */
446   0,                                    /* static_pass_number */
447   TV_BRANCH_PROB,                       /* tv_id */
448   PROP_gimple_leh | PROP_cfg,           /* properties_required */
449   PROP_gimple_leh | PROP_cfg,           /* properties_provided */
450   0,                                    /* properties_destroyed */
451   0,                                    /* todo_flags_start */
452   TODO_verify_stmts | TODO_dump_func,   /* todo_flags_finish */
453   0                                     /* letter */
454 };
455
456 struct profile_hooks tree_profile_hooks =
457 {
458   tree_init_edge_profiler,       /* init_edge_profiler */
459   tree_gen_edge_profiler,        /* gen_edge_profiler */
460   tree_gen_interval_profiler,    /* gen_interval_profiler */
461   tree_gen_pow2_profiler,        /* gen_pow2_profiler */
462   tree_gen_one_value_profiler,   /* gen_one_value_profiler */
463   tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
464   tree_gen_ic_profiler,          /* gen_ic_profiler */
465   tree_gen_average_profiler,     /* gen_average_profiler */
466   tree_gen_ior_profiler          /* gen_ior_profiler */
467 };
468
469 #include "gt-tree-profile.h"