OSDN Git Service

contrib/
[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, 2006, 2007, 2008
4    Free Software Foundation, Inc.
5    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6    based on some ideas from Dain Samples of UC Berkeley.
7    Further mangling by Bob Manson, Cygnus Support.
8    Converted to use trees by Dale Johannesen, Apple Computer.
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3.  If not see
24 <http://www.gnu.org/licenses/>.  */
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 gcov_type_tmp_var;
52 static GTY(()) tree tree_interval_profiler_fn;
53 static GTY(()) tree tree_pow2_profiler_fn;
54 static GTY(()) tree tree_one_value_profiler_fn;
55 static GTY(()) tree tree_indirect_call_profiler_fn;
56 static GTY(()) tree tree_average_profiler_fn;
57 static GTY(()) tree tree_ior_profiler_fn;
58 \f
59
60 static GTY(()) tree ic_void_ptr_var;
61 static GTY(()) tree ic_gcov_type_ptr_var;
62 static GTY(()) tree ptr_void;
63
64 /* Do initialization work for the edge profiler.  */
65
66 /* Add code:
67    static gcov* __gcov_indirect_call_counters; // pointer to actual counter
68    static void* __gcov_indirect_call_callee; // actual callee address
69 */
70 static void
71 tree_init_ic_make_global_vars (void)
72 {
73   tree  gcov_type_ptr;
74
75   ptr_void = build_pointer_type (void_type_node);
76   
77   ic_void_ptr_var 
78     = build_decl (VAR_DECL, 
79                   get_identifier ("__gcov_indirect_call_callee"), 
80                   ptr_void);
81   TREE_STATIC (ic_void_ptr_var) = 1;
82   TREE_PUBLIC (ic_void_ptr_var) = 0;
83   DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
84   DECL_INITIAL (ic_void_ptr_var) = NULL;
85   assemble_variable (ic_void_ptr_var, 0, 0, 0);
86
87   gcov_type_ptr = build_pointer_type (get_gcov_type ());
88   ic_gcov_type_ptr_var 
89     = build_decl (VAR_DECL, 
90                   get_identifier ("__gcov_indirect_call_counters"), 
91                   gcov_type_ptr);
92   TREE_STATIC (ic_gcov_type_ptr_var) = 1;
93   TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
94   DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
95   DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
96   assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
97 }
98
99 static void
100 tree_init_edge_profiler (void)
101 {
102   tree interval_profiler_fn_type;
103   tree pow2_profiler_fn_type;
104   tree one_value_profiler_fn_type;
105   tree gcov_type_ptr;
106   tree ic_profiler_fn_type;
107   tree average_profiler_fn_type;
108
109   if (!gcov_type_node)
110     {
111       gcov_type_node = get_gcov_type ();
112       gcov_type_ptr = build_pointer_type (gcov_type_node);
113
114       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
115       interval_profiler_fn_type
116               = build_function_type_list (void_type_node,
117                                           gcov_type_ptr, gcov_type_node,
118                                           integer_type_node,
119                                           unsigned_type_node, NULL_TREE);
120       tree_interval_profiler_fn
121               = build_fn_decl ("__gcov_interval_profiler",
122                                      interval_profiler_fn_type);
123
124       /* void (*) (gcov_type *, gcov_type)  */
125       pow2_profiler_fn_type
126               = build_function_type_list (void_type_node,
127                                           gcov_type_ptr, gcov_type_node,
128                                           NULL_TREE);
129       tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
130                                                    pow2_profiler_fn_type);
131
132       /* void (*) (gcov_type *, gcov_type)  */
133       one_value_profiler_fn_type
134               = build_function_type_list (void_type_node,
135                                           gcov_type_ptr, gcov_type_node,
136                                           NULL_TREE);
137       tree_one_value_profiler_fn
138               = build_fn_decl ("__gcov_one_value_profiler",
139                                      one_value_profiler_fn_type);
140
141       tree_init_ic_make_global_vars ();
142       
143       /* void (*) (gcov_type *, gcov_type, void *, void *)  */
144       ic_profiler_fn_type
145                = build_function_type_list (void_type_node,
146                                           gcov_type_ptr, gcov_type_node,
147                                           ptr_void,
148                                           ptr_void, NULL_TREE);
149       tree_indirect_call_profiler_fn
150               = build_fn_decl ("__gcov_indirect_call_profiler",
151                                      ic_profiler_fn_type);
152       /* void (*) (gcov_type *, gcov_type)  */
153       average_profiler_fn_type
154               = build_function_type_list (void_type_node,
155                                           gcov_type_ptr, gcov_type_node, NULL_TREE);
156       tree_average_profiler_fn
157               = build_fn_decl ("__gcov_average_profiler",
158                                      average_profiler_fn_type);
159       tree_ior_profiler_fn
160               = build_fn_decl ("__gcov_ior_profiler",
161                                      average_profiler_fn_type);
162     }
163 }
164
165 /* Output instructions as GIMPLE trees to increment the edge 
166    execution count, and insert them on E.  We rely on 
167    bsi_insert_on_edge to preserve the order.  */
168
169 static void
170 tree_gen_edge_profiler (int edgeno, edge e)
171 {
172   tree ref, one, stmt1, stmt2, stmt3;
173
174   /* We share one temporary variable declaration per function.  This
175      gets re-set in tree_profiling.  */
176   if (gcov_type_tmp_var == NULL_TREE)
177     gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
178   ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
179   one = build_int_cst (gcov_type_node, 1);
180   stmt1 = build_gimple_modify_stmt (gcov_type_tmp_var, ref);
181   stmt2 = build_gimple_modify_stmt (gcov_type_tmp_var,
182                                     build2 (PLUS_EXPR, gcov_type_node,
183                                             gcov_type_tmp_var, one));
184   stmt3 = build_gimple_modify_stmt (unshare_expr (ref), gcov_type_tmp_var);
185   bsi_insert_on_edge (e, stmt1);
186   bsi_insert_on_edge (e, stmt2);
187   bsi_insert_on_edge (e, stmt3);
188 }
189
190 /* Emits code to get VALUE to instrument at BSI, and returns the
191    variable containing the value.  */
192
193 static tree
194 prepare_instrumented_value (block_stmt_iterator *bsi,
195                             histogram_value value)
196 {
197   tree val = value->hvalue.value;
198   return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
199                                    true, NULL_TREE, true, BSI_SAME_STMT);
200 }
201
202 /* Output instructions as GIMPLE trees to increment the interval histogram 
203    counter.  VALUE is the expression whose value is profiled.  TAG is the 
204    tag of the section for counters, BASE is offset of the counter position.  */
205
206 static void
207 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
208 {
209   tree stmt = value->hvalue.stmt;
210   block_stmt_iterator bsi = bsi_for_stmt (stmt);
211   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
212   tree call, val;
213   tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start);
214   tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps);
215   
216   ref_ptr = force_gimple_operand_bsi (&bsi,
217                                       build_addr (ref, current_function_decl),
218                                       true, NULL_TREE, true, BSI_SAME_STMT);
219   val = prepare_instrumented_value (&bsi, value);
220   call = build_call_expr (tree_interval_profiler_fn, 4,
221                           ref_ptr, val, start, steps);
222   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
223 }
224
225 /* Output instructions as GIMPLE trees to increment the power of two histogram 
226    counter.  VALUE is the expression whose value is profiled.  TAG is the tag 
227    of the section for counters, BASE is offset of the counter position.  */
228
229 static void
230 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
231 {
232   tree stmt = value->hvalue.stmt;
233   block_stmt_iterator bsi = bsi_for_stmt (stmt);
234   tree ref_ptr = tree_coverage_counter_addr (tag, base);
235   tree call, val;
236   
237   ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
238                                       true, NULL_TREE, true, BSI_SAME_STMT);
239   val = prepare_instrumented_value (&bsi, value);
240   call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val);
241   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
242 }
243
244 /* Output instructions as GIMPLE trees for code to find the most common value.
245    VALUE is the expression whose value is profiled.  TAG is the tag of the
246    section for counters, BASE is offset of the counter position.  */
247
248 static void
249 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
250 {
251   tree stmt = value->hvalue.stmt;
252   block_stmt_iterator bsi = bsi_for_stmt (stmt);
253   tree ref_ptr = tree_coverage_counter_addr (tag, base);
254   tree call, val;
255   
256   ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
257                                       true, NULL_TREE, true, BSI_SAME_STMT);
258   val = prepare_instrumented_value (&bsi, value);
259   call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val);
260   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
261 }
262
263
264 /* Output instructions as GIMPLE trees for code to find the most
265    common called function in indirect call.  
266    VALUE is the call expression whose indirect callee is profiled.
267    TAG is the tag of the section for counters, BASE is offset of the
268    counter position.  */
269
270 static void
271 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
272 {
273   tree tmp1, stmt1, stmt2, stmt3;
274   tree stmt = value->hvalue.stmt;
275   block_stmt_iterator bsi = bsi_for_stmt (stmt);
276   tree ref_ptr = tree_coverage_counter_addr (tag, base);
277
278   ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
279                                       true, NULL_TREE, true, BSI_SAME_STMT);
280
281   /* Insert code:
282     
283     __gcov_indirect_call_counters = get_relevant_counter_ptr (); 
284     __gcov_indirect_call_callee = (void *) indirect call argument;
285    */
286
287   tmp1 = create_tmp_var (ptr_void, "PROF");
288   stmt1 = build_gimple_modify_stmt (ic_gcov_type_ptr_var, ref_ptr);
289   stmt2 = build_gimple_modify_stmt (tmp1, unshare_expr (value->hvalue.value));
290   stmt3 = build_gimple_modify_stmt (ic_void_ptr_var, tmp1);
291
292   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
293   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
294   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
295 }
296
297
298 /* Output instructions as GIMPLE trees for code to find the most
299    common called function in indirect call. Insert instructions at the
300    beginning of every possible called function.
301   */
302
303 static void
304 tree_gen_ic_func_profiler (void)
305 {
306   struct cgraph_node * c_node = cgraph_node (current_function_decl);
307   block_stmt_iterator bsi;
308   edge e;
309   basic_block bb;
310   edge_iterator ei;
311   tree stmt1, stmt2;
312   tree tree_uid, cur_func;
313
314   if (flag_unit_at_a_time)
315     {
316       if (!c_node->needed)
317         return;
318     }
319   
320   tree_init_edge_profiler ();
321   
322   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
323     {
324       tree void0;
325
326       bb = split_edge (e);
327       bsi = bsi_start (bb);
328
329       cur_func = force_gimple_operand_bsi (&bsi,
330                                            build_addr (current_function_decl, 
331                                                        current_function_decl),
332                                            true, NULL_TREE,
333                                            true, BSI_SAME_STMT);
334       tree_uid = build_int_cst (gcov_type_node, c_node->pid);
335       stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4,
336                                ic_gcov_type_ptr_var,
337                                tree_uid,
338                                cur_func,
339                                ic_void_ptr_var);
340       bsi_insert_after (&bsi, stmt1, BSI_NEW_STMT);
341
342       gcc_assert (EDGE_COUNT (bb->succs) == 1);
343       bb = split_edge (EDGE_I (bb->succs, 0));
344       bsi = bsi_start (bb);
345       /* Set __gcov_indirect_call_callee to 0,
346          so that calls from other modules won't get misattributed
347          to the last caller of the current callee. */
348       void0 = build_int_cst (build_pointer_type (void_type_node), 0);
349       stmt2 = build_gimple_modify_stmt (ic_void_ptr_var, void0);
350       bsi_insert_after (&bsi, stmt2, BSI_NEW_STMT);
351     }
352 }
353
354 /* Output instructions as GIMPLE trees for code to find the most common value 
355    of a difference between two evaluations of an expression.
356    VALUE is the expression whose value is profiled.  TAG is the tag of the
357    section for counters, BASE is offset of the counter position.  */
358
359 static void
360 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, 
361                                 unsigned tag ATTRIBUTE_UNUSED,
362                                 unsigned base ATTRIBUTE_UNUSED)
363 {
364   /* FIXME implement this.  */
365 #ifdef ENABLE_CHECKING
366   internal_error ("unimplemented functionality");
367 #endif
368   gcc_unreachable ();
369 }
370
371 /* Output instructions as GIMPLE trees to increment the average histogram 
372    counter.  VALUE is the expression whose value is profiled.  TAG is the 
373    tag of the section for counters, BASE is offset of the counter position.  */
374
375 static void
376 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
377 {
378   tree stmt = value->hvalue.stmt;
379   block_stmt_iterator bsi = bsi_for_stmt (stmt);
380   tree ref_ptr = tree_coverage_counter_addr (tag, base);
381   tree call, val;
382   
383   ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
384                                       true, NULL_TREE,
385                                       true, BSI_SAME_STMT);
386   val = prepare_instrumented_value (&bsi, value);
387   call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val);
388   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
389 }
390
391 /* Output instructions as GIMPLE trees to increment the ior histogram 
392    counter.  VALUE is the expression whose value is profiled.  TAG is the 
393    tag of the section for counters, BASE is offset of the counter position.  */
394
395 static void
396 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
397 {
398   tree stmt = value->hvalue.stmt;
399   block_stmt_iterator bsi = bsi_for_stmt (stmt);
400   tree ref_ptr = tree_coverage_counter_addr (tag, base);
401   tree call, val;
402   
403   ref_ptr = force_gimple_operand_bsi (&bsi, ref_ptr,
404                                       true, NULL_TREE, true, BSI_SAME_STMT);
405   val = prepare_instrumented_value (&bsi, value);
406   call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val);
407   bsi_insert_before (&bsi, call, BSI_SAME_STMT);
408 }
409
410 /* Return 1 if tree-based profiling is in effect, else 0.
411    If it is, set up hooks for tree-based profiling.
412    Gate for pass_tree_profile.  */
413
414 static bool
415 do_tree_profiling (void)
416 {
417   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
418     {
419       tree_register_profile_hooks ();
420       tree_register_value_prof_hooks ();
421       return true;
422     }
423   return false;
424 }
425
426 static unsigned int
427 tree_profiling (void)
428 {
429   /* Don't profile functions produced at destruction time, particularly
430      the gcov datastructure initializer.  Don't profile if it has been
431      already instrumented either (when OpenMP expansion creates
432      child function from already instrumented body).  */
433   if (cgraph_state == CGRAPH_STATE_FINISHED
434       || cfun->after_tree_profile)
435     return 0;
436
437   /* Re-set global shared temporary variable for edge-counters.  */
438   gcov_type_tmp_var = NULL_TREE;
439
440   branch_prob ();
441
442   if (! flag_branch_probabilities 
443       && flag_profile_values)
444     tree_gen_ic_func_profiler ();
445
446   if (flag_branch_probabilities
447       && flag_profile_values
448       && flag_value_profile_transformations)
449     value_profile_transformations ();
450   /* The above could hose dominator info.  Currently there is
451      none coming in, this is a safety valve.  It should be
452      easy to adjust it, if and when there is some.  */
453   free_dominance_info (CDI_DOMINATORS);
454   free_dominance_info (CDI_POST_DOMINATORS);
455   cfun->after_tree_profile = 1;
456   return 0;
457 }
458
459 struct gimple_opt_pass pass_tree_profile = 
460 {
461  {
462   GIMPLE_PASS,
463   "tree_profile",                       /* name */
464   do_tree_profiling,                    /* gate */
465   tree_profiling,                       /* execute */
466   NULL,                                 /* sub */
467   NULL,                                 /* next */
468   0,                                    /* static_pass_number */
469   TV_BRANCH_PROB,                       /* tv_id */
470   PROP_gimple_leh | PROP_cfg,           /* properties_required */
471   PROP_gimple_leh | PROP_cfg,           /* properties_provided */
472   0,                                    /* properties_destroyed */
473   0,                                    /* todo_flags_start */
474   TODO_verify_stmts | TODO_dump_func    /* todo_flags_finish */
475  }
476 };
477
478 struct profile_hooks tree_profile_hooks =
479 {
480   tree_init_edge_profiler,       /* init_edge_profiler */
481   tree_gen_edge_profiler,        /* gen_edge_profiler */
482   tree_gen_interval_profiler,    /* gen_interval_profiler */
483   tree_gen_pow2_profiler,        /* gen_pow2_profiler */
484   tree_gen_one_value_profiler,   /* gen_one_value_profiler */
485   tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
486   tree_gen_ic_profiler,          /* gen_ic_profiler */
487   tree_gen_average_profiler,     /* gen_average_profiler */
488   tree_gen_ior_profiler          /* gen_ior_profiler */
489 };
490
491 #include "gt-tree-profile.h"