comparison gcc/tree-profile.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 /* Calculate branch probabilities, and basic block execution counts. 1 /* Calculate branch probabilities, and basic block execution counts.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2 Copyright (C) 1990-2017 Free Software Foundation, Inc.
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
4 Free Software Foundation, Inc.
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6 based on some ideas from Dain Samples of UC Berkeley. 4 based on some ideas from Dain Samples of UC Berkeley.
7 Further mangling by Bob Manson, Cygnus Support. 5 Further mangling by Bob Manson, Cygnus Support.
8 Converted to use trees by Dale Johannesen, Apple Computer. 6 Converted to use trees by Dale Johannesen, Apple Computer.
9 7
27 Tree-based version. See profile.c for overview. */ 25 Tree-based version. See profile.c for overview. */
28 26
29 #include "config.h" 27 #include "config.h"
30 #include "system.h" 28 #include "system.h"
31 #include "coretypes.h" 29 #include "coretypes.h"
32 #include "tm.h" 30 #include "memmodel.h"
33 #include "flags.h" 31 #include "backend.h"
34 #include "regs.h" 32 #include "target.h"
35 #include "function.h" 33 #include "tree.h"
36 #include "basic-block.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"
37 #include "diagnostic-core.h" 40 #include "diagnostic-core.h"
38 #include "coverage.h" 41 #include "fold-const.h"
39 #include "tree.h" 42 #include "varasm.h"
40 #include "tree-flow.h" 43 #include "tree-nested.h"
41 #include "tree-dump.h" 44 #include "gimplify.h"
42 #include "tree-pass.h" 45 #include "gimple-iterator.h"
43 #include "timevar.h" 46 #include "gimplify-me.h"
47 #include "tree-cfg.h"
48 #include "tree-into-ssa.h"
44 #include "value-prof.h" 49 #include "value-prof.h"
45 #include "cgraph.h" 50 #include "profile.h"
51 #include "tree-cfgcleanup.h"
52 #include "params.h"
53 #include "stringpool.h"
54 #include "attribs.h"
46 55
47 static GTY(()) tree gcov_type_node; 56 static GTY(()) tree gcov_type_node;
48 static GTY(()) tree gcov_type_tmp_var;
49 static GTY(()) tree tree_interval_profiler_fn; 57 static GTY(()) tree tree_interval_profiler_fn;
50 static GTY(()) tree tree_pow2_profiler_fn; 58 static GTY(()) tree tree_pow2_profiler_fn;
51 static GTY(()) tree tree_one_value_profiler_fn; 59 static GTY(()) tree tree_one_value_profiler_fn;
52 static GTY(()) tree tree_indirect_call_profiler_fn; 60 static GTY(()) tree tree_indirect_call_profiler_fn;
53 static GTY(()) tree tree_average_profiler_fn; 61 static GTY(()) tree tree_average_profiler_fn;
54 static GTY(()) tree tree_ior_profiler_fn; 62 static GTY(()) tree tree_ior_profiler_fn;
55 63 static GTY(()) tree tree_time_profiler_counter;
64
56 65
57 static GTY(()) tree ic_void_ptr_var; 66 static GTY(()) tree ic_void_ptr_var;
58 static GTY(()) tree ic_gcov_type_ptr_var; 67 static GTY(()) tree ic_gcov_type_ptr_var;
59 static GTY(()) tree ptr_void; 68 static GTY(()) tree ptr_void;
60 69
61 /* Do initialization work for the edge profiler. */ 70 /* Do initialization work for the edge profiler. */
62 71
63 /* Add code: 72 /* Add code:
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter 73 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
65 static void* __gcov_indirect_call_callee; // actual callee address 74 __thread void* __gcov_indirect_call_callee; // actual callee address
75 __thread int __gcov_function_counter; // time profiler function counter
66 */ 76 */
67 static void 77 static void
68 init_ic_make_global_vars (void) 78 init_ic_make_global_vars (void)
69 { 79 {
70 tree gcov_type_ptr; 80 tree gcov_type_ptr;
71 81
72 ptr_void = build_pointer_type (void_type_node); 82 ptr_void = build_pointer_type (void_type_node);
73 83
74 ic_void_ptr_var 84 ic_void_ptr_var
75 = build_decl (UNKNOWN_LOCATION, VAR_DECL, 85 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
76 get_identifier ("__gcov_indirect_call_callee"), 86 get_identifier (
87 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
88 "__gcov_indirect_call_topn_callee" :
89 "__gcov_indirect_call_callee")),
77 ptr_void); 90 ptr_void);
91 TREE_PUBLIC (ic_void_ptr_var) = 1;
92 DECL_EXTERNAL (ic_void_ptr_var) = 1;
78 TREE_STATIC (ic_void_ptr_var) = 1; 93 TREE_STATIC (ic_void_ptr_var) = 1;
79 TREE_PUBLIC (ic_void_ptr_var) = 0;
80 DECL_ARTIFICIAL (ic_void_ptr_var) = 1; 94 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
81 DECL_INITIAL (ic_void_ptr_var) = NULL; 95 DECL_INITIAL (ic_void_ptr_var) = NULL;
82 varpool_finalize_decl (ic_void_ptr_var); 96 if (targetm.have_tls)
83 varpool_mark_needed_node (varpool_node (ic_void_ptr_var)); 97 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
84 98
85 gcov_type_ptr = build_pointer_type (get_gcov_type ()); 99 gcov_type_ptr = build_pointer_type (get_gcov_type ());
100
86 ic_gcov_type_ptr_var 101 ic_gcov_type_ptr_var
87 = build_decl (UNKNOWN_LOCATION, VAR_DECL, 102 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
88 get_identifier ("__gcov_indirect_call_counters"), 103 get_identifier (
104 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
105 "__gcov_indirect_call_topn_counters" :
106 "__gcov_indirect_call_counters")),
89 gcov_type_ptr); 107 gcov_type_ptr);
108 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
109 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
90 TREE_STATIC (ic_gcov_type_ptr_var) = 1; 110 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
91 TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
92 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1; 111 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
93 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; 112 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
94 varpool_finalize_decl (ic_gcov_type_ptr_var); 113 if (targetm.have_tls)
95 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var)); 114 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
96 } 115 }
97 116
98 void 117 /* Create the type and function decls for the interface with gcov. */
99 gimple_init_edge_profiler (void) 118
119 void
120 gimple_init_gcov_profiler (void)
100 { 121 {
101 tree interval_profiler_fn_type; 122 tree interval_profiler_fn_type;
102 tree pow2_profiler_fn_type; 123 tree pow2_profiler_fn_type;
103 tree one_value_profiler_fn_type; 124 tree one_value_profiler_fn_type;
104 tree gcov_type_ptr; 125 tree gcov_type_ptr;
105 tree ic_profiler_fn_type; 126 tree ic_profiler_fn_type;
106 tree average_profiler_fn_type; 127 tree average_profiler_fn_type;
128 const char *profiler_fn_name;
129 const char *fn_name;
107 130
108 if (!gcov_type_node) 131 if (!gcov_type_node)
109 { 132 {
133 const char *fn_suffix
134 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : "";
135
110 gcov_type_node = get_gcov_type (); 136 gcov_type_node = get_gcov_type ();
111 gcov_type_ptr = build_pointer_type (gcov_type_node); 137 gcov_type_ptr = build_pointer_type (gcov_type_node);
112 138
113 /* void (*) (gcov_type *, gcov_type, int, unsigned) */ 139 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
114 interval_profiler_fn_type 140 interval_profiler_fn_type
115 = build_function_type_list (void_type_node, 141 = build_function_type_list (void_type_node,
116 gcov_type_ptr, gcov_type_node, 142 gcov_type_ptr, gcov_type_node,
117 integer_type_node, 143 integer_type_node,
118 unsigned_type_node, NULL_TREE); 144 unsigned_type_node, NULL_TREE);
119 tree_interval_profiler_fn 145 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL);
120 = build_fn_decl ("__gcov_interval_profiler", 146 tree_interval_profiler_fn = build_fn_decl (fn_name,
121 interval_profiler_fn_type); 147 interval_profiler_fn_type);
148 free (CONST_CAST (char *, fn_name));
122 TREE_NOTHROW (tree_interval_profiler_fn) = 1; 149 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
123 DECL_ATTRIBUTES (tree_interval_profiler_fn) 150 DECL_ATTRIBUTES (tree_interval_profiler_fn)
124 = tree_cons (get_identifier ("leaf"), NULL, 151 = tree_cons (get_identifier ("leaf"), NULL,
125 DECL_ATTRIBUTES (tree_interval_profiler_fn)); 152 DECL_ATTRIBUTES (tree_interval_profiler_fn));
126 153
127 /* void (*) (gcov_type *, gcov_type) */ 154 /* void (*) (gcov_type *, gcov_type) */
128 pow2_profiler_fn_type 155 pow2_profiler_fn_type
129 = build_function_type_list (void_type_node, 156 = build_function_type_list (void_type_node,
130 gcov_type_ptr, gcov_type_node, 157 gcov_type_ptr, gcov_type_node,
131 NULL_TREE); 158 NULL_TREE);
132 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", 159 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL);
133 pow2_profiler_fn_type); 160 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type);
161 free (CONST_CAST (char *, fn_name));
134 TREE_NOTHROW (tree_pow2_profiler_fn) = 1; 162 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
135 DECL_ATTRIBUTES (tree_pow2_profiler_fn) 163 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
136 = tree_cons (get_identifier ("leaf"), NULL, 164 = tree_cons (get_identifier ("leaf"), NULL,
137 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); 165 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
138 166
139 /* void (*) (gcov_type *, gcov_type) */ 167 /* void (*) (gcov_type *, gcov_type) */
140 one_value_profiler_fn_type 168 one_value_profiler_fn_type
141 = build_function_type_list (void_type_node, 169 = build_function_type_list (void_type_node,
142 gcov_type_ptr, gcov_type_node, 170 gcov_type_ptr, gcov_type_node,
143 NULL_TREE); 171 NULL_TREE);
144 tree_one_value_profiler_fn 172 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
145 = build_fn_decl ("__gcov_one_value_profiler", 173 tree_one_value_profiler_fn = build_fn_decl (fn_name,
146 one_value_profiler_fn_type); 174 one_value_profiler_fn_type);
175 free (CONST_CAST (char *, fn_name));
147 TREE_NOTHROW (tree_one_value_profiler_fn) = 1; 176 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
148 DECL_ATTRIBUTES (tree_one_value_profiler_fn) 177 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
149 = tree_cons (get_identifier ("leaf"), NULL, 178 = tree_cons (get_identifier ("leaf"), NULL,
150 DECL_ATTRIBUTES (tree_one_value_profiler_fn)); 179 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
151 180
152 init_ic_make_global_vars (); 181 init_ic_make_global_vars ();
153 182
154 /* void (*) (gcov_type *, gcov_type, void *, void *) */ 183 /* void (*) (gcov_type, void *) */
155 ic_profiler_fn_type 184 ic_profiler_fn_type
156 = build_function_type_list (void_type_node, 185 = build_function_type_list (void_type_node,
157 gcov_type_ptr, gcov_type_node, 186 gcov_type_node,
158 ptr_void, 187 ptr_void,
159 ptr_void, NULL_TREE); 188 NULL_TREE);
189 profiler_fn_name = "__gcov_indirect_call_profiler_v2";
190 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
191 profiler_fn_name = "__gcov_indirect_call_topn_profiler";
192
160 tree_indirect_call_profiler_fn 193 tree_indirect_call_profiler_fn
161 = build_fn_decl ("__gcov_indirect_call_profiler", 194 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
162 ic_profiler_fn_type); 195
163 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; 196 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
164 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) 197 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
165 = tree_cons (get_identifier ("leaf"), NULL, 198 = tree_cons (get_identifier ("leaf"), NULL,
166 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); 199 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
167 200
201 tree_time_profiler_counter
202 = build_decl (UNKNOWN_LOCATION, VAR_DECL,
203 get_identifier ("__gcov_time_profiler_counter"),
204 get_gcov_type ());
205 TREE_PUBLIC (tree_time_profiler_counter) = 1;
206 DECL_EXTERNAL (tree_time_profiler_counter) = 1;
207 TREE_STATIC (tree_time_profiler_counter) = 1;
208 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
209 DECL_INITIAL (tree_time_profiler_counter) = NULL;
210
168 /* void (*) (gcov_type *, gcov_type) */ 211 /* void (*) (gcov_type *, gcov_type) */
169 average_profiler_fn_type 212 average_profiler_fn_type
170 = build_function_type_list (void_type_node, 213 = build_function_type_list (void_type_node,
171 gcov_type_ptr, gcov_type_node, NULL_TREE); 214 gcov_type_ptr, gcov_type_node, NULL_TREE);
172 tree_average_profiler_fn 215 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL);
173 = build_fn_decl ("__gcov_average_profiler", 216 tree_average_profiler_fn = build_fn_decl (fn_name,
174 average_profiler_fn_type); 217 average_profiler_fn_type);
218 free (CONST_CAST (char *, fn_name));
175 TREE_NOTHROW (tree_average_profiler_fn) = 1; 219 TREE_NOTHROW (tree_average_profiler_fn) = 1;
176 DECL_ATTRIBUTES (tree_average_profiler_fn) 220 DECL_ATTRIBUTES (tree_average_profiler_fn)
177 = tree_cons (get_identifier ("leaf"), NULL, 221 = tree_cons (get_identifier ("leaf"), NULL,
178 DECL_ATTRIBUTES (tree_average_profiler_fn)); 222 DECL_ATTRIBUTES (tree_average_profiler_fn));
179 tree_ior_profiler_fn 223 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL);
180 = build_fn_decl ("__gcov_ior_profiler", 224 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type);
181 average_profiler_fn_type); 225 free (CONST_CAST (char *, fn_name));
182 TREE_NOTHROW (tree_ior_profiler_fn) = 1; 226 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
183 DECL_ATTRIBUTES (tree_ior_profiler_fn) 227 DECL_ATTRIBUTES (tree_ior_profiler_fn)
184 = tree_cons (get_identifier ("leaf"), NULL, 228 = tree_cons (get_identifier ("leaf"), NULL,
185 DECL_ATTRIBUTES (tree_ior_profiler_fn)); 229 DECL_ATTRIBUTES (tree_ior_profiler_fn));
186 230
200 gsi_insert_on_edge to preserve the order. */ 244 gsi_insert_on_edge to preserve the order. */
201 245
202 void 246 void
203 gimple_gen_edge_profiler (int edgeno, edge e) 247 gimple_gen_edge_profiler (int edgeno, edge e)
204 { 248 {
205 tree ref, one; 249 tree one;
206 gimple stmt1, stmt2, stmt3; 250
207
208 /* We share one temporary variable declaration per function. This
209 gets re-set in tree_profiling. */
210 if (gcov_type_tmp_var == NULL_TREE)
211 gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter");
212 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
213 one = build_int_cst (gcov_type_node, 1); 251 one = build_int_cst (gcov_type_node, 1);
214 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); 252
215 gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1)); 253 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
216 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var, 254 {
217 gimple_assign_lhs (stmt1), one); 255 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
218 gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2)); 256 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno);
219 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2)); 257 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
220 gsi_insert_on_edge (e, stmt1); 258 ? BUILT_IN_ATOMIC_FETCH_ADD_8:
221 gsi_insert_on_edge (e, stmt2); 259 BUILT_IN_ATOMIC_FETCH_ADD_4);
222 gsi_insert_on_edge (e, stmt3); 260 gcall *stmt = gimple_build_call (f, 3, addr, one,
261 build_int_cst (integer_type_node,
262 MEMMODEL_RELAXED));
263 gsi_insert_on_edge (e, stmt);
264 }
265 else
266 {
267 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
268 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
269 NULL, "PROF_edge_counter");
270 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
271 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node,
272 NULL, "PROF_edge_counter");
273 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR,
274 gimple_assign_lhs (stmt1), one);
275 gassign *stmt3 = gimple_build_assign (unshare_expr (ref),
276 gimple_assign_lhs (stmt2));
277 gsi_insert_on_edge (e, stmt1);
278 gsi_insert_on_edge (e, stmt2);
279 gsi_insert_on_edge (e, stmt3);
280 }
223 } 281 }
224 282
225 /* Emits code to get VALUE to instrument at GSI, and returns the 283 /* Emits code to get VALUE to instrument at GSI, and returns the
226 variable containing the value. */ 284 variable containing the value. */
227 285
228 static tree 286 static tree
229 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value) 287 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
230 { 288 {
231 tree val = value->hvalue.value; 289 tree val = value->hvalue.value;
232 if (POINTER_TYPE_P (TREE_TYPE (val))) 290 if (POINTER_TYPE_P (TREE_TYPE (val)))
233 val = fold_convert (sizetype, val); 291 val = fold_convert (build_nonstandard_integer_type
292 (TYPE_PRECISION (TREE_TYPE (val)), 1), val);
234 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val), 293 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
235 true, NULL_TREE, true, GSI_SAME_STMT); 294 true, NULL_TREE, true, GSI_SAME_STMT);
236 } 295 }
237 296
238 /* Output instructions as GIMPLE trees to increment the interval histogram 297 /* Output instructions as GIMPLE trees to increment the interval histogram
240 tag of the section for counters, BASE is offset of the counter position. */ 299 tag of the section for counters, BASE is offset of the counter position. */
241 300
242 void 301 void
243 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) 302 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
244 { 303 {
245 gimple stmt = value->hvalue.stmt; 304 gimple *stmt = value->hvalue.stmt;
246 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 305 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
247 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; 306 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
248 gimple call; 307 gcall *call;
249 tree val; 308 tree val;
250 tree start = build_int_cst_type (integer_type_node, 309 tree start = build_int_cst_type (integer_type_node,
251 value->hdata.intvl.int_start); 310 value->hdata.intvl.int_start);
252 tree steps = build_int_cst_type (unsigned_type_node, 311 tree steps = build_int_cst_type (unsigned_type_node,
253 value->hdata.intvl.steps); 312 value->hdata.intvl.steps);
254 313
255 ref_ptr = force_gimple_operand_gsi (&gsi, 314 ref_ptr = force_gimple_operand_gsi (&gsi,
256 build_addr (ref, current_function_decl), 315 build_addr (ref),
257 true, NULL_TREE, true, GSI_SAME_STMT); 316 true, NULL_TREE, true, GSI_SAME_STMT);
258 val = prepare_instrumented_value (&gsi, value); 317 val = prepare_instrumented_value (&gsi, value);
259 call = gimple_build_call (tree_interval_profiler_fn, 4, 318 call = gimple_build_call (tree_interval_profiler_fn, 4,
260 ref_ptr, val, start, steps); 319 ref_ptr, val, start, steps);
261 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 320 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
266 of the section for counters, BASE is offset of the counter position. */ 325 of the section for counters, BASE is offset of the counter position. */
267 326
268 void 327 void
269 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) 328 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
270 { 329 {
271 gimple stmt = value->hvalue.stmt; 330 gimple *stmt = value->hvalue.stmt;
272 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 331 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
273 tree ref_ptr = tree_coverage_counter_addr (tag, base); 332 tree ref_ptr = tree_coverage_counter_addr (tag, base);
274 gimple call; 333 gcall *call;
275 tree val; 334 tree val;
276 335
277 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 336 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
278 true, NULL_TREE, true, GSI_SAME_STMT); 337 true, NULL_TREE, true, GSI_SAME_STMT);
279 val = prepare_instrumented_value (&gsi, value); 338 val = prepare_instrumented_value (&gsi, value);
286 section for counters, BASE is offset of the counter position. */ 345 section for counters, BASE is offset of the counter position. */
287 346
288 void 347 void
289 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) 348 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
290 { 349 {
291 gimple stmt = value->hvalue.stmt; 350 gimple *stmt = value->hvalue.stmt;
292 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 351 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
293 tree ref_ptr = tree_coverage_counter_addr (tag, base); 352 tree ref_ptr = tree_coverage_counter_addr (tag, base);
294 gimple call; 353 gcall *call;
295 tree val; 354 tree val;
296 355
297 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 356 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
298 true, NULL_TREE, true, GSI_SAME_STMT); 357 true, NULL_TREE, true, GSI_SAME_STMT);
299 val = prepare_instrumented_value (&gsi, value); 358 val = prepare_instrumented_value (&gsi, value);
310 369
311 void 370 void
312 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) 371 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
313 { 372 {
314 tree tmp1; 373 tree tmp1;
315 gimple stmt1, stmt2, stmt3; 374 gassign *stmt1, *stmt2, *stmt3;
316 gimple stmt = value->hvalue.stmt; 375 gimple *stmt = value->hvalue.stmt;
317 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 376 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
318 tree ref_ptr = tree_coverage_counter_addr (tag, base); 377 tree ref_ptr = tree_coverage_counter_addr (tag, base);
319 378
379 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
380 tag == GCOV_COUNTER_V_INDIR) ||
381 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
382 tag == GCOV_COUNTER_ICALL_TOPNV))
383 return;
384
320 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 385 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
321 true, NULL_TREE, true, GSI_SAME_STMT); 386 true, NULL_TREE, true, GSI_SAME_STMT);
322 387
323 /* Insert code: 388 /* Insert code:
324 389
325 __gcov_indirect_call_counters = get_relevant_counter_ptr (); 390 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
326 __gcov_indirect_call_callee = (void *) indirect call argument; 391 stmt2: tmp1 = (void *) (indirect call argument value)
392 stmt3: __gcov_indirect_call_callee = tmp1;
393
394 Example:
395 f_1 = foo;
396 __gcov_indirect_call_counters = &__gcov4.main[0];
397 PROF_9 = f_1;
398 __gcov_indirect_call_callee = PROF_9;
399 _4 = f_1 ();
327 */ 400 */
328 401
329 tmp1 = create_tmp_reg (ptr_void, "PROF");
330 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); 402 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
403 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
331 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); 404 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
332 gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2));
333 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2)); 405 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
334 406
335 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); 407 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
336 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); 408 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
337 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); 409 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
344 */ 416 */
345 417
346 void 418 void
347 gimple_gen_ic_func_profiler (void) 419 gimple_gen_ic_func_profiler (void)
348 { 420 {
349 struct cgraph_node * c_node = cgraph_node (current_function_decl); 421 struct cgraph_node * c_node = cgraph_node::get (current_function_decl);
350 gimple_stmt_iterator gsi; 422 gcall *stmt1;
351 gimple stmt1, stmt2; 423 tree tree_uid, cur_func, void0;
352 tree tree_uid, cur_func, counter_ptr, ptr_var, void0; 424
353 425 if (c_node->only_called_directly_p ())
354 if (cgraph_only_called_directly_p (c_node))
355 return; 426 return;
356 427
357 gimple_init_edge_profiler (); 428 gimple_init_gcov_profiler ();
358 429
359 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); 430 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
431 basic_block cond_bb = split_edge (single_succ_edge (entry));
432 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
433
434 /* We need to do an extra split in order to not create an input
435 for a possible PHI node. */
436 split_edge (single_succ_edge (update_bb));
437
438 edge true_edge = single_succ_edge (cond_bb);
439 true_edge->flags = EDGE_TRUE_VALUE;
440
441 profile_probability probability;
442 if (DECL_VIRTUAL_P (current_function_decl))
443 probability = profile_probability::very_likely ();
444 else
445 probability = profile_probability::unlikely ();
446
447 true_edge->probability = probability;
448 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
449 EDGE_FALSE_VALUE);
450 e->probability = true_edge->probability.invert ();
451
452 /* Insert code:
453
454 if (__gcov_indirect_call_callee != NULL)
455 __gcov_indirect_call_profiler_v2 (profile_id, &current_function_decl);
456
457 The function __gcov_indirect_call_profiler_v2 is responsible for
458 resetting __gcov_indirect_call_callee to NULL. */
459
460 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
461 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
462
463 tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE,
464 true, GSI_SAME_STMT);
465
466 gcond *cond = gimple_build_cond (NE_EXPR, ref,
467 void0, NULL, NULL);
468 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
469
470 gsi = gsi_after_labels (update_bb);
360 471
361 cur_func = force_gimple_operand_gsi (&gsi, 472 cur_func = force_gimple_operand_gsi (&gsi,
362 build_addr (current_function_decl, 473 build_addr (current_function_decl),
363 current_function_decl),
364 true, NULL_TREE, 474 true, NULL_TREE,
365 true, GSI_SAME_STMT); 475 true, GSI_SAME_STMT);
366 counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var, 476 tree_uid = build_int_cst
367 true, NULL_TREE, true, 477 (gcov_type_node,
368 GSI_SAME_STMT); 478 cgraph_node::get (current_function_decl)->profile_id);
369 ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, 479 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
370 true, NULL_TREE, true, 480 tree_uid, cur_func);
371 GSI_SAME_STMT);
372 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
373 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
374 counter_ptr, tree_uid, cur_func, ptr_var);
375 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); 481 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
376 482 }
377 /* Set __gcov_indirect_call_callee to 0, 483
378 so that calls from other modules won't get misattributed 484 /* Output instructions as GIMPLE tree at the beginning for each function.
379 to the last caller of the current callee. */ 485 TAG is the tag of the section for counters, BASE is offset of the
380 void0 = build_int_cst (build_pointer_type (void_type_node), 0); 486 counter position and GSI is the iterator we place the counter. */
381 stmt2 = gimple_build_assign (ic_void_ptr_var, void0); 487
382 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); 488 void
383 } 489 gimple_gen_time_profiler (unsigned tag, unsigned base)
384 490 {
385 /* Output instructions as GIMPLE trees for code to find the most common value 491 tree type = get_gcov_type ();
386 of a difference between two evaluations of an expression. 492 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
387 VALUE is the expression whose value is profiled. TAG is the tag of the 493 basic_block cond_bb = split_edge (single_succ_edge (entry));
388 section for counters, BASE is offset of the counter position. */ 494 basic_block update_bb = split_edge (single_succ_edge (cond_bb));
389 495
390 void 496 /* We need to do an extra split in order to not create an input
391 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, 497 for a possible PHI node. */
392 unsigned tag ATTRIBUTE_UNUSED, 498 split_edge (single_succ_edge (update_bb));
393 unsigned base ATTRIBUTE_UNUSED) 499
394 { 500 edge true_edge = single_succ_edge (cond_bb);
395 /* FIXME implement this. */ 501 true_edge->flags = EDGE_TRUE_VALUE;
396 #ifdef ENABLE_CHECKING 502 true_edge->probability = profile_probability::unlikely ();
397 internal_error ("unimplemented functionality"); 503 edge e
398 #endif 504 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
399 gcc_unreachable (); 505 e->probability = true_edge->probability.invert ();
506
507 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
508 tree original_ref = tree_coverage_counter_ref (tag, base);
509 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
510 true, GSI_SAME_STMT);
511 tree one = build_int_cst (type, 1);
512
513 /* Emit: if (counters[0] != 0). */
514 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
515 NULL, NULL);
516 gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
517
518 gsi = gsi_start_bb (update_bb);
519
520 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
521 if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
522 {
523 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
524 "time_profiler_counter_ptr");
525 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
526 tree_time_profiler_counter);
527 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
528 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
529 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
530 ? BUILT_IN_ATOMIC_ADD_FETCH_8:
531 BUILT_IN_ATOMIC_ADD_FETCH_4);
532 gcall *stmt = gimple_build_call (f, 3, ptr, one,
533 build_int_cst (integer_type_node,
534 MEMMODEL_RELAXED));
535 tree result_type = TREE_TYPE (TREE_TYPE (f));
536 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
537 gimple_set_lhs (stmt, tmp);
538 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
539 tmp = make_temp_ssa_name (type, NULL, "time_profile");
540 assign = gimple_build_assign (tmp, NOP_EXPR,
541 gimple_call_lhs (stmt));
542 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
543 assign = gimple_build_assign (original_ref, tmp);
544 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
545 }
546 else
547 {
548 tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
549 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
550 gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
551
552 tmp = make_temp_ssa_name (type, NULL, "time_profile");
553 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
554 one);
555 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
556 assign = gimple_build_assign (original_ref, tmp);
557 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
558 assign = gimple_build_assign (tree_time_profiler_counter, tmp);
559 gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
560 }
400 } 561 }
401 562
402 /* Output instructions as GIMPLE trees to increment the average histogram 563 /* Output instructions as GIMPLE trees to increment the average histogram
403 counter. VALUE is the expression whose value is profiled. TAG is the 564 counter. VALUE is the expression whose value is profiled. TAG is the
404 tag of the section for counters, BASE is offset of the counter position. */ 565 tag of the section for counters, BASE is offset of the counter position. */
405 566
406 void 567 void
407 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) 568 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
408 { 569 {
409 gimple stmt = value->hvalue.stmt; 570 gimple *stmt = value->hvalue.stmt;
410 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 571 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
411 tree ref_ptr = tree_coverage_counter_addr (tag, base); 572 tree ref_ptr = tree_coverage_counter_addr (tag, base);
412 gimple call; 573 gcall *call;
413 tree val; 574 tree val;
414 575
415 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 576 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
416 true, NULL_TREE, 577 true, NULL_TREE,
417 true, GSI_SAME_STMT); 578 true, GSI_SAME_STMT);
425 tag of the section for counters, BASE is offset of the counter position. */ 586 tag of the section for counters, BASE is offset of the counter position. */
426 587
427 void 588 void
428 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) 589 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
429 { 590 {
430 gimple stmt = value->hvalue.stmt; 591 gimple *stmt = value->hvalue.stmt;
431 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 592 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
432 tree ref_ptr = tree_coverage_counter_addr (tag, base); 593 tree ref_ptr = tree_coverage_counter_addr (tag, base);
433 gimple call; 594 gcall *call;
434 tree val; 595 tree val;
435 596
436 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 597 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
437 true, NULL_TREE, true, GSI_SAME_STMT); 598 true, NULL_TREE, true, GSI_SAME_STMT);
438 val = prepare_instrumented_value (&gsi, value); 599 val = prepare_instrumented_value (&gsi, value);
439 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); 600 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
440 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 601 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
441 } 602 }
442 603
604 #ifndef HAVE_sync_compare_and_swapsi
605 #define HAVE_sync_compare_and_swapsi 0
606 #endif
607 #ifndef HAVE_atomic_compare_and_swapsi
608 #define HAVE_atomic_compare_and_swapsi 0
609 #endif
610
611 #ifndef HAVE_sync_compare_and_swapdi
612 #define HAVE_sync_compare_and_swapdi 0
613 #endif
614 #ifndef HAVE_atomic_compare_and_swapdi
615 #define HAVE_atomic_compare_and_swapdi 0
616 #endif
617
443 /* Profile all functions in the callgraph. */ 618 /* Profile all functions in the callgraph. */
444 619
445 static unsigned int 620 static unsigned int
446 tree_profiling (void) 621 tree_profiling (void)
447 { 622 {
448 struct cgraph_node *node; 623 struct cgraph_node *node;
449 624
450 /* Don't profile functions produced at destruction time, particularly 625 /* Verify whether we can utilize atomic update operations. */
451 the gcov datastructure initializer. Don't profile if it has been 626 bool can_support_atomic = false;
452 already instrumented either (when OpenMP expansion creates 627 unsigned HOST_WIDE_INT gcov_type_size
453 child function from already instrumented body). */ 628 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ()));
454 if (cgraph_state == CGRAPH_STATE_FINISHED) 629 if (gcov_type_size == 4)
455 return 0; 630 can_support_atomic
456 631 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi;
457 for (node = cgraph_nodes; node; node = node->next) 632 else if (gcov_type_size == 8)
633 can_support_atomic
634 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi;
635
636 if (flag_profile_update == PROFILE_UPDATE_ATOMIC
637 && !can_support_atomic)
458 { 638 {
459 if (!node->analyzed 639 warning (0, "target does not support atomic profile update, "
460 || !gimple_has_body_p (node->decl) 640 "single mode is selected");
461 || !(!node->clone_of || node->decl != node->clone_of->decl)) 641 flag_profile_update = PROFILE_UPDATE_SINGLE;
642 }
643 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC)
644 flag_profile_update = can_support_atomic
645 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE;
646
647 /* This is a small-ipa pass that gets called only once, from
648 cgraphunit.c:ipa_passes(). */
649 gcc_assert (symtab->state == IPA_SSA);
650
651 init_node_map (true);
652
653 FOR_EACH_DEFINED_FUNCTION (node)
654 {
655 if (!gimple_has_body_p (node->decl))
462 continue; 656 continue;
463 657
464 /* Don't profile functions produced for builtin stuff. */ 658 /* Don't profile functions produced for builtin stuff. */
465 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION 659 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
466 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
467 continue; 660 continue;
468 661
662 if (lookup_attribute ("no_profile_instrument_function",
663 DECL_ATTRIBUTES (node->decl)))
664 continue;
665 /* Do not instrument extern inline functions when testing coverage.
666 While this is not perfectly consistent (early inlined extern inlines
667 will get acocunted), testsuite expects that. */
668 if (DECL_EXTERNAL (node->decl)
669 && flag_test_coverage)
670 continue;
671
469 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); 672 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
470 current_function_decl = node->decl; 673
471 674 /* Local pure-const may imply need to fixup the cfg. */
472 /* Re-set global shared temporary variable for edge-counters. */ 675 if (execute_fixup_cfg () & TODO_cleanup_cfg)
473 gcov_type_tmp_var = NULL_TREE; 676 cleanup_tree_cfg ();
474 677
475 branch_prob (); 678 branch_prob ();
476 679
477 if (! flag_branch_probabilities 680 if (! flag_branch_probabilities
478 && flag_profile_values) 681 && flag_profile_values)
486 /* The above could hose dominator info. Currently there is 689 /* The above could hose dominator info. Currently there is
487 none coming in, this is a safety valve. It should be 690 none coming in, this is a safety valve. It should be
488 easy to adjust it, if and when there is some. */ 691 easy to adjust it, if and when there is some. */
489 free_dominance_info (CDI_DOMINATORS); 692 free_dominance_info (CDI_DOMINATORS);
490 free_dominance_info (CDI_POST_DOMINATORS); 693 free_dominance_info (CDI_POST_DOMINATORS);
491
492 current_function_decl = NULL;
493 pop_cfun (); 694 pop_cfun ();
494 } 695 }
495 696
496 /* Drop pure/const flags from instrumented functions. */ 697 /* Drop pure/const flags from instrumented functions. */
497 for (node = cgraph_nodes; node; node = node->next) 698 if (profile_arc_flag || flag_test_coverage)
498 { 699 FOR_EACH_DEFINED_FUNCTION (node)
499 if (!node->analyzed 700 {
500 || !gimple_has_body_p (node->decl) 701 if (!gimple_has_body_p (node->decl)
501 || !(!node->clone_of || node->decl != node->clone_of->decl)) 702 || !(!node->clone_of
502 continue; 703 || node->decl != node->clone_of->decl))
503 704 continue;
504 /* Don't profile functions produced for builtin stuff. */ 705
505 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION 706 /* Don't profile functions produced for builtin stuff. */
506 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile) 707 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
507 continue; 708 continue;
508 709
509 cgraph_set_const_flag (node, false, false); 710 node->set_const_flag (false, false);
510 cgraph_set_pure_flag (node, false, false); 711 node->set_pure_flag (false, false);
511 } 712 }
512 713
513 /* Update call statements and rebuild the cgraph. */ 714 /* Update call statements and rebuild the cgraph. */
514 for (node = cgraph_nodes; node; node = node->next) 715 FOR_EACH_DEFINED_FUNCTION (node)
515 { 716 {
516 basic_block bb; 717 basic_block bb;
517 718
518 if (!node->analyzed 719 if (!gimple_has_body_p (node->decl)
519 || !gimple_has_body_p (node->decl) 720 || !(!node->clone_of
520 || !(!node->clone_of || node->decl != node->clone_of->decl)) 721 || node->decl != node->clone_of->decl))
521 continue; 722 continue;
522 723
523 /* Don't profile functions produced for builtin stuff. */ 724 /* Don't profile functions produced for builtin stuff. */
524 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION 725 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
525 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
526 continue; 726 continue;
527 727
528 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); 728 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
529 current_function_decl = node->decl; 729
530 730 FOR_EACH_BB_FN (bb, cfun)
531 FOR_EACH_BB (bb)
532 { 731 {
533 gimple_stmt_iterator gsi; 732 gimple_stmt_iterator gsi;
534 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 733 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
535 { 734 {
536 gimple stmt = gsi_stmt (gsi); 735 gimple *stmt = gsi_stmt (gsi);
537 if (is_gimple_call (stmt)) 736 if (is_gimple_call (stmt))
538 update_stmt (stmt); 737 update_stmt (stmt);
539 } 738 }
540 } 739 }
541 740
542 cfun->after_tree_profile = 1; 741 /* re-merge split blocks. */
742 cleanup_tree_cfg ();
543 update_ssa (TODO_update_ssa); 743 update_ssa (TODO_update_ssa);
544 744
545 rebuild_cgraph_edges (); 745 cgraph_edge::rebuild_edges ();
546 746
547 current_function_decl = NULL;
548 pop_cfun (); 747 pop_cfun ();
549 } 748 }
550 749
750 handle_missing_profiles ();
751
752 del_node_map ();
551 return 0; 753 return 0;
552 } 754 }
553 755
554 /* When profile instrumentation, use or test coverage shall be performed. */ 756 namespace {
555 757
556 static bool 758 const pass_data pass_data_ipa_tree_profile =
557 gate_tree_profile_ipa (void) 759 {
558 { 760 SIMPLE_IPA_PASS, /* type */
559 return (!in_lto_p 761 "profile", /* name */
762 OPTGROUP_NONE, /* optinfo_flags */
763 TV_IPA_PROFILE, /* tv_id */
764 0, /* properties_required */
765 0, /* properties_provided */
766 0, /* properties_destroyed */
767 0, /* todo_flags_start */
768 TODO_dump_symtab, /* todo_flags_finish */
769 };
770
771 class pass_ipa_tree_profile : public simple_ipa_opt_pass
772 {
773 public:
774 pass_ipa_tree_profile (gcc::context *ctxt)
775 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
776 {}
777
778 /* opt_pass methods: */
779 virtual bool gate (function *);
780 virtual unsigned int execute (function *) { return tree_profiling (); }
781
782 }; // class pass_ipa_tree_profile
783
784 bool
785 pass_ipa_tree_profile::gate (function *)
786 {
787 /* When profile instrumentation, use or test coverage shall be performed.
788 But for AutoFDO, this there is no instrumentation, thus this pass is
789 diabled. */
790 return (!in_lto_p && !flag_auto_profile
560 && (flag_branch_probabilities || flag_test_coverage 791 && (flag_branch_probabilities || flag_test_coverage
561 || profile_arc_flag)); 792 || profile_arc_flag));
562 } 793 }
563 794
564 struct simple_ipa_opt_pass pass_ipa_tree_profile = 795 } // anon namespace
565 { 796
566 { 797 simple_ipa_opt_pass *
567 SIMPLE_IPA_PASS, 798 make_pass_ipa_tree_profile (gcc::context *ctxt)
568 "tree_profile_ipa", /* name */ 799 {
569 gate_tree_profile_ipa, /* gate */ 800 return new pass_ipa_tree_profile (ctxt);
570 tree_profiling, /* execute */ 801 }
571 NULL, /* sub */
572 NULL, /* next */
573 0, /* static_pass_number */
574 TV_IPA_PROFILE, /* tv_id */
575 0, /* properties_required */
576 0, /* properties_provided */
577 0, /* properties_destroyed */
578 0, /* todo_flags_start */
579 TODO_dump_func /* todo_flags_finish */
580 }
581 };
582 802
583 #include "gt-tree-profile.h" 803 #include "gt-tree-profile.h"