OSDN Git Service

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