OSDN Git Service

2008-07-28 Richard Guenther <rguenther@suse.de>
[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    gsi_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;
173   gimple stmt1, stmt2, stmt3;
174
175   /* We share one temporary variable declaration per function.  This
176      gets re-set in tree_profiling.  */
177   if (gcov_type_tmp_var == NULL_TREE)
178     gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
179   ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
180   one = build_int_cst (gcov_type_node, 1);
181   stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
182   stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
183                                         gcov_type_tmp_var, one);
184   stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
185   gsi_insert_on_edge (e, stmt1);
186   gsi_insert_on_edge (e, stmt2);
187   gsi_insert_on_edge (e, stmt3);
188 }
189
190 /* Emits code to get VALUE to instrument at GSI, and returns the
191    variable containing the value.  */
192
193 static tree
194 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
195 {
196   tree val = value->hvalue.value;
197   return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
198                                    true, NULL_TREE, true, GSI_SAME_STMT);
199 }
200
201 /* Output instructions as GIMPLE trees to increment the interval histogram 
202    counter.  VALUE is the expression whose value is profiled.  TAG is the 
203    tag of the section for counters, BASE is offset of the counter position.  */
204
205 static void
206 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
207 {
208   gimple stmt = value->hvalue.stmt;
209   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
210   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
211   gimple call;
212   tree val;
213   tree start = build_int_cst_type (integer_type_node,
214                                    value->hdata.intvl.int_start);
215   tree steps = build_int_cst_type (unsigned_type_node,
216                                    value->hdata.intvl.steps);
217   
218   ref_ptr = force_gimple_operand_gsi (&gsi,
219                                       build_addr (ref, current_function_decl),
220                                       true, NULL_TREE, true, GSI_SAME_STMT);
221   val = prepare_instrumented_value (&gsi, value);
222   call = gimple_build_call (tree_interval_profiler_fn, 4,
223                             ref_ptr, val, start, steps);
224   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
225 }
226
227 /* Output instructions as GIMPLE trees to increment the power of two histogram 
228    counter.  VALUE is the expression whose value is profiled.  TAG is the tag 
229    of the section for counters, BASE is offset of the counter position.  */
230
231 static void
232 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
233 {
234   gimple stmt = value->hvalue.stmt;
235   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
236   tree ref_ptr = tree_coverage_counter_addr (tag, base);
237   gimple call;
238   tree val;
239   
240   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
241                                       true, NULL_TREE, true, GSI_SAME_STMT);
242   val = prepare_instrumented_value (&gsi, value);
243   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
244   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
245 }
246
247 /* Output instructions as GIMPLE trees for code to find the most common value.
248    VALUE is the expression whose value is profiled.  TAG is the tag of the
249    section for counters, BASE is offset of the counter position.  */
250
251 static void
252 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
253 {
254   gimple stmt = value->hvalue.stmt;
255   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
256   tree ref_ptr = tree_coverage_counter_addr (tag, base);
257   gimple call;
258   tree val;
259   
260   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
261                                       true, NULL_TREE, true, GSI_SAME_STMT);
262   val = prepare_instrumented_value (&gsi, value);
263   call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
264   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
265 }
266
267
268 /* Output instructions as GIMPLE trees for code to find the most
269    common called function in indirect call.  
270    VALUE is the call expression whose indirect callee is profiled.
271    TAG is the tag of the section for counters, BASE is offset of the
272    counter position.  */
273
274 static void
275 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
276 {
277   tree tmp1;
278   gimple stmt1, stmt2, stmt3;
279   gimple stmt = value->hvalue.stmt;
280   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
281   tree ref_ptr = tree_coverage_counter_addr (tag, base);
282
283   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
284                                       true, NULL_TREE, true, GSI_SAME_STMT);
285
286   /* Insert code:
287     
288     __gcov_indirect_call_counters = get_relevant_counter_ptr (); 
289     __gcov_indirect_call_callee = (void *) indirect call argument;
290    */
291
292   tmp1 = create_tmp_var (ptr_void, "PROF");
293   stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
294   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
295   stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
296
297   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
298   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
299   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
300 }
301
302
303 /* Output instructions as GIMPLE trees for code to find the most
304    common called function in indirect call. Insert instructions at the
305    beginning of every possible called function.
306   */
307
308 static void
309 tree_gen_ic_func_profiler (void)
310 {
311   struct cgraph_node * c_node = cgraph_node (current_function_decl);
312   gimple_stmt_iterator gsi;
313   edge e;
314   basic_block bb;
315   edge_iterator ei;
316   gimple stmt1, stmt2;
317   tree tree_uid, cur_func;
318
319   if (!c_node->needed)
320     return;
321   
322   tree_init_edge_profiler ();
323   
324   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
325     {
326       tree void0;
327
328       bb = split_edge (e);
329       gsi = gsi_start_bb (bb);
330
331       cur_func = force_gimple_operand_gsi (&gsi,
332                                            build_addr (current_function_decl, 
333                                                        current_function_decl),
334                                            true, NULL_TREE,
335                                            true, GSI_SAME_STMT);
336       tree_uid = build_int_cst (gcov_type_node, c_node->pid);
337       stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
338                                  ic_gcov_type_ptr_var,
339                                  tree_uid,
340                                  cur_func,
341                                  ic_void_ptr_var);
342       gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
343
344       gcc_assert (EDGE_COUNT (bb->succs) == 1);
345       bb = split_edge (EDGE_I (bb->succs, 0));
346       gsi = gsi_start_bb (bb);
347       /* Set __gcov_indirect_call_callee to 0,
348          so that calls from other modules won't get misattributed
349          to the last caller of the current callee. */
350       void0 = build_int_cst (build_pointer_type (void_type_node), 0);
351       stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
352       gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
353     }
354 }
355
356 /* Output instructions as GIMPLE trees for code to find the most common value 
357    of a difference between two evaluations of an expression.
358    VALUE is the expression whose value is profiled.  TAG is the tag of the
359    section for counters, BASE is offset of the counter position.  */
360
361 static void
362 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
363                                unsigned tag ATTRIBUTE_UNUSED,
364                                unsigned base ATTRIBUTE_UNUSED)
365 {
366   /* FIXME implement this.  */
367 #ifdef ENABLE_CHECKING
368   internal_error ("unimplemented functionality");
369 #endif
370   gcc_unreachable ();
371 }
372
373 /* Output instructions as GIMPLE trees to increment the average histogram 
374    counter.  VALUE is the expression whose value is profiled.  TAG is the 
375    tag of the section for counters, BASE is offset of the counter position.  */
376
377 static void
378 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
379 {
380   gimple stmt = value->hvalue.stmt;
381   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
382   tree ref_ptr = tree_coverage_counter_addr (tag, base);
383   gimple call;
384   tree val;
385   
386   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
387                                       true, NULL_TREE,
388                                       true, GSI_SAME_STMT);
389   val = prepare_instrumented_value (&gsi, value);
390   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
391   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
392 }
393
394 /* Output instructions as GIMPLE trees to increment the ior histogram 
395    counter.  VALUE is the expression whose value is profiled.  TAG is the 
396    tag of the section for counters, BASE is offset of the counter position.  */
397
398 static void
399 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
400 {
401   gimple stmt = value->hvalue.stmt;
402   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
403   tree ref_ptr = tree_coverage_counter_addr (tag, base);
404   gimple call;
405   tree val;
406   
407   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
408                                       true, NULL_TREE, true, GSI_SAME_STMT);
409   val = prepare_instrumented_value (&gsi, value);
410   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
411   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
412 }
413
414 /* Return 1 if tree-based profiling is in effect, else 0.
415    If it is, set up hooks for tree-based profiling.
416    Gate for pass_tree_profile.  */
417
418 static bool
419 do_tree_profiling (void)
420 {
421   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
422     {
423       tree_register_profile_hooks ();
424       gimple_register_value_prof_hooks ();
425       return true;
426     }
427   return false;
428 }
429
430 static unsigned int
431 tree_profiling (void)
432 {
433   /* Don't profile functions produced at destruction time, particularly
434      the gcov datastructure initializer.  Don't profile if it has been
435      already instrumented either (when OpenMP expansion creates
436      child function from already instrumented body).  */
437   if (cgraph_state == CGRAPH_STATE_FINISHED
438       || cfun->after_tree_profile)
439     return 0;
440
441   /* Re-set global shared temporary variable for edge-counters.  */
442   gcov_type_tmp_var = NULL_TREE;
443
444   branch_prob ();
445
446   if (! flag_branch_probabilities 
447       && flag_profile_values)
448     tree_gen_ic_func_profiler ();
449
450   if (flag_branch_probabilities
451       && flag_profile_values
452       && flag_value_profile_transformations)
453     value_profile_transformations ();
454   /* The above could hose dominator info.  Currently there is
455      none coming in, this is a safety valve.  It should be
456      easy to adjust it, if and when there is some.  */
457   free_dominance_info (CDI_DOMINATORS);
458   free_dominance_info (CDI_POST_DOMINATORS);
459   cfun->after_tree_profile = 1;
460   return 0;
461 }
462
463 struct gimple_opt_pass pass_tree_profile = 
464 {
465  {
466   GIMPLE_PASS,
467   "tree_profile",                       /* name */
468   do_tree_profiling,                    /* gate */
469   tree_profiling,                       /* execute */
470   NULL,                                 /* sub */
471   NULL,                                 /* next */
472   0,                                    /* static_pass_number */
473   TV_BRANCH_PROB,                       /* tv_id */
474   PROP_gimple_leh | PROP_cfg,           /* properties_required */
475   PROP_gimple_leh | PROP_cfg,           /* properties_provided */
476   0,                                    /* properties_destroyed */
477   0,                                    /* todo_flags_start */
478   TODO_verify_stmts | TODO_dump_func    /* todo_flags_finish */
479  }
480 };
481
482 struct profile_hooks tree_profile_hooks =
483 {
484   tree_init_edge_profiler,       /* init_edge_profiler */
485   tree_gen_edge_profiler,        /* gen_edge_profiler */
486   tree_gen_interval_profiler,    /* gen_interval_profiler */
487   tree_gen_pow2_profiler,        /* gen_pow2_profiler */
488   tree_gen_one_value_profiler,   /* gen_one_value_profiler */
489   tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
490   tree_gen_ic_profiler,          /* gen_ic_profiler */
491   tree_gen_average_profiler,     /* gen_average_profiler */
492   tree_gen_ior_profiler          /* gen_ior_profiler */
493 };
494
495 #include "gt-tree-profile.h"