PR tree-optimization/84740
[official-gcc.git] / gcc / tree-profile.c
blobf96bd4b97048718ad33fb9eab3d22277cea20b8c
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"
57 static GTY(()) tree gcov_type_node;
58 static GTY(()) tree tree_interval_profiler_fn;
59 static GTY(()) tree tree_pow2_profiler_fn;
60 static GTY(()) tree tree_one_value_profiler_fn;
61 static GTY(()) tree tree_indirect_call_profiler_fn;
62 static GTY(()) tree tree_average_profiler_fn;
63 static GTY(()) tree tree_ior_profiler_fn;
64 static GTY(()) tree tree_time_profiler_counter;
67 static GTY(()) tree ic_void_ptr_var;
68 static GTY(()) tree ic_gcov_type_ptr_var;
69 static GTY(()) tree ptr_void;
71 /* Do initialization work for the edge profiler. */
73 /* Add code:
74 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
75 __thread void* __gcov_indirect_call_callee; // actual callee address
76 __thread int __gcov_function_counter; // time profiler function counter
78 static void
79 init_ic_make_global_vars (void)
81 tree gcov_type_ptr;
83 ptr_void = build_pointer_type (void_type_node);
85 ic_void_ptr_var
86 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
87 get_identifier (
88 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
89 "__gcov_indirect_call_topn_callee" :
90 "__gcov_indirect_call_callee")),
91 ptr_void);
92 TREE_PUBLIC (ic_void_ptr_var) = 1;
93 DECL_EXTERNAL (ic_void_ptr_var) = 1;
94 TREE_STATIC (ic_void_ptr_var) = 1;
95 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
96 DECL_INITIAL (ic_void_ptr_var) = NULL;
97 if (targetm.have_tls)
98 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
100 gcov_type_ptr = build_pointer_type (get_gcov_type ());
102 ic_gcov_type_ptr_var
103 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
104 get_identifier (
105 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
106 "__gcov_indirect_call_topn_counters" :
107 "__gcov_indirect_call_counters")),
108 gcov_type_ptr);
109 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
110 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
111 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
112 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
113 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
114 if (targetm.have_tls)
115 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
118 /* Create the type and function decls for the interface with gcov. */
120 void
121 gimple_init_gcov_profiler (void)
123 tree interval_profiler_fn_type;
124 tree pow2_profiler_fn_type;
125 tree one_value_profiler_fn_type;
126 tree gcov_type_ptr;
127 tree ic_profiler_fn_type;
128 tree average_profiler_fn_type;
129 const char *profiler_fn_name;
130 const char *fn_name;
132 if (!gcov_type_node)
134 const char *fn_suffix
135 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
137 gcov_type_node = get_gcov_type ();
138 gcov_type_ptr = build_pointer_type (gcov_type_node);
140 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
141 interval_profiler_fn_type
142 = build_function_type_list (void_type_node,
143 gcov_type_ptr, gcov_type_node,
144 integer_type_node,
145 unsigned_type_node, NULL_TREE);
146 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
147 tree_interval_profiler_fn = build_fn_decl (fn_name,
148 interval_profiler_fn_type);
149 free (CONST_CAST (char *, fn_name));
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));
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 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
161 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
162 free (CONST_CAST (char *, fn_name));
163 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
164 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
165 = tree_cons (get_identifier ("leaf"), NULL,
166 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
168 /* void (*) (gcov_type *, gcov_type) */
169 one_value_profiler_fn_type
170 = build_function_type_list (void_type_node,
171 gcov_type_ptr, gcov_type_node,
172 NULL_TREE);
173 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
174 tree_one_value_profiler_fn = build_fn_decl (fn_name,
175 one_value_profiler_fn_type);
176 free (CONST_CAST (char *, fn_name));
177 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
178 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
179 = tree_cons (get_identifier ("leaf"), NULL,
180 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
182 init_ic_make_global_vars ();
184 /* void (*) (gcov_type, void *) */
185 ic_profiler_fn_type
186 = build_function_type_list (void_type_node,
187 gcov_type_node,
188 ptr_void,
189 NULL_TREE);
190 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
191 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
192 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
194 tree_indirect_call_profiler_fn
195 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
197 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
198 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
199 = tree_cons (get_identifier ("leaf"), NULL,
200 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
202 tree_time_profiler_counter
203 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
204 get_identifier ("__gcov_time_profiler_counter"),
205 get_gcov_type ());
206 TREE_PUBLIC (tree_time_profiler_counter) = 1;
207 DECL_EXTERNAL (tree_time_profiler_counter) = 1;
208 TREE_STATIC (tree_time_profiler_counter) = 1;
209 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
210 DECL_INITIAL (tree_time_profiler_counter) = NULL;
212 /* void (*) (gcov_type *, gcov_type) */
213 average_profiler_fn_type
214 = build_function_type_list (void_type_node,
215 gcov_type_ptr, gcov_type_node, NULL_TREE);
216 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
217 tree_average_profiler_fn = build_fn_decl (fn_name,
218 average_profiler_fn_type);
219 free (CONST_CAST (char *, fn_name));
220 TREE_NOTHROW (tree_average_profiler_fn) = 1;
221 DECL_ATTRIBUTES (tree_average_profiler_fn)
222 = tree_cons (get_identifier ("leaf"), NULL,
223 DECL_ATTRIBUTES (tree_average_profiler_fn));
224 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
225 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
226 free (CONST_CAST (char *, fn_name));
227 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
228 DECL_ATTRIBUTES (tree_ior_profiler_fn)
229 = tree_cons (get_identifier ("leaf"), NULL,
230 DECL_ATTRIBUTES (tree_ior_profiler_fn));
232 /* LTO streamer needs assembler names. Because we create these decls
233 late, we need to initialize them by hand. */
234 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
235 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
236 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
237 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
238 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
239 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
243 /* Output instructions as GIMPLE trees to increment the edge
244 execution count, and insert them on E. We rely on
245 gsi_insert_on_edge to preserve the order. */
247 void
248 gimple_gen_edge_profiler (int edgeno, edge e)
250 tree one;
252 one = build_int_cst (gcov_type_node, 1);
254 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
256 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
257 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
258 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
259 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
260 BUILT_IN_ATOMIC_FETCH_ADD_4);
261 gcall *stmt = gimple_build_call (f, 3, addr, one,
262 build_int_cst (integer_type_node,
263 MEMMODEL_RELAXED));
264 gsi_insert_on_edge (e, stmt);
266 else
268 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
269 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
270 NULL, "PROF_edge_counter");
271 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
272 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
273 NULL, "PROF_edge_counter");
274 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
275 gimple_assign_lhs (stmt1), one);
276 gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
277 gimple_assign_lhs (stmt2));
278 gsi_insert_on_edge (e, stmt1);
279 gsi_insert_on_edge (e, stmt2);
280 gsi_insert_on_edge (e, stmt3);
284 /* Emits code to get VALUE to instrument at GSI, and returns the
285 variable containing the value. */
287 static tree
288 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
290 tree val = value->hvalue.value;
291 if (POINTER_TYPE_P (TREE_TYPE (val)))
292 val = fold_convert (build_nonstandard_integer_type
293 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
294 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
295 true, NULL_TREE, true, GSI_SAME_STMT);
298 /* Output instructions as GIMPLE trees to increment the interval histogram
299 counter. VALUE is the expression whose value is profiled. TAG is the
300 tag of the section for counters, BASE is offset of the counter position. */
302 void
303 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
305 gimple *stmt = value->hvalue.stmt;
306 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
307 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
308 gcall *call;
309 tree val;
310 tree start = build_int_cst_type (integer_type_node,
311 value->hdata.intvl.int_start);
312 tree steps = build_int_cst_type (unsigned_type_node,
313 value->hdata.intvl.steps);
315 ref_ptr = force_gimple_operand_gsi (&gsi,
316 build_addr (ref),
317 true, NULL_TREE, true, GSI_SAME_STMT);
318 val = prepare_instrumented_value (&gsi, value);
319 call = gimple_build_call (tree_interval_profiler_fn, 4,
320 ref_ptr, val, start, steps);
321 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
324 /* Output instructions as GIMPLE trees to increment the power of two histogram
325 counter. VALUE is the expression whose value is profiled. TAG is the tag
326 of the section for counters, BASE is offset of the counter position. */
328 void
329 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
331 gimple *stmt = value->hvalue.stmt;
332 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
333 tree ref_ptr = tree_coverage_counter_addr (tag, base);
334 gcall *call;
335 tree val;
337 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
338 true, NULL_TREE, true, GSI_SAME_STMT);
339 val = prepare_instrumented_value (&gsi, value);
340 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
341 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
344 /* Output instructions as GIMPLE trees for code to find the most common value.
345 VALUE is the expression whose value is profiled. TAG is the tag of the
346 section for counters, BASE is offset of the counter position. */
348 void
349 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
351 gimple *stmt = value->hvalue.stmt;
352 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
353 tree ref_ptr = tree_coverage_counter_addr (tag, base);
354 gcall *call;
355 tree val;
357 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
358 true, NULL_TREE, true, GSI_SAME_STMT);
359 val = prepare_instrumented_value (&gsi, value);
360 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
361 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
365 /* Output instructions as GIMPLE trees for code to find the most
366 common called function in indirect call.
367 VALUE is the call expression whose indirect callee is profiled.
368 TAG is the tag of the section for counters, BASE is offset of the
369 counter position. */
371 void
372 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
374 tree tmp1;
375 gassign *stmt1, *stmt2, *stmt3;
376 gimple *stmt = value->hvalue.stmt;
377 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
378 tree ref_ptr = tree_coverage_counter_addr (tag, base);
380 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
381 tag == GCOV_COUNTER_V_INDIR) ||
382 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
383 tag == GCOV_COUNTER_ICALL_TOPNV))
384 return;
386 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
387 true, NULL_TREE, true, GSI_SAME_STMT);
389 /* Insert code:
391 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
392 stmt2: tmp1 = (void *) (indirect call argument value)
393 stmt3: __gcov_indirect_call_callee = tmp1;
395 Example:
396 f_1 = foo;
397 __gcov_indirect_call_counters = &__gcov4.main[0];
398 PROF_9 = f_1;
399 __gcov_indirect_call_callee = PROF_9;
400 _4 = f_1 ();
403 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
404 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
405 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
406 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
408 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
409 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
410 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
414 /* Output instructions as GIMPLE trees for code to find the most
415 common called function in indirect call. Insert instructions at the
416 beginning of every possible called function.
419 void
420 gimple_gen_ic_func_profiler (void)
422 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
423 gcall *stmt1;
424 tree tree_uid, cur_func, void0;
426 if (c_node->only_called_directly_p ())
427 return;
429 gimple_init_gcov_profiler ();
431 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
432 basic_block cond_bb = split_edge (single_succ_edge (entry));
433 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
435 /* We need to do an extra split in order to not create an input
436 for a possible PHI node. */
437 split_edge (single_succ_edge (update_bb));
439 edge true_edge = single_succ_edge (cond_bb);
440 true_edge->flags = EDGE_TRUE_VALUE;
442 profile_probability probability;
443 if (DECL_VIRTUAL_P (current_function_decl))
444 probability = profile_probability::very_likely ();
445 else
446 probability = profile_probability::unlikely ();
448 true_edge->probability = probability;
449 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
450 EDGE_FALSE_VALUE);
451 e->probability = true_edge->probability.invert ();
453 /* Insert code:
455 if (__gcov_indirect_call_callee != NULL)
456 __gcov_indirect_call_profiler_v2 (profile_id, &current_function_decl);
458 The function __gcov_indirect_call_profiler_v2 is responsible for
459 resetting __gcov_indirect_call_callee to NULL. */
461 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
462 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
464 tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE,
465 true, GSI_SAME_STMT);
467 gcond *cond = gimple_build_cond (NE_EXPR, ref,
468 void0, NULL, NULL);
469 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
471 gsi = gsi_after_labels (update_bb);
473 cur_func = force_gimple_operand_gsi (&gsi,
474 build_addr (current_function_decl),
475 true, NULL_TREE,
476 true, GSI_SAME_STMT);
477 tree_uid = build_int_cst
478 (gcov_type_node,
479 cgraph_node::get (current_function_decl)->profile_id);
480 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
481 tree_uid, cur_func);
482 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
485 /* Output instructions as GIMPLE tree at the beginning for each function.
486 TAG is the tag of the section for counters, BASE is offset of the
487 counter position and GSI is the iterator we place the counter. */
489 void
490 gimple_gen_time_profiler (unsigned tag, unsigned base)
492 tree type = get_gcov_type ();
493 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
494 basic_block cond_bb = split_edge (single_succ_edge (entry));
495 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
497 /* We need to do an extra split in order to not create an input
498 for a possible PHI node. */
499 split_edge (single_succ_edge (update_bb));
501 edge true_edge = single_succ_edge (cond_bb);
502 true_edge->flags = EDGE_TRUE_VALUE;
503 true_edge->probability = profile_probability::unlikely ();
504 edge e
505 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
506 e->probability = true_edge->probability.invert ();
508 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
509 tree original_ref = tree_coverage_counter_ref (tag, base);
510 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
511 true, GSI_SAME_STMT);
512 tree one = build_int_cst (type, 1);
514 /* Emit: if (counters[0] != 0). */
515 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
516 NULL, NULL);
517 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
519 gsi = gsi_start_bb (update_bb);
521 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
522 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
524 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
525 "time_profiler_counter_ptr");
526 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
527 tree_time_profiler_counter);
528 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
529 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
530 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
531 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
532 BUILT_IN_ATOMIC_ADD_FETCH_4);
533 gcall *stmt = gimple_build_call (f, 3, ptr, one,
534 build_int_cst (integer_type_node,
535 MEMMODEL_RELAXED));
536 tree result_type = TREE_TYPE (TREE_TYPE (f));
537 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
538 gimple_set_lhs (stmt, tmp);
539 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
540 tmp = make_temp_ssa_name (type, NULL, "time_profile");
541 assign = gimple_build_assign (tmp, NOP_EXPR,
542 gimple_call_lhs (stmt));
543 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
544 assign = gimple_build_assign (original_ref, tmp);
545 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
547 else
549 tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
550 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
551 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
553 tmp = make_temp_ssa_name (type, NULL, "time_profile");
554 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
555 one);
556 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
557 assign = gimple_build_assign (original_ref, tmp);
558 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
559 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
560 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
564 /* Output instructions as GIMPLE trees to increment the average histogram
565 counter. VALUE is the expression whose value is profiled. TAG is the
566 tag of the section for counters, BASE is offset of the counter position. */
568 void
569 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
571 gimple *stmt = value->hvalue.stmt;
572 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
573 tree ref_ptr = tree_coverage_counter_addr (tag, base);
574 gcall *call;
575 tree val;
577 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
578 true, NULL_TREE,
579 true, GSI_SAME_STMT);
580 val = prepare_instrumented_value (&gsi, value);
581 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
582 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
585 /* Output instructions as GIMPLE trees to increment the ior histogram
586 counter. VALUE is the expression whose value is profiled. TAG is the
587 tag of the section for counters, BASE is offset of the counter position. */
589 void
590 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
592 gimple *stmt = value->hvalue.stmt;
593 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
594 tree ref_ptr = tree_coverage_counter_addr (tag, base);
595 gcall *call;
596 tree val;
598 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
599 true, NULL_TREE, true, GSI_SAME_STMT);
600 val = prepare_instrumented_value (&gsi, value);
601 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
602 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
605 #ifndef HAVE_sync_compare_and_swapsi
606 #define HAVE_sync_compare_and_swapsi 0
607 #endif
608 #ifndef HAVE_atomic_compare_and_swapsi
609 #define HAVE_atomic_compare_and_swapsi 0
610 #endif
612 #ifndef HAVE_sync_compare_and_swapdi
613 #define HAVE_sync_compare_and_swapdi 0
614 #endif
615 #ifndef HAVE_atomic_compare_and_swapdi
616 #define HAVE_atomic_compare_and_swapdi 0
617 #endif
619 /* Profile all functions in the callgraph. */
621 static unsigned int
622 tree_profiling (void)
624 struct cgraph_node *node;
626 /* Verify whether we can utilize atomic update operations. */
627 bool can_support_atomic = false;
628 unsigned HOST_WIDE_INT gcov_type_size
629 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
630 if (gcov_type_size == 4)
631 can_support_atomic
632 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
633 else if (gcov_type_size == 8)
634 can_support_atomic
635 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
637 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
638 && !can_support_atomic)
640 warning (0, "target does not support atomic profile update, "
641 "single mode is selected");
642 flag_profile_update = PROFILE_UPDATE_SINGLE;
644 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
645 flag_profile_update = can_support_atomic
646 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
648 /* This is a small-ipa pass that gets called only once, from
649 cgraphunit.c:ipa_passes(). */
650 gcc_assert (symtab->state == IPA_SSA);
652 init_node_map (true);
654 FOR_EACH_DEFINED_FUNCTION (node)
656 if (!gimple_has_body_p (node->decl))
657 continue;
659 /* Don't profile functions produced for builtin stuff. */
660 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
661 continue;
663 if (lookup_attribute ("no_profile_instrument_function",
664 DECL_ATTRIBUTES (node->decl)))
665 continue;
666 /* Do not instrument extern inline functions when testing coverage.
667 While this is not perfectly consistent (early inlined extern inlines
668 will get acocunted), testsuite expects that. */
669 if (DECL_EXTERNAL (node->decl)
670 && flag_test_coverage)
671 continue;
673 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
675 if (dump_file)
676 dump_function_header (dump_file, cfun->decl, dump_flags);
678 /* Local pure-const may imply need to fixup the cfg. */
679 if (execute_fixup_cfg () & TODO_cleanup_cfg)
680 cleanup_tree_cfg ();
682 branch_prob ();
684 if (! flag_branch_probabilities
685 && flag_profile_values)
686 gimple_gen_ic_func_profiler ();
688 if (flag_branch_probabilities
689 && flag_profile_values
690 && flag_value_profile_transformations)
691 gimple_value_profile_transformations ();
693 /* The above could hose dominator info. Currently there is
694 none coming in, this is a safety valve. It should be
695 easy to adjust it, if and when there is some. */
696 free_dominance_info (CDI_DOMINATORS);
697 free_dominance_info (CDI_POST_DOMINATORS);
698 pop_cfun ();
701 /* Drop pure/const flags from instrumented functions. */
702 if (profile_arc_flag || flag_test_coverage)
703 FOR_EACH_DEFINED_FUNCTION (node)
705 if (!gimple_has_body_p (node->decl)
706 || !(!node->clone_of
707 || node->decl != node->clone_of->decl))
708 continue;
710 /* Don't profile functions produced for builtin stuff. */
711 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
712 continue;
714 node->set_const_flag (false, false);
715 node->set_pure_flag (false, false);
718 /* Update call statements and rebuild the cgraph. */
719 FOR_EACH_DEFINED_FUNCTION (node)
721 basic_block bb;
723 if (!gimple_has_body_p (node->decl)
724 || !(!node->clone_of
725 || node->decl != node->clone_of->decl))
726 continue;
728 /* Don't profile functions produced for builtin stuff. */
729 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
730 continue;
732 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
734 FOR_EACH_BB_FN (bb, cfun)
736 gimple_stmt_iterator gsi;
737 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
739 gimple *stmt = gsi_stmt (gsi);
740 if (is_gimple_call (stmt))
741 update_stmt (stmt);
745 /* re-merge split blocks. */
746 cleanup_tree_cfg ();
747 update_ssa (TODO_update_ssa);
749 cgraph_edge::rebuild_edges ();
751 pop_cfun ();
754 handle_missing_profiles ();
756 del_node_map ();
757 return 0;
760 namespace {
762 const pass_data pass_data_ipa_tree_profile =
764 SIMPLE_IPA_PASS, /* type */
765 "profile", /* name */
766 OPTGROUP_NONE, /* optinfo_flags */
767 TV_IPA_PROFILE, /* tv_id */
768 0, /* properties_required */
769 0, /* properties_provided */
770 0, /* properties_destroyed */
771 0, /* todo_flags_start */
772 TODO_dump_symtab, /* todo_flags_finish */
775 class pass_ipa_tree_profile : public simple_ipa_opt_pass
777 public:
778 pass_ipa_tree_profile (gcc::context *ctxt)
779 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
782 /* opt_pass methods: */
783 virtual bool gate (function *);
784 virtual unsigned int execute (function *) { return tree_profiling (); }
786 }; // class pass_ipa_tree_profile
788 bool
789 pass_ipa_tree_profile::gate (function *)
791 /* When profile instrumentation, use or test coverage shall be performed.
792 But for AutoFDO, this there is no instrumentation, thus this pass is
793 diabled. */
794 return (!in_lto_p && !flag_auto_profile
795 && (flag_branch_probabilities || flag_test_coverage
796 || profile_arc_flag));
799 } // anon namespace
801 simple_ipa_opt_pass *
802 make_pass_ipa_tree_profile (gcc::context *ctxt)
804 return new pass_ipa_tree_profile (ctxt);
807 #include "gt-tree-profile.h"