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
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"
53 #include "stringpool.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. */
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
79 init_ic_make_global_vars (void)
83 ptr_void
= build_pointer_type (void_type_node
);
86 = build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
88 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
) ?
89 "__gcov_indirect_call_topn_callee" :
90 "__gcov_indirect_call_callee")),
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
;
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 ());
103 = build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
105 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
) ?
106 "__gcov_indirect_call_topn_counters" :
107 "__gcov_indirect_call_counters")),
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. */
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
;
127 tree ic_profiler_fn_type
;
128 tree average_profiler_fn_type
;
129 const char *profiler_fn_name
;
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
,
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
,
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
,
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 *) */
186 = build_function_type_list (void_type_node
,
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"),
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. */
248 gimple_gen_edge_profiler (int edgeno
, edge e
)
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
,
264 gsi_insert_on_edge (e
, stmt
);
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. */
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. */
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
;
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
,
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. */
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
);
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. */
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
);
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
372 gimple_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
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
))
386 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
387 true, NULL_TREE
, true, GSI_SAME_STMT
);
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;
397 __gcov_indirect_call_counters = &__gcov4.main[0];
399 __gcov_indirect_call_callee = PROF_9;
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.
420 gimple_gen_ic_func_profiler (void)
422 struct cgraph_node
* c_node
= cgraph_node::get (current_function_decl
);
424 tree tree_uid
, cur_func
, void0
;
426 if (c_node
->only_called_directly_p ())
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 ();
446 probability
= profile_probability::unlikely ();
448 true_edge
->probability
= probability
;
449 edge e
= make_edge (cond_bb
, single_succ_edge (update_bb
)->dest
,
451 e
->probability
= true_edge
->probability
.invert ();
455 if (__gcov_indirect_call_callee != NULL)
456 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_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
,
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
),
476 true, GSI_SAME_STMT
);
477 tree_uid
= build_int_cst
479 cgraph_node::get (current_function_decl
)->profile_id
);
480 stmt1
= gimple_build_call (tree_indirect_call_profiler_fn
, 2,
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. */
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 ();
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),
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
,
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
);
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
),
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. */
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
);
577 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
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. */
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
);
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
608 #ifndef HAVE_atomic_compare_and_swapsi
609 #define HAVE_atomic_compare_and_swapsi 0
612 #ifndef HAVE_sync_compare_and_swapdi
613 #define HAVE_sync_compare_and_swapdi 0
615 #ifndef HAVE_atomic_compare_and_swapdi
616 #define HAVE_atomic_compare_and_swapdi 0
619 /* Profile all functions in the callgraph. */
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)
632 = HAVE_sync_compare_and_swapsi
|| HAVE_atomic_compare_and_swapsi
;
633 else if (gcov_type_size
== 8)
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
))
659 /* Don't profile functions produced for builtin stuff. */
660 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
663 if (lookup_attribute ("no_profile_instrument_function",
664 DECL_ATTRIBUTES (node
->decl
)))
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
)
673 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
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
)
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
);
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
)
707 || node
->decl
!= node
->clone_of
->decl
))
710 /* Don't profile functions produced for builtin stuff. */
711 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
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
)
723 if (!gimple_has_body_p (node
->decl
)
725 || node
->decl
!= node
->clone_of
->decl
))
728 /* Don't profile functions produced for builtin stuff. */
729 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
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
))
745 /* re-merge split blocks. */
747 update_ssa (TODO_update_ssa
);
749 cgraph_edge::rebuild_edges ();
754 handle_missing_profiles ();
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
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
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
794 return (!in_lto_p
&& !flag_auto_profile
795 && (flag_branch_probabilities
|| flag_test_coverage
796 || profile_arc_flag
));
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"