OSDN Git Service

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