comparison gcc/tree-profile.c @ 67:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children 04ced10e8804
comparison
equal deleted inserted replaced
65:65488c3d617d 67:f6334be47118
30 #include "system.h" 30 #include "system.h"
31 #include "coretypes.h" 31 #include "coretypes.h"
32 #include "tm.h" 32 #include "tm.h"
33 #include "flags.h" 33 #include "flags.h"
34 #include "regs.h" 34 #include "regs.h"
35 #include "expr.h"
36 #include "function.h" 35 #include "function.h"
37 #include "toplev.h" 36 #include "basic-block.h"
37 #include "diagnostic-core.h"
38 #include "coverage.h" 38 #include "coverage.h"
39 #include "tree.h" 39 #include "tree.h"
40 #include "tree-flow.h" 40 #include "tree-flow.h"
41 #include "tree-dump.h" 41 #include "tree-dump.h"
42 #include "tree-pass.h" 42 #include "tree-pass.h"
63 /* Add code: 63 /* Add code:
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter 64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
65 static void* __gcov_indirect_call_callee; // actual callee address 65 static void* __gcov_indirect_call_callee; // actual callee address
66 */ 66 */
67 static void 67 static void
68 tree_init_ic_make_global_vars (void) 68 init_ic_make_global_vars (void)
69 { 69 {
70 tree gcov_type_ptr; 70 tree gcov_type_ptr;
71 71
72 ptr_void = build_pointer_type (void_type_node); 72 ptr_void = build_pointer_type (void_type_node);
73 73
93 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; 93 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
94 varpool_finalize_decl (ic_gcov_type_ptr_var); 94 varpool_finalize_decl (ic_gcov_type_ptr_var);
95 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var)); 95 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var));
96 } 96 }
97 97
98 static void 98 void
99 tree_init_edge_profiler (void) 99 gimple_init_edge_profiler (void)
100 { 100 {
101 tree interval_profiler_fn_type; 101 tree interval_profiler_fn_type;
102 tree pow2_profiler_fn_type; 102 tree pow2_profiler_fn_type;
103 tree one_value_profiler_fn_type; 103 tree one_value_profiler_fn_type;
104 tree gcov_type_ptr; 104 tree gcov_type_ptr;
117 integer_type_node, 117 integer_type_node,
118 unsigned_type_node, NULL_TREE); 118 unsigned_type_node, NULL_TREE);
119 tree_interval_profiler_fn 119 tree_interval_profiler_fn
120 = build_fn_decl ("__gcov_interval_profiler", 120 = build_fn_decl ("__gcov_interval_profiler",
121 interval_profiler_fn_type); 121 interval_profiler_fn_type);
122 TREE_NOTHROW (tree_interval_profiler_fn) = 1;
123 DECL_ATTRIBUTES (tree_interval_profiler_fn)
124 = tree_cons (get_identifier ("leaf"), NULL,
125 DECL_ATTRIBUTES (tree_interval_profiler_fn));
122 126
123 /* void (*) (gcov_type *, gcov_type) */ 127 /* void (*) (gcov_type *, gcov_type) */
124 pow2_profiler_fn_type 128 pow2_profiler_fn_type
125 = build_function_type_list (void_type_node, 129 = build_function_type_list (void_type_node,
126 gcov_type_ptr, gcov_type_node, 130 gcov_type_ptr, gcov_type_node,
127 NULL_TREE); 131 NULL_TREE);
128 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", 132 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
129 pow2_profiler_fn_type); 133 pow2_profiler_fn_type);
134 TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
135 DECL_ATTRIBUTES (tree_pow2_profiler_fn)
136 = tree_cons (get_identifier ("leaf"), NULL,
137 DECL_ATTRIBUTES (tree_pow2_profiler_fn));
130 138
131 /* void (*) (gcov_type *, gcov_type) */ 139 /* void (*) (gcov_type *, gcov_type) */
132 one_value_profiler_fn_type 140 one_value_profiler_fn_type
133 = build_function_type_list (void_type_node, 141 = build_function_type_list (void_type_node,
134 gcov_type_ptr, gcov_type_node, 142 gcov_type_ptr, gcov_type_node,
135 NULL_TREE); 143 NULL_TREE);
136 tree_one_value_profiler_fn 144 tree_one_value_profiler_fn
137 = build_fn_decl ("__gcov_one_value_profiler", 145 = build_fn_decl ("__gcov_one_value_profiler",
138 one_value_profiler_fn_type); 146 one_value_profiler_fn_type);
139 147 TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
140 tree_init_ic_make_global_vars (); 148 DECL_ATTRIBUTES (tree_one_value_profiler_fn)
149 = tree_cons (get_identifier ("leaf"), NULL,
150 DECL_ATTRIBUTES (tree_one_value_profiler_fn));
151
152 init_ic_make_global_vars ();
141 153
142 /* void (*) (gcov_type *, gcov_type, void *, void *) */ 154 /* void (*) (gcov_type *, gcov_type, void *, void *) */
143 ic_profiler_fn_type 155 ic_profiler_fn_type
144 = build_function_type_list (void_type_node, 156 = build_function_type_list (void_type_node,
145 gcov_type_ptr, gcov_type_node, 157 gcov_type_ptr, gcov_type_node,
146 ptr_void, 158 ptr_void,
147 ptr_void, NULL_TREE); 159 ptr_void, NULL_TREE);
148 tree_indirect_call_profiler_fn 160 tree_indirect_call_profiler_fn
149 = build_fn_decl ("__gcov_indirect_call_profiler", 161 = build_fn_decl ("__gcov_indirect_call_profiler",
150 ic_profiler_fn_type); 162 ic_profiler_fn_type);
163 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
164 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
165 = tree_cons (get_identifier ("leaf"), NULL,
166 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
167
151 /* void (*) (gcov_type *, gcov_type) */ 168 /* void (*) (gcov_type *, gcov_type) */
152 average_profiler_fn_type 169 average_profiler_fn_type
153 = build_function_type_list (void_type_node, 170 = build_function_type_list (void_type_node,
154 gcov_type_ptr, gcov_type_node, NULL_TREE); 171 gcov_type_ptr, gcov_type_node, NULL_TREE);
155 tree_average_profiler_fn 172 tree_average_profiler_fn
156 = build_fn_decl ("__gcov_average_profiler", 173 = build_fn_decl ("__gcov_average_profiler",
157 average_profiler_fn_type); 174 average_profiler_fn_type);
175 TREE_NOTHROW (tree_average_profiler_fn) = 1;
176 DECL_ATTRIBUTES (tree_average_profiler_fn)
177 = tree_cons (get_identifier ("leaf"), NULL,
178 DECL_ATTRIBUTES (tree_average_profiler_fn));
158 tree_ior_profiler_fn 179 tree_ior_profiler_fn
159 = build_fn_decl ("__gcov_ior_profiler", 180 = build_fn_decl ("__gcov_ior_profiler",
160 average_profiler_fn_type); 181 average_profiler_fn_type);
182 TREE_NOTHROW (tree_ior_profiler_fn) = 1;
183 DECL_ATTRIBUTES (tree_ior_profiler_fn)
184 = tree_cons (get_identifier ("leaf"), NULL,
185 DECL_ATTRIBUTES (tree_ior_profiler_fn));
186
161 /* LTO streamer needs assembler names. Because we create these decls 187 /* LTO streamer needs assembler names. Because we create these decls
162 late, we need to initialize them by hand. */ 188 late, we need to initialize them by hand. */
163 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); 189 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
164 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); 190 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
165 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); 191 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
167 DECL_ASSEMBLER_NAME (tree_average_profiler_fn); 193 DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
168 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); 194 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
169 } 195 }
170 } 196 }
171 197
172 /* New call was added, make goto call edges if neccesary. */
173
174 static void
175 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
176 {
177 gimple stmt = gsi_stmt (gsi);
178
179 if (!stmt_can_make_abnormal_goto (stmt))
180 return;
181 if (!gsi_end_p (gsi))
182 split_block (gimple_bb (stmt), stmt);
183 make_abnormal_goto_edges (gimple_bb (stmt), true);
184 }
185
186 /* Output instructions as GIMPLE trees to increment the edge 198 /* Output instructions as GIMPLE trees to increment the edge
187 execution count, and insert them on E. We rely on 199 execution count, and insert them on E. We rely on
188 gsi_insert_on_edge to preserve the order. */ 200 gsi_insert_on_edge to preserve the order. */
189 201
190 static void 202 void
191 tree_gen_edge_profiler (int edgeno, edge e) 203 gimple_gen_edge_profiler (int edgeno, edge e)
192 { 204 {
193 tree ref, one; 205 tree ref, one;
194 gimple stmt1, stmt2, stmt3; 206 gimple stmt1, stmt2, stmt3;
195 207
196 /* We share one temporary variable declaration per function. This 208 /* We share one temporary variable declaration per function. This
197 gets re-set in tree_profiling. */ 209 gets re-set in tree_profiling. */
198 if (gcov_type_tmp_var == NULL_TREE) 210 if (gcov_type_tmp_var == NULL_TREE)
199 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter"); 211 gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter");
200 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); 212 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
201 one = build_int_cst (gcov_type_node, 1); 213 one = build_int_cst (gcov_type_node, 1);
202 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); 214 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
215 gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1));
203 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var, 216 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
204 gcov_type_tmp_var, one); 217 gimple_assign_lhs (stmt1), one);
205 stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var); 218 gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2));
219 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
206 gsi_insert_on_edge (e, stmt1); 220 gsi_insert_on_edge (e, stmt1);
207 gsi_insert_on_edge (e, stmt2); 221 gsi_insert_on_edge (e, stmt2);
208 gsi_insert_on_edge (e, stmt3); 222 gsi_insert_on_edge (e, stmt3);
209 } 223 }
210 224
223 237
224 /* Output instructions as GIMPLE trees to increment the interval histogram 238 /* Output instructions as GIMPLE trees to increment the interval histogram
225 counter. VALUE is the expression whose value is profiled. TAG is the 239 counter. VALUE is the expression whose value is profiled. TAG is the
226 tag of the section for counters, BASE is offset of the counter position. */ 240 tag of the section for counters, BASE is offset of the counter position. */
227 241
228 static void 242 void
229 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) 243 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
230 { 244 {
231 gimple stmt = value->hvalue.stmt; 245 gimple stmt = value->hvalue.stmt;
232 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 246 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
233 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; 247 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
234 gimple call; 248 gimple call;
243 true, NULL_TREE, true, GSI_SAME_STMT); 257 true, NULL_TREE, true, GSI_SAME_STMT);
244 val = prepare_instrumented_value (&gsi, value); 258 val = prepare_instrumented_value (&gsi, value);
245 call = gimple_build_call (tree_interval_profiler_fn, 4, 259 call = gimple_build_call (tree_interval_profiler_fn, 4,
246 ref_ptr, val, start, steps); 260 ref_ptr, val, start, steps);
247 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 261 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
248 add_abnormal_goto_call_edges (gsi);
249 } 262 }
250 263
251 /* Output instructions as GIMPLE trees to increment the power of two histogram 264 /* Output instructions as GIMPLE trees to increment the power of two histogram
252 counter. VALUE is the expression whose value is profiled. TAG is the tag 265 counter. VALUE is the expression whose value is profiled. TAG is the tag
253 of the section for counters, BASE is offset of the counter position. */ 266 of the section for counters, BASE is offset of the counter position. */
254 267
255 static void 268 void
256 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) 269 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
257 { 270 {
258 gimple stmt = value->hvalue.stmt; 271 gimple stmt = value->hvalue.stmt;
259 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 272 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
260 tree ref_ptr = tree_coverage_counter_addr (tag, base); 273 tree ref_ptr = tree_coverage_counter_addr (tag, base);
261 gimple call; 274 gimple call;
264 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 277 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
265 true, NULL_TREE, true, GSI_SAME_STMT); 278 true, NULL_TREE, true, GSI_SAME_STMT);
266 val = prepare_instrumented_value (&gsi, value); 279 val = prepare_instrumented_value (&gsi, value);
267 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); 280 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
268 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 281 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
269 add_abnormal_goto_call_edges (gsi);
270 } 282 }
271 283
272 /* Output instructions as GIMPLE trees for code to find the most common value. 284 /* Output instructions as GIMPLE trees for code to find the most common value.
273 VALUE is the expression whose value is profiled. TAG is the tag of the 285 VALUE is the expression whose value is profiled. TAG is the tag of the
274 section for counters, BASE is offset of the counter position. */ 286 section for counters, BASE is offset of the counter position. */
275 287
276 static void 288 void
277 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) 289 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
278 { 290 {
279 gimple stmt = value->hvalue.stmt; 291 gimple stmt = value->hvalue.stmt;
280 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 292 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
281 tree ref_ptr = tree_coverage_counter_addr (tag, base); 293 tree ref_ptr = tree_coverage_counter_addr (tag, base);
282 gimple call; 294 gimple call;
285 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 297 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
286 true, NULL_TREE, true, GSI_SAME_STMT); 298 true, NULL_TREE, true, GSI_SAME_STMT);
287 val = prepare_instrumented_value (&gsi, value); 299 val = prepare_instrumented_value (&gsi, value);
288 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val); 300 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
289 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 301 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
290 add_abnormal_goto_call_edges (gsi);
291 } 302 }
292 303
293 304
294 /* Output instructions as GIMPLE trees for code to find the most 305 /* Output instructions as GIMPLE trees for code to find the most
295 common called function in indirect call. 306 common called function in indirect call.
296 VALUE is the call expression whose indirect callee is profiled. 307 VALUE is the call expression whose indirect callee is profiled.
297 TAG is the tag of the section for counters, BASE is offset of the 308 TAG is the tag of the section for counters, BASE is offset of the
298 counter position. */ 309 counter position. */
299 310
300 static void 311 void
301 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) 312 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
302 { 313 {
303 tree tmp1; 314 tree tmp1;
304 gimple stmt1, stmt2, stmt3; 315 gimple stmt1, stmt2, stmt3;
305 gimple stmt = value->hvalue.stmt; 316 gimple stmt = value->hvalue.stmt;
306 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 317 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
313 324
314 __gcov_indirect_call_counters = get_relevant_counter_ptr (); 325 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
315 __gcov_indirect_call_callee = (void *) indirect call argument; 326 __gcov_indirect_call_callee = (void *) indirect call argument;
316 */ 327 */
317 328
318 tmp1 = create_tmp_var (ptr_void, "PROF"); 329 tmp1 = create_tmp_reg (ptr_void, "PROF");
319 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); 330 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
320 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); 331 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
321 stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1); 332 gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2));
333 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
322 334
323 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); 335 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
324 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); 336 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
325 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); 337 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
326 } 338 }
329 /* Output instructions as GIMPLE trees for code to find the most 341 /* Output instructions as GIMPLE trees for code to find the most
330 common called function in indirect call. Insert instructions at the 342 common called function in indirect call. Insert instructions at the
331 beginning of every possible called function. 343 beginning of every possible called function.
332 */ 344 */
333 345
334 static void 346 void
335 tree_gen_ic_func_profiler (void) 347 gimple_gen_ic_func_profiler (void)
336 { 348 {
337 struct cgraph_node * c_node = cgraph_node (current_function_decl); 349 struct cgraph_node * c_node = cgraph_node (current_function_decl);
338 gimple_stmt_iterator gsi; 350 gimple_stmt_iterator gsi;
339 edge e;
340 basic_block bb;
341 edge_iterator ei;
342 gimple stmt1, stmt2; 351 gimple stmt1, stmt2;
343 tree tree_uid, cur_func; 352 tree tree_uid, cur_func, counter_ptr, ptr_var, void0;
344 353
345 if (cgraph_only_called_directly_p (c_node)) 354 if (cgraph_only_called_directly_p (c_node))
346 return; 355 return;
347 356
348 tree_init_edge_profiler (); 357 gimple_init_edge_profiler ();
349 358
350 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) 359 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
351 { 360
352 tree void0; 361 cur_func = force_gimple_operand_gsi (&gsi,
353 362 build_addr (current_function_decl,
354 bb = split_edge (e); 363 current_function_decl),
355 gsi = gsi_start_bb (bb); 364 true, NULL_TREE,
356 365 true, GSI_SAME_STMT);
357 cur_func = force_gimple_operand_gsi (&gsi, 366 counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
358 build_addr (current_function_decl, 367 true, NULL_TREE, true,
359 current_function_decl), 368 GSI_SAME_STMT);
360 true, NULL_TREE, 369 ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
361 true, GSI_SAME_STMT); 370 true, NULL_TREE, true,
362 tree_uid = build_int_cst (gcov_type_node, c_node->pid); 371 GSI_SAME_STMT);
363 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4, 372 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
364 ic_gcov_type_ptr_var, 373 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
365 tree_uid, 374 counter_ptr, tree_uid, cur_func, ptr_var);
366 cur_func, 375 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
367 ic_void_ptr_var); 376
368 gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT); 377 /* Set __gcov_indirect_call_callee to 0,
369 gcc_assert (EDGE_COUNT (bb->succs) == 1); 378 so that calls from other modules won't get misattributed
370 bb = split_edge (EDGE_I (bb->succs, 0)); 379 to the last caller of the current callee. */
371 add_abnormal_goto_call_edges (gsi); 380 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
372 381 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
373 gsi = gsi_start_bb (bb); 382 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
374 /* Set __gcov_indirect_call_callee to 0,
375 so that calls from other modules won't get misattributed
376 to the last caller of the current callee. */
377 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
378 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
379 gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
380 }
381 } 383 }
382 384
383 /* Output instructions as GIMPLE trees for code to find the most common value 385 /* Output instructions as GIMPLE trees for code to find the most common value
384 of a difference between two evaluations of an expression. 386 of a difference between two evaluations of an expression.
385 VALUE is the expression whose value is profiled. TAG is the tag of the 387 VALUE is the expression whose value is profiled. TAG is the tag of the
386 section for counters, BASE is offset of the counter position. */ 388 section for counters, BASE is offset of the counter position. */
387 389
388 static void 390 void
389 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, 391 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
390 unsigned tag ATTRIBUTE_UNUSED, 392 unsigned tag ATTRIBUTE_UNUSED,
391 unsigned base ATTRIBUTE_UNUSED) 393 unsigned base ATTRIBUTE_UNUSED)
392 { 394 {
393 /* FIXME implement this. */ 395 /* FIXME implement this. */
394 #ifdef ENABLE_CHECKING 396 #ifdef ENABLE_CHECKING
399 401
400 /* Output instructions as GIMPLE trees to increment the average histogram 402 /* Output instructions as GIMPLE trees to increment the average histogram
401 counter. VALUE is the expression whose value is profiled. TAG is the 403 counter. VALUE is the expression whose value is profiled. TAG is the
402 tag of the section for counters, BASE is offset of the counter position. */ 404 tag of the section for counters, BASE is offset of the counter position. */
403 405
404 static void 406 void
405 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) 407 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
406 { 408 {
407 gimple stmt = value->hvalue.stmt; 409 gimple stmt = value->hvalue.stmt;
408 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 410 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
409 tree ref_ptr = tree_coverage_counter_addr (tag, base); 411 tree ref_ptr = tree_coverage_counter_addr (tag, base);
410 gimple call; 412 gimple call;
414 true, NULL_TREE, 416 true, NULL_TREE,
415 true, GSI_SAME_STMT); 417 true, GSI_SAME_STMT);
416 val = prepare_instrumented_value (&gsi, value); 418 val = prepare_instrumented_value (&gsi, value);
417 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val); 419 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
418 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 420 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
419 add_abnormal_goto_call_edges (gsi);
420 } 421 }
421 422
422 /* Output instructions as GIMPLE trees to increment the ior histogram 423 /* Output instructions as GIMPLE trees to increment the ior histogram
423 counter. VALUE is the expression whose value is profiled. TAG is the 424 counter. VALUE is the expression whose value is profiled. TAG is the
424 tag of the section for counters, BASE is offset of the counter position. */ 425 tag of the section for counters, BASE is offset of the counter position. */
425 426
426 static void 427 void
427 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) 428 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
428 { 429 {
429 gimple stmt = value->hvalue.stmt; 430 gimple stmt = value->hvalue.stmt;
430 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 431 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
431 tree ref_ptr = tree_coverage_counter_addr (tag, base); 432 tree ref_ptr = tree_coverage_counter_addr (tag, base);
432 gimple call; 433 gimple call;
435 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, 436 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
436 true, NULL_TREE, true, GSI_SAME_STMT); 437 true, NULL_TREE, true, GSI_SAME_STMT);
437 val = prepare_instrumented_value (&gsi, value); 438 val = prepare_instrumented_value (&gsi, value);
438 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); 439 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
439 gsi_insert_before (&gsi, call, GSI_NEW_STMT); 440 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
440 add_abnormal_goto_call_edges (gsi); 441 }
441 } 442
442 443 /* Profile all functions in the callgraph. */
443 /* Return 1 if tree-based profiling is in effect, else 0.
444 If it is, set up hooks for tree-based profiling.
445 Gate for pass_tree_profile. */
446
447 static bool
448 do_tree_profiling (void)
449 {
450 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
451 {
452 tree_register_profile_hooks ();
453 gimple_register_value_prof_hooks ();
454 return true;
455 }
456 return false;
457 }
458 444
459 static unsigned int 445 static unsigned int
460 tree_profiling (void) 446 tree_profiling (void)
461 { 447 {
448 struct cgraph_node *node;
449
462 /* Don't profile functions produced at destruction time, particularly 450 /* Don't profile functions produced at destruction time, particularly
463 the gcov datastructure initializer. Don't profile if it has been 451 the gcov datastructure initializer. Don't profile if it has been
464 already instrumented either (when OpenMP expansion creates 452 already instrumented either (when OpenMP expansion creates
465 child function from already instrumented body). */ 453 child function from already instrumented body). */
466 if (cgraph_state == CGRAPH_STATE_FINISHED 454 if (cgraph_state == CGRAPH_STATE_FINISHED)
467 || cfun->after_tree_profile)
468 return 0; 455 return 0;
469 456
470 /* Re-set global shared temporary variable for edge-counters. */ 457 for (node = cgraph_nodes; node; node = node->next)
471 gcov_type_tmp_var = NULL_TREE; 458 {
472 459 if (!node->analyzed
473 branch_prob (); 460 || !gimple_has_body_p (node->decl)
474 461 || !(!node->clone_of || node->decl != node->clone_of->decl))
475 if (! flag_branch_probabilities 462 continue;
476 && flag_profile_values) 463
477 tree_gen_ic_func_profiler (); 464 /* Don't profile functions produced for builtin stuff. */
478 465 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
479 if (flag_branch_probabilities 466 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
480 && flag_profile_values 467 continue;
481 && flag_value_profile_transformations) 468
482 value_profile_transformations (); 469 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
483 /* The above could hose dominator info. Currently there is 470 current_function_decl = node->decl;
484 none coming in, this is a safety valve. It should be 471
485 easy to adjust it, if and when there is some. */ 472 /* Re-set global shared temporary variable for edge-counters. */
486 free_dominance_info (CDI_DOMINATORS); 473 gcov_type_tmp_var = NULL_TREE;
487 free_dominance_info (CDI_POST_DOMINATORS); 474
488 cfun->after_tree_profile = 1; 475 branch_prob ();
476
477 if (! flag_branch_probabilities
478 && flag_profile_values)
479 gimple_gen_ic_func_profiler ();
480
481 if (flag_branch_probabilities
482 && flag_profile_values
483 && flag_value_profile_transformations)
484 gimple_value_profile_transformations ();
485
486 /* The above could hose dominator info. Currently there is
487 none coming in, this is a safety valve. It should be
488 easy to adjust it, if and when there is some. */
489 free_dominance_info (CDI_DOMINATORS);
490 free_dominance_info (CDI_POST_DOMINATORS);
491
492 current_function_decl = NULL;
493 pop_cfun ();
494 }
495
496 /* Drop pure/const flags from instrumented functions. */
497 for (node = cgraph_nodes; node; node = node->next)
498 {
499 if (!node->analyzed
500 || !gimple_has_body_p (node->decl)
501 || !(!node->clone_of || node->decl != node->clone_of->decl))
502 continue;
503
504 /* Don't profile functions produced for builtin stuff. */
505 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
506 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
507 continue;
508
509 cgraph_set_const_flag (node, false, false);
510 cgraph_set_pure_flag (node, false, false);
511 }
512
513 /* Update call statements and rebuild the cgraph. */
514 for (node = cgraph_nodes; node; node = node->next)
515 {
516 basic_block bb;
517
518 if (!node->analyzed
519 || !gimple_has_body_p (node->decl)
520 || !(!node->clone_of || node->decl != node->clone_of->decl))
521 continue;
522
523 /* Don't profile functions produced for builtin stuff. */
524 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
525 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
526 continue;
527
528 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
529 current_function_decl = node->decl;
530
531 FOR_EACH_BB (bb)
532 {
533 gimple_stmt_iterator gsi;
534 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
535 {
536 gimple stmt = gsi_stmt (gsi);
537 if (is_gimple_call (stmt))
538 update_stmt (stmt);
539 }
540 }
541
542 cfun->after_tree_profile = 1;
543 update_ssa (TODO_update_ssa);
544
545 rebuild_cgraph_edges ();
546
547 current_function_decl = NULL;
548 pop_cfun ();
549 }
550
489 return 0; 551 return 0;
490 } 552 }
491 553
492 struct gimple_opt_pass pass_tree_profile = 554 /* When profile instrumentation, use or test coverage shall be performed. */
555
556 static bool
557 gate_tree_profile_ipa (void)
558 {
559 return (!in_lto_p
560 && (flag_branch_probabilities || flag_test_coverage
561 || profile_arc_flag));
562 }
563
564 struct simple_ipa_opt_pass pass_ipa_tree_profile =
493 { 565 {
494 { 566 {
495 GIMPLE_PASS, 567 SIMPLE_IPA_PASS,
496 "tree_profile", /* name */ 568 "tree_profile_ipa", /* name */
497 do_tree_profiling, /* gate */ 569 gate_tree_profile_ipa, /* gate */
498 tree_profiling, /* execute */ 570 tree_profiling, /* execute */
499 NULL, /* sub */ 571 NULL, /* sub */
500 NULL, /* next */ 572 NULL, /* next */
501 0, /* static_pass_number */ 573 0, /* static_pass_number */
502 TV_BRANCH_PROB, /* tv_id */ 574 TV_IPA_PROFILE, /* tv_id */
503 PROP_gimple_leh | PROP_cfg, /* properties_required */ 575 0, /* properties_required */
504 0, /* properties_provided */ 576 0, /* properties_provided */
505 0, /* properties_destroyed */ 577 0, /* properties_destroyed */
506 0, /* todo_flags_start */ 578 0, /* todo_flags_start */
507 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */ 579 TODO_dump_func /* todo_flags_finish */
508 } 580 }
509 }; 581 };
510 582
511 struct profile_hooks tree_profile_hooks =
512 {
513 tree_init_edge_profiler, /* init_edge_profiler */
514 tree_gen_edge_profiler, /* gen_edge_profiler */
515 tree_gen_interval_profiler, /* gen_interval_profiler */
516 tree_gen_pow2_profiler, /* gen_pow2_profiler */
517 tree_gen_one_value_profiler, /* gen_one_value_profiler */
518 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
519 tree_gen_ic_profiler, /* gen_ic_profiler */
520 tree_gen_average_profiler, /* gen_average_profiler */
521 tree_gen_ior_profiler /* gen_ior_profiler */
522 };
523
524 #include "gt-tree-profile.h" 583 #include "gt-tree-profile.h"