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.
7
8 This file is part of GCC.
9
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.
14
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.
19
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/>. */
23
24 /* Generate basic block profile instrumentation and auxiliary files.
25 Tree-based version. See profile.c for overview. */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "memmodel.h"
31 #include "backend.h"
32 #include "target.h"
33 #include "tree.h"
34 #include "gimple.h"
35 #include "cfghooks.h"
36 #include "tree-pass.h"
37 #include "ssa.h"
38 #include "cgraph.h"
39 #include "coverage.h"
40 #include "diagnostic-core.h"
41 #include "fold-const.h"
42 #include "varasm.h"
43 #include "tree-nested.h"
44 #include "gimplify.h"
45 #include "gimple-iterator.h"
46 #include "gimplify-me.h"
47 #include "tree-cfg.h"
48 #include "tree-into-ssa.h"
49 #include "value-prof.h"
50 #include "profile.h"
51 #include "tree-cfgcleanup.h"
52 #include "params.h"
53 #include "stringpool.h"
54 #include "attribs.h"
55 #include "tree-pretty-print.h"
56
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;
65
66
67 static GTY(()) tree ic_void_ptr_var;
68 static GTY(()) tree ic_gcov_type_ptr_var;
69 static GTY(()) tree ptr_void;
70
71 /* Do initialization work for the edge profiler. */
72
73 /* Add code:
74 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
75 __thread void* __gcov_indirect_call_callee; // actual callee address
76 __thread int __gcov_function_counter; // time profiler function counter
77 */
78 static void
init_ic_make_global_vars(void)79 init_ic_make_global_vars (void)
80 {
81 tree gcov_type_ptr;
82
83 ptr_void = build_pointer_type (void_type_node);
84
85 ic_void_ptr_var
86 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
87 get_identifier (
88 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
89 "__gcov_indirect_call_topn_callee" :
90 "__gcov_indirect_call_callee")),
91 ptr_void);
92 TREE_PUBLIC (ic_void_ptr_var) = 1;
93 DECL_EXTERNAL (ic_void_ptr_var) = 1;
94 TREE_STATIC (ic_void_ptr_var) = 1;
95 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
96 DECL_INITIAL (ic_void_ptr_var) = NULL;
97 if (targetm.have_tls)
98 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
99
100 gcov_type_ptr = build_pointer_type (get_gcov_type ());
101
102 ic_gcov_type_ptr_var
103 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
104 get_identifier (
105 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
106 "__gcov_indirect_call_topn_counters" :
107 "__gcov_indirect_call_counters")),
108 gcov_type_ptr);
109 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
110 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
111 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
112 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
113 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
114 if (targetm.have_tls)
115 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
116 }
117
118 /* Create the type and function decls for the interface with gcov. */
119
120 void
gimple_init_gcov_profiler(void)121 gimple_init_gcov_profiler (void)
122 {
123 tree interval_profiler_fn_type;
124 tree pow2_profiler_fn_type;
125 tree one_value_profiler_fn_type;
126 tree gcov_type_ptr;
127 tree ic_profiler_fn_type;
128 tree average_profiler_fn_type;
129 const char *profiler_fn_name;
130 const char *fn_name;
131
132 if (!gcov_type_node)
133 {
134 const char *fn_suffix
135 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
136
137 gcov_type_node = get_gcov_type ();
138 gcov_type_ptr = build_pointer_type (gcov_type_node);
139
140 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
141 interval_profiler_fn_type
142 = build_function_type_list (void_type_node,
143 gcov_type_ptr, gcov_type_node,
144 integer_type_node,
145 unsigned_type_node, NULL_TREE);
146 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
147 tree_interval_profiler_fn = build_fn_decl (fn_name,
148 interval_profiler_fn_type);
149 free (CONST_CAST (char *, fn_name));
150 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
151 DECL_ATTRIBUTES (tree_interval_profiler_fn)
152 = tree_cons (get_identifier ("leaf"), NULL,
153 DECL_ATTRIBUTES (tree_interval_profiler_fn));
154
155 /* void (*) (gcov_type *, gcov_type) */
156 pow2_profiler_fn_type
157 = build_function_type_list (void_type_node,
158 gcov_type_ptr, gcov_type_node,
159 NULL_TREE);
160 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
161 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
162 free (CONST_CAST (char *, fn_name));
163 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
164 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
165 = tree_cons (get_identifier ("leaf"), NULL,
166 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
167
168 /* void (*) (gcov_type *, gcov_type) */
169 one_value_profiler_fn_type
170 = build_function_type_list (void_type_node,
171 gcov_type_ptr, gcov_type_node,
172 NULL_TREE);
173 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
174 tree_one_value_profiler_fn = build_fn_decl (fn_name,
175 one_value_profiler_fn_type);
176 free (CONST_CAST (char *, fn_name));
177 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
178 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
179 = tree_cons (get_identifier ("leaf"), NULL,
180 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
181
182 init_ic_make_global_vars ();
183
184 /* void (*) (gcov_type, void *) */
185 ic_profiler_fn_type
186 = build_function_type_list (void_type_node,
187 gcov_type_node,
188 ptr_void,
189 NULL_TREE);
190 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
191 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
192 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
193
194 tree_indirect_call_profiler_fn
195 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
196
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));
201
202 tree_time_profiler_counter
203 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
204 get_identifier ("__gcov_time_profiler_counter"),
205 get_gcov_type ());
206 TREE_PUBLIC (tree_time_profiler_counter) = 1;
207 DECL_EXTERNAL (tree_time_profiler_counter) = 1;
208 TREE_STATIC (tree_time_profiler_counter) = 1;
209 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
210 DECL_INITIAL (tree_time_profiler_counter) = NULL;
211
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));
231
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);
240 }
241 }
242
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. */
246
247 void
gimple_gen_edge_profiler(int edgeno,edge e)248 gimple_gen_edge_profiler (int edgeno, edge e)
249 {
250 tree one;
251
252 one = build_int_cst (gcov_type_node, 1);
253
254 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
255 {
256 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
257 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
258 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
259 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
260 BUILT_IN_ATOMIC_FETCH_ADD_4);
261 gcall *stmt = gimple_build_call (f, 3, addr, one,
262 build_int_cst (integer_type_node,
263 MEMMODEL_RELAXED));
264 gsi_insert_on_edge (e, stmt);
265 }
266 else
267 {
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);
281 }
282 }
283
284 /* Emits code to get VALUE to instrument at GSI, and returns the
285 variable containing the value. */
286
287 static tree
prepare_instrumented_value(gimple_stmt_iterator * gsi,histogram_value value)288 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
289 {
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);
296 }
297
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. */
301
302 void
gimple_gen_interval_profiler(histogram_value value,unsigned tag,unsigned base)303 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
304 {
305 gimple *stmt = value->hvalue.stmt;
306 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
307 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
308 gcall *call;
309 tree val;
310 tree start = build_int_cst_type (integer_type_node,
311 value->hdata.intvl.int_start);
312 tree steps = build_int_cst_type (unsigned_type_node,
313 value->hdata.intvl.steps);
314
315 ref_ptr = force_gimple_operand_gsi (&gsi,
316 build_addr (ref),
317 true, NULL_TREE, true, GSI_SAME_STMT);
318 val = prepare_instrumented_value (&gsi, value);
319 call = gimple_build_call (tree_interval_profiler_fn, 4,
320 ref_ptr, val, start, steps);
321 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
322 }
323
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. */
327
328 void
gimple_gen_pow2_profiler(histogram_value value,unsigned tag,unsigned base)329 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
330 {
331 gimple *stmt = value->hvalue.stmt;
332 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
333 tree ref_ptr = tree_coverage_counter_addr (tag, base);
334 gcall *call;
335 tree val;
336
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);
342 }
343
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. */
347
348 void
gimple_gen_one_value_profiler(histogram_value value,unsigned tag,unsigned base)349 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
350 {
351 gimple *stmt = value->hvalue.stmt;
352 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
353 tree ref_ptr = tree_coverage_counter_addr (tag, base);
354 gcall *call;
355 tree val;
356
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);
362 }
363
364
365 /* Output instructions as GIMPLE trees for code to find the most
366 common called function in indirect call.
367 VALUE is the call expression whose indirect callee is profiled.
368 TAG is the tag of the section for counters, BASE is offset of the
369 counter position. */
370
371 void
gimple_gen_ic_profiler(histogram_value value,unsigned tag,unsigned base)372 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
373 {
374 tree tmp1;
375 gassign *stmt1, *stmt2, *stmt3;
376 gimple *stmt = value->hvalue.stmt;
377 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
378 tree ref_ptr = tree_coverage_counter_addr (tag, base);
379
380 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
381 tag == GCOV_COUNTER_V_INDIR) ||
382 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
383 tag == GCOV_COUNTER_ICALL_TOPNV))
384 return;
385
386 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
387 true, NULL_TREE, true, GSI_SAME_STMT);
388
389 /* Insert code:
390
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;
394
395 Example:
396 f_1 = foo;
397 __gcov_indirect_call_counters = &__gcov4.main[0];
398 PROF_9 = f_1;
399 __gcov_indirect_call_callee = PROF_9;
400 _4 = f_1 ();
401 */
402
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));
407
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);
411 }
412
413
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.
417 */
418
419 void
gimple_gen_ic_func_profiler(void)420 gimple_gen_ic_func_profiler (void)
421 {
422 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
423 gcall *stmt1;
424 tree tree_uid, cur_func, void0;
425
426 if (c_node->only_called_directly_p ())
427 return;
428
429 gimple_init_gcov_profiler ();
430
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));
434
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));
438
439 edge true_edge = single_succ_edge (cond_bb);
440 true_edge->flags = EDGE_TRUE_VALUE;
441
442 profile_probability probability;
443 if (DECL_VIRTUAL_P (current_function_decl))
444 probability = profile_probability::very_likely ();
445 else
446 probability = profile_probability::unlikely ();
447
448 true_edge->probability = probability;
449 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
450 EDGE_FALSE_VALUE);
451 e->probability = true_edge->probability.invert ();
452
453 /* Insert code:
454
455 if (__gcov_indirect_call_callee != NULL)
456 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl);
457
458 The function __gcov_indirect_call_profiler_v2 is responsible for
459 resetting __gcov_indirect_call_callee to NULL. */
460
461 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
462 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
463
464 tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE,
465 true, GSI_SAME_STMT);
466
467 gcond *cond = gimple_build_cond (NE_EXPR, ref,
468 void0, NULL, NULL);
469 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
470
471 gsi = gsi_after_labels (update_bb);
472
473 cur_func = force_gimple_operand_gsi (&gsi,
474 build_addr (current_function_decl),
475 true, NULL_TREE,
476 true, GSI_SAME_STMT);
477 tree_uid = build_int_cst
478 (gcov_type_node,
479 cgraph_node::get (current_function_decl)->profile_id);
480 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
481 tree_uid, cur_func);
482 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
483 }
484
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. */
488
489 void
gimple_gen_time_profiler(unsigned tag,unsigned base)490 gimple_gen_time_profiler (unsigned tag, unsigned base)
491 {
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));
496
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));
500
501 edge true_edge = single_succ_edge (cond_bb);
502 true_edge->flags = EDGE_TRUE_VALUE;
503 true_edge->probability = profile_probability::unlikely ();
504 edge e
505 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
506 e->probability = true_edge->probability.invert ();
507
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);
513
514 /* Emit: if (counters[0] != 0). */
515 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
516 NULL, NULL);
517 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
518
519 gsi = gsi_start_bb (update_bb);
520
521 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
522 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
523 {
524 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
525 "time_profiler_counter_ptr");
526 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
527 tree_time_profiler_counter);
528 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
529 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
530 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
531 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
532 BUILT_IN_ATOMIC_ADD_FETCH_4);
533 gcall *stmt = gimple_build_call (f, 3, ptr, one,
534 build_int_cst (integer_type_node,
535 MEMMODEL_RELAXED));
536 tree result_type = TREE_TYPE (TREE_TYPE (f));
537 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
538 gimple_set_lhs (stmt, tmp);
539 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
540 tmp = make_temp_ssa_name (type, NULL, "time_profile");
541 assign = gimple_build_assign (tmp, NOP_EXPR,
542 gimple_call_lhs (stmt));
543 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
544 assign = gimple_build_assign (original_ref, tmp);
545 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
546 }
547 else
548 {
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);
552
553 tmp = make_temp_ssa_name (type, NULL, "time_profile");
554 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
555 one);
556 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
557 assign = gimple_build_assign (original_ref, tmp);
558 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
559 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
560 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
561 }
562 }
563
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. */
567
568 void
gimple_gen_average_profiler(histogram_value value,unsigned tag,unsigned base)569 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
570 {
571 gimple *stmt = value->hvalue.stmt;
572 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
573 tree ref_ptr = tree_coverage_counter_addr (tag, base);
574 gcall *call;
575 tree val;
576
577 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
578 true, NULL_TREE,
579 true, GSI_SAME_STMT);
580 val = prepare_instrumented_value (&gsi, value);
581 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
582 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
583 }
584
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. */
588
589 void
gimple_gen_ior_profiler(histogram_value value,unsigned tag,unsigned base)590 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
591 {
592 gimple *stmt = value->hvalue.stmt;
593 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
594 tree ref_ptr = tree_coverage_counter_addr (tag, base);
595 gcall *call;
596 tree val;
597
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);
603 }
604
605 #ifndef HAVE_sync_compare_and_swapsi
606 #define HAVE_sync_compare_and_swapsi 0
607 #endif
608 #ifndef HAVE_atomic_compare_and_swapsi
609 #define HAVE_atomic_compare_and_swapsi 0
610 #endif
611
612 #ifndef HAVE_sync_compare_and_swapdi
613 #define HAVE_sync_compare_and_swapdi 0
614 #endif
615 #ifndef HAVE_atomic_compare_and_swapdi
616 #define HAVE_atomic_compare_and_swapdi 0
617 #endif
618
619 /* Profile all functions in the callgraph. */
620
621 static unsigned int
tree_profiling(void)622 tree_profiling (void)
623 {
624 struct cgraph_node *node;
625
626 /* Verify whether we can utilize atomic update operations. */
627 bool can_support_atomic = false;
628 unsigned HOST_WIDE_INT gcov_type_size
629 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
630 if (gcov_type_size == 4)
631 can_support_atomic
632 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
633 else if (gcov_type_size == 8)
634 can_support_atomic
635 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
636
637 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
638 && !can_support_atomic)
639 {
640 warning (0, "target does not support atomic profile update, "
641 "single mode is selected");
642 flag_profile_update = PROFILE_UPDATE_SINGLE;
643 }
644 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
645 flag_profile_update = can_support_atomic
646 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
647
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);
651
652 init_node_map (true);
653
654 FOR_EACH_DEFINED_FUNCTION (node)
655 {
656 bool thunk = false;
657 if (!gimple_has_body_p (node->decl) && !node->thunk.thunk_p)
658 continue;
659
660 /* Don't profile functions produced for builtin stuff. */
661 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
662 continue;
663
664 if (lookup_attribute ("no_profile_instrument_function",
665 DECL_ATTRIBUTES (node->decl)))
666 continue;
667 /* Do not instrument extern inline functions when testing coverage.
668 While this is not perfectly consistent (early inlined extern inlines
669 will get acocunted), testsuite expects that. */
670 if (DECL_EXTERNAL (node->decl)
671 && flag_test_coverage)
672 continue;
673
674 if (node->thunk.thunk_p)
675 {
676 /* We can not expand variadic thunks to Gimple. */
677 if (stdarg_p (TREE_TYPE (node->decl)))
678 continue;
679 thunk = true;
680 /* When generate profile, expand thunk to gimple so it can be
681 instrumented same way as other functions. */
682 if (profile_arc_flag)
683 node->expand_thunk (false, true);
684 /* Read cgraph profile but keep function as thunk at profile-use
685 time. */
686 else
687 {
688 read_thunk_profile (node);
689 continue;
690 }
691 }
692
693 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
694
695 if (dump_file)
696 dump_function_header (dump_file, cfun->decl, dump_flags);
697
698 /* Local pure-const may imply need to fixup the cfg. */
699 if (gimple_has_body_p (node->decl)
700 && (execute_fixup_cfg () & TODO_cleanup_cfg))
701 cleanup_tree_cfg ();
702
703 branch_prob (thunk);
704
705 if (! flag_branch_probabilities
706 && flag_profile_values)
707 gimple_gen_ic_func_profiler ();
708
709 if (flag_branch_probabilities
710 && !thunk
711 && flag_profile_values
712 && flag_value_profile_transformations)
713 gimple_value_profile_transformations ();
714
715 /* The above could hose dominator info. Currently there is
716 none coming in, this is a safety valve. It should be
717 easy to adjust it, if and when there is some. */
718 free_dominance_info (CDI_DOMINATORS);
719 free_dominance_info (CDI_POST_DOMINATORS);
720 pop_cfun ();
721 }
722
723 /* Drop pure/const flags from instrumented functions. */
724 if (profile_arc_flag || flag_test_coverage)
725 FOR_EACH_DEFINED_FUNCTION (node)
726 {
727 if (!gimple_has_body_p (node->decl)
728 || !(!node->clone_of
729 || node->decl != node->clone_of->decl))
730 continue;
731
732 /* Don't profile functions produced for builtin stuff. */
733 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
734 continue;
735
736 node->set_const_flag (false, false);
737 node->set_pure_flag (false, false);
738 }
739
740 /* Update call statements and rebuild the cgraph. */
741 FOR_EACH_DEFINED_FUNCTION (node)
742 {
743 basic_block bb;
744
745 if (!gimple_has_body_p (node->decl)
746 || !(!node->clone_of
747 || node->decl != node->clone_of->decl))
748 continue;
749
750 /* Don't profile functions produced for builtin stuff. */
751 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
752 continue;
753
754 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
755
756 FOR_EACH_BB_FN (bb, cfun)
757 {
758 gimple_stmt_iterator gsi;
759 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
760 {
761 gimple *stmt = gsi_stmt (gsi);
762 if (is_gimple_call (stmt))
763 update_stmt (stmt);
764 }
765 }
766
767 /* re-merge split blocks. */
768 cleanup_tree_cfg ();
769 update_ssa (TODO_update_ssa);
770
771 cgraph_edge::rebuild_edges ();
772
773 pop_cfun ();
774 }
775
776 handle_missing_profiles ();
777
778 del_node_map ();
779 return 0;
780 }
781
782 namespace {
783
784 const pass_data pass_data_ipa_tree_profile =
785 {
786 SIMPLE_IPA_PASS, /* type */
787 "profile", /* name */
788 OPTGROUP_NONE, /* optinfo_flags */
789 TV_IPA_PROFILE, /* tv_id */
790 0, /* properties_required */
791 0, /* properties_provided */
792 0, /* properties_destroyed */
793 0, /* todo_flags_start */
794 TODO_dump_symtab, /* todo_flags_finish */
795 };
796
797 class pass_ipa_tree_profile : public simple_ipa_opt_pass
798 {
799 public:
pass_ipa_tree_profile(gcc::context * ctxt)800 pass_ipa_tree_profile (gcc::context *ctxt)
801 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
802 {}
803
804 /* opt_pass methods: */
805 virtual bool gate (function *);
execute(function *)806 virtual unsigned int execute (function *) { return tree_profiling (); }
807
808 }; // class pass_ipa_tree_profile
809
810 bool
gate(function *)811 pass_ipa_tree_profile::gate (function *)
812 {
813 /* When profile instrumentation, use or test coverage shall be performed.
814 But for AutoFDO, this there is no instrumentation, thus this pass is
815 diabled. */
816 return (!in_lto_p && !flag_auto_profile
817 && (flag_branch_probabilities || flag_test_coverage
818 || profile_arc_flag));
819 }
820
821 } // anon namespace
822
823 simple_ipa_opt_pass *
make_pass_ipa_tree_profile(gcc::context * ctxt)824 make_pass_ipa_tree_profile (gcc::context *ctxt)
825 {
826 return new pass_ipa_tree_profile (ctxt);
827 }
828
829 #include "gt-tree-profile.h"
830