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
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
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. */
29 #include "coretypes.h"
36 #include "tree-pass.h"
40 #include "diagnostic-core.h"
41 #include "fold-const.h"
43 #include "tree-nested.h"
45 #include "gimple-iterator.h"
46 #include "gimplify-me.h"
48 #include "tree-into-ssa.h"
49 #include "value-prof.h"
51 #include "tree-cfgcleanup.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. */
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
76 init_ic_make_global_vars (void)
80 ptr_void = build_pointer_type (void_type_node);
83 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
85 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
86 "__gcov_indirect_call_topn_callee" :
87 "__gcov_indirect_call_callee")),
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;
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 ());
100 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
102 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
103 "__gcov_indirect_call_topn_counters" :
104 "__gcov_indirect_call_counters")),
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. */
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;
124 tree ic_profiler_fn_type;
125 tree average_profiler_fn_type;
126 const char *profiler_fn_name;
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,
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,
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,
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 *) */
183 = build_function_type_list (void_type_node,
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"),
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. */
245 gimple_gen_edge_profiler (int edgeno, edge e)
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,
261 gsi_insert_on_edge (e, stmt);
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. */
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. */
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;
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,
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. */
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);
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. */
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);
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
369 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
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))
383 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
384 true, NULL_TREE, true, GSI_SAME_STMT);
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;
394 __gcov_indirect_call_counters = &__gcov4.main[0];
396 __gcov_indirect_call_callee = PROF_9;
400 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
401 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
402 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
403 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
405 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
406 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
407 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
411 /* Output instructions as GIMPLE trees for code to find the most
412 common called function in indirect call. Insert instructions at the
413 beginning of every possible called function.
417 gimple_gen_ic_func_profiler (void)
419 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
421 tree tree_uid, cur_func, void0;
423 if (c_node->only_called_directly_p ())
426 gimple_init_gcov_profiler ();
428 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
429 basic_block cond_bb = split_edge (single_succ_edge (entry));
430 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
432 edge true_edge = single_succ_edge (cond_bb);
433 true_edge->flags = EDGE_TRUE_VALUE;
436 if (DECL_VIRTUAL_P (current_function_decl))
437 probability = PROB_VERY_LIKELY;
439 probability = PROB_UNLIKELY;
441 true_edge->probability = probability;
442 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
444 e->probability = REG_BR_PROB_BASE - true_edge->probability;
448 if (__gcov_indirect_call_callee != NULL)
449 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl);
451 The function __gcov_indirect_call_profiler_v2 is responsible for
452 resetting __gcov_indirect_call_callee to NULL. */
454 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
455 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
457 tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE,
458 true, GSI_SAME_STMT);
460 gcond *cond = gimple_build_cond (NE_EXPR, ref,
462 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
464 gsi = gsi_after_labels (update_bb);
466 cur_func = force_gimple_operand_gsi (&gsi,
467 build_addr (current_function_decl),
469 true, GSI_SAME_STMT);
470 tree_uid = build_int_cst
472 cgraph_node::get (current_function_decl)->profile_id);
473 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
475 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
478 /* Output instructions as GIMPLE tree at the beginning for each function.
479 TAG is the tag of the section for counters, BASE is offset of the
480 counter position and GSI is the iterator we place the counter. */
483 gimple_gen_time_profiler (unsigned tag, unsigned base)
485 tree type = get_gcov_type ();
486 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
487 basic_block cond_bb = split_edge (single_succ_edge (entry));
488 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
490 edge true_edge = single_succ_edge (cond_bb);
491 true_edge->flags = EDGE_TRUE_VALUE;
492 true_edge->probability = PROB_UNLIKELY;
494 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
495 e->probability = REG_BR_PROB_BASE - true_edge->probability;
497 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
498 tree original_ref = tree_coverage_counter_ref (tag, base);
499 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
500 true, GSI_SAME_STMT);
501 tree one = build_int_cst (type, 1);
503 /* Emit: if (counters[0] != 0). */
504 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
506 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
508 gsi = gsi_start_bb (update_bb);
510 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
511 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
513 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
514 "time_profiler_counter_ptr");
515 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
516 tree_time_profiler_counter);
517 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
518 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
519 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
520 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
521 BUILT_IN_ATOMIC_ADD_FETCH_4);
522 gcall *stmt = gimple_build_call (f, 3, ptr, one,
523 build_int_cst (integer_type_node,
525 tree result_type = TREE_TYPE (TREE_TYPE (f));
526 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
527 gimple_set_lhs (stmt, tmp);
528 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
529 tmp = make_temp_ssa_name (type, NULL, "time_profile");
530 assign = gimple_build_assign (tmp, NOP_EXPR,
531 gimple_call_lhs (stmt));
532 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
533 assign = gimple_build_assign (original_ref, tmp);
534 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
538 tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
539 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
540 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
542 tmp = make_temp_ssa_name (type, NULL, "time_profile");
543 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
545 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
546 assign = gimple_build_assign (original_ref, tmp);
547 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
548 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
549 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
553 /* Output instructions as GIMPLE trees to increment the average histogram
554 counter. VALUE is the expression whose value is profiled. TAG is the
555 tag of the section for counters, BASE is offset of the counter position. */
558 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
560 gimple *stmt = value->hvalue.stmt;
561 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
562 tree ref_ptr = tree_coverage_counter_addr (tag, base);
566 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
568 true, GSI_SAME_STMT);
569 val = prepare_instrumented_value (&gsi, value);
570 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
571 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
574 /* Output instructions as GIMPLE trees to increment the ior histogram
575 counter. VALUE is the expression whose value is profiled. TAG is the
576 tag of the section for counters, BASE is offset of the counter position. */
579 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
581 gimple *stmt = value->hvalue.stmt;
582 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
583 tree ref_ptr = tree_coverage_counter_addr (tag, base);
587 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
588 true, NULL_TREE, true, GSI_SAME_STMT);
589 val = prepare_instrumented_value (&gsi, value);
590 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
591 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
594 #ifndef HAVE_sync_compare_and_swapsi
595 #define HAVE_sync_compare_and_swapsi 0
597 #ifndef HAVE_atomic_compare_and_swapsi
598 #define HAVE_atomic_compare_and_swapsi 0
601 #ifndef HAVE_sync_compare_and_swapdi
602 #define HAVE_sync_compare_and_swapdi 0
604 #ifndef HAVE_atomic_compare_and_swapdi
605 #define HAVE_atomic_compare_and_swapdi 0
608 /* Profile all functions in the callgraph. */
611 tree_profiling (void)
613 struct cgraph_node *node;
615 /* Verify whether we can utilize atomic update operations. */
616 bool can_support_atomic = false;
617 unsigned HOST_WIDE_INT gcov_type_size
618 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
619 if (gcov_type_size == 4)
621 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
622 else if (gcov_type_size == 8)
624 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
626 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
627 && !can_support_atomic)
629 warning (0, "target does not support atomic profile update, "
630 "single mode is selected");
631 flag_profile_update = PROFILE_UPDATE_SINGLE;
633 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
634 flag_profile_update = can_support_atomic
635 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
637 /* This is a small-ipa pass that gets called only once, from
638 cgraphunit.c:ipa_passes(). */
639 gcc_assert (symtab->state == IPA_SSA);
641 init_node_map (true);
643 FOR_EACH_DEFINED_FUNCTION (node)
645 if (!gimple_has_body_p (node->decl))
648 /* Don't profile functions produced for builtin stuff. */
649 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
652 if (lookup_attribute ("no_profile_instrument_function",
653 DECL_ATTRIBUTES (node->decl)))
655 /* Do not instrument extern inline functions when testing coverage.
656 While this is not perfectly consistent (early inlined extern inlines
657 will get acocunted), testsuite expects that. */
658 if (DECL_EXTERNAL (node->decl)
659 && flag_test_coverage)
662 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
664 /* Local pure-const may imply need to fixup the cfg. */
665 if (execute_fixup_cfg () & TODO_cleanup_cfg)
670 if (! flag_branch_probabilities
671 && flag_profile_values)
672 gimple_gen_ic_func_profiler ();
674 if (flag_branch_probabilities
675 && flag_profile_values
676 && flag_value_profile_transformations)
677 gimple_value_profile_transformations ();
679 /* The above could hose dominator info. Currently there is
680 none coming in, this is a safety valve. It should be
681 easy to adjust it, if and when there is some. */
682 free_dominance_info (CDI_DOMINATORS);
683 free_dominance_info (CDI_POST_DOMINATORS);
687 /* Drop pure/const flags from instrumented functions. */
688 if (profile_arc_flag || flag_test_coverage)
689 FOR_EACH_DEFINED_FUNCTION (node)
691 if (!gimple_has_body_p (node->decl)
693 || node->decl != node->clone_of->decl))
696 /* Don't profile functions produced for builtin stuff. */
697 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
700 node->set_const_flag (false, false);
701 node->set_pure_flag (false, false);
704 /* Update call statements and rebuild the cgraph. */
705 FOR_EACH_DEFINED_FUNCTION (node)
709 if (!gimple_has_body_p (node->decl)
711 || node->decl != node->clone_of->decl))
714 /* Don't profile functions produced for builtin stuff. */
715 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
718 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
720 FOR_EACH_BB_FN (bb, cfun)
722 gimple_stmt_iterator gsi;
723 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
725 gimple *stmt = gsi_stmt (gsi);
726 if (is_gimple_call (stmt))
731 /* re-merge split blocks. */
733 update_ssa (TODO_update_ssa);
735 cgraph_edge::rebuild_edges ();
740 handle_missing_profiles ();
748 const pass_data pass_data_ipa_tree_profile =
750 SIMPLE_IPA_PASS, /* type */
751 "profile", /* name */
752 OPTGROUP_NONE, /* optinfo_flags */
753 TV_IPA_PROFILE, /* tv_id */
754 0, /* properties_required */
755 0, /* properties_provided */
756 0, /* properties_destroyed */
757 0, /* todo_flags_start */
758 TODO_dump_symtab, /* todo_flags_finish */
761 class pass_ipa_tree_profile : public simple_ipa_opt_pass
764 pass_ipa_tree_profile (gcc::context *ctxt)
765 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
768 /* opt_pass methods: */
769 virtual bool gate (function *);
770 virtual unsigned int execute (function *) { return tree_profiling (); }
772 }; // class pass_ipa_tree_profile
775 pass_ipa_tree_profile::gate (function *)
777 /* When profile instrumentation, use or test coverage shall be performed.
778 But for AutoFDO, this there is no instrumentation, thus this pass is
780 return (!in_lto_p && !flag_auto_profile
781 && (flag_branch_probabilities || flag_test_coverage
782 || profile_arc_flag));
787 simple_ipa_opt_pass *
788 make_pass_ipa_tree_profile (gcc::context *ctxt)
790 return new pass_ipa_tree_profile (ctxt);
793 #include "gt-tree-profile.h"