C++: suggestions for misspelled private members (PR c++/84993)
[official-gcc.git] / gcc / tree-profile.c
blobd8f2a3b1ba40b83d949a02afe57d51ce6645a48e
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990-2018 Free Software Foundation, Inc.
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.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 /* Generate basic block profile instrumentation and auxiliary files.
25 Tree-based version. See profile.c for overview. */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "memmodel.h"
31 #include "backend.h"
32 #include "target.h"
33 #include "tree.h"
34 #include "gimple.h"
35 #include "cfghooks.h"
36 #include "tree-pass.h"
37 #include "ssa.h"
38 #include "cgraph.h"
39 #include "coverage.h"
40 #include "diagnostic-core.h"
41 #include "fold-const.h"
42 #include "varasm.h"
43 #include "tree-nested.h"
44 #include "gimplify.h"
45 #include "gimple-iterator.h"
46 #include "gimplify-me.h"
47 #include "tree-cfg.h"
48 #include "tree-into-ssa.h"
49 #include "value-prof.h"
50 #include "profile.h"
51 #include "tree-cfgcleanup.h"
52 #include "params.h"
53 #include "stringpool.h"
54 #include "attribs.h"
55 #include "tree-pretty-print.h"
56 #include "langhooks.h"
57 #include "stor-layout.h"
59 static GTY(()) tree gcov_type_node;
60 static GTY(()) tree tree_interval_profiler_fn;
61 static GTY(()) tree tree_pow2_profiler_fn;
62 static GTY(()) tree tree_one_value_profiler_fn;
63 static GTY(()) tree tree_indirect_call_profiler_fn;
64 static GTY(()) tree tree_average_profiler_fn;
65 static GTY(()) tree tree_ior_profiler_fn;
66 static GTY(()) tree tree_time_profiler_counter;
69 static GTY(()) tree ic_tuple_var;
70 static GTY(()) tree ic_tuple_counters_field;
71 static GTY(()) tree ic_tuple_callee_field;
73 /* Do initialization work for the edge profiler. */
75 /* Add code:
76 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
77 __thread void* __gcov_indirect_call_callee; // actual callee address
78 __thread int __gcov_function_counter; // time profiler function counter
80 static void
81 init_ic_make_global_vars (void)
83 tree gcov_type_ptr;
85 gcov_type_ptr = build_pointer_type (get_gcov_type ());
87 tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
89 /* callee */
90 ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
91 ptr_type_node);
93 /* counters */
94 ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
95 NULL_TREE, gcov_type_ptr);
96 DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field;
98 finish_builtin_struct (tuple_type, "indirect_call_tuple",
99 ic_tuple_counters_field, NULL_TREE);
101 ic_tuple_var
102 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
103 get_identifier (
104 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
105 "__gcov_indirect_call_topn" :
106 "__gcov_indirect_call")),
107 tuple_type);
108 TREE_PUBLIC (ic_tuple_var) = 1;
109 DECL_ARTIFICIAL (ic_tuple_var) = 1;
110 DECL_INITIAL (ic_tuple_var) = NULL;
111 DECL_EXTERNAL (ic_tuple_var) = 1;
112 if (targetm.have_tls)
113 set_decl_tls_model (ic_tuple_var, decl_default_tls_model (tuple_type));
116 /* Create the type and function decls for the interface with gcov. */
118 void
119 gimple_init_gcov_profiler (void)
121 tree interval_profiler_fn_type;
122 tree pow2_profiler_fn_type;
123 tree one_value_profiler_fn_type;
124 tree gcov_type_ptr;
125 tree ic_profiler_fn_type;
126 tree average_profiler_fn_type;
127 const char *profiler_fn_name;
128 const char *fn_name;
130 if (!gcov_type_node)
132 const char *fn_suffix
133 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
135 gcov_type_node = get_gcov_type ();
136 gcov_type_ptr = build_pointer_type (gcov_type_node);
138 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
139 interval_profiler_fn_type
140 = build_function_type_list (void_type_node,
141 gcov_type_ptr, gcov_type_node,
142 integer_type_node,
143 unsigned_type_node, NULL_TREE);
144 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
145 tree_interval_profiler_fn = build_fn_decl (fn_name,
146 interval_profiler_fn_type);
147 free (CONST_CAST (char *, fn_name));
148 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
149 DECL_ATTRIBUTES (tree_interval_profiler_fn)
150 = tree_cons (get_identifier ("leaf"), NULL,
151 DECL_ATTRIBUTES (tree_interval_profiler_fn));
153 /* void (*) (gcov_type *, gcov_type) */
154 pow2_profiler_fn_type
155 = build_function_type_list (void_type_node,
156 gcov_type_ptr, gcov_type_node,
157 NULL_TREE);
158 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
159 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
160 free (CONST_CAST (char *, fn_name));
161 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
162 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
163 = tree_cons (get_identifier ("leaf"), NULL,
164 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
166 /* void (*) (gcov_type *, gcov_type) */
167 one_value_profiler_fn_type
168 = build_function_type_list (void_type_node,
169 gcov_type_ptr, gcov_type_node,
170 NULL_TREE);
171 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
172 tree_one_value_profiler_fn = build_fn_decl (fn_name,
173 one_value_profiler_fn_type);
174 free (CONST_CAST (char *, fn_name));
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));
180 init_ic_make_global_vars ();
182 /* void (*) (gcov_type, void *) */
183 ic_profiler_fn_type
184 = build_function_type_list (void_type_node,
185 gcov_type_node,
186 ptr_type_node,
187 NULL_TREE);
188 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
189 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
190 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
192 tree_indirect_call_profiler_fn
193 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
195 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
196 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
197 = tree_cons (get_identifier ("leaf"), NULL,
198 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
200 tree_time_profiler_counter
201 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
202 get_identifier ("__gcov_time_profiler_counter"),
203 get_gcov_type ());
204 TREE_PUBLIC (tree_time_profiler_counter) = 1;
205 DECL_EXTERNAL (tree_time_profiler_counter) = 1;
206 TREE_STATIC (tree_time_profiler_counter) = 1;
207 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
208 DECL_INITIAL (tree_time_profiler_counter) = NULL;
210 /* void (*) (gcov_type *, gcov_type) */
211 average_profiler_fn_type
212 = build_function_type_list (void_type_node,
213 gcov_type_ptr, gcov_type_node, NULL_TREE);
214 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
215 tree_average_profiler_fn = build_fn_decl (fn_name,
216 average_profiler_fn_type);
217 free (CONST_CAST (char *, fn_name));
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));
222 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
223 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
224 free (CONST_CAST (char *, fn_name));
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));
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);
236 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
237 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
241 /* Output instructions as GIMPLE trees to increment the edge
242 execution count, and insert them on E. We rely on
243 gsi_insert_on_edge to preserve the order. */
245 void
246 gimple_gen_edge_profiler (int edgeno, edge e)
248 tree one;
250 one = build_int_cst (gcov_type_node, 1);
252 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
254 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
255 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
256 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
257 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
258 BUILT_IN_ATOMIC_FETCH_ADD_4);
259 gcall *stmt = gimple_build_call (f, 3, addr, one,
260 build_int_cst (integer_type_node,
261 MEMMODEL_RELAXED));
262 gsi_insert_on_edge (e, stmt);
264 else
266 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
267 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
268 NULL, "PROF_edge_counter");
269 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
270 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
271 NULL, "PROF_edge_counter");
272 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
273 gimple_assign_lhs (stmt1), one);
274 gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
275 gimple_assign_lhs (stmt2));
276 gsi_insert_on_edge (e, stmt1);
277 gsi_insert_on_edge (e, stmt2);
278 gsi_insert_on_edge (e, stmt3);
282 /* Emits code to get VALUE to instrument at GSI, and returns the
283 variable containing the value. */
285 static tree
286 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
288 tree val = value->hvalue.value;
289 if (POINTER_TYPE_P (TREE_TYPE (val)))
290 val = fold_convert (build_nonstandard_integer_type
291 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
292 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
293 true, NULL_TREE, true, GSI_SAME_STMT);
296 /* Output instructions as GIMPLE trees to increment the interval histogram
297 counter. VALUE is the expression whose value is profiled. TAG is the
298 tag of the section for counters, BASE is offset of the counter position. */
300 void
301 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
303 gimple *stmt = value->hvalue.stmt;
304 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
305 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
306 gcall *call;
307 tree val;
308 tree start = build_int_cst_type (integer_type_node,
309 value->hdata.intvl.int_start);
310 tree steps = build_int_cst_type (unsigned_type_node,
311 value->hdata.intvl.steps);
313 ref_ptr = force_gimple_operand_gsi (&gsi,
314 build_addr (ref),
315 true, NULL_TREE, true, GSI_SAME_STMT);
316 val = prepare_instrumented_value (&gsi, value);
317 call = gimple_build_call (tree_interval_profiler_fn, 4,
318 ref_ptr, val, start, steps);
319 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
322 /* Output instructions as GIMPLE trees to increment the power of two histogram
323 counter. VALUE is the expression whose value is profiled. TAG is the tag
324 of the section for counters, BASE is offset of the counter position. */
326 void
327 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
329 gimple *stmt = value->hvalue.stmt;
330 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
331 tree ref_ptr = tree_coverage_counter_addr (tag, base);
332 gcall *call;
333 tree val;
335 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
336 true, NULL_TREE, true, GSI_SAME_STMT);
337 val = prepare_instrumented_value (&gsi, value);
338 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
339 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
342 /* Output instructions as GIMPLE trees for code to find the most common value.
343 VALUE is the expression whose value is profiled. TAG is the tag of the
344 section for counters, BASE is offset of the counter position. */
346 void
347 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
349 gimple *stmt = value->hvalue.stmt;
350 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
351 tree ref_ptr = tree_coverage_counter_addr (tag, base);
352 gcall *call;
353 tree val;
355 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
356 true, NULL_TREE, true, GSI_SAME_STMT);
357 val = prepare_instrumented_value (&gsi, value);
358 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
359 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
363 /* Output instructions as GIMPLE trees for code to find the most
364 common called function in indirect call.
365 VALUE is the call expression whose indirect callee is profiled.
366 TAG is the tag of the section for counters, BASE is offset of the
367 counter position. */
369 void
370 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
372 tree tmp1;
373 gassign *stmt1, *stmt2, *stmt3;
374 gimple *stmt = value->hvalue.stmt;
375 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
376 tree ref_ptr = tree_coverage_counter_addr (tag, base);
378 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
379 tag == GCOV_COUNTER_V_INDIR) ||
380 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
381 tag == GCOV_COUNTER_ICALL_TOPNV))
382 return;
384 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
385 true, NULL_TREE, true, GSI_SAME_STMT);
387 /* Insert code:
389 stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
390 stmt2: tmp1 = (void *) (indirect call argument value)
391 stmt3: __gcov_indirect_call.callee = tmp1;
393 Example:
394 f_1 = foo;
395 __gcov_indirect_call.counters = &__gcov4.main[0];
396 PROF_9 = f_1;
397 __gcov_indirect_call_callee = PROF_9;
398 _4 = f_1 ();
401 tree gcov_type_ptr = build_pointer_type (get_gcov_type ());
403 tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr,
404 ic_tuple_var, ic_tuple_counters_field, NULL_TREE);
406 stmt1 = gimple_build_assign (counter_ref, ref_ptr);
407 tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
408 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
409 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
410 ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
411 stmt3 = gimple_build_assign (callee_ref, tmp1);
413 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
414 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
415 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
419 /* Output instructions as GIMPLE trees for code to find the most
420 common called function in indirect call. Insert instructions at the
421 beginning of every possible called function.
424 void
425 gimple_gen_ic_func_profiler (void)
427 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
428 gcall *stmt1;
429 tree tree_uid, cur_func, void0;
431 if (c_node->only_called_directly_p ())
432 return;
434 gimple_init_gcov_profiler ();
436 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
437 basic_block cond_bb = split_edge (single_succ_edge (entry));
438 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
440 /* We need to do an extra split in order to not create an input
441 for a possible PHI node. */
442 split_edge (single_succ_edge (update_bb));
444 edge true_edge = single_succ_edge (cond_bb);
445 true_edge->flags = EDGE_TRUE_VALUE;
447 profile_probability probability;
448 if (DECL_VIRTUAL_P (current_function_decl))
449 probability = profile_probability::very_likely ();
450 else
451 probability = profile_probability::unlikely ();
453 true_edge->probability = probability;
454 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
455 EDGE_FALSE_VALUE);
456 e->probability = true_edge->probability.invert ();
458 /* Insert code:
460 if (__gcov_indirect_call_callee != NULL)
461 __gcov_indirect_call_profiler_v2 (profile_id, &current_function_decl);
463 The function __gcov_indirect_call_profiler_v2 is responsible for
464 resetting __gcov_indirect_call_callee to NULL. */
466 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
467 void0 = build_int_cst (ptr_type_node, 0);
469 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
470 ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
472 tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE,
473 true, GSI_SAME_STMT);
475 gcond *cond = gimple_build_cond (NE_EXPR, ref,
476 void0, NULL, NULL);
477 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
479 gsi = gsi_after_labels (update_bb);
481 cur_func = force_gimple_operand_gsi (&gsi,
482 build_addr (current_function_decl),
483 true, NULL_TREE,
484 true, GSI_SAME_STMT);
485 tree_uid = build_int_cst
486 (gcov_type_node,
487 cgraph_node::get (current_function_decl)->profile_id);
488 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
489 tree_uid, cur_func);
490 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
493 /* Output instructions as GIMPLE tree at the beginning for each function.
494 TAG is the tag of the section for counters, BASE is offset of the
495 counter position and GSI is the iterator we place the counter. */
497 void
498 gimple_gen_time_profiler (unsigned tag, unsigned base)
500 tree type = get_gcov_type ();
501 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
502 basic_block cond_bb = split_edge (single_succ_edge (entry));
503 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
505 /* We need to do an extra split in order to not create an input
506 for a possible PHI node. */
507 split_edge (single_succ_edge (update_bb));
509 edge true_edge = single_succ_edge (cond_bb);
510 true_edge->flags = EDGE_TRUE_VALUE;
511 true_edge->probability = profile_probability::unlikely ();
512 edge e
513 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
514 e->probability = true_edge->probability.invert ();
516 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
517 tree original_ref = tree_coverage_counter_ref (tag, base);
518 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
519 true, GSI_SAME_STMT);
520 tree one = build_int_cst (type, 1);
522 /* Emit: if (counters[0] != 0). */
523 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
524 NULL, NULL);
525 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
527 gsi = gsi_start_bb (update_bb);
529 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
530 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
532 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
533 "time_profiler_counter_ptr");
534 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
535 tree_time_profiler_counter);
536 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
537 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
538 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
539 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
540 BUILT_IN_ATOMIC_ADD_FETCH_4);
541 gcall *stmt = gimple_build_call (f, 3, ptr, one,
542 build_int_cst (integer_type_node,
543 MEMMODEL_RELAXED));
544 tree result_type = TREE_TYPE (TREE_TYPE (f));
545 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
546 gimple_set_lhs (stmt, tmp);
547 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
548 tmp = make_temp_ssa_name (type, NULL, "time_profile");
549 assign = gimple_build_assign (tmp, NOP_EXPR,
550 gimple_call_lhs (stmt));
551 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
552 assign = gimple_build_assign (original_ref, tmp);
553 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
555 else
557 tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
558 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
559 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
561 tmp = make_temp_ssa_name (type, NULL, "time_profile");
562 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
563 one);
564 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
565 assign = gimple_build_assign (original_ref, tmp);
566 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
567 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
568 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
572 /* Output instructions as GIMPLE trees to increment the average histogram
573 counter. VALUE is the expression whose value is profiled. TAG is the
574 tag of the section for counters, BASE is offset of the counter position. */
576 void
577 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
579 gimple *stmt = value->hvalue.stmt;
580 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
581 tree ref_ptr = tree_coverage_counter_addr (tag, base);
582 gcall *call;
583 tree val;
585 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
586 true, NULL_TREE,
587 true, GSI_SAME_STMT);
588 val = prepare_instrumented_value (&gsi, value);
589 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
590 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
593 /* Output instructions as GIMPLE trees to increment the ior histogram
594 counter. VALUE is the expression whose value is profiled. TAG is the
595 tag of the section for counters, BASE is offset of the counter position. */
597 void
598 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
600 gimple *stmt = value->hvalue.stmt;
601 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
602 tree ref_ptr = tree_coverage_counter_addr (tag, base);
603 gcall *call;
604 tree val;
606 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
607 true, NULL_TREE, true, GSI_SAME_STMT);
608 val = prepare_instrumented_value (&gsi, value);
609 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
610 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
613 #ifndef HAVE_sync_compare_and_swapsi
614 #define HAVE_sync_compare_and_swapsi 0
615 #endif
616 #ifndef HAVE_atomic_compare_and_swapsi
617 #define HAVE_atomic_compare_and_swapsi 0
618 #endif
620 #ifndef HAVE_sync_compare_and_swapdi
621 #define HAVE_sync_compare_and_swapdi 0
622 #endif
623 #ifndef HAVE_atomic_compare_and_swapdi
624 #define HAVE_atomic_compare_and_swapdi 0
625 #endif
627 /* Profile all functions in the callgraph. */
629 static unsigned int
630 tree_profiling (void)
632 struct cgraph_node *node;
634 /* Verify whether we can utilize atomic update operations. */
635 bool can_support_atomic = false;
636 unsigned HOST_WIDE_INT gcov_type_size
637 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
638 if (gcov_type_size == 4)
639 can_support_atomic
640 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
641 else if (gcov_type_size == 8)
642 can_support_atomic
643 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
645 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
646 && !can_support_atomic)
648 warning (0, "target does not support atomic profile update, "
649 "single mode is selected");
650 flag_profile_update = PROFILE_UPDATE_SINGLE;
652 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
653 flag_profile_update = can_support_atomic
654 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
656 /* This is a small-ipa pass that gets called only once, from
657 cgraphunit.c:ipa_passes(). */
658 gcc_assert (symtab->state == IPA_SSA);
660 init_node_map (true);
662 FOR_EACH_DEFINED_FUNCTION (node)
664 if (!gimple_has_body_p (node->decl))
665 continue;
667 /* Don't profile functions produced for builtin stuff. */
668 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
669 continue;
671 if (lookup_attribute ("no_profile_instrument_function",
672 DECL_ATTRIBUTES (node->decl)))
673 continue;
674 /* Do not instrument extern inline functions when testing coverage.
675 While this is not perfectly consistent (early inlined extern inlines
676 will get acocunted), testsuite expects that. */
677 if (DECL_EXTERNAL (node->decl)
678 && flag_test_coverage)
679 continue;
681 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
683 if (dump_file)
684 dump_function_header (dump_file, cfun->decl, dump_flags);
686 /* Local pure-const may imply need to fixup the cfg. */
687 if (execute_fixup_cfg () & TODO_cleanup_cfg)
688 cleanup_tree_cfg ();
690 branch_prob ();
692 if (! flag_branch_probabilities
693 && flag_profile_values)
694 gimple_gen_ic_func_profiler ();
696 if (flag_branch_probabilities
697 && flag_profile_values
698 && flag_value_profile_transformations)
699 gimple_value_profile_transformations ();
701 /* The above could hose dominator info. Currently there is
702 none coming in, this is a safety valve. It should be
703 easy to adjust it, if and when there is some. */
704 free_dominance_info (CDI_DOMINATORS);
705 free_dominance_info (CDI_POST_DOMINATORS);
706 pop_cfun ();
709 /* Drop pure/const flags from instrumented functions. */
710 if (profile_arc_flag || flag_test_coverage)
711 FOR_EACH_DEFINED_FUNCTION (node)
713 if (!gimple_has_body_p (node->decl)
714 || !(!node->clone_of
715 || node->decl != node->clone_of->decl))
716 continue;
718 /* Don't profile functions produced for builtin stuff. */
719 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
720 continue;
722 node->set_const_flag (false, false);
723 node->set_pure_flag (false, false);
726 /* Update call statements and rebuild the cgraph. */
727 FOR_EACH_DEFINED_FUNCTION (node)
729 basic_block bb;
731 if (!gimple_has_body_p (node->decl)
732 || !(!node->clone_of
733 || node->decl != node->clone_of->decl))
734 continue;
736 /* Don't profile functions produced for builtin stuff. */
737 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
738 continue;
740 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
742 FOR_EACH_BB_FN (bb, cfun)
744 gimple_stmt_iterator gsi;
745 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
747 gimple *stmt = gsi_stmt (gsi);
748 if (is_gimple_call (stmt))
749 update_stmt (stmt);
753 /* re-merge split blocks. */
754 cleanup_tree_cfg ();
755 update_ssa (TODO_update_ssa);
757 cgraph_edge::rebuild_edges ();
759 pop_cfun ();
762 handle_missing_profiles ();
764 del_node_map ();
765 return 0;
768 namespace {
770 const pass_data pass_data_ipa_tree_profile =
772 SIMPLE_IPA_PASS, /* type */
773 "profile", /* name */
774 OPTGROUP_NONE, /* optinfo_flags */
775 TV_IPA_PROFILE, /* tv_id */
776 0, /* properties_required */
777 0, /* properties_provided */
778 0, /* properties_destroyed */
779 0, /* todo_flags_start */
780 TODO_dump_symtab, /* todo_flags_finish */
783 class pass_ipa_tree_profile : public simple_ipa_opt_pass
785 public:
786 pass_ipa_tree_profile (gcc::context *ctxt)
787 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
790 /* opt_pass methods: */
791 virtual bool gate (function *);
792 virtual unsigned int execute (function *) { return tree_profiling (); }
794 }; // class pass_ipa_tree_profile
796 bool
797 pass_ipa_tree_profile::gate (function *)
799 /* When profile instrumentation, use or test coverage shall be performed.
800 But for AutoFDO, this there is no instrumentation, thus this pass is
801 diabled. */
802 return (!in_lto_p && !flag_auto_profile
803 && (flag_branch_probabilities || flag_test_coverage
804 || profile_arc_flag));
807 } // anon namespace
809 simple_ipa_opt_pass *
810 make_pass_ipa_tree_profile (gcc::context *ctxt)
812 return new pass_ipa_tree_profile (ctxt);
815 #include "gt-tree-profile.h"