2017-02-20 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / tree-profile.c
bloba49ec37f8bbc7d3608f21e0108ded34d747501fc
1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990-2017 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"
54 static GTY(()) tree gcov_type_node;
55 static GTY(()) tree tree_interval_profiler_fn;
56 static GTY(()) tree tree_pow2_profiler_fn;
57 static GTY(()) tree tree_one_value_profiler_fn;
58 static GTY(()) tree tree_indirect_call_profiler_fn;
59 static GTY(()) tree tree_average_profiler_fn;
60 static GTY(()) tree tree_ior_profiler_fn;
61 static GTY(()) tree tree_time_profiler_counter;
64 static GTY(()) tree ic_void_ptr_var;
65 static GTY(()) tree ic_gcov_type_ptr_var;
66 static GTY(()) tree ptr_void;
68 /* Do initialization work for the edge profiler. */
70 /* Add code:
71 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
72 __thread void* __gcov_indirect_call_callee; // actual callee address
73 __thread int __gcov_function_counter; // time profiler function counter
75 static void
76 init_ic_make_global_vars (void)
78 tree gcov_type_ptr;
80 ptr_void = build_pointer_type (void_type_node);
82 ic_void_ptr_var
83 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
84 get_identifier (
85 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
86 "__gcov_indirect_call_topn_callee" :
87 "__gcov_indirect_call_callee")),
88 ptr_void);
89 TREE_PUBLIC (ic_void_ptr_var) = 1;
90 DECL_EXTERNAL (ic_void_ptr_var) = 1;
91 TREE_STATIC (ic_void_ptr_var) = 1;
92 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
93 DECL_INITIAL (ic_void_ptr_var) = NULL;
94 if (targetm.have_tls)
95 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
97 gcov_type_ptr = build_pointer_type (get_gcov_type ());
99 ic_gcov_type_ptr_var
100 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
101 get_identifier (
102 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
103 "__gcov_indirect_call_topn_counters" :
104 "__gcov_indirect_call_counters")),
105 gcov_type_ptr);
106 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
107 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
108 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
109 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
110 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
111 if (targetm.have_tls)
112 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
115 /* Create the type and function decls for the interface with gcov. */
117 void
118 gimple_init_gcov_profiler (void)
120 tree interval_profiler_fn_type;
121 tree pow2_profiler_fn_type;
122 tree one_value_profiler_fn_type;
123 tree gcov_type_ptr;
124 tree ic_profiler_fn_type;
125 tree average_profiler_fn_type;
126 const char *profiler_fn_name;
127 const char *fn_name;
129 if (!gcov_type_node)
131 const char *fn_suffix
132 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
134 gcov_type_node = get_gcov_type ();
135 gcov_type_ptr = build_pointer_type (gcov_type_node);
137 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
138 interval_profiler_fn_type
139 = build_function_type_list (void_type_node,
140 gcov_type_ptr, gcov_type_node,
141 integer_type_node,
142 unsigned_type_node, NULL_TREE);
143 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
144 tree_interval_profiler_fn = build_fn_decl (fn_name,
145 interval_profiler_fn_type);
146 free (CONST_CAST (char *, fn_name));
147 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
148 DECL_ATTRIBUTES (tree_interval_profiler_fn)
149 = tree_cons (get_identifier ("leaf"), NULL,
150 DECL_ATTRIBUTES (tree_interval_profiler_fn));
152 /* void (*) (gcov_type *, gcov_type) */
153 pow2_profiler_fn_type
154 = build_function_type_list (void_type_node,
155 gcov_type_ptr, gcov_type_node,
156 NULL_TREE);
157 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
158 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
159 free (CONST_CAST (char *, fn_name));
160 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
161 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
162 = tree_cons (get_identifier ("leaf"), NULL,
163 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
165 /* void (*) (gcov_type *, gcov_type) */
166 one_value_profiler_fn_type
167 = build_function_type_list (void_type_node,
168 gcov_type_ptr, gcov_type_node,
169 NULL_TREE);
170 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
171 tree_one_value_profiler_fn = build_fn_decl (fn_name,
172 one_value_profiler_fn_type);
173 free (CONST_CAST (char *, fn_name));
174 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
175 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
176 = tree_cons (get_identifier ("leaf"), NULL,
177 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
179 init_ic_make_global_vars ();
181 /* void (*) (gcov_type, void *) */
182 ic_profiler_fn_type
183 = build_function_type_list (void_type_node,
184 gcov_type_node,
185 ptr_void,
186 NULL_TREE);
187 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
188 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
189 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
191 tree_indirect_call_profiler_fn
192 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
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));
199 tree_time_profiler_counter
200 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
201 get_identifier ("__gcov_time_profiler_counter"),
202 get_gcov_type ());
203 TREE_PUBLIC (tree_time_profiler_counter) = 1;
204 DECL_EXTERNAL (tree_time_profiler_counter) = 1;
205 TREE_STATIC (tree_time_profiler_counter) = 1;
206 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
207 DECL_INITIAL (tree_time_profiler_counter) = NULL;
209 /* void (*) (gcov_type *, gcov_type) */
210 average_profiler_fn_type
211 = build_function_type_list (void_type_node,
212 gcov_type_ptr, gcov_type_node, NULL_TREE);
213 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
214 tree_average_profiler_fn = build_fn_decl (fn_name,
215 average_profiler_fn_type);
216 free (CONST_CAST (char *, fn_name));
217 TREE_NOTHROW (tree_average_profiler_fn) = 1;
218 DECL_ATTRIBUTES (tree_average_profiler_fn)
219 = tree_cons (get_identifier ("leaf"), NULL,
220 DECL_ATTRIBUTES (tree_average_profiler_fn));
221 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
222 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
223 free (CONST_CAST (char *, fn_name));
224 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
225 DECL_ATTRIBUTES (tree_ior_profiler_fn)
226 = tree_cons (get_identifier ("leaf"), NULL,
227 DECL_ATTRIBUTES (tree_ior_profiler_fn));
229 /* LTO streamer needs assembler names. Because we create these decls
230 late, we need to initialize them by hand. */
231 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
232 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
233 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
234 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
235 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
236 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
240 /* Output instructions as GIMPLE trees to increment the edge
241 execution count, and insert them on E. We rely on
242 gsi_insert_on_edge to preserve the order. */
244 void
245 gimple_gen_edge_profiler (int edgeno, edge e)
247 tree one;
249 one = build_int_cst (gcov_type_node, 1);
251 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
253 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
254 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
255 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
256 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
257 BUILT_IN_ATOMIC_FETCH_ADD_4);
258 gcall *stmt = gimple_build_call (f, 3, addr, one,
259 build_int_cst (integer_type_node,
260 MEMMODEL_RELAXED));
261 gsi_insert_on_edge (e, stmt);
263 else
265 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
266 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
267 NULL, "PROF_edge_counter");
268 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
269 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
270 NULL, "PROF_edge_counter");
271 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
272 gimple_assign_lhs (stmt1), one);
273 gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
274 gimple_assign_lhs (stmt2));
275 gsi_insert_on_edge (e, stmt1);
276 gsi_insert_on_edge (e, stmt2);
277 gsi_insert_on_edge (e, stmt3);
281 /* Emits code to get VALUE to instrument at GSI, and returns the
282 variable containing the value. */
284 static tree
285 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
287 tree val = value->hvalue.value;
288 if (POINTER_TYPE_P (TREE_TYPE (val)))
289 val = fold_convert (build_nonstandard_integer_type
290 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
291 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
292 true, NULL_TREE, true, GSI_SAME_STMT);
295 /* Output instructions as GIMPLE trees to increment the interval histogram
296 counter. VALUE is the expression whose value is profiled. TAG is the
297 tag of the section for counters, BASE is offset of the counter position. */
299 void
300 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
302 gimple *stmt = value->hvalue.stmt;
303 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
304 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
305 gcall *call;
306 tree val;
307 tree start = build_int_cst_type (integer_type_node,
308 value->hdata.intvl.int_start);
309 tree steps = build_int_cst_type (unsigned_type_node,
310 value->hdata.intvl.steps);
312 ref_ptr = force_gimple_operand_gsi (&gsi,
313 build_addr (ref),
314 true, NULL_TREE, true, GSI_SAME_STMT);
315 val = prepare_instrumented_value (&gsi, value);
316 call = gimple_build_call (tree_interval_profiler_fn, 4,
317 ref_ptr, val, start, steps);
318 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
321 /* Output instructions as GIMPLE trees to increment the power of two histogram
322 counter. VALUE is the expression whose value is profiled. TAG is the tag
323 of the section for counters, BASE is offset of the counter position. */
325 void
326 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
328 gimple *stmt = value->hvalue.stmt;
329 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
330 tree ref_ptr = tree_coverage_counter_addr (tag, base);
331 gcall *call;
332 tree val;
334 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
335 true, NULL_TREE, true, GSI_SAME_STMT);
336 val = prepare_instrumented_value (&gsi, value);
337 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
338 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
341 /* Output instructions as GIMPLE trees for code to find the most common value.
342 VALUE is the expression whose value is profiled. TAG is the tag of the
343 section for counters, BASE is offset of the counter position. */
345 void
346 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
348 gimple *stmt = value->hvalue.stmt;
349 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
350 tree ref_ptr = tree_coverage_counter_addr (tag, base);
351 gcall *call;
352 tree val;
354 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
355 true, NULL_TREE, true, GSI_SAME_STMT);
356 val = prepare_instrumented_value (&gsi, value);
357 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
358 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
362 /* Output instructions as GIMPLE trees for code to find the most
363 common called function in indirect call.
364 VALUE is the call expression whose indirect callee is profiled.
365 TAG is the tag of the section for counters, BASE is offset of the
366 counter position. */
368 void
369 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
371 tree tmp1;
372 gassign *stmt1, *stmt2, *stmt3;
373 gimple *stmt = value->hvalue.stmt;
374 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
375 tree ref_ptr = tree_coverage_counter_addr (tag, base);
377 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
378 tag == GCOV_COUNTER_V_INDIR) ||
379 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
380 tag == GCOV_COUNTER_ICALL_TOPNV))
381 return;
383 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
384 true, NULL_TREE, true, GSI_SAME_STMT);
386 /* Insert code:
388 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
389 stmt2: tmp1 = (void *) (indirect call argument value)
390 stmt3: __gcov_indirect_call_callee = tmp1;
393 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
394 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
395 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
396 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
398 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
399 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
400 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
404 /* Output instructions as GIMPLE trees for code to find the most
405 common called function in indirect call. Insert instructions at the
406 beginning of every possible called function.
409 void
410 gimple_gen_ic_func_profiler (void)
412 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
413 gimple_stmt_iterator gsi;
414 gcall *stmt1;
415 gassign *stmt2;
416 tree tree_uid, cur_func, void0;
418 if (c_node->only_called_directly_p ())
419 return;
421 gimple_init_gcov_profiler ();
423 /* Insert code:
425 stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
426 &current_function_decl)
428 gsi = gsi_after_labels (split_edge (single_succ_edge
429 (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
431 cur_func = force_gimple_operand_gsi (&gsi,
432 build_addr (current_function_decl),
433 true, NULL_TREE,
434 true, GSI_SAME_STMT);
435 tree_uid = build_int_cst
436 (gcov_type_node,
437 cgraph_node::get (current_function_decl)->profile_id);
438 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
439 tree_uid, cur_func);
440 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
442 /* Set __gcov_indirect_call_callee to 0,
443 so that calls from other modules won't get misattributed
444 to the last caller of the current callee. */
445 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
446 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
447 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
450 /* Output instructions as GIMPLE tree at the beginning for each function.
451 TAG is the tag of the section for counters, BASE is offset of the
452 counter position and GSI is the iterator we place the counter. */
454 void
455 gimple_gen_time_profiler (unsigned tag, unsigned base)
457 tree type = get_gcov_type ();
458 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
459 basic_block cond_bb = split_edge (single_succ_edge (entry));
460 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
461 split_edge (single_succ_edge (update_bb));
463 edge true_edge = single_succ_edge (cond_bb);
464 true_edge->flags = EDGE_TRUE_VALUE;
465 true_edge->probability = PROB_VERY_UNLIKELY;
466 edge e
467 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
468 e->probability = REG_BR_PROB_BASE - true_edge->probability;
470 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
471 tree original_ref = tree_coverage_counter_ref (tag, base);
472 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
473 true, GSI_SAME_STMT);
474 tree one = build_int_cst (type, 1);
476 /* Emit: if (counters[0] != 0). */
477 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
478 NULL, NULL);
479 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
481 gsi = gsi_start_bb (update_bb);
483 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
484 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
486 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
487 "time_profiler_counter_ptr");
488 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
489 tree_time_profiler_counter);
490 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
491 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
492 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
493 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
494 BUILT_IN_ATOMIC_ADD_FETCH_4);
495 gcall *stmt = gimple_build_call (f, 3, ptr, one,
496 build_int_cst (integer_type_node,
497 MEMMODEL_RELAXED));
498 tree result_type = TREE_TYPE (TREE_TYPE (f));
499 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
500 gimple_set_lhs (stmt, tmp);
501 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
502 tmp = make_temp_ssa_name (type, NULL, "time_profile");
503 assign = gimple_build_assign (tmp, NOP_EXPR,
504 gimple_call_lhs (stmt));
505 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
506 assign = gimple_build_assign (original_ref, tmp);
507 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
509 else
511 tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
512 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
513 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
515 tmp = make_temp_ssa_name (type, NULL, "time_profile");
516 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
517 one);
518 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
519 assign = gimple_build_assign (original_ref, tmp);
520 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
521 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
522 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
526 /* Output instructions as GIMPLE trees to increment the average histogram
527 counter. VALUE is the expression whose value is profiled. TAG is the
528 tag of the section for counters, BASE is offset of the counter position. */
530 void
531 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
533 gimple *stmt = value->hvalue.stmt;
534 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
535 tree ref_ptr = tree_coverage_counter_addr (tag, base);
536 gcall *call;
537 tree val;
539 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
540 true, NULL_TREE,
541 true, GSI_SAME_STMT);
542 val = prepare_instrumented_value (&gsi, value);
543 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
544 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
547 /* Output instructions as GIMPLE trees to increment the ior histogram
548 counter. VALUE is the expression whose value is profiled. TAG is the
549 tag of the section for counters, BASE is offset of the counter position. */
551 void
552 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
554 gimple *stmt = value->hvalue.stmt;
555 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
556 tree ref_ptr = tree_coverage_counter_addr (tag, base);
557 gcall *call;
558 tree val;
560 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
561 true, NULL_TREE, true, GSI_SAME_STMT);
562 val = prepare_instrumented_value (&gsi, value);
563 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
564 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
567 #ifndef HAVE_sync_compare_and_swapsi
568 #define HAVE_sync_compare_and_swapsi 0
569 #endif
570 #ifndef HAVE_atomic_compare_and_swapsi
571 #define HAVE_atomic_compare_and_swapsi 0
572 #endif
574 #ifndef HAVE_sync_compare_and_swapdi
575 #define HAVE_sync_compare_and_swapdi 0
576 #endif
577 #ifndef HAVE_atomic_compare_and_swapdi
578 #define HAVE_atomic_compare_and_swapdi 0
579 #endif
581 /* Profile all functions in the callgraph. */
583 static unsigned int
584 tree_profiling (void)
586 struct cgraph_node *node;
588 /* Verify whether we can utilize atomic update operations. */
589 bool can_support_atomic = false;
590 unsigned HOST_WIDE_INT gcov_type_size
591 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
592 if (gcov_type_size == 4)
593 can_support_atomic
594 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
595 else if (gcov_type_size == 8)
596 can_support_atomic
597 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
599 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
600 && !can_support_atomic)
602 warning (0, "target does not support atomic profile update, "
603 "single mode is selected");
604 flag_profile_update = PROFILE_UPDATE_SINGLE;
606 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
607 flag_profile_update = can_support_atomic
608 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
610 /* This is a small-ipa pass that gets called only once, from
611 cgraphunit.c:ipa_passes(). */
612 gcc_assert (symtab->state == IPA_SSA);
614 init_node_map (true);
616 FOR_EACH_DEFINED_FUNCTION (node)
618 if (!gimple_has_body_p (node->decl))
619 continue;
621 /* Don't profile functions produced for builtin stuff. */
622 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
623 continue;
625 if (lookup_attribute ("no_profile_instrument_function",
626 DECL_ATTRIBUTES (node->decl)))
627 continue;
628 /* Do not instrument extern inline functions when testing coverage.
629 While this is not perfectly consistent (early inlined extern inlines
630 will get acocunted), testsuite expects that. */
631 if (DECL_EXTERNAL (node->decl)
632 && flag_test_coverage)
633 continue;
635 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
637 /* Local pure-const may imply need to fixup the cfg. */
638 if (execute_fixup_cfg () & TODO_cleanup_cfg)
639 cleanup_tree_cfg ();
641 branch_prob ();
643 if (! flag_branch_probabilities
644 && flag_profile_values)
645 gimple_gen_ic_func_profiler ();
647 if (flag_branch_probabilities
648 && flag_profile_values
649 && flag_value_profile_transformations)
650 gimple_value_profile_transformations ();
652 /* The above could hose dominator info. Currently there is
653 none coming in, this is a safety valve. It should be
654 easy to adjust it, if and when there is some. */
655 free_dominance_info (CDI_DOMINATORS);
656 free_dominance_info (CDI_POST_DOMINATORS);
657 pop_cfun ();
660 /* Drop pure/const flags from instrumented functions. */
661 if (profile_arc_flag || flag_test_coverage)
662 FOR_EACH_DEFINED_FUNCTION (node)
664 if (!gimple_has_body_p (node->decl)
665 || !(!node->clone_of
666 || node->decl != node->clone_of->decl))
667 continue;
669 /* Don't profile functions produced for builtin stuff. */
670 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
671 continue;
673 node->set_const_flag (false, false);
674 node->set_pure_flag (false, false);
677 /* Update call statements and rebuild the cgraph. */
678 FOR_EACH_DEFINED_FUNCTION (node)
680 basic_block bb;
682 if (!gimple_has_body_p (node->decl)
683 || !(!node->clone_of
684 || node->decl != node->clone_of->decl))
685 continue;
687 /* Don't profile functions produced for builtin stuff. */
688 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
689 continue;
691 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
693 FOR_EACH_BB_FN (bb, cfun)
695 gimple_stmt_iterator gsi;
696 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
698 gimple *stmt = gsi_stmt (gsi);
699 if (is_gimple_call (stmt))
700 update_stmt (stmt);
704 /* re-merge split blocks. */
705 cleanup_tree_cfg ();
706 update_ssa (TODO_update_ssa);
708 cgraph_edge::rebuild_edges ();
710 pop_cfun ();
713 handle_missing_profiles ();
715 del_node_map ();
716 return 0;
719 namespace {
721 const pass_data pass_data_ipa_tree_profile =
723 SIMPLE_IPA_PASS, /* type */
724 "profile", /* name */
725 OPTGROUP_NONE, /* optinfo_flags */
726 TV_IPA_PROFILE, /* tv_id */
727 0, /* properties_required */
728 0, /* properties_provided */
729 0, /* properties_destroyed */
730 0, /* todo_flags_start */
731 TODO_dump_symtab, /* todo_flags_finish */
734 class pass_ipa_tree_profile : public simple_ipa_opt_pass
736 public:
737 pass_ipa_tree_profile (gcc::context *ctxt)
738 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
741 /* opt_pass methods: */
742 virtual bool gate (function *);
743 virtual unsigned int execute (function *) { return tree_profiling (); }
745 }; // class pass_ipa_tree_profile
747 bool
748 pass_ipa_tree_profile::gate (function *)
750 /* When profile instrumentation, use or test coverage shall be performed.
751 But for AutoFDO, this there is no instrumentation, thus this pass is
752 diabled. */
753 return (!in_lto_p && !flag_auto_profile
754 && (flag_branch_probabilities || flag_test_coverage
755 || profile_arc_flag));
758 } // anon namespace
760 simple_ipa_opt_pass *
761 make_pass_ipa_tree_profile (gcc::context *ctxt)
763 return new pass_ipa_tree_profile (ctxt);
766 #include "gt-tree-profile.h"