OSDN Git Service

2008-12-29 Seongbae Park <seongbae.park@gmail.com>
[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   DECL_TLS_MODEL (ic_void_ptr_var) = decl_default_tls_model (ic_void_ptr_var);
86   assemble_variable (ic_void_ptr_var, 0, 0, 0);
87
88   gcov_type_ptr = build_pointer_type (get_gcov_type ());
89   ic_gcov_type_ptr_var 
90     = build_decl (VAR_DECL, 
91                   get_identifier ("__gcov_indirect_call_counters"), 
92                   gcov_type_ptr);
93   TREE_STATIC (ic_gcov_type_ptr_var) = 1;
94   TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
95   DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
96   DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
97   DECL_TLS_MODEL (ic_gcov_type_ptr_var) = decl_default_tls_model (ic_gcov_type_ptr_var);
98   assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
99 }
100
101 static void
102 tree_init_edge_profiler (void)
103 {
104   tree interval_profiler_fn_type;
105   tree pow2_profiler_fn_type;
106   tree one_value_profiler_fn_type;
107   tree gcov_type_ptr;
108   tree ic_profiler_fn_type;
109   tree average_profiler_fn_type;
110
111   if (!gcov_type_node)
112     {
113       gcov_type_node = get_gcov_type ();
114       gcov_type_ptr = build_pointer_type (gcov_type_node);
115
116       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
117       interval_profiler_fn_type
118               = build_function_type_list (void_type_node,
119                                           gcov_type_ptr, gcov_type_node,
120                                           integer_type_node,
121                                           unsigned_type_node, NULL_TREE);
122       tree_interval_profiler_fn
123               = build_fn_decl ("__gcov_interval_profiler",
124                                      interval_profiler_fn_type);
125
126       /* void (*) (gcov_type *, gcov_type)  */
127       pow2_profiler_fn_type
128               = build_function_type_list (void_type_node,
129                                           gcov_type_ptr, gcov_type_node,
130                                           NULL_TREE);
131       tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
132                                                    pow2_profiler_fn_type);
133
134       /* void (*) (gcov_type *, gcov_type)  */
135       one_value_profiler_fn_type
136               = build_function_type_list (void_type_node,
137                                           gcov_type_ptr, gcov_type_node,
138                                           NULL_TREE);
139       tree_one_value_profiler_fn
140               = build_fn_decl ("__gcov_one_value_profiler",
141                                      one_value_profiler_fn_type);
142
143       tree_init_ic_make_global_vars ();
144       
145       /* void (*) (gcov_type *, gcov_type, void *, void *)  */
146       ic_profiler_fn_type
147                = build_function_type_list (void_type_node,
148                                           gcov_type_ptr, gcov_type_node,
149                                           ptr_void,
150                                           ptr_void, NULL_TREE);
151       tree_indirect_call_profiler_fn
152               = build_fn_decl ("__gcov_indirect_call_profiler",
153                                      ic_profiler_fn_type);
154       /* void (*) (gcov_type *, gcov_type)  */
155       average_profiler_fn_type
156               = build_function_type_list (void_type_node,
157                                           gcov_type_ptr, gcov_type_node, NULL_TREE);
158       tree_average_profiler_fn
159               = build_fn_decl ("__gcov_average_profiler",
160                                      average_profiler_fn_type);
161       tree_ior_profiler_fn
162               = build_fn_decl ("__gcov_ior_profiler",
163                                      average_profiler_fn_type);
164     }
165 }
166
167 /* New call was added, make goto call edges if neccesary.  */
168
169 static void
170 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
171 {
172   gimple stmt = gsi_stmt (gsi);
173
174   if (!stmt_can_make_abnormal_goto (stmt))
175     return;
176   if (!gsi_end_p (gsi))
177     split_block (gimple_bb (stmt), stmt);
178   make_abnormal_goto_edges (gimple_bb (stmt), true);
179 }
180
181 /* Output instructions as GIMPLE trees to increment the edge 
182    execution count, and insert them on E.  We rely on 
183    gsi_insert_on_edge to preserve the order.  */
184
185 static void
186 tree_gen_edge_profiler (int edgeno, edge e)
187 {
188   tree ref, one;
189   gimple stmt1, stmt2, stmt3;
190
191   /* We share one temporary variable declaration per function.  This
192      gets re-set in tree_profiling.  */
193   if (gcov_type_tmp_var == NULL_TREE)
194     gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
195   ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
196   one = build_int_cst (gcov_type_node, 1);
197   stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
198   stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
199                                         gcov_type_tmp_var, one);
200   stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
201   gsi_insert_on_edge (e, stmt1);
202   gsi_insert_on_edge (e, stmt2);
203   gsi_insert_on_edge (e, stmt3);
204 }
205
206 /* Emits code to get VALUE to instrument at GSI, and returns the
207    variable containing the value.  */
208
209 static tree
210 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
211 {
212   tree val = value->hvalue.value;
213   return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
214                                    true, NULL_TREE, true, GSI_SAME_STMT);
215 }
216
217 /* Output instructions as GIMPLE trees to increment the interval histogram 
218    counter.  VALUE is the expression whose value is profiled.  TAG is the 
219    tag of the section for counters, BASE is offset of the counter position.  */
220
221 static void
222 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
223 {
224   gimple stmt = value->hvalue.stmt;
225   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
226   tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
227   gimple call;
228   tree val;
229   tree start = build_int_cst_type (integer_type_node,
230                                    value->hdata.intvl.int_start);
231   tree steps = build_int_cst_type (unsigned_type_node,
232                                    value->hdata.intvl.steps);
233   
234   ref_ptr = force_gimple_operand_gsi (&gsi,
235                                       build_addr (ref, current_function_decl),
236                                       true, NULL_TREE, true, GSI_SAME_STMT);
237   val = prepare_instrumented_value (&gsi, value);
238   call = gimple_build_call (tree_interval_profiler_fn, 4,
239                             ref_ptr, val, start, steps);
240   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
241   add_abnormal_goto_call_edges (gsi);
242 }
243
244 /* Output instructions as GIMPLE trees to increment the power of two histogram 
245    counter.  VALUE is the expression whose value is profiled.  TAG is the tag 
246    of the section for counters, BASE is offset of the counter position.  */
247
248 static void
249 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
250 {
251   gimple stmt = value->hvalue.stmt;
252   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
253   tree ref_ptr = tree_coverage_counter_addr (tag, base);
254   gimple call;
255   tree val;
256   
257   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
258                                       true, NULL_TREE, true, GSI_SAME_STMT);
259   val = prepare_instrumented_value (&gsi, value);
260   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
261   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
262   add_abnormal_goto_call_edges (gsi);
263 }
264
265 /* Output instructions as GIMPLE trees for code to find the most common value.
266    VALUE is the expression whose value is profiled.  TAG is the tag of the
267    section for counters, BASE is offset of the counter position.  */
268
269 static void
270 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
271 {
272   gimple stmt = value->hvalue.stmt;
273   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
274   tree ref_ptr = tree_coverage_counter_addr (tag, base);
275   gimple call;
276   tree val;
277   
278   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
279                                       true, NULL_TREE, true, GSI_SAME_STMT);
280   val = prepare_instrumented_value (&gsi, value);
281   call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
282   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
283   add_abnormal_goto_call_edges (gsi);
284 }
285
286
287 /* Output instructions as GIMPLE trees for code to find the most
288    common called function in indirect call.  
289    VALUE is the call expression whose indirect callee is profiled.
290    TAG is the tag of the section for counters, BASE is offset of the
291    counter position.  */
292
293 static void
294 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
295 {
296   tree tmp1;
297   gimple stmt1, stmt2, stmt3;
298   gimple stmt = value->hvalue.stmt;
299   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
300   tree ref_ptr = tree_coverage_counter_addr (tag, base);
301
302   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
303                                       true, NULL_TREE, true, GSI_SAME_STMT);
304
305   /* Insert code:
306     
307     __gcov_indirect_call_counters = get_relevant_counter_ptr (); 
308     __gcov_indirect_call_callee = (void *) indirect call argument;
309    */
310
311   tmp1 = create_tmp_var (ptr_void, "PROF");
312   stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
313   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
314   stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
315
316   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
317   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
318   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
319 }
320
321
322 /* Output instructions as GIMPLE trees for code to find the most
323    common called function in indirect call. Insert instructions at the
324    beginning of every possible called function.
325   */
326
327 static void
328 tree_gen_ic_func_profiler (void)
329 {
330   struct cgraph_node * c_node = cgraph_node (current_function_decl);
331   gimple_stmt_iterator gsi;
332   edge e;
333   basic_block bb;
334   edge_iterator ei;
335   gimple stmt1, stmt2;
336   tree tree_uid, cur_func;
337
338   if (!c_node->needed)
339     return;
340   
341   tree_init_edge_profiler ();
342   
343   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
344     {
345       tree void0;
346
347       bb = split_edge (e);
348       gsi = gsi_start_bb (bb);
349
350       cur_func = force_gimple_operand_gsi (&gsi,
351                                            build_addr (current_function_decl, 
352                                                        current_function_decl),
353                                            true, NULL_TREE,
354                                            true, GSI_SAME_STMT);
355       tree_uid = build_int_cst (gcov_type_node, c_node->pid);
356       stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
357                                  ic_gcov_type_ptr_var,
358                                  tree_uid,
359                                  cur_func,
360                                  ic_void_ptr_var);
361       gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
362       gcc_assert (EDGE_COUNT (bb->succs) == 1);
363       bb = split_edge (EDGE_I (bb->succs, 0));
364       add_abnormal_goto_call_edges (gsi);
365
366       gsi = gsi_start_bb (bb);
367       /* Set __gcov_indirect_call_callee to 0,
368          so that calls from other modules won't get misattributed
369          to the last caller of the current callee. */
370       void0 = build_int_cst (build_pointer_type (void_type_node), 0);
371       stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
372       gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
373     }
374 }
375
376 /* Output instructions as GIMPLE trees for code to find the most common value 
377    of a difference between two evaluations of an expression.
378    VALUE is the expression whose value is profiled.  TAG is the tag of the
379    section for counters, BASE is offset of the counter position.  */
380
381 static void
382 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
383                                unsigned tag ATTRIBUTE_UNUSED,
384                                unsigned base ATTRIBUTE_UNUSED)
385 {
386   /* FIXME implement this.  */
387 #ifdef ENABLE_CHECKING
388   internal_error ("unimplemented functionality");
389 #endif
390   gcc_unreachable ();
391 }
392
393 /* Output instructions as GIMPLE trees to increment the average histogram 
394    counter.  VALUE is the expression whose value is profiled.  TAG is the 
395    tag of the section for counters, BASE is offset of the counter position.  */
396
397 static void
398 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
399 {
400   gimple stmt = value->hvalue.stmt;
401   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
402   tree ref_ptr = tree_coverage_counter_addr (tag, base);
403   gimple call;
404   tree val;
405   
406   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
407                                       true, NULL_TREE,
408                                       true, GSI_SAME_STMT);
409   val = prepare_instrumented_value (&gsi, value);
410   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
411   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
412   add_abnormal_goto_call_edges (gsi);
413 }
414
415 /* Output instructions as GIMPLE trees to increment the ior histogram 
416    counter.  VALUE is the expression whose value is profiled.  TAG is the 
417    tag of the section for counters, BASE is offset of the counter position.  */
418
419 static void
420 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
421 {
422   gimple stmt = value->hvalue.stmt;
423   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
424   tree ref_ptr = tree_coverage_counter_addr (tag, base);
425   gimple call;
426   tree val;
427   
428   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
429                                       true, NULL_TREE, true, GSI_SAME_STMT);
430   val = prepare_instrumented_value (&gsi, value);
431   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
432   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
433   add_abnormal_goto_call_edges (gsi);
434 }
435
436 /* Return 1 if tree-based profiling is in effect, else 0.
437    If it is, set up hooks for tree-based profiling.
438    Gate for pass_tree_profile.  */
439
440 static bool
441 do_tree_profiling (void)
442 {
443   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
444     {
445       tree_register_profile_hooks ();
446       gimple_register_value_prof_hooks ();
447       return true;
448     }
449   return false;
450 }
451
452 static unsigned int
453 tree_profiling (void)
454 {
455   /* Don't profile functions produced at destruction time, particularly
456      the gcov datastructure initializer.  Don't profile if it has been
457      already instrumented either (when OpenMP expansion creates
458      child function from already instrumented body).  */
459   if (cgraph_state == CGRAPH_STATE_FINISHED
460       || cfun->after_tree_profile)
461     return 0;
462
463   /* Re-set global shared temporary variable for edge-counters.  */
464   gcov_type_tmp_var = NULL_TREE;
465
466   branch_prob ();
467
468   if (! flag_branch_probabilities 
469       && flag_profile_values)
470     tree_gen_ic_func_profiler ();
471
472   if (flag_branch_probabilities
473       && flag_profile_values
474       && flag_value_profile_transformations)
475     value_profile_transformations ();
476   /* The above could hose dominator info.  Currently there is
477      none coming in, this is a safety valve.  It should be
478      easy to adjust it, if and when there is some.  */
479   free_dominance_info (CDI_DOMINATORS);
480   free_dominance_info (CDI_POST_DOMINATORS);
481   cfun->after_tree_profile = 1;
482   return 0;
483 }
484
485 struct gimple_opt_pass pass_tree_profile = 
486 {
487  {
488   GIMPLE_PASS,
489   "tree_profile",                       /* name */
490   do_tree_profiling,                    /* gate */
491   tree_profiling,                       /* execute */
492   NULL,                                 /* sub */
493   NULL,                                 /* next */
494   0,                                    /* static_pass_number */
495   TV_BRANCH_PROB,                       /* tv_id */
496   PROP_gimple_leh | PROP_cfg,           /* properties_required */
497   PROP_gimple_leh | PROP_cfg,           /* properties_provided */
498   0,                                    /* properties_destroyed */
499   0,                                    /* todo_flags_start */
500   TODO_verify_stmts | TODO_dump_func    /* todo_flags_finish */
501  }
502 };
503
504 struct profile_hooks tree_profile_hooks =
505 {
506   tree_init_edge_profiler,       /* init_edge_profiler */
507   tree_gen_edge_profiler,        /* gen_edge_profiler */
508   tree_gen_interval_profiler,    /* gen_interval_profiler */
509   tree_gen_pow2_profiler,        /* gen_pow2_profiler */
510   tree_gen_one_value_profiler,   /* gen_one_value_profiler */
511   tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
512   tree_gen_ic_profiler,          /* gen_ic_profiler */
513   tree_gen_average_profiler,     /* gen_average_profiler */
514   tree_gen_ior_profiler          /* gen_ior_profiler */
515 };
516
517 #include "gt-tree-profile.h"