IVOPT performance tuning patch. The main problem is a variant of maximal weight
[official-gcc.git] / gcc / tree-profile.c
blob50ce013830d2cae4bf57b642e80031df5f29cd91
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.
10 This file is part of GCC.
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.
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.
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/>. */
26 /* Generate basic block profile instrumentation and auxiliary files.
27 Tree-based version. See profile.c for overview. */
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"
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;
58 static GTY(()) tree ic_void_ptr_var;
59 static GTY(()) tree ic_gcov_type_ptr_var;
60 static GTY(()) tree ptr_void;
62 /* Do initialization work for the edge profiler. */
64 /* Add code:
65 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
66 static void* __gcov_indirect_call_callee; // actual callee address
68 static void
69 tree_init_ic_make_global_vars (void)
71 tree gcov_type_ptr;
73 ptr_void = build_pointer_type (void_type_node);
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));
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));
99 static void
100 tree_init_edge_profiler (void)
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;
109 if (!gcov_type_node)
111 gcov_type_node = get_gcov_type ();
112 gcov_type_ptr = build_pointer_type (gcov_type_node);
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);
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);
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);
141 tree_init_ic_make_global_vars ();
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);
173 /* New call was added, make goto call edges if neccesary. */
175 static void
176 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
178 gimple stmt = gsi_stmt (gsi);
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);
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. */
191 static void
192 tree_gen_edge_profiler (int edgeno, edge e)
194 tree ref, one;
195 gimple stmt1, stmt2, stmt3;
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);
212 /* Emits code to get VALUE to instrument at GSI, and returns the
213 variable containing the value. */
215 static tree
216 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
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);
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. */
229 static void
230 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
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);
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);
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. */
256 static void
257 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
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;
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);
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. */
277 static void
278 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
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;
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);
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. */
301 static void
302 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
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);
310 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
311 true, NULL_TREE, true, GSI_SAME_STMT);
313 /* Insert code:
315 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
316 __gcov_indirect_call_callee = (void *) indirect call argument;
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);
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);
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.
335 static void
336 tree_gen_ic_func_profiler (void)
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;
346 if (cgraph_only_called_directly_p (c_node))
347 return;
349 tree_init_edge_profiler ();
351 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
353 tree void0;
355 bb = split_edge (e);
356 gsi = gsi_start_bb (bb);
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);
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);
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. */
392 static void
393 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
394 unsigned tag ATTRIBUTE_UNUSED,
395 unsigned base ATTRIBUTE_UNUSED)
397 /* FIXME implement this. */
398 #ifdef ENABLE_CHECKING
399 internal_error ("unimplemented functionality");
400 #endif
401 gcc_unreachable ();
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. */
408 static void
409 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
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;
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);
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. */
430 static void
431 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
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;
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);
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. */
451 static bool
452 do_tree_profiling (void)
454 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
456 tree_register_profile_hooks ();
457 gimple_register_value_prof_hooks ();
458 return true;
460 return false;
463 static unsigned int
464 tree_profiling (void)
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;
474 /* Don't profile functions produced for builtin stuff. */
475 if (DECL_SOURCE_LOCATION (current_function_decl) == BUILTINS_LOCATION)
476 return 0;
478 /* Re-set global shared temporary variable for edge-counters. */
479 gcov_type_tmp_var = NULL_TREE;
481 branch_prob ();
483 if (! flag_branch_probabilities
484 && flag_profile_values)
485 tree_gen_ic_func_profiler ();
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;
500 struct gimple_opt_pass pass_tree_profile =
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 */
519 struct profile_hooks tree_profile_hooks =
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 */
532 #include "gt-tree-profile.h"