xref: /netbsd-src/external/gpl3/gcc/dist/gcc/tree-profile.cc (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Calculate branch probabilities, and basic block execution counts.
2    Copyright (C) 1990-2022 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.cc 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 "stringpool.h"
53 #include "attribs.h"
54 #include "tree-pretty-print.h"
55 #include "langhooks.h"
56 #include "stor-layout.h"
57 #include "xregex.h"
58 #include "alloc-pool.h"
59 #include "symbol-summary.h"
60 #include "symtab-thunks.h"
61 
62 static GTY(()) tree gcov_type_node;
63 static GTY(()) tree tree_interval_profiler_fn;
64 static GTY(()) tree tree_pow2_profiler_fn;
65 static GTY(()) tree tree_topn_values_profiler_fn;
66 static GTY(()) tree tree_indirect_call_profiler_fn;
67 static GTY(()) tree tree_average_profiler_fn;
68 static GTY(()) tree tree_ior_profiler_fn;
69 static GTY(()) tree tree_time_profiler_counter;
70 
71 
72 static GTY(()) tree ic_tuple_var;
73 static GTY(()) tree ic_tuple_counters_field;
74 static GTY(()) tree ic_tuple_callee_field;
75 
76 /* Do initialization work for the edge profiler.  */
77 
78 /* Add code:
79    __thread gcov*	__gcov_indirect_call.counters; // pointer to actual counter
80    __thread void*	__gcov_indirect_call.callee; // actual callee address
81    __thread int __gcov_function_counter; // time profiler function counter
82 */
83 static void
init_ic_make_global_vars(void)84 init_ic_make_global_vars (void)
85 {
86   tree gcov_type_ptr;
87 
88   gcov_type_ptr = build_pointer_type (get_gcov_type ());
89 
90   tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
91 
92   /* callee */
93   ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
94 				      ptr_type_node);
95 
96   /* counters */
97   ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
98 					NULL_TREE, gcov_type_ptr);
99   DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field;
100 
101   finish_builtin_struct (tuple_type, "indirect_call_tuple",
102 			 ic_tuple_counters_field, NULL_TREE);
103 
104   ic_tuple_var
105     = build_decl (UNKNOWN_LOCATION, VAR_DECL,
106 		  get_identifier ("__gcov_indirect_call"), tuple_type);
107   TREE_PUBLIC (ic_tuple_var) = 1;
108   DECL_ARTIFICIAL (ic_tuple_var) = 1;
109   DECL_INITIAL (ic_tuple_var) = NULL;
110   DECL_EXTERNAL (ic_tuple_var) = 1;
111   if (targetm.have_tls)
112     set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var));
113 }
114 
115 /* Create the type and function decls for the interface with gcov.  */
116 
117 void
gimple_init_gcov_profiler(void)118 gimple_init_gcov_profiler (void)
119 {
120   tree interval_profiler_fn_type;
121   tree pow2_profiler_fn_type;
122   tree topn_values_profiler_fn_type;
123   tree gcov_type_ptr;
124   tree ic_profiler_fn_type;
125   tree average_profiler_fn_type;
126   const char *fn_name;
127 
128   if (!gcov_type_node)
129     {
130       const char *fn_suffix
131 	= flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
132 
133       gcov_type_node = get_gcov_type ();
134       gcov_type_ptr = build_pointer_type (gcov_type_node);
135 
136       /* void (*) (gcov_type *, gcov_type, int, unsigned)  */
137       interval_profiler_fn_type
138 	      = build_function_type_list (void_type_node,
139 					  gcov_type_ptr, gcov_type_node,
140 					  integer_type_node,
141 					  unsigned_type_node, NULL_TREE);
142       fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
143       tree_interval_profiler_fn = build_fn_decl (fn_name,
144 						 interval_profiler_fn_type);
145       free (CONST_CAST (char *, fn_name));
146       TREE_NOTHROW (tree_interval_profiler_fn) = 1;
147       DECL_ATTRIBUTES (tree_interval_profiler_fn)
148 	= tree_cons (get_identifier ("leaf"), NULL,
149 		     DECL_ATTRIBUTES (tree_interval_profiler_fn));
150 
151       /* void (*) (gcov_type *, gcov_type)  */
152       pow2_profiler_fn_type
153 	      = build_function_type_list (void_type_node,
154 					  gcov_type_ptr, gcov_type_node,
155 					  NULL_TREE);
156       fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
157       tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
158       free (CONST_CAST (char *, fn_name));
159       TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
160       DECL_ATTRIBUTES (tree_pow2_profiler_fn)
161 	= tree_cons (get_identifier ("leaf"), NULL,
162 		     DECL_ATTRIBUTES (tree_pow2_profiler_fn));
163 
164       /* void (*) (gcov_type *, gcov_type)  */
165       topn_values_profiler_fn_type
166 	      = build_function_type_list (void_type_node,
167 					  gcov_type_ptr, gcov_type_node,
168 					  NULL_TREE);
169       fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL);
170       tree_topn_values_profiler_fn
171 	= build_fn_decl (fn_name, topn_values_profiler_fn_type);
172       free (CONST_CAST (char *, fn_name));
173 
174       TREE_NOTHROW (tree_topn_values_profiler_fn) = 1;
175       DECL_ATTRIBUTES (tree_topn_values_profiler_fn)
176 	= tree_cons (get_identifier ("leaf"), NULL,
177 		     DECL_ATTRIBUTES (tree_topn_values_profiler_fn));
178 
179       init_ic_make_global_vars ();
180 
181       /* void (*) (gcov_type, void *)  */
182       ic_profiler_fn_type
183 	       = build_function_type_list (void_type_node,
184 					  gcov_type_node,
185 					  ptr_type_node,
186 					  NULL_TREE);
187       fn_name = concat ("__gcov_indirect_call_profiler_v4", fn_suffix, NULL);
188       tree_indirect_call_profiler_fn
189 	= build_fn_decl (fn_name, ic_profiler_fn_type);
190       free (CONST_CAST (char *, fn_name));
191 
192       TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
193       DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
194 	= tree_cons (get_identifier ("leaf"), NULL,
195 		     DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
196 
197       tree_time_profiler_counter
198 	= build_decl (UNKNOWN_LOCATION, VAR_DECL,
199 		      get_identifier ("__gcov_time_profiler_counter"),
200 		      get_gcov_type ());
201       TREE_PUBLIC (tree_time_profiler_counter) = 1;
202       DECL_EXTERNAL (tree_time_profiler_counter) = 1;
203       TREE_STATIC (tree_time_profiler_counter) = 1;
204       DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
205       DECL_INITIAL (tree_time_profiler_counter) = NULL;
206 
207       /* void (*) (gcov_type *, gcov_type)  */
208       average_profiler_fn_type
209 	      = build_function_type_list (void_type_node,
210 					  gcov_type_ptr, gcov_type_node, NULL_TREE);
211       fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
212       tree_average_profiler_fn = build_fn_decl (fn_name,
213 						average_profiler_fn_type);
214       free (CONST_CAST (char *, fn_name));
215       TREE_NOTHROW (tree_average_profiler_fn) = 1;
216       DECL_ATTRIBUTES (tree_average_profiler_fn)
217 	= tree_cons (get_identifier ("leaf"), NULL,
218 		     DECL_ATTRIBUTES (tree_average_profiler_fn));
219       fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
220       tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
221       free (CONST_CAST (char *, fn_name));
222       TREE_NOTHROW (tree_ior_profiler_fn) = 1;
223       DECL_ATTRIBUTES (tree_ior_profiler_fn)
224 	= tree_cons (get_identifier ("leaf"), NULL,
225 		     DECL_ATTRIBUTES (tree_ior_profiler_fn));
226 
227       /* LTO streamer needs assembler names.  Because we create these decls
228          late, we need to initialize them by hand.  */
229       DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
230       DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
231       DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn);
232       DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
233       DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
234       DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
235     }
236 }
237 
238 /* Output instructions as GIMPLE trees to increment the edge
239    execution count, and insert them on E.  We rely on
240    gsi_insert_on_edge to preserve the order.  */
241 
242 void
gimple_gen_edge_profiler(int edgeno,edge e)243 gimple_gen_edge_profiler (int edgeno, edge e)
244 {
245   tree one;
246 
247   one = build_int_cst (gcov_type_node, 1);
248 
249   if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
250     {
251       /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
252       tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
253       tree f = builtin_decl_explicit (TYPE_PRECISION (gcov_type_node) > 32
254 				      ? BUILT_IN_ATOMIC_FETCH_ADD_8:
255 				      BUILT_IN_ATOMIC_FETCH_ADD_4);
256       gcall *stmt = gimple_build_call (f, 3, addr, one,
257 				       build_int_cst (integer_type_node,
258 						      MEMMODEL_RELAXED));
259       gsi_insert_on_edge (e, stmt);
260     }
261   else
262     {
263       tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
264       tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
265 						   NULL, "PROF_edge_counter");
266       gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
267       gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
268 					      NULL, "PROF_edge_counter");
269       gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
270 					    gimple_assign_lhs (stmt1), one);
271       gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
272 					    gimple_assign_lhs (stmt2));
273       gsi_insert_on_edge (e, stmt1);
274       gsi_insert_on_edge (e, stmt2);
275       gsi_insert_on_edge (e, stmt3);
276     }
277 }
278 
279 /* Emits code to get VALUE to instrument at GSI, and returns the
280    variable containing the value.  */
281 
282 static tree
prepare_instrumented_value(gimple_stmt_iterator * gsi,histogram_value value)283 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
284 {
285   tree val = value->hvalue.value;
286   if (POINTER_TYPE_P (TREE_TYPE (val)))
287     val = fold_convert (build_nonstandard_integer_type
288 			  (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
289   return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
290 				   true, NULL_TREE, true, GSI_SAME_STMT);
291 }
292 
293 /* Output instructions as GIMPLE trees to increment the interval histogram
294    counter.  VALUE is the expression whose value is profiled.  TAG is the
295    tag of the section for counters, BASE is offset of the counter position.  */
296 
297 void
gimple_gen_interval_profiler(histogram_value value,unsigned tag)298 gimple_gen_interval_profiler (histogram_value value, unsigned tag)
299 {
300   gimple *stmt = value->hvalue.stmt;
301   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
302   tree ref = tree_coverage_counter_ref (tag, 0), ref_ptr;
303   gcall *call;
304   tree val;
305   tree start = build_int_cst_type (integer_type_node,
306 				   value->hdata.intvl.int_start);
307   tree steps = build_int_cst_type (unsigned_type_node,
308 				   value->hdata.intvl.steps);
309 
310   ref_ptr = force_gimple_operand_gsi (&gsi,
311 				      build_addr (ref),
312 				      true, NULL_TREE, true, GSI_SAME_STMT);
313   val = prepare_instrumented_value (&gsi, value);
314   call = gimple_build_call (tree_interval_profiler_fn, 4,
315 			    ref_ptr, val, start, steps);
316   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
317 }
318 
319 /* Output instructions as GIMPLE trees to increment the power of two histogram
320    counter.  VALUE is the expression whose value is profiled.  TAG is the tag
321    of the section for counters.  */
322 
323 void
gimple_gen_pow2_profiler(histogram_value value,unsigned tag)324 gimple_gen_pow2_profiler (histogram_value value, unsigned tag)
325 {
326   gimple *stmt = value->hvalue.stmt;
327   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
328   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
329   gcall *call;
330   tree val;
331 
332   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
333 				      true, NULL_TREE, true, GSI_SAME_STMT);
334   val = prepare_instrumented_value (&gsi, value);
335   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
336   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
337 }
338 
339 /* Output instructions as GIMPLE trees for code to find the most N common
340    values.  VALUE is the expression whose value is profiled.  TAG is the tag
341    of the section for counters.  */
342 
343 void
gimple_gen_topn_values_profiler(histogram_value value,unsigned tag)344 gimple_gen_topn_values_profiler (histogram_value value, unsigned tag)
345 {
346   gimple *stmt = value->hvalue.stmt;
347   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
348   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
349   gcall *call;
350   tree val;
351 
352   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
353 				      true, NULL_TREE, true, GSI_SAME_STMT);
354   val = prepare_instrumented_value (&gsi, value);
355   call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val);
356   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
357 }
358 
359 
360 /* Output instructions as GIMPLE trees for code to find the most
361    common called function in indirect call.
362    VALUE is the call expression whose indirect callee is profiled.
363    TAG is the tag of the section for counters.  */
364 
365 void
gimple_gen_ic_profiler(histogram_value value,unsigned tag)366 gimple_gen_ic_profiler (histogram_value value, unsigned tag)
367 {
368   tree tmp1;
369   gassign *stmt1, *stmt2, *stmt3;
370   gimple *stmt = value->hvalue.stmt;
371   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
372   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
373 
374   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
375 				      true, NULL_TREE, true, GSI_SAME_STMT);
376 
377   /* Insert code:
378 
379     stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
380     stmt2: tmp1 = (void *) (indirect call argument value)
381     stmt3: __gcov_indirect_call.callee = tmp1;
382 
383     Example:
384       f_1 = foo;
385       __gcov_indirect_call.counters = &__gcov4.main[0];
386       PROF_9 = f_1;
387       __gcov_indirect_call.callee = PROF_9;
388       _4 = f_1 ();
389    */
390 
391   tree gcov_type_ptr = build_pointer_type (get_gcov_type ());
392 
393   tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr,
394 			     ic_tuple_var, ic_tuple_counters_field, NULL_TREE);
395 
396   stmt1 = gimple_build_assign (counter_ref, ref_ptr);
397   tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
398   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
399   tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
400 			     ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
401   stmt3 = gimple_build_assign (callee_ref, tmp1);
402 
403   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
404   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
405   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
406 }
407 
408 
409 /* Output instructions as GIMPLE trees for code to find the most
410    common called function in indirect call. Insert instructions at the
411    beginning of every possible called function.
412   */
413 
414 void
gimple_gen_ic_func_profiler(void)415 gimple_gen_ic_func_profiler (void)
416 {
417   struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
418   gcall *stmt1;
419   tree tree_uid, cur_func, void0;
420 
421   /* Disable indirect call profiling for an IFUNC resolver and its
422      callees since it requires TLS which hasn't been set up yet when
423      the dynamic linker is resolving IFUNC symbols.  See
424      https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114115
425    */
426   if (c_node->only_called_directly_p ()
427       || c_node->called_by_ifunc_resolver)
428     return;
429 
430   gimple_init_gcov_profiler ();
431 
432   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
433   basic_block cond_bb = split_edge (single_succ_edge (entry));
434   basic_block update_bb = split_edge (single_succ_edge (cond_bb));
435 
436   /* We need to do an extra split in order to not create an input
437      for a possible PHI node.  */
438   split_edge (single_succ_edge (update_bb));
439 
440   edge true_edge = single_succ_edge (cond_bb);
441   true_edge->flags = EDGE_TRUE_VALUE;
442 
443   profile_probability probability;
444   if (DECL_VIRTUAL_P (current_function_decl))
445     probability = profile_probability::very_likely ();
446   else
447     probability = profile_probability::unlikely ();
448 
449   true_edge->probability = probability;
450   edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
451 		      EDGE_FALSE_VALUE);
452   e->probability = true_edge->probability.invert ();
453 
454   /* Insert code:
455 
456      if (__gcov_indirect_call.callee != NULL)
457        __gcov_indirect_call_profiler_v3 (profile_id, &current_function_decl);
458 
459      The function __gcov_indirect_call_profiler_v3 is responsible for
460      resetting __gcov_indirect_call.callee to NULL.  */
461 
462   gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
463   void0 = build_int_cst (ptr_type_node, 0);
464 
465   tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
466 			    ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
467 
468   tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE,
469 				       true, GSI_SAME_STMT);
470 
471   gcond *cond = gimple_build_cond (NE_EXPR, ref,
472 				   void0, NULL, NULL);
473   gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
474 
475   gsi = gsi_after_labels (update_bb);
476 
477   cur_func = force_gimple_operand_gsi (&gsi,
478 				       build_addr (current_function_decl),
479 				       true, NULL_TREE,
480 				       true, GSI_SAME_STMT);
481   tree_uid = build_int_cst
482 	      (gcov_type_node,
483 	       cgraph_node::get (current_function_decl)->profile_id);
484   stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
485 			     tree_uid, cur_func);
486   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
487 }
488 
489 /* Output instructions as GIMPLE tree at the beginning for each function.
490    TAG is the tag of the section for counters, BASE is offset of the
491    counter position and GSI is the iterator we place the counter.  */
492 
493 void
gimple_gen_time_profiler(unsigned tag)494 gimple_gen_time_profiler (unsigned tag)
495 {
496   tree type = get_gcov_type ();
497   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
498   basic_block cond_bb = split_edge (single_succ_edge (entry));
499   basic_block update_bb = split_edge (single_succ_edge (cond_bb));
500 
501   /* We need to do an extra split in order to not create an input
502      for a possible PHI node.  */
503   split_edge (single_succ_edge (update_bb));
504 
505   edge true_edge = single_succ_edge (cond_bb);
506   true_edge->flags = EDGE_TRUE_VALUE;
507   true_edge->probability = profile_probability::unlikely ();
508   edge e
509     = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
510   e->probability = true_edge->probability.invert ();
511 
512   gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
513   tree original_ref = tree_coverage_counter_ref (tag, 0);
514   tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
515 				       true, GSI_SAME_STMT);
516   tree one = build_int_cst (type, 1);
517 
518   /* Emit: if (counters[0] != 0).  */
519   gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
520 				   NULL, NULL);
521   gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
522 
523   gsi = gsi_start_bb (update_bb);
524 
525   /* Emit: counters[0] = ++__gcov_time_profiler_counter.  */
526   if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
527     {
528       tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
529 				     "time_profiler_counter_ptr");
530       tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
531 			  tree_time_profiler_counter);
532       gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
533       gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
534       tree f = builtin_decl_explicit (TYPE_PRECISION (gcov_type_node) > 32
535 				      ? BUILT_IN_ATOMIC_ADD_FETCH_8:
536 				      BUILT_IN_ATOMIC_ADD_FETCH_4);
537       gcall *stmt = gimple_build_call (f, 3, ptr, one,
538 				       build_int_cst (integer_type_node,
539 						      MEMMODEL_RELAXED));
540       tree result_type = TREE_TYPE (TREE_TYPE (f));
541       tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
542       gimple_set_lhs (stmt, tmp);
543       gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
544       tmp = make_temp_ssa_name (type, NULL, "time_profile");
545       assign = gimple_build_assign (tmp, NOP_EXPR,
546 				    gimple_call_lhs (stmt));
547       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
548       assign = gimple_build_assign (original_ref, tmp);
549       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
550     }
551   else
552     {
553       tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
554       gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
555       gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
556 
557       tmp = make_temp_ssa_name (type, NULL, "time_profile");
558       assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
559 				    one);
560       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
561       assign = gimple_build_assign (original_ref, tmp);
562       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
563       assign = gimple_build_assign (tree_time_profiler_counter, tmp);
564       gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
565     }
566 }
567 
568 /* Output instructions as GIMPLE trees to increment the average histogram
569    counter.  VALUE is the expression whose value is profiled.  TAG is the
570    tag of the section for counters, BASE is offset of the counter position.  */
571 
572 void
gimple_gen_average_profiler(histogram_value value,unsigned tag)573 gimple_gen_average_profiler (histogram_value value, unsigned tag)
574 {
575   gimple *stmt = value->hvalue.stmt;
576   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
577   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
578   gcall *call;
579   tree val;
580 
581   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
582 				      true, NULL_TREE,
583 				      true, GSI_SAME_STMT);
584   val = prepare_instrumented_value (&gsi, value);
585   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
586   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
587 }
588 
589 /* Output instructions as GIMPLE trees to increment the ior histogram
590    counter.  VALUE is the expression whose value is profiled.  TAG is the
591    tag of the section for counters, BASE is offset of the counter position.  */
592 
593 void
gimple_gen_ior_profiler(histogram_value value,unsigned tag)594 gimple_gen_ior_profiler (histogram_value value, unsigned tag)
595 {
596   gimple *stmt = value->hvalue.stmt;
597   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
598   tree ref_ptr = tree_coverage_counter_addr (tag, 0);
599   gcall *call;
600   tree val;
601 
602   ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
603 				      true, NULL_TREE, true, GSI_SAME_STMT);
604   val = prepare_instrumented_value (&gsi, value);
605   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
606   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
607 }
608 
609 static vec<regex_t> profile_filter_files;
610 static vec<regex_t> profile_exclude_files;
611 
612 /* Parse list of provided REGEX (separated with semi-collon) and
613    create expressions (of type regex_t) and save them into V vector.
614    If there is a regular expression parsing error, error message is
615    printed for FLAG_NAME.  */
616 
617 static void
parse_profile_filter(const char * regex,vec<regex_t> * v,const char * flag_name)618 parse_profile_filter (const char *regex, vec<regex_t> *v,
619 		      const char *flag_name)
620 {
621   v->create (4);
622   if (regex != NULL)
623     {
624       char *str = xstrdup (regex);
625       for (char *p = strtok (str, ";"); p != NULL; p = strtok (NULL, ";"))
626 	{
627 	  regex_t r;
628 	  if (regcomp (&r, p, REG_EXTENDED | REG_NOSUB) != 0)
629 	    {
630 	      error ("invalid regular expression %qs in %qs",
631 		     p, flag_name);
632 	      return;
633 	    }
634 
635 	  v->safe_push (r);
636 	}
637     }
638 }
639 
640 /* Parse values of -fprofile-filter-files and -fprofile-exclude-files
641    options.  */
642 
643 static void
parse_profile_file_filtering()644 parse_profile_file_filtering ()
645 {
646   parse_profile_filter (flag_profile_filter_files, &profile_filter_files,
647 			"-fprofile-filter-files");
648   parse_profile_filter (flag_profile_exclude_files, &profile_exclude_files,
649 			"-fprofile-exclude-files");
650 }
651 
652 /* Parse vectors of regular expressions.  */
653 
654 static void
release_profile_file_filtering()655 release_profile_file_filtering ()
656 {
657   profile_filter_files.release ();
658   profile_exclude_files.release ();
659 }
660 
661 /* Return true when FILENAME should be instrumented based on
662    -fprofile-filter-files and -fprofile-exclude-files options.  */
663 
664 static bool
include_source_file_for_profile(const char * filename)665 include_source_file_for_profile (const char *filename)
666 {
667   /* First check whether file is included in flag_profile_exclude_files.  */
668   for (unsigned i = 0; i < profile_exclude_files.length (); i++)
669     if (regexec (&profile_exclude_files[i],
670 		 filename, 0, NULL, 0) == REG_NOERROR)
671       return false;
672 
673   /* For non-empty flag_profile_filter_files include only files matching a
674      regex in the flag.  */
675   if (profile_filter_files.is_empty ())
676     return true;
677 
678   for (unsigned i = 0; i < profile_filter_files.length (); i++)
679     if (regexec (&profile_filter_files[i], filename, 0, NULL, 0) == REG_NOERROR)
680       return true;
681 
682   return false;
683 }
684 
685 #ifndef HAVE_sync_compare_and_swapsi
686 #define HAVE_sync_compare_and_swapsi 0
687 #endif
688 #ifndef HAVE_atomic_compare_and_swapsi
689 #define HAVE_atomic_compare_and_swapsi 0
690 #endif
691 
692 #ifndef HAVE_sync_compare_and_swapdi
693 #define HAVE_sync_compare_and_swapdi 0
694 #endif
695 #ifndef HAVE_atomic_compare_and_swapdi
696 #define HAVE_atomic_compare_and_swapdi 0
697 #endif
698 
699 /* Profile all functions in the callgraph.  */
700 
701 static unsigned int
tree_profiling(void)702 tree_profiling (void)
703 {
704   struct cgraph_node *node;
705 
706   /* Verify whether we can utilize atomic update operations.  */
707   bool can_support_atomic = false;
708   unsigned HOST_WIDE_INT gcov_type_size
709     = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
710   if (gcov_type_size == 4)
711     can_support_atomic
712       = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
713   else if (gcov_type_size == 8)
714     can_support_atomic
715       = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
716 
717   if (flag_profile_update == PROFILE_UPDATE_ATOMIC
718       && !can_support_atomic)
719     {
720       warning (0, "target does not support atomic profile update, "
721 	       "single mode is selected");
722       flag_profile_update = PROFILE_UPDATE_SINGLE;
723     }
724   else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
725     flag_profile_update = can_support_atomic
726       ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
727 
728   /* This is a small-ipa pass that gets called only once, from
729      cgraphunit.cc:ipa_passes().  */
730   gcc_assert (symtab->state == IPA_SSA);
731 
732   init_node_map (true);
733   parse_profile_file_filtering ();
734 
735   FOR_EACH_DEFINED_FUNCTION (node)
736     {
737       bool thunk = false;
738       if (!gimple_has_body_p (node->decl) && !node->thunk)
739 	continue;
740 
741       /* Don't profile functions produced for builtin stuff.  */
742       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
743 	continue;
744 
745       if (lookup_attribute ("no_profile_instrument_function",
746 			    DECL_ATTRIBUTES (node->decl)))
747 	continue;
748       /* Do not instrument extern inline functions when testing coverage.
749 	 While this is not perfectly consistent (early inlined extern inlines
750 	 will get acocunted), testsuite expects that.  */
751       if (DECL_EXTERNAL (node->decl)
752 	  && flag_test_coverage)
753 	continue;
754 
755       const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl));
756       if (!include_source_file_for_profile (file))
757 	continue;
758 
759       if (node->thunk)
760 	{
761 	  /* We cannot expand variadic thunks to Gimple.  */
762 	  if (stdarg_p (TREE_TYPE (node->decl)))
763 	    continue;
764 	  thunk = true;
765 	  /* When generate profile, expand thunk to gimple so it can be
766 	     instrumented same way as other functions.  */
767 	  if (profile_arc_flag)
768 	    expand_thunk (node, false, true);
769 	  /* Read cgraph profile but keep function as thunk at profile-use
770 	     time.  */
771 	  else
772 	    {
773 	      read_thunk_profile (node);
774 	      continue;
775 	    }
776 	}
777 
778       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
779 
780       if (dump_file)
781 	dump_function_header (dump_file, cfun->decl, dump_flags);
782 
783       /* Local pure-const may imply need to fixup the cfg.  */
784       if (gimple_has_body_p (node->decl)
785 	  && (execute_fixup_cfg () & TODO_cleanup_cfg))
786 	cleanup_tree_cfg ();
787 
788       branch_prob (thunk);
789 
790       if (! flag_branch_probabilities
791 	  && flag_profile_values)
792 	gimple_gen_ic_func_profiler ();
793 
794       if (flag_branch_probabilities
795 	  && !thunk
796 	  && flag_profile_values
797 	  && flag_value_profile_transformations
798 	  && profile_status_for_fn (cfun) == PROFILE_READ)
799 	gimple_value_profile_transformations ();
800 
801       /* The above could hose dominator info.  Currently there is
802 	 none coming in, this is a safety valve.  It should be
803 	 easy to adjust it, if and when there is some.  */
804       free_dominance_info (CDI_DOMINATORS);
805       free_dominance_info (CDI_POST_DOMINATORS);
806       pop_cfun ();
807     }
808 
809   release_profile_file_filtering ();
810 
811   /* Drop pure/const flags from instrumented functions.  */
812   if (profile_arc_flag || flag_test_coverage)
813     FOR_EACH_DEFINED_FUNCTION (node)
814       {
815 	if (!gimple_has_body_p (node->decl)
816 	    || !(!node->clone_of
817 	    || node->decl != node->clone_of->decl))
818 	  continue;
819 
820 	/* Don't profile functions produced for builtin stuff.  */
821 	if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
822 	  continue;
823 
824 	node->set_const_flag (false, false);
825 	node->set_pure_flag (false, false);
826       }
827 
828   /* Update call statements and rebuild the cgraph.  */
829   FOR_EACH_DEFINED_FUNCTION (node)
830     {
831       basic_block bb;
832 
833       if (!gimple_has_body_p (node->decl)
834 	  || !(!node->clone_of
835 	  || node->decl != node->clone_of->decl))
836 	continue;
837 
838       /* Don't profile functions produced for builtin stuff.  */
839       if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
840 	continue;
841 
842       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
843 
844       FOR_EACH_BB_FN (bb, cfun)
845 	{
846 	  gimple_stmt_iterator gsi;
847 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
848 	    {
849 	      gimple *stmt = gsi_stmt (gsi);
850 	      if (is_gimple_call (stmt))
851 		update_stmt (stmt);
852 	    }
853 	}
854 
855       /* re-merge split blocks.  */
856       cleanup_tree_cfg ();
857       update_ssa (TODO_update_ssa);
858 
859       cgraph_edge::rebuild_edges ();
860 
861       pop_cfun ();
862     }
863 
864   handle_missing_profiles ();
865 
866   del_node_map ();
867   return 0;
868 }
869 
870 namespace {
871 
872 const pass_data pass_data_ipa_tree_profile =
873 {
874   SIMPLE_IPA_PASS, /* type */
875   "profile", /* name */
876   OPTGROUP_NONE, /* optinfo_flags */
877   TV_IPA_PROFILE, /* tv_id */
878   0, /* properties_required */
879   0, /* properties_provided */
880   0, /* properties_destroyed */
881   0, /* todo_flags_start */
882   TODO_dump_symtab, /* todo_flags_finish */
883 };
884 
885 class pass_ipa_tree_profile : public simple_ipa_opt_pass
886 {
887 public:
pass_ipa_tree_profile(gcc::context * ctxt)888   pass_ipa_tree_profile (gcc::context *ctxt)
889     : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
890   {}
891 
892   /* opt_pass methods: */
893   virtual bool gate (function *);
execute(function *)894   virtual unsigned int execute (function *) { return tree_profiling (); }
895 
896 }; // class pass_ipa_tree_profile
897 
898 bool
gate(function *)899 pass_ipa_tree_profile::gate (function *)
900 {
901   /* When profile instrumentation, use or test coverage shall be performed.
902      But for AutoFDO, this there is no instrumentation, thus this pass is
903      disabled.  */
904   return (!in_lto_p && !flag_auto_profile
905 	  && (flag_branch_probabilities || flag_test_coverage
906 	      || profile_arc_flag));
907 }
908 
909 } // anon namespace
910 
911 simple_ipa_opt_pass *
make_pass_ipa_tree_profile(gcc::context * ctxt)912 make_pass_ipa_tree_profile (gcc::context *ctxt)
913 {
914   return new pass_ipa_tree_profile (ctxt);
915 }
916 
917 #include "gt-tree-profile.h"
918