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"
56 #include "langhooks.h"
57 #include "stor-layout.h"
59 static GTY(()) tree gcov_type_node
;
60 static GTY(()) tree tree_interval_profiler_fn
;
61 static GTY(()) tree tree_pow2_profiler_fn
;
62 static GTY(()) tree tree_one_value_profiler_fn
;
63 static GTY(()) tree tree_indirect_call_profiler_fn
;
64 static GTY(()) tree tree_average_profiler_fn
;
65 static GTY(()) tree tree_ior_profiler_fn
;
66 static GTY(()) tree tree_time_profiler_counter
;
69 static GTY(()) tree ic_tuple_var
;
70 static GTY(()) tree ic_tuple_counters_field
;
71 static GTY(()) tree ic_tuple_callee_field
;
73 /* Do initialization work for the edge profiler. */
76 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
77 __thread void* __gcov_indirect_call_callee; // actual callee address
78 __thread int __gcov_function_counter; // time profiler function counter
81 init_ic_make_global_vars (void)
85 gcov_type_ptr
= build_pointer_type (get_gcov_type ());
87 tree tuple_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
90 ic_tuple_callee_field
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
, NULL_TREE
,
94 ic_tuple_counters_field
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
95 NULL_TREE
, gcov_type_ptr
);
96 DECL_CHAIN (ic_tuple_counters_field
) = ic_tuple_callee_field
;
98 finish_builtin_struct (tuple_type
, "indirect_call_tuple",
99 ic_tuple_counters_field
, NULL_TREE
);
102 = build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
104 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
) ?
105 "__gcov_indirect_call_topn" :
106 "__gcov_indirect_call")),
108 TREE_PUBLIC (ic_tuple_var
) = 1;
109 DECL_ARTIFICIAL (ic_tuple_var
) = 1;
110 DECL_INITIAL (ic_tuple_var
) = NULL
;
111 DECL_EXTERNAL (ic_tuple_var
) = 1;
112 if (targetm
.have_tls
)
113 set_decl_tls_model (ic_tuple_var
, decl_default_tls_model (tuple_type
));
116 /* Create the type and function decls for the interface with gcov. */
119 gimple_init_gcov_profiler (void)
121 tree interval_profiler_fn_type
;
122 tree pow2_profiler_fn_type
;
123 tree one_value_profiler_fn_type
;
125 tree ic_profiler_fn_type
;
126 tree average_profiler_fn_type
;
127 const char *profiler_fn_name
;
132 const char *fn_suffix
133 = flag_profile_update
== PROFILE_UPDATE_ATOMIC
? "_atomic" : "";
135 gcov_type_node
= get_gcov_type ();
136 gcov_type_ptr
= build_pointer_type (gcov_type_node
);
138 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
139 interval_profiler_fn_type
140 = build_function_type_list (void_type_node
,
141 gcov_type_ptr
, gcov_type_node
,
143 unsigned_type_node
, NULL_TREE
);
144 fn_name
= concat ("__gcov_interval_profiler", fn_suffix
, NULL
);
145 tree_interval_profiler_fn
= build_fn_decl (fn_name
,
146 interval_profiler_fn_type
);
147 free (CONST_CAST (char *, fn_name
));
148 TREE_NOTHROW (tree_interval_profiler_fn
) = 1;
149 DECL_ATTRIBUTES (tree_interval_profiler_fn
)
150 = tree_cons (get_identifier ("leaf"), NULL
,
151 DECL_ATTRIBUTES (tree_interval_profiler_fn
));
153 /* void (*) (gcov_type *, gcov_type) */
154 pow2_profiler_fn_type
155 = build_function_type_list (void_type_node
,
156 gcov_type_ptr
, gcov_type_node
,
158 fn_name
= concat ("__gcov_pow2_profiler", fn_suffix
, NULL
);
159 tree_pow2_profiler_fn
= build_fn_decl (fn_name
, pow2_profiler_fn_type
);
160 free (CONST_CAST (char *, fn_name
));
161 TREE_NOTHROW (tree_pow2_profiler_fn
) = 1;
162 DECL_ATTRIBUTES (tree_pow2_profiler_fn
)
163 = tree_cons (get_identifier ("leaf"), NULL
,
164 DECL_ATTRIBUTES (tree_pow2_profiler_fn
));
166 /* void (*) (gcov_type *, gcov_type) */
167 one_value_profiler_fn_type
168 = build_function_type_list (void_type_node
,
169 gcov_type_ptr
, gcov_type_node
,
171 fn_name
= concat ("__gcov_one_value_profiler", fn_suffix
, NULL
);
172 tree_one_value_profiler_fn
= build_fn_decl (fn_name
,
173 one_value_profiler_fn_type
);
174 free (CONST_CAST (char *, fn_name
));
175 TREE_NOTHROW (tree_one_value_profiler_fn
) = 1;
176 DECL_ATTRIBUTES (tree_one_value_profiler_fn
)
177 = tree_cons (get_identifier ("leaf"), NULL
,
178 DECL_ATTRIBUTES (tree_one_value_profiler_fn
));
180 init_ic_make_global_vars ();
182 /* void (*) (gcov_type, void *) */
184 = build_function_type_list (void_type_node
,
188 profiler_fn_name
= "__gcov_indirect_call_profiler_v2";
189 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
))
190 profiler_fn_name
= "__gcov_indirect_call_topn_profiler";
192 tree_indirect_call_profiler_fn
193 = build_fn_decl (profiler_fn_name
, ic_profiler_fn_type
);
195 TREE_NOTHROW (tree_indirect_call_profiler_fn
) = 1;
196 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn
)
197 = tree_cons (get_identifier ("leaf"), NULL
,
198 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn
));
200 tree_time_profiler_counter
201 = build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
202 get_identifier ("__gcov_time_profiler_counter"),
204 TREE_PUBLIC (tree_time_profiler_counter
) = 1;
205 DECL_EXTERNAL (tree_time_profiler_counter
) = 1;
206 TREE_STATIC (tree_time_profiler_counter
) = 1;
207 DECL_ARTIFICIAL (tree_time_profiler_counter
) = 1;
208 DECL_INITIAL (tree_time_profiler_counter
) = NULL
;
210 /* void (*) (gcov_type *, gcov_type) */
211 average_profiler_fn_type
212 = build_function_type_list (void_type_node
,
213 gcov_type_ptr
, gcov_type_node
, NULL_TREE
);
214 fn_name
= concat ("__gcov_average_profiler", fn_suffix
, NULL
);
215 tree_average_profiler_fn
= build_fn_decl (fn_name
,
216 average_profiler_fn_type
);
217 free (CONST_CAST (char *, fn_name
));
218 TREE_NOTHROW (tree_average_profiler_fn
) = 1;
219 DECL_ATTRIBUTES (tree_average_profiler_fn
)
220 = tree_cons (get_identifier ("leaf"), NULL
,
221 DECL_ATTRIBUTES (tree_average_profiler_fn
));
222 fn_name
= concat ("__gcov_ior_profiler", fn_suffix
, NULL
);
223 tree_ior_profiler_fn
= build_fn_decl (fn_name
, average_profiler_fn_type
);
224 free (CONST_CAST (char *, fn_name
));
225 TREE_NOTHROW (tree_ior_profiler_fn
) = 1;
226 DECL_ATTRIBUTES (tree_ior_profiler_fn
)
227 = tree_cons (get_identifier ("leaf"), NULL
,
228 DECL_ATTRIBUTES (tree_ior_profiler_fn
));
230 /* LTO streamer needs assembler names. Because we create these decls
231 late, we need to initialize them by hand. */
232 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn
);
233 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn
);
234 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn
);
235 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn
);
236 DECL_ASSEMBLER_NAME (tree_average_profiler_fn
);
237 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn
);
241 /* Output instructions as GIMPLE trees to increment the edge
242 execution count, and insert them on E. We rely on
243 gsi_insert_on_edge to preserve the order. */
246 gimple_gen_edge_profiler (int edgeno
, edge e
)
250 one
= build_int_cst (gcov_type_node
, 1);
252 if (flag_profile_update
== PROFILE_UPDATE_ATOMIC
)
254 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
255 tree addr
= tree_coverage_counter_addr (GCOV_COUNTER_ARCS
, edgeno
);
256 tree f
= builtin_decl_explicit (LONG_LONG_TYPE_SIZE
> 32
257 ? BUILT_IN_ATOMIC_FETCH_ADD_8
:
258 BUILT_IN_ATOMIC_FETCH_ADD_4
);
259 gcall
*stmt
= gimple_build_call (f
, 3, addr
, one
,
260 build_int_cst (integer_type_node
,
262 gsi_insert_on_edge (e
, stmt
);
266 tree ref
= tree_coverage_counter_ref (GCOV_COUNTER_ARCS
, edgeno
);
267 tree gcov_type_tmp_var
= make_temp_ssa_name (gcov_type_node
,
268 NULL
, "PROF_edge_counter");
269 gassign
*stmt1
= gimple_build_assign (gcov_type_tmp_var
, ref
);
270 gcov_type_tmp_var
= make_temp_ssa_name (gcov_type_node
,
271 NULL
, "PROF_edge_counter");
272 gassign
*stmt2
= gimple_build_assign (gcov_type_tmp_var
, PLUS_EXPR
,
273 gimple_assign_lhs (stmt1
), one
);
274 gassign
*stmt3
= gimple_build_assign (unshare_expr (ref
),
275 gimple_assign_lhs (stmt2
));
276 gsi_insert_on_edge (e
, stmt1
);
277 gsi_insert_on_edge (e
, stmt2
);
278 gsi_insert_on_edge (e
, stmt3
);
282 /* Emits code to get VALUE to instrument at GSI, and returns the
283 variable containing the value. */
286 prepare_instrumented_value (gimple_stmt_iterator
*gsi
, histogram_value value
)
288 tree val
= value
->hvalue
.value
;
289 if (POINTER_TYPE_P (TREE_TYPE (val
)))
290 val
= fold_convert (build_nonstandard_integer_type
291 (TYPE_PRECISION (TREE_TYPE (val
)), 1), val
);
292 return force_gimple_operand_gsi (gsi
, fold_convert (gcov_type_node
, val
),
293 true, NULL_TREE
, true, GSI_SAME_STMT
);
296 /* Output instructions as GIMPLE trees to increment the interval histogram
297 counter. VALUE is the expression whose value is profiled. TAG is the
298 tag of the section for counters, BASE is offset of the counter position. */
301 gimple_gen_interval_profiler (histogram_value value
, unsigned tag
, unsigned base
)
303 gimple
*stmt
= value
->hvalue
.stmt
;
304 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
305 tree ref
= tree_coverage_counter_ref (tag
, base
), ref_ptr
;
308 tree start
= build_int_cst_type (integer_type_node
,
309 value
->hdata
.intvl
.int_start
);
310 tree steps
= build_int_cst_type (unsigned_type_node
,
311 value
->hdata
.intvl
.steps
);
313 ref_ptr
= force_gimple_operand_gsi (&gsi
,
315 true, NULL_TREE
, true, GSI_SAME_STMT
);
316 val
= prepare_instrumented_value (&gsi
, value
);
317 call
= gimple_build_call (tree_interval_profiler_fn
, 4,
318 ref_ptr
, val
, start
, steps
);
319 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
322 /* Output instructions as GIMPLE trees to increment the power of two histogram
323 counter. VALUE is the expression whose value is profiled. TAG is the tag
324 of the section for counters, BASE is offset of the counter position. */
327 gimple_gen_pow2_profiler (histogram_value value
, unsigned tag
, unsigned base
)
329 gimple
*stmt
= value
->hvalue
.stmt
;
330 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
331 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
335 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
336 true, NULL_TREE
, true, GSI_SAME_STMT
);
337 val
= prepare_instrumented_value (&gsi
, value
);
338 call
= gimple_build_call (tree_pow2_profiler_fn
, 2, ref_ptr
, val
);
339 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
342 /* Output instructions as GIMPLE trees for code to find the most common value.
343 VALUE is the expression whose value is profiled. TAG is the tag of the
344 section for counters, BASE is offset of the counter position. */
347 gimple_gen_one_value_profiler (histogram_value value
, unsigned tag
, unsigned base
)
349 gimple
*stmt
= value
->hvalue
.stmt
;
350 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
351 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
355 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
356 true, NULL_TREE
, true, GSI_SAME_STMT
);
357 val
= prepare_instrumented_value (&gsi
, value
);
358 call
= gimple_build_call (tree_one_value_profiler_fn
, 2, ref_ptr
, val
);
359 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
363 /* Output instructions as GIMPLE trees for code to find the most
364 common called function in indirect call.
365 VALUE is the call expression whose indirect callee is profiled.
366 TAG is the tag of the section for counters, BASE is offset of the
370 gimple_gen_ic_profiler (histogram_value value
, unsigned tag
, unsigned base
)
373 gassign
*stmt1
, *stmt2
, *stmt3
;
374 gimple
*stmt
= value
->hvalue
.stmt
;
375 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
376 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
378 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
) &&
379 tag
== GCOV_COUNTER_V_INDIR
) ||
380 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE
) &&
381 tag
== GCOV_COUNTER_ICALL_TOPNV
))
384 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
385 true, NULL_TREE
, true, GSI_SAME_STMT
);
389 stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
390 stmt2: tmp1 = (void *) (indirect call argument value)
391 stmt3: __gcov_indirect_call.callee = tmp1;
395 __gcov_indirect_call.counters = &__gcov4.main[0];
397 __gcov_indirect_call_callee = PROF_9;
401 tree gcov_type_ptr
= build_pointer_type (get_gcov_type ());
403 tree counter_ref
= build3 (COMPONENT_REF
, gcov_type_ptr
,
404 ic_tuple_var
, ic_tuple_counters_field
, NULL_TREE
);
406 stmt1
= gimple_build_assign (counter_ref
, ref_ptr
);
407 tmp1
= make_temp_ssa_name (ptr_type_node
, NULL
, "PROF");
408 stmt2
= gimple_build_assign (tmp1
, unshare_expr (value
->hvalue
.value
));
409 tree callee_ref
= build3 (COMPONENT_REF
, ptr_type_node
,
410 ic_tuple_var
, ic_tuple_callee_field
, NULL_TREE
);
411 stmt3
= gimple_build_assign (callee_ref
, tmp1
);
413 gsi_insert_before (&gsi
, stmt1
, GSI_SAME_STMT
);
414 gsi_insert_before (&gsi
, stmt2
, GSI_SAME_STMT
);
415 gsi_insert_before (&gsi
, stmt3
, GSI_SAME_STMT
);
419 /* Output instructions as GIMPLE trees for code to find the most
420 common called function in indirect call. Insert instructions at the
421 beginning of every possible called function.
425 gimple_gen_ic_func_profiler (void)
427 struct cgraph_node
* c_node
= cgraph_node::get (current_function_decl
);
429 tree tree_uid
, cur_func
, void0
;
431 if (c_node
->only_called_directly_p ())
434 gimple_init_gcov_profiler ();
436 basic_block entry
= ENTRY_BLOCK_PTR_FOR_FN (cfun
);
437 basic_block cond_bb
= split_edge (single_succ_edge (entry
));
438 basic_block update_bb
= split_edge (single_succ_edge (cond_bb
));
440 /* We need to do an extra split in order to not create an input
441 for a possible PHI node. */
442 split_edge (single_succ_edge (update_bb
));
444 edge true_edge
= single_succ_edge (cond_bb
);
445 true_edge
->flags
= EDGE_TRUE_VALUE
;
447 profile_probability probability
;
448 if (DECL_VIRTUAL_P (current_function_decl
))
449 probability
= profile_probability::very_likely ();
451 probability
= profile_probability::unlikely ();
453 true_edge
->probability
= probability
;
454 edge e
= make_edge (cond_bb
, single_succ_edge (update_bb
)->dest
,
456 e
->probability
= true_edge
->probability
.invert ();
460 if (__gcov_indirect_call_callee != NULL)
461 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl);
463 The function __gcov_indirect_call_profiler_v2 is responsible for
464 resetting __gcov_indirect_call_callee to NULL. */
466 gimple_stmt_iterator gsi
= gsi_start_bb (cond_bb
);
467 void0
= build_int_cst (ptr_type_node
, 0);
469 tree callee_ref
= build3 (COMPONENT_REF
, ptr_type_node
,
470 ic_tuple_var
, ic_tuple_callee_field
, NULL_TREE
);
472 tree ref
= force_gimple_operand_gsi (&gsi
, callee_ref
, true, NULL_TREE
,
473 true, GSI_SAME_STMT
);
475 gcond
*cond
= gimple_build_cond (NE_EXPR
, ref
,
477 gsi_insert_before (&gsi
, cond
, GSI_NEW_STMT
);
479 gsi
= gsi_after_labels (update_bb
);
481 cur_func
= force_gimple_operand_gsi (&gsi
,
482 build_addr (current_function_decl
),
484 true, GSI_SAME_STMT
);
485 tree_uid
= build_int_cst
487 cgraph_node::get (current_function_decl
)->profile_id
);
488 stmt1
= gimple_build_call (tree_indirect_call_profiler_fn
, 2,
490 gsi_insert_before (&gsi
, stmt1
, GSI_SAME_STMT
);
493 /* Output instructions as GIMPLE tree at the beginning for each function.
494 TAG is the tag of the section for counters, BASE is offset of the
495 counter position and GSI is the iterator we place the counter. */
498 gimple_gen_time_profiler (unsigned tag
, unsigned base
)
500 tree type
= get_gcov_type ();
501 basic_block entry
= ENTRY_BLOCK_PTR_FOR_FN (cfun
);
502 basic_block cond_bb
= split_edge (single_succ_edge (entry
));
503 basic_block update_bb
= split_edge (single_succ_edge (cond_bb
));
505 /* We need to do an extra split in order to not create an input
506 for a possible PHI node. */
507 split_edge (single_succ_edge (update_bb
));
509 edge true_edge
= single_succ_edge (cond_bb
);
510 true_edge
->flags
= EDGE_TRUE_VALUE
;
511 true_edge
->probability
= profile_probability::unlikely ();
513 = make_edge (cond_bb
, single_succ_edge (update_bb
)->dest
, EDGE_FALSE_VALUE
);
514 e
->probability
= true_edge
->probability
.invert ();
516 gimple_stmt_iterator gsi
= gsi_start_bb (cond_bb
);
517 tree original_ref
= tree_coverage_counter_ref (tag
, base
);
518 tree ref
= force_gimple_operand_gsi (&gsi
, original_ref
, true, NULL_TREE
,
519 true, GSI_SAME_STMT
);
520 tree one
= build_int_cst (type
, 1);
522 /* Emit: if (counters[0] != 0). */
523 gcond
*cond
= gimple_build_cond (EQ_EXPR
, ref
, build_int_cst (type
, 0),
525 gsi_insert_before (&gsi
, cond
, GSI_NEW_STMT
);
527 gsi
= gsi_start_bb (update_bb
);
529 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
530 if (flag_profile_update
== PROFILE_UPDATE_ATOMIC
)
532 tree ptr
= make_temp_ssa_name (build_pointer_type (type
), NULL
,
533 "time_profiler_counter_ptr");
534 tree addr
= build1 (ADDR_EXPR
, TREE_TYPE (ptr
),
535 tree_time_profiler_counter
);
536 gassign
*assign
= gimple_build_assign (ptr
, NOP_EXPR
, addr
);
537 gsi_insert_before (&gsi
, assign
, GSI_NEW_STMT
);
538 tree f
= builtin_decl_explicit (LONG_LONG_TYPE_SIZE
> 32
539 ? BUILT_IN_ATOMIC_ADD_FETCH_8
:
540 BUILT_IN_ATOMIC_ADD_FETCH_4
);
541 gcall
*stmt
= gimple_build_call (f
, 3, ptr
, one
,
542 build_int_cst (integer_type_node
,
544 tree result_type
= TREE_TYPE (TREE_TYPE (f
));
545 tree tmp
= make_temp_ssa_name (result_type
, NULL
, "time_profile");
546 gimple_set_lhs (stmt
, tmp
);
547 gsi_insert_after (&gsi
, stmt
, GSI_NEW_STMT
);
548 tmp
= make_temp_ssa_name (type
, NULL
, "time_profile");
549 assign
= gimple_build_assign (tmp
, NOP_EXPR
,
550 gimple_call_lhs (stmt
));
551 gsi_insert_after (&gsi
, assign
, GSI_NEW_STMT
);
552 assign
= gimple_build_assign (original_ref
, tmp
);
553 gsi_insert_after (&gsi
, assign
, GSI_NEW_STMT
);
557 tree tmp
= make_temp_ssa_name (type
, NULL
, "time_profile");
558 gassign
*assign
= gimple_build_assign (tmp
, tree_time_profiler_counter
);
559 gsi_insert_before (&gsi
, assign
, GSI_NEW_STMT
);
561 tmp
= make_temp_ssa_name (type
, NULL
, "time_profile");
562 assign
= gimple_build_assign (tmp
, PLUS_EXPR
, gimple_assign_lhs (assign
),
564 gsi_insert_after (&gsi
, assign
, GSI_NEW_STMT
);
565 assign
= gimple_build_assign (original_ref
, tmp
);
566 gsi_insert_after (&gsi
, assign
, GSI_NEW_STMT
);
567 assign
= gimple_build_assign (tree_time_profiler_counter
, tmp
);
568 gsi_insert_after (&gsi
, assign
, GSI_NEW_STMT
);
572 /* Output instructions as GIMPLE trees to increment the average histogram
573 counter. VALUE is the expression whose value is profiled. TAG is the
574 tag of the section for counters, BASE is offset of the counter position. */
577 gimple_gen_average_profiler (histogram_value value
, unsigned tag
, unsigned base
)
579 gimple
*stmt
= value
->hvalue
.stmt
;
580 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
581 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
585 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
587 true, GSI_SAME_STMT
);
588 val
= prepare_instrumented_value (&gsi
, value
);
589 call
= gimple_build_call (tree_average_profiler_fn
, 2, ref_ptr
, val
);
590 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
593 /* Output instructions as GIMPLE trees to increment the ior histogram
594 counter. VALUE is the expression whose value is profiled. TAG is the
595 tag of the section for counters, BASE is offset of the counter position. */
598 gimple_gen_ior_profiler (histogram_value value
, unsigned tag
, unsigned base
)
600 gimple
*stmt
= value
->hvalue
.stmt
;
601 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
602 tree ref_ptr
= tree_coverage_counter_addr (tag
, base
);
606 ref_ptr
= force_gimple_operand_gsi (&gsi
, ref_ptr
,
607 true, NULL_TREE
, true, GSI_SAME_STMT
);
608 val
= prepare_instrumented_value (&gsi
, value
);
609 call
= gimple_build_call (tree_ior_profiler_fn
, 2, ref_ptr
, val
);
610 gsi_insert_before (&gsi
, call
, GSI_NEW_STMT
);
613 #ifndef HAVE_sync_compare_and_swapsi
614 #define HAVE_sync_compare_and_swapsi 0
616 #ifndef HAVE_atomic_compare_and_swapsi
617 #define HAVE_atomic_compare_and_swapsi 0
620 #ifndef HAVE_sync_compare_and_swapdi
621 #define HAVE_sync_compare_and_swapdi 0
623 #ifndef HAVE_atomic_compare_and_swapdi
624 #define HAVE_atomic_compare_and_swapdi 0
627 /* Profile all functions in the callgraph. */
630 tree_profiling (void)
632 struct cgraph_node
*node
;
634 /* Verify whether we can utilize atomic update operations. */
635 bool can_support_atomic
= false;
636 unsigned HOST_WIDE_INT gcov_type_size
637 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
638 if (gcov_type_size
== 4)
640 = HAVE_sync_compare_and_swapsi
|| HAVE_atomic_compare_and_swapsi
;
641 else if (gcov_type_size
== 8)
643 = HAVE_sync_compare_and_swapdi
|| HAVE_atomic_compare_and_swapdi
;
645 if (flag_profile_update
== PROFILE_UPDATE_ATOMIC
646 && !can_support_atomic
)
648 warning (0, "target does not support atomic profile update, "
649 "single mode is selected");
650 flag_profile_update
= PROFILE_UPDATE_SINGLE
;
652 else if (flag_profile_update
== PROFILE_UPDATE_PREFER_ATOMIC
)
653 flag_profile_update
= can_support_atomic
654 ? PROFILE_UPDATE_ATOMIC
: PROFILE_UPDATE_SINGLE
;
656 /* This is a small-ipa pass that gets called only once, from
657 cgraphunit.c:ipa_passes(). */
658 gcc_assert (symtab
->state
== IPA_SSA
);
660 init_node_map (true);
662 FOR_EACH_DEFINED_FUNCTION (node
)
664 if (!gimple_has_body_p (node
->decl
))
667 /* Don't profile functions produced for builtin stuff. */
668 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
671 if (lookup_attribute ("no_profile_instrument_function",
672 DECL_ATTRIBUTES (node
->decl
)))
674 /* Do not instrument extern inline functions when testing coverage.
675 While this is not perfectly consistent (early inlined extern inlines
676 will get acocunted), testsuite expects that. */
677 if (DECL_EXTERNAL (node
->decl
)
678 && flag_test_coverage
)
681 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
684 dump_function_header (dump_file
, cfun
->decl
, dump_flags
);
686 /* Local pure-const may imply need to fixup the cfg. */
687 if (execute_fixup_cfg () & TODO_cleanup_cfg
)
692 if (! flag_branch_probabilities
693 && flag_profile_values
)
694 gimple_gen_ic_func_profiler ();
696 if (flag_branch_probabilities
697 && flag_profile_values
698 && flag_value_profile_transformations
)
699 gimple_value_profile_transformations ();
701 /* The above could hose dominator info. Currently there is
702 none coming in, this is a safety valve. It should be
703 easy to adjust it, if and when there is some. */
704 free_dominance_info (CDI_DOMINATORS
);
705 free_dominance_info (CDI_POST_DOMINATORS
);
709 /* Drop pure/const flags from instrumented functions. */
710 if (profile_arc_flag
|| flag_test_coverage
)
711 FOR_EACH_DEFINED_FUNCTION (node
)
713 if (!gimple_has_body_p (node
->decl
)
715 || node
->decl
!= node
->clone_of
->decl
))
718 /* Don't profile functions produced for builtin stuff. */
719 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
722 node
->set_const_flag (false, false);
723 node
->set_pure_flag (false, false);
726 /* Update call statements and rebuild the cgraph. */
727 FOR_EACH_DEFINED_FUNCTION (node
)
731 if (!gimple_has_body_p (node
->decl
)
733 || node
->decl
!= node
->clone_of
->decl
))
736 /* Don't profile functions produced for builtin stuff. */
737 if (DECL_SOURCE_LOCATION (node
->decl
) == BUILTINS_LOCATION
)
740 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
742 FOR_EACH_BB_FN (bb
, cfun
)
744 gimple_stmt_iterator gsi
;
745 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
747 gimple
*stmt
= gsi_stmt (gsi
);
748 if (is_gimple_call (stmt
))
753 /* re-merge split blocks. */
755 update_ssa (TODO_update_ssa
);
757 cgraph_edge::rebuild_edges ();
762 handle_missing_profiles ();
770 const pass_data pass_data_ipa_tree_profile
=
772 SIMPLE_IPA_PASS
, /* type */
773 "profile", /* name */
774 OPTGROUP_NONE
, /* optinfo_flags */
775 TV_IPA_PROFILE
, /* tv_id */
776 0, /* properties_required */
777 0, /* properties_provided */
778 0, /* properties_destroyed */
779 0, /* todo_flags_start */
780 TODO_dump_symtab
, /* todo_flags_finish */
783 class pass_ipa_tree_profile
: public simple_ipa_opt_pass
786 pass_ipa_tree_profile (gcc::context
*ctxt
)
787 : simple_ipa_opt_pass (pass_data_ipa_tree_profile
, ctxt
)
790 /* opt_pass methods: */
791 virtual bool gate (function
*);
792 virtual unsigned int execute (function
*) { return tree_profiling (); }
794 }; // class pass_ipa_tree_profile
797 pass_ipa_tree_profile::gate (function
*)
799 /* When profile instrumentation, use or test coverage shall be performed.
800 But for AutoFDO, this there is no instrumentation, thus this pass is
802 return (!in_lto_p
&& !flag_auto_profile
803 && (flag_branch_probabilities
|| flag_test_coverage
804 || profile_arc_flag
));
809 simple_ipa_opt_pass
*
810 make_pass_ipa_tree_profile (gcc::context
*ctxt
)
812 return new pass_ipa_tree_profile (ctxt
);
815 #include "gt-tree-profile.h"