]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-profile.c
[PATCH 7/9] ENABLE_CHECKING refactoring: middle-end, LTO FE
[thirdparty/gcc.git] / gcc / tree-profile.c
CommitLineData
4ee9c684 1/* Calculate branch probabilities, and basic block execution counts.
d353bf18 2 Copyright (C) 1990-2015 Free Software Foundation, Inc.
4ee9c684 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
4 based on some ideas from Dain Samples of UC Berkeley.
5 Further mangling by Bob Manson, Cygnus Support.
6 Converted to use trees by Dale Johannesen, Apple Computer.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
8c4c00c1 12Software Foundation; either version 3, or (at your option) any later
4ee9c684 13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
8c4c00c1 21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
4ee9c684 23
24/* Generate basic block profile instrumentation and auxiliary files.
d2971487 25 Tree-based version. See profile.c for overview. */
4ee9c684 26
27#include "config.h"
28#include "system.h"
29#include "coretypes.h"
9ef16211 30#include "backend.h"
d040a5b0 31#include "cfghooks.h"
9ef16211 32#include "tree.h"
33#include "gimple.h"
a3020f2f 34#include "hard-reg-set.h"
9ef16211 35#include "ssa.h"
36#include "flags.h"
0b205f4c 37#include "diagnostic-core.h"
4ee9c684 38#include "coverage.h"
b20a8bb4 39#include "alias.h"
b20a8bb4 40#include "fold-const.h"
bc61cadb 41#include "internal-fn.h"
9ed99284 42#include "varasm.h"
43#include "tree-nested.h"
a8783bee 44#include "gimplify.h"
dcf1a1ec 45#include "gimple-iterator.h"
e795d6e1 46#include "gimplify-me.h"
073c1fd5 47#include "cgraph.h"
48#include "tree-cfg.h"
073c1fd5 49#include "tree-into-ssa.h"
4ee9c684 50#include "tree-pass.h"
4ee9c684 51#include "value-prof.h"
1ad3e14c 52#include "profile.h"
109cfbe4 53#include "target.h"
424a4a92 54#include "tree-cfgcleanup.h"
e797f49f 55#include "tree-nested.h"
b74245ec 56#include "params.h"
4ee9c684 57
d7683f13 58static GTY(()) tree gcov_type_node;
59static GTY(()) tree tree_interval_profiler_fn;
60static GTY(()) tree tree_pow2_profiler_fn;
61static GTY(()) tree tree_one_value_profiler_fn;
167b550b 62static GTY(()) tree tree_indirect_call_profiler_fn;
38fe12e3 63static GTY(()) tree tree_time_profiler_fn;
162719b3 64static GTY(()) tree tree_average_profiler_fn;
65static GTY(()) tree tree_ior_profiler_fn;
38fe12e3 66
4b0a9554 67
167b550b 68static GTY(()) tree ic_void_ptr_var;
69static GTY(()) tree ic_gcov_type_ptr_var;
70static GTY(()) tree ptr_void;
71
4b0a9554 72/* Do initialization work for the edge profiler. */
73
167b550b 74/* Add code:
fe37be54 75 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
38fe12e3 76 __thread void* __gcov_indirect_call_callee; // actual callee address
77 __thread int __gcov_function_counter; // time profiler function counter
167b550b 78*/
79static void
fc49fbc1 80init_ic_make_global_vars (void)
167b550b 81{
82 tree gcov_type_ptr;
83
84 ptr_void = build_pointer_type (void_type_node);
48e1416a 85
ca13b0e8 86 ic_void_ptr_var
87 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
88 get_identifier (
89 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
90 "__gcov_indirect_call_topn_callee" :
91 "__gcov_indirect_call_callee")),
92 ptr_void);
93 TREE_PUBLIC (ic_void_ptr_var) = 1;
94 DECL_EXTERNAL (ic_void_ptr_var) = 1;
167b550b 95 TREE_STATIC (ic_void_ptr_var) = 1;
167b550b 96 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
97 DECL_INITIAL (ic_void_ptr_var) = NULL;
109cfbe4 98 if (targetm.have_tls)
5e68df57 99 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
109cfbe4 100
97221fd7 101 varpool_node::finalize_decl (ic_void_ptr_var);
167b550b 102
103 gcov_type_ptr = build_pointer_type (get_gcov_type ());
ca13b0e8 104
105 ic_gcov_type_ptr_var
106 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
107 get_identifier (
108 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
109 "__gcov_indirect_call_topn_counters" :
110 "__gcov_indirect_call_counters")),
111 gcov_type_ptr);
112 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
113 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
167b550b 114 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
167b550b 115 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
116 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
109cfbe4 117 if (targetm.have_tls)
5e68df57 118 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
109cfbe4 119
97221fd7 120 varpool_node::finalize_decl (ic_gcov_type_ptr_var);
167b550b 121}
122
3e7f455b 123/* Create the type and function decls for the interface with gcov. */
124
fc49fbc1 125void
126gimple_init_edge_profiler (void)
4b0a9554 127{
d7683f13 128 tree interval_profiler_fn_type;
129 tree pow2_profiler_fn_type;
130 tree one_value_profiler_fn_type;
131 tree gcov_type_ptr;
167b550b 132 tree ic_profiler_fn_type;
162719b3 133 tree average_profiler_fn_type;
38fe12e3 134 tree time_profiler_fn_type;
d7683f13 135
136 if (!gcov_type_node)
137 {
138 gcov_type_node = get_gcov_type ();
139 gcov_type_ptr = build_pointer_type (gcov_type_node);
140
141 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
142 interval_profiler_fn_type
143 = build_function_type_list (void_type_node,
144 gcov_type_ptr, gcov_type_node,
145 integer_type_node,
146 unsigned_type_node, NULL_TREE);
147 tree_interval_profiler_fn
148 = build_fn_decl ("__gcov_interval_profiler",
149 interval_profiler_fn_type);
85344eeb 150 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
151 DECL_ATTRIBUTES (tree_interval_profiler_fn)
152 = tree_cons (get_identifier ("leaf"), NULL,
153 DECL_ATTRIBUTES (tree_interval_profiler_fn));
d7683f13 154
155 /* void (*) (gcov_type *, gcov_type) */
156 pow2_profiler_fn_type
157 = build_function_type_list (void_type_node,
158 gcov_type_ptr, gcov_type_node,
159 NULL_TREE);
160 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
161 pow2_profiler_fn_type);
85344eeb 162 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
163 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
164 = tree_cons (get_identifier ("leaf"), NULL,
165 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
d7683f13 166
167 /* void (*) (gcov_type *, gcov_type) */
168 one_value_profiler_fn_type
169 = build_function_type_list (void_type_node,
170 gcov_type_ptr, gcov_type_node,
171 NULL_TREE);
172 tree_one_value_profiler_fn
173 = build_fn_decl ("__gcov_one_value_profiler",
174 one_value_profiler_fn_type);
85344eeb 175 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
176 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
177 = tree_cons (get_identifier ("leaf"), NULL,
178 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
167b550b 179
fc49fbc1 180 init_ic_make_global_vars ();
48e1416a 181
ca13b0e8 182 /* void (*) (gcov_type, void *) */
183 ic_profiler_fn_type
184 = build_function_type_list (void_type_node,
185 gcov_type_node,
186 ptr_void,
187 NULL_TREE);
188 tree_indirect_call_profiler_fn
189 = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
190 "__gcov_indirect_call_topn_profiler":
191 "__gcov_indirect_call_profiler_v2"),
192 ic_profiler_fn_type);
193
85344eeb 194 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
195 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
196 = tree_cons (get_identifier ("leaf"), NULL,
197 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
198
38fe12e3 199 /* void (*) (gcov_type *, gcov_type, void *) */
200 time_profiler_fn_type
201 = build_function_type_list (void_type_node,
202 gcov_type_ptr, NULL_TREE);
203 tree_time_profiler_fn
204 = build_fn_decl ("__gcov_time_profiler",
205 time_profiler_fn_type);
206 TREE_NOTHROW (tree_time_profiler_fn) = 1;
207 DECL_ATTRIBUTES (tree_time_profiler_fn)
208 = tree_cons (get_identifier ("leaf"), NULL,
209 DECL_ATTRIBUTES (tree_time_profiler_fn));
210
162719b3 211 /* void (*) (gcov_type *, gcov_type) */
212 average_profiler_fn_type
213 = build_function_type_list (void_type_node,
214 gcov_type_ptr, gcov_type_node, NULL_TREE);
215 tree_average_profiler_fn
216 = build_fn_decl ("__gcov_average_profiler",
217 average_profiler_fn_type);
85344eeb 218 TREE_NOTHROW (tree_average_profiler_fn) = 1;
219 DECL_ATTRIBUTES (tree_average_profiler_fn)
220 = tree_cons (get_identifier ("leaf"), NULL,
221 DECL_ATTRIBUTES (tree_average_profiler_fn));
162719b3 222 tree_ior_profiler_fn
223 = build_fn_decl ("__gcov_ior_profiler",
224 average_profiler_fn_type);
85344eeb 225 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
226 DECL_ATTRIBUTES (tree_ior_profiler_fn)
227 = tree_cons (get_identifier ("leaf"), NULL,
228 DECL_ATTRIBUTES (tree_ior_profiler_fn));
229
6c0782b1 230 /* LTO streamer needs assembler names. Because we create these decls
231 late, we need to initialize them by hand. */
232 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
233 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
234 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
235 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
38fe12e3 236 DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
6c0782b1 237 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
238 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
d7683f13 239 }
4b0a9554 240}
241
48e1416a 242/* Output instructions as GIMPLE trees to increment the edge
243 execution count, and insert them on E. We rely on
75a70cf9 244 gsi_insert_on_edge to preserve the order. */
4ee9c684 245
fc49fbc1 246void
247gimple_gen_edge_profiler (int edgeno, edge e)
4ee9c684 248{
03d37e4e 249 tree ref, one, gcov_type_tmp_var;
1a91d914 250 gassign *stmt1, *stmt2, *stmt3;
f81207a7 251
f81207a7 252 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
253 one = build_int_cst (gcov_type_node, 1);
03d37e4e 254 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
255 NULL, "PROF_edge_counter");
75a70cf9 256 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
03d37e4e 257 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
258 NULL, "PROF_edge_counter");
e9cf809e 259 stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
260 gimple_assign_lhs (stmt1), one);
85344eeb 261 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
75a70cf9 262 gsi_insert_on_edge (e, stmt1);
263 gsi_insert_on_edge (e, stmt2);
264 gsi_insert_on_edge (e, stmt3);
4ee9c684 265}
266
75a70cf9 267/* Emits code to get VALUE to instrument at GSI, and returns the
d7683f13 268 variable containing the value. */
269
270static tree
75a70cf9 271prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
d7683f13 272{
ed4294da 273 tree val = value->hvalue.value;
c821ef7d 274 if (POINTER_TYPE_P (TREE_TYPE (val)))
a0553bff 275 val = fold_convert (build_nonstandard_integer_type
276 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
75a70cf9 277 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
278 true, NULL_TREE, true, GSI_SAME_STMT);
d7683f13 279}
280
48e1416a 281/* Output instructions as GIMPLE trees to increment the interval histogram
282 counter. VALUE is the expression whose value is profiled. TAG is the
4ee9c684 283 tag of the section for counters, BASE is offset of the counter position. */
284
fc49fbc1 285void
286gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
4ee9c684 287{
42acab1c 288 gimple *stmt = value->hvalue.stmt;
75a70cf9 289 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
d7683f13 290 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
1a91d914 291 gcall *call;
75a70cf9 292 tree val;
293 tree start = build_int_cst_type (integer_type_node,
294 value->hdata.intvl.int_start);
295 tree steps = build_int_cst_type (unsigned_type_node,
296 value->hdata.intvl.steps);
48e1416a 297
75a70cf9 298 ref_ptr = force_gimple_operand_gsi (&gsi,
0e49e441 299 build_addr (ref),
75a70cf9 300 true, NULL_TREE, true, GSI_SAME_STMT);
301 val = prepare_instrumented_value (&gsi, value);
302 call = gimple_build_call (tree_interval_profiler_fn, 4,
303 ref_ptr, val, start, steps);
77fca8b5 304 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
4ee9c684 305}
306
48e1416a 307/* Output instructions as GIMPLE trees to increment the power of two histogram
308 counter. VALUE is the expression whose value is profiled. TAG is the tag
4ee9c684 309 of the section for counters, BASE is offset of the counter position. */
310
fc49fbc1 311void
312gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
4ee9c684 313{
42acab1c 314 gimple *stmt = value->hvalue.stmt;
75a70cf9 315 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
a961cdc2 316 tree ref_ptr = tree_coverage_counter_addr (tag, base);
1a91d914 317 gcall *call;
75a70cf9 318 tree val;
48e1416a 319
75a70cf9 320 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
321 true, NULL_TREE, true, GSI_SAME_STMT);
322 val = prepare_instrumented_value (&gsi, value);
323 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
77fca8b5 324 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
4ee9c684 325}
326
327/* Output instructions as GIMPLE trees for code to find the most common value.
328 VALUE is the expression whose value is profiled. TAG is the tag of the
329 section for counters, BASE is offset of the counter position. */
330
fc49fbc1 331void
332gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
4ee9c684 333{
42acab1c 334 gimple *stmt = value->hvalue.stmt;
75a70cf9 335 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
a961cdc2 336 tree ref_ptr = tree_coverage_counter_addr (tag, base);
1a91d914 337 gcall *call;
75a70cf9 338 tree val;
48e1416a 339
75a70cf9 340 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
341 true, NULL_TREE, true, GSI_SAME_STMT);
342 val = prepare_instrumented_value (&gsi, value);
343 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
77fca8b5 344 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
4ee9c684 345}
346
167b550b 347
348/* Output instructions as GIMPLE trees for code to find the most
48e1416a 349 common called function in indirect call.
0d424440 350 VALUE is the call expression whose indirect callee is profiled.
167b550b 351 TAG is the tag of the section for counters, BASE is offset of the
352 counter position. */
353
fc49fbc1 354void
355gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
167b550b 356{
75a70cf9 357 tree tmp1;
1a91d914 358 gassign *stmt1, *stmt2, *stmt3;
42acab1c 359 gimple *stmt = value->hvalue.stmt;
75a70cf9 360 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
a961cdc2 361 tree ref_ptr = tree_coverage_counter_addr (tag, base);
167b550b 362
b74245ec 363 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
364 tag == GCOV_COUNTER_V_INDIR) ||
365 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
366 tag == GCOV_COUNTER_ICALL_TOPNV))
367 return;
368
75a70cf9 369 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
370 true, NULL_TREE, true, GSI_SAME_STMT);
167b550b 371
372 /* Insert code:
48e1416a 373
3e7f455b 374 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
375 stmt2: tmp1 = (void *) (indirect call argument value)
376 stmt3: __gcov_indirect_call_callee = tmp1;
167b550b 377 */
378
75a70cf9 379 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
03d37e4e 380 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
75a70cf9 381 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
85344eeb 382 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
167b550b 383
75a70cf9 384 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
385 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
386 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
167b550b 387}
388
389
390/* Output instructions as GIMPLE trees for code to find the most
391 common called function in indirect call. Insert instructions at the
0d424440 392 beginning of every possible called function.
167b550b 393 */
394
fc49fbc1 395void
396gimple_gen_ic_func_profiler (void)
167b550b 397{
415d1b9a 398 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
75a70cf9 399 gimple_stmt_iterator gsi;
1a91d914 400 gcall *stmt1;
401 gassign *stmt2;
fe37be54 402 tree tree_uid, cur_func, void0;
167b550b 403
415d1b9a 404 if (c_node->only_called_directly_p ())
6329636b 405 return;
48e1416a 406
fc49fbc1 407 gimple_init_edge_profiler ();
48e1416a 408
3e7f455b 409 /* Insert code:
410
fe37be54 411 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
412 &current_function_decl)
3e7f455b 413 */
ca13b0e8 414 gsi = gsi_after_labels (split_edge (single_succ_edge
415 (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
85344eeb 416
417 cur_func = force_gimple_operand_gsi (&gsi,
0e49e441 418 build_addr (current_function_decl),
85344eeb 419 true, NULL_TREE,
420 true, GSI_SAME_STMT);
fe37be54 421 tree_uid = build_int_cst
ca13b0e8 422 (gcov_type_node,
423 cgraph_node::get (current_function_decl)->profile_id);
424 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
425 tree_uid, cur_func);
85344eeb 426 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
427
428 /* Set __gcov_indirect_call_callee to 0,
429 so that calls from other modules won't get misattributed
430 to the last caller of the current callee. */
431 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
432 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
433 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
167b550b 434}
435
38fe12e3 436/* Output instructions as GIMPLE tree at the beginning for each function.
437 TAG is the tag of the section for counters, BASE is offset of the
438 counter position and GSI is the iterator we place the counter. */
439
440void
441gimple_gen_time_profiler (unsigned tag, unsigned base,
442 gimple_stmt_iterator &gsi)
443{
444 tree ref_ptr = tree_coverage_counter_addr (tag, base);
1a91d914 445 gcall *call;
38fe12e3 446
447 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
448 true, NULL_TREE, true, GSI_SAME_STMT);
449 call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
450 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
451}
452
48e1416a 453/* Output instructions as GIMPLE trees for code to find the most common value
4ee9c684 454 of a difference between two evaluations of an expression.
455 VALUE is the expression whose value is profiled. TAG is the tag of the
456 section for counters, BASE is offset of the counter position. */
457
fc49fbc1 458void
459gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
75a70cf9 460 unsigned tag ATTRIBUTE_UNUSED,
461 unsigned base ATTRIBUTE_UNUSED)
4ee9c684 462{
463 /* FIXME implement this. */
382ecba7 464 if (flag_checking)
465 internal_error ("unimplemented functionality");
8c0963c4 466 gcc_unreachable ();
4ee9c684 467}
468
48e1416a 469/* Output instructions as GIMPLE trees to increment the average histogram
470 counter. VALUE is the expression whose value is profiled. TAG is the
162719b3 471 tag of the section for counters, BASE is offset of the counter position. */
472
fc49fbc1 473void
474gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
162719b3 475{
42acab1c 476 gimple *stmt = value->hvalue.stmt;
75a70cf9 477 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
a961cdc2 478 tree ref_ptr = tree_coverage_counter_addr (tag, base);
1a91d914 479 gcall *call;
75a70cf9 480 tree val;
48e1416a 481
75a70cf9 482 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
0d734975 483 true, NULL_TREE,
75a70cf9 484 true, GSI_SAME_STMT);
485 val = prepare_instrumented_value (&gsi, value);
486 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
77fca8b5 487 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
162719b3 488}
489
48e1416a 490/* Output instructions as GIMPLE trees to increment the ior histogram
491 counter. VALUE is the expression whose value is profiled. TAG is the
162719b3 492 tag of the section for counters, BASE is offset of the counter position. */
493
fc49fbc1 494void
495gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
162719b3 496{
42acab1c 497 gimple *stmt = value->hvalue.stmt;
75a70cf9 498 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
a961cdc2 499 tree ref_ptr = tree_coverage_counter_addr (tag, base);
1a91d914 500 gcall *call;
75a70cf9 501 tree val;
48e1416a 502
75a70cf9 503 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
504 true, NULL_TREE, true, GSI_SAME_STMT);
505 val = prepare_instrumented_value (&gsi, value);
506 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
77fca8b5 507 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
162719b3 508}
509
85344eeb 510/* Profile all functions in the callgraph. */
4ee9c684 511
2a1990e9 512static unsigned int
d2971487 513tree_profiling (void)
514{
85344eeb 515 struct cgraph_node *node;
516
3e7f455b 517 /* This is a small-ipa pass that gets called only once, from
518 cgraphunit.c:ipa_passes(). */
35ee1c66 519 gcc_assert (symtab->state == IPA_SSA);
f81207a7 520
fe37be54 521 init_node_map (true);
1ad3e14c 522
7c455d87 523 FOR_EACH_DEFINED_FUNCTION (node)
85344eeb 524 {
02774f2d 525 if (!gimple_has_body_p (node->decl))
85344eeb 526 continue;
527
528 /* Don't profile functions produced for builtin stuff. */
02774f2d 529 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
85344eeb 530 continue;
531
1a382068 532 /* Do not instrument extern inline functions when testing coverage.
533 While this is not perfectly consistent (early inlined extern inlines
534 will get acocunted), testsuite expects that. */
535 if (DECL_EXTERNAL (node->decl)
536 && flag_test_coverage)
537 continue;
538
02774f2d 539 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
85344eeb 540
8c1fce46 541 /* Local pure-const may imply need to fixup the cfg. */
141de90e 542 if (execute_fixup_cfg () & TODO_cleanup_cfg)
543 cleanup_tree_cfg ();
3e7f455b 544
85344eeb 545 branch_prob ();
546
547 if (! flag_branch_probabilities
548 && flag_profile_values)
fc49fbc1 549 gimple_gen_ic_func_profiler ();
85344eeb 550
551 if (flag_branch_probabilities
552 && flag_profile_values
553 && flag_value_profile_transformations)
fc49fbc1 554 gimple_value_profile_transformations ();
85344eeb 555
556 /* The above could hose dominator info. Currently there is
557 none coming in, this is a safety valve. It should be
558 easy to adjust it, if and when there is some. */
559 free_dominance_info (CDI_DOMINATORS);
560 free_dominance_info (CDI_POST_DOMINATORS);
85344eeb 561 pop_cfun ();
562 }
563
564 /* Drop pure/const flags from instrumented functions. */
1059fe86 565 if (profile_arc_flag || flag_test_coverage)
566 FOR_EACH_DEFINED_FUNCTION (node)
567 {
568 if (!gimple_has_body_p (node->decl)
569 || !(!node->clone_of
570 || node->decl != node->clone_of->decl))
571 continue;
572
573 /* Don't profile functions produced for builtin stuff. */
574 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
575 continue;
576
577 node->set_const_flag (false, false);
578 node->set_pure_flag (false, false);
579 }
85344eeb 580
581 /* Update call statements and rebuild the cgraph. */
7c455d87 582 FOR_EACH_DEFINED_FUNCTION (node)
85344eeb 583 {
584 basic_block bb;
585
02774f2d 586 if (!gimple_has_body_p (node->decl)
7d0d0ce1 587 || !(!node->clone_of
02774f2d 588 || node->decl != node->clone_of->decl))
85344eeb 589 continue;
590
591 /* Don't profile functions produced for builtin stuff. */
02774f2d 592 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
85344eeb 593 continue;
594
02774f2d 595 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
85344eeb 596
fc00614f 597 FOR_EACH_BB_FN (bb, cfun)
85344eeb 598 {
599 gimple_stmt_iterator gsi;
600 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
601 {
42acab1c 602 gimple *stmt = gsi_stmt (gsi);
85344eeb 603 if (is_gimple_call (stmt))
604 update_stmt (stmt);
605 }
606 }
607
2701a3fd 608 /* re-merge split blocks. */
609 cleanup_tree_cfg ();
85344eeb 610 update_ssa (TODO_update_ssa);
611
35ee1c66 612 cgraph_edge::rebuild_edges ();
85344eeb 613
85344eeb 614 pop_cfun ();
615 }
fdc47e9a 616
38a65d4e 617 handle_missing_profiles ();
618
9af5ce0c 619 del_node_map ();
2a1990e9 620 return 0;
d2971487 621}
622
cbe8bda8 623namespace {
624
625const pass_data pass_data_ipa_tree_profile =
4ee9c684 626{
cbe8bda8 627 SIMPLE_IPA_PASS, /* type */
628 "profile", /* name */
629 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 630 TV_IPA_PROFILE, /* tv_id */
631 0, /* properties_required */
632 0, /* properties_provided */
633 0, /* properties_destroyed */
634 0, /* todo_flags_start */
1059fe86 635 TODO_dump_symtab, /* todo_flags_finish */
4ee9c684 636};
637
cbe8bda8 638class pass_ipa_tree_profile : public simple_ipa_opt_pass
639{
640public:
9af5ce0c 641 pass_ipa_tree_profile (gcc::context *ctxt)
642 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
cbe8bda8 643 {}
644
645 /* opt_pass methods: */
31315c24 646 virtual bool gate (function *);
65b0537f 647 virtual unsigned int execute (function *) { return tree_profiling (); }
cbe8bda8 648
649}; // class pass_ipa_tree_profile
650
31315c24 651bool
652pass_ipa_tree_profile::gate (function *)
653{
94bed7c3 654 /* When profile instrumentation, use or test coverage shall be performed.
655 But for AutoFDO, this there is no instrumentation, thus this pass is
656 diabled. */
657 return (!in_lto_p && !flag_auto_profile
31315c24 658 && (flag_branch_probabilities || flag_test_coverage
659 || profile_arc_flag));
660}
661
cbe8bda8 662} // anon namespace
663
664simple_ipa_opt_pass *
665make_pass_ipa_tree_profile (gcc::context *ctxt)
666{
667 return new pass_ipa_tree_profile (ctxt);
668}
669
d7683f13 670#include "gt-tree-profile.h"