Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-profile.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Calculate branch probabilities, and basic block execution counts. | 1 /* Calculate branch probabilities, and basic block execution counts. |
2 Copyright (C) 1990-2018 Free Software Foundation, Inc. | 2 Copyright (C) 1990-2020 Free Software Foundation, Inc. |
3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; | 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; |
4 based on some ideas from Dain Samples of UC Berkeley. | 4 based on some ideas from Dain Samples of UC Berkeley. |
5 Further mangling by Bob Manson, Cygnus Support. | 5 Further mangling by Bob Manson, Cygnus Support. |
6 Converted to use trees by Dale Johannesen, Apple Computer. | 6 Converted to use trees by Dale Johannesen, Apple Computer. |
7 | 7 |
47 #include "tree-cfg.h" | 47 #include "tree-cfg.h" |
48 #include "tree-into-ssa.h" | 48 #include "tree-into-ssa.h" |
49 #include "value-prof.h" | 49 #include "value-prof.h" |
50 #include "profile.h" | 50 #include "profile.h" |
51 #include "tree-cfgcleanup.h" | 51 #include "tree-cfgcleanup.h" |
52 #include "params.h" | |
53 #include "stringpool.h" | 52 #include "stringpool.h" |
54 #include "attribs.h" | 53 #include "attribs.h" |
55 #include "tree-pretty-print.h" | 54 #include "tree-pretty-print.h" |
56 #include "langhooks.h" | 55 #include "langhooks.h" |
57 #include "stor-layout.h" | 56 #include "stor-layout.h" |
57 #include "xregex.h" | |
58 | 58 |
59 static GTY(()) tree gcov_type_node; | 59 static GTY(()) tree gcov_type_node; |
60 static GTY(()) tree tree_interval_profiler_fn; | 60 static GTY(()) tree tree_interval_profiler_fn; |
61 static GTY(()) tree tree_pow2_profiler_fn; | 61 static GTY(()) tree tree_pow2_profiler_fn; |
62 static GTY(()) tree tree_one_value_profiler_fn; | 62 static GTY(()) tree tree_topn_values_profiler_fn; |
63 static GTY(()) tree tree_indirect_call_profiler_fn; | 63 static GTY(()) tree tree_indirect_call_profiler_fn; |
64 static GTY(()) tree tree_average_profiler_fn; | 64 static GTY(()) tree tree_average_profiler_fn; |
65 static GTY(()) tree tree_ior_profiler_fn; | 65 static GTY(()) tree tree_ior_profiler_fn; |
66 static GTY(()) tree tree_time_profiler_counter; | 66 static GTY(()) tree tree_time_profiler_counter; |
67 | 67 |
71 static GTY(()) tree ic_tuple_callee_field; | 71 static GTY(()) tree ic_tuple_callee_field; |
72 | 72 |
73 /* Do initialization work for the edge profiler. */ | 73 /* Do initialization work for the edge profiler. */ |
74 | 74 |
75 /* Add code: | 75 /* Add code: |
76 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter | 76 __thread gcov* __gcov_indirect_call.counters; // pointer to actual counter |
77 __thread void* __gcov_indirect_call_callee; // actual callee address | 77 __thread void* __gcov_indirect_call.callee; // actual callee address |
78 __thread int __gcov_function_counter; // time profiler function counter | 78 __thread int __gcov_function_counter; // time profiler function counter |
79 */ | 79 */ |
80 static void | 80 static void |
81 init_ic_make_global_vars (void) | 81 init_ic_make_global_vars (void) |
82 { | 82 { |
98 finish_builtin_struct (tuple_type, "indirect_call_tuple", | 98 finish_builtin_struct (tuple_type, "indirect_call_tuple", |
99 ic_tuple_counters_field, NULL_TREE); | 99 ic_tuple_counters_field, NULL_TREE); |
100 | 100 |
101 ic_tuple_var | 101 ic_tuple_var |
102 = build_decl (UNKNOWN_LOCATION, VAR_DECL, | 102 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
103 get_identifier ( | 103 get_identifier ("__gcov_indirect_call"), tuple_type); |
104 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ? | |
105 "__gcov_indirect_call_topn" : | |
106 "__gcov_indirect_call")), | |
107 tuple_type); | |
108 TREE_PUBLIC (ic_tuple_var) = 1; | 104 TREE_PUBLIC (ic_tuple_var) = 1; |
109 DECL_ARTIFICIAL (ic_tuple_var) = 1; | 105 DECL_ARTIFICIAL (ic_tuple_var) = 1; |
110 DECL_INITIAL (ic_tuple_var) = NULL; | 106 DECL_INITIAL (ic_tuple_var) = NULL; |
111 DECL_EXTERNAL (ic_tuple_var) = 1; | 107 DECL_EXTERNAL (ic_tuple_var) = 1; |
112 if (targetm.have_tls) | 108 if (targetm.have_tls) |
113 set_decl_tls_model (ic_tuple_var, decl_default_tls_model (tuple_type)); | 109 set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var)); |
114 } | 110 } |
115 | 111 |
116 /* Create the type and function decls for the interface with gcov. */ | 112 /* Create the type and function decls for the interface with gcov. */ |
117 | 113 |
118 void | 114 void |
119 gimple_init_gcov_profiler (void) | 115 gimple_init_gcov_profiler (void) |
120 { | 116 { |
121 tree interval_profiler_fn_type; | 117 tree interval_profiler_fn_type; |
122 tree pow2_profiler_fn_type; | 118 tree pow2_profiler_fn_type; |
123 tree one_value_profiler_fn_type; | 119 tree topn_values_profiler_fn_type; |
124 tree gcov_type_ptr; | 120 tree gcov_type_ptr; |
125 tree ic_profiler_fn_type; | 121 tree ic_profiler_fn_type; |
126 tree average_profiler_fn_type; | 122 tree average_profiler_fn_type; |
127 const char *profiler_fn_name; | |
128 const char *fn_name; | 123 const char *fn_name; |
129 | 124 |
130 if (!gcov_type_node) | 125 if (!gcov_type_node) |
131 { | 126 { |
132 const char *fn_suffix | 127 const char *fn_suffix |
162 DECL_ATTRIBUTES (tree_pow2_profiler_fn) | 157 DECL_ATTRIBUTES (tree_pow2_profiler_fn) |
163 = tree_cons (get_identifier ("leaf"), NULL, | 158 = tree_cons (get_identifier ("leaf"), NULL, |
164 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); | 159 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); |
165 | 160 |
166 /* void (*) (gcov_type *, gcov_type) */ | 161 /* void (*) (gcov_type *, gcov_type) */ |
167 one_value_profiler_fn_type | 162 topn_values_profiler_fn_type |
168 = build_function_type_list (void_type_node, | 163 = build_function_type_list (void_type_node, |
169 gcov_type_ptr, gcov_type_node, | 164 gcov_type_ptr, gcov_type_node, |
170 NULL_TREE); | 165 NULL_TREE); |
171 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL); | 166 fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL); |
172 tree_one_value_profiler_fn = build_fn_decl (fn_name, | 167 tree_topn_values_profiler_fn |
173 one_value_profiler_fn_type); | 168 = build_fn_decl (fn_name, topn_values_profiler_fn_type); |
174 free (CONST_CAST (char *, fn_name)); | 169 free (CONST_CAST (char *, fn_name)); |
175 TREE_NOTHROW (tree_one_value_profiler_fn) = 1; | 170 |
176 DECL_ATTRIBUTES (tree_one_value_profiler_fn) | 171 TREE_NOTHROW (tree_topn_values_profiler_fn) = 1; |
172 DECL_ATTRIBUTES (tree_topn_values_profiler_fn) | |
177 = tree_cons (get_identifier ("leaf"), NULL, | 173 = tree_cons (get_identifier ("leaf"), NULL, |
178 DECL_ATTRIBUTES (tree_one_value_profiler_fn)); | 174 DECL_ATTRIBUTES (tree_topn_values_profiler_fn)); |
179 | 175 |
180 init_ic_make_global_vars (); | 176 init_ic_make_global_vars (); |
181 | 177 |
182 /* void (*) (gcov_type, void *) */ | 178 /* void (*) (gcov_type, void *) */ |
183 ic_profiler_fn_type | 179 ic_profiler_fn_type |
184 = build_function_type_list (void_type_node, | 180 = build_function_type_list (void_type_node, |
185 gcov_type_node, | 181 gcov_type_node, |
186 ptr_type_node, | 182 ptr_type_node, |
187 NULL_TREE); | 183 NULL_TREE); |
188 profiler_fn_name = "__gcov_indirect_call_profiler_v2"; | 184 fn_name = concat ("__gcov_indirect_call_profiler_v4", fn_suffix, NULL); |
189 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE)) | |
190 profiler_fn_name = "__gcov_indirect_call_topn_profiler"; | |
191 | |
192 tree_indirect_call_profiler_fn | 185 tree_indirect_call_profiler_fn |
193 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type); | 186 = build_fn_decl (fn_name, ic_profiler_fn_type); |
187 free (CONST_CAST (char *, fn_name)); | |
194 | 188 |
195 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; | 189 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; |
196 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) | 190 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) |
197 = tree_cons (get_identifier ("leaf"), NULL, | 191 = tree_cons (get_identifier ("leaf"), NULL, |
198 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); | 192 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); |
229 | 223 |
230 /* LTO streamer needs assembler names. Because we create these decls | 224 /* LTO streamer needs assembler names. Because we create these decls |
231 late, we need to initialize them by hand. */ | 225 late, we need to initialize them by hand. */ |
232 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); | 226 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); |
233 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); | 227 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); |
234 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); | 228 DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn); |
235 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); | 229 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); |
236 DECL_ASSEMBLER_NAME (tree_average_profiler_fn); | 230 DECL_ASSEMBLER_NAME (tree_average_profiler_fn); |
237 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); | 231 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); |
238 } | 232 } |
239 } | 233 } |
296 /* Output instructions as GIMPLE trees to increment the interval histogram | 290 /* Output instructions as GIMPLE trees to increment the interval histogram |
297 counter. VALUE is the expression whose value is profiled. TAG is the | 291 counter. VALUE is the expression whose value is profiled. TAG is the |
298 tag of the section for counters, BASE is offset of the counter position. */ | 292 tag of the section for counters, BASE is offset of the counter position. */ |
299 | 293 |
300 void | 294 void |
301 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) | 295 gimple_gen_interval_profiler (histogram_value value, unsigned tag) |
302 { | 296 { |
303 gimple *stmt = value->hvalue.stmt; | 297 gimple *stmt = value->hvalue.stmt; |
304 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 298 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
305 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; | 299 tree ref = tree_coverage_counter_ref (tag, 0), ref_ptr; |
306 gcall *call; | 300 gcall *call; |
307 tree val; | 301 tree val; |
308 tree start = build_int_cst_type (integer_type_node, | 302 tree start = build_int_cst_type (integer_type_node, |
309 value->hdata.intvl.int_start); | 303 value->hdata.intvl.int_start); |
310 tree steps = build_int_cst_type (unsigned_type_node, | 304 tree steps = build_int_cst_type (unsigned_type_node, |
319 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 313 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
320 } | 314 } |
321 | 315 |
322 /* Output instructions as GIMPLE trees to increment the power of two histogram | 316 /* Output instructions as GIMPLE trees to increment the power of two histogram |
323 counter. VALUE is the expression whose value is profiled. TAG is the tag | 317 counter. VALUE is the expression whose value is profiled. TAG is the tag |
324 of the section for counters, BASE is offset of the counter position. */ | 318 of the section for counters. */ |
325 | 319 |
326 void | 320 void |
327 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) | 321 gimple_gen_pow2_profiler (histogram_value value, unsigned tag) |
328 { | 322 { |
329 gimple *stmt = value->hvalue.stmt; | 323 gimple *stmt = value->hvalue.stmt; |
330 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 324 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
331 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 325 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
332 gcall *call; | 326 gcall *call; |
333 tree val; | 327 tree val; |
334 | 328 |
335 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 329 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
336 true, NULL_TREE, true, GSI_SAME_STMT); | 330 true, NULL_TREE, true, GSI_SAME_STMT); |
337 val = prepare_instrumented_value (&gsi, value); | 331 val = prepare_instrumented_value (&gsi, value); |
338 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); | 332 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); |
339 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 333 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
340 } | 334 } |
341 | 335 |
342 /* Output instructions as GIMPLE trees for code to find the most common value. | 336 /* Output instructions as GIMPLE trees for code to find the most N common |
343 VALUE is the expression whose value is profiled. TAG is the tag of the | 337 values. VALUE is the expression whose value is profiled. TAG is the tag |
344 section for counters, BASE is offset of the counter position. */ | 338 of the section for counters. */ |
345 | 339 |
346 void | 340 void |
347 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) | 341 gimple_gen_topn_values_profiler (histogram_value value, unsigned tag) |
348 { | 342 { |
349 gimple *stmt = value->hvalue.stmt; | 343 gimple *stmt = value->hvalue.stmt; |
350 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 344 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
351 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 345 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
352 gcall *call; | 346 gcall *call; |
353 tree val; | 347 tree val; |
354 | 348 |
355 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 349 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
356 true, NULL_TREE, true, GSI_SAME_STMT); | 350 true, NULL_TREE, true, GSI_SAME_STMT); |
357 val = prepare_instrumented_value (&gsi, value); | 351 val = prepare_instrumented_value (&gsi, value); |
358 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val); | 352 call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val); |
359 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 353 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
360 } | 354 } |
361 | 355 |
362 | 356 |
363 /* Output instructions as GIMPLE trees for code to find the most | 357 /* Output instructions as GIMPLE trees for code to find the most |
364 common called function in indirect call. | 358 common called function in indirect call. |
365 VALUE is the call expression whose indirect callee is profiled. | 359 VALUE is the call expression whose indirect callee is profiled. |
366 TAG is the tag of the section for counters, BASE is offset of the | 360 TAG is the tag of the section for counters. */ |
367 counter position. */ | |
368 | 361 |
369 void | 362 void |
370 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) | 363 gimple_gen_ic_profiler (histogram_value value, unsigned tag) |
371 { | 364 { |
372 tree tmp1; | 365 tree tmp1; |
373 gassign *stmt1, *stmt2, *stmt3; | 366 gassign *stmt1, *stmt2, *stmt3; |
374 gimple *stmt = value->hvalue.stmt; | 367 gimple *stmt = value->hvalue.stmt; |
375 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 368 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
376 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 369 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
377 | |
378 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && | |
379 tag == GCOV_COUNTER_V_INDIR) || | |
380 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && | |
381 tag == GCOV_COUNTER_ICALL_TOPNV)) | |
382 return; | |
383 | 370 |
384 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 371 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
385 true, NULL_TREE, true, GSI_SAME_STMT); | 372 true, NULL_TREE, true, GSI_SAME_STMT); |
386 | 373 |
387 /* Insert code: | 374 /* Insert code: |
392 | 379 |
393 Example: | 380 Example: |
394 f_1 = foo; | 381 f_1 = foo; |
395 __gcov_indirect_call.counters = &__gcov4.main[0]; | 382 __gcov_indirect_call.counters = &__gcov4.main[0]; |
396 PROF_9 = f_1; | 383 PROF_9 = f_1; |
397 __gcov_indirect_call_callee = PROF_9; | 384 __gcov_indirect_call.callee = PROF_9; |
398 _4 = f_1 (); | 385 _4 = f_1 (); |
399 */ | 386 */ |
400 | 387 |
401 tree gcov_type_ptr = build_pointer_type (get_gcov_type ()); | 388 tree gcov_type_ptr = build_pointer_type (get_gcov_type ()); |
402 | 389 |
455 EDGE_FALSE_VALUE); | 442 EDGE_FALSE_VALUE); |
456 e->probability = true_edge->probability.invert (); | 443 e->probability = true_edge->probability.invert (); |
457 | 444 |
458 /* Insert code: | 445 /* Insert code: |
459 | 446 |
460 if (__gcov_indirect_call_callee != NULL) | 447 if (__gcov_indirect_call.callee != NULL) |
461 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl); | 448 __gcov_indirect_call_profiler_v3 (profile_id, ¤t_function_decl); |
462 | 449 |
463 The function __gcov_indirect_call_profiler_v2 is responsible for | 450 The function __gcov_indirect_call_profiler_v3 is responsible for |
464 resetting __gcov_indirect_call_callee to NULL. */ | 451 resetting __gcov_indirect_call.callee to NULL. */ |
465 | 452 |
466 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | 453 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); |
467 void0 = build_int_cst (ptr_type_node, 0); | 454 void0 = build_int_cst (ptr_type_node, 0); |
468 | 455 |
469 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node, | 456 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node, |
493 /* Output instructions as GIMPLE tree at the beginning for each function. | 480 /* Output instructions as GIMPLE tree at the beginning for each function. |
494 TAG is the tag of the section for counters, BASE is offset of the | 481 TAG is the tag of the section for counters, BASE is offset of the |
495 counter position and GSI is the iterator we place the counter. */ | 482 counter position and GSI is the iterator we place the counter. */ |
496 | 483 |
497 void | 484 void |
498 gimple_gen_time_profiler (unsigned tag, unsigned base) | 485 gimple_gen_time_profiler (unsigned tag) |
499 { | 486 { |
500 tree type = get_gcov_type (); | 487 tree type = get_gcov_type (); |
501 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); | 488 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); |
502 basic_block cond_bb = split_edge (single_succ_edge (entry)); | 489 basic_block cond_bb = split_edge (single_succ_edge (entry)); |
503 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); | 490 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); |
512 edge e | 499 edge e |
513 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE); | 500 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE); |
514 e->probability = true_edge->probability.invert (); | 501 e->probability = true_edge->probability.invert (); |
515 | 502 |
516 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | 503 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); |
517 tree original_ref = tree_coverage_counter_ref (tag, base); | 504 tree original_ref = tree_coverage_counter_ref (tag, 0); |
518 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE, | 505 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE, |
519 true, GSI_SAME_STMT); | 506 true, GSI_SAME_STMT); |
520 tree one = build_int_cst (type, 1); | 507 tree one = build_int_cst (type, 1); |
521 | 508 |
522 /* Emit: if (counters[0] != 0). */ | 509 /* Emit: if (counters[0] != 0). */ |
572 /* Output instructions as GIMPLE trees to increment the average histogram | 559 /* Output instructions as GIMPLE trees to increment the average histogram |
573 counter. VALUE is the expression whose value is profiled. TAG is the | 560 counter. VALUE is the expression whose value is profiled. TAG is the |
574 tag of the section for counters, BASE is offset of the counter position. */ | 561 tag of the section for counters, BASE is offset of the counter position. */ |
575 | 562 |
576 void | 563 void |
577 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) | 564 gimple_gen_average_profiler (histogram_value value, unsigned tag) |
578 { | 565 { |
579 gimple *stmt = value->hvalue.stmt; | 566 gimple *stmt = value->hvalue.stmt; |
580 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 567 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
581 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 568 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
582 gcall *call; | 569 gcall *call; |
583 tree val; | 570 tree val; |
584 | 571 |
585 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 572 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
586 true, NULL_TREE, | 573 true, NULL_TREE, |
593 /* Output instructions as GIMPLE trees to increment the ior histogram | 580 /* Output instructions as GIMPLE trees to increment the ior histogram |
594 counter. VALUE is the expression whose value is profiled. TAG is the | 581 counter. VALUE is the expression whose value is profiled. TAG is the |
595 tag of the section for counters, BASE is offset of the counter position. */ | 582 tag of the section for counters, BASE is offset of the counter position. */ |
596 | 583 |
597 void | 584 void |
598 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) | 585 gimple_gen_ior_profiler (histogram_value value, unsigned tag) |
599 { | 586 { |
600 gimple *stmt = value->hvalue.stmt; | 587 gimple *stmt = value->hvalue.stmt; |
601 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 588 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
602 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 589 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
603 gcall *call; | 590 gcall *call; |
604 tree val; | 591 tree val; |
605 | 592 |
606 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 593 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
607 true, NULL_TREE, true, GSI_SAME_STMT); | 594 true, NULL_TREE, true, GSI_SAME_STMT); |
608 val = prepare_instrumented_value (&gsi, value); | 595 val = prepare_instrumented_value (&gsi, value); |
609 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); | 596 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); |
610 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 597 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
598 } | |
599 | |
600 static vec<regex_t> profile_filter_files; | |
601 static vec<regex_t> profile_exclude_files; | |
602 | |
603 /* Parse list of provided REGEX (separated with semi-collon) and | |
604 create expressions (of type regex_t) and save them into V vector. | |
605 If there is a regular expression parsing error, error message is | |
606 printed for FLAG_NAME. */ | |
607 | |
608 static void | |
609 parse_profile_filter (const char *regex, vec<regex_t> *v, | |
610 const char *flag_name) | |
611 { | |
612 v->create (4); | |
613 if (regex != NULL) | |
614 { | |
615 char *str = xstrdup (regex); | |
616 for (char *p = strtok (str, ";"); p != NULL; p = strtok (NULL, ";")) | |
617 { | |
618 regex_t r; | |
619 if (regcomp (&r, p, REG_EXTENDED | REG_NOSUB) != 0) | |
620 { | |
621 error ("invalid regular expression %qs in %qs", | |
622 p, flag_name); | |
623 return; | |
624 } | |
625 | |
626 v->safe_push (r); | |
627 } | |
628 } | |
629 } | |
630 | |
631 /* Parse values of -fprofile-filter-files and -fprofile-exclude-files | |
632 options. */ | |
633 | |
634 static void | |
635 parse_profile_file_filtering () | |
636 { | |
637 parse_profile_filter (flag_profile_filter_files, &profile_filter_files, | |
638 "-fprofile-filter-files"); | |
639 parse_profile_filter (flag_profile_exclude_files, &profile_exclude_files, | |
640 "-fprofile-exclude-files"); | |
641 } | |
642 | |
643 /* Parse vectors of regular expressions. */ | |
644 | |
645 static void | |
646 release_profile_file_filtering () | |
647 { | |
648 profile_filter_files.release (); | |
649 profile_exclude_files.release (); | |
650 } | |
651 | |
652 /* Return true when FILENAME should be instrumented based on | |
653 -fprofile-filter-files and -fprofile-exclude-files options. */ | |
654 | |
655 static bool | |
656 include_source_file_for_profile (const char *filename) | |
657 { | |
658 /* First check whether file is included in flag_profile_exclude_files. */ | |
659 for (unsigned i = 0; i < profile_exclude_files.length (); i++) | |
660 if (regexec (&profile_exclude_files[i], | |
661 filename, 0, NULL, 0) == REG_NOERROR) | |
662 return false; | |
663 | |
664 /* For non-empty flag_profile_filter_files include only files matching a | |
665 regex in the flag. */ | |
666 if (profile_filter_files.is_empty ()) | |
667 return true; | |
668 | |
669 for (unsigned i = 0; i < profile_filter_files.length (); i++) | |
670 if (regexec (&profile_filter_files[i], filename, 0, NULL, 0) == REG_NOERROR) | |
671 return true; | |
672 | |
673 return false; | |
611 } | 674 } |
612 | 675 |
613 #ifndef HAVE_sync_compare_and_swapsi | 676 #ifndef HAVE_sync_compare_and_swapsi |
614 #define HAVE_sync_compare_and_swapsi 0 | 677 #define HAVE_sync_compare_and_swapsi 0 |
615 #endif | 678 #endif |
656 /* This is a small-ipa pass that gets called only once, from | 719 /* This is a small-ipa pass that gets called only once, from |
657 cgraphunit.c:ipa_passes(). */ | 720 cgraphunit.c:ipa_passes(). */ |
658 gcc_assert (symtab->state == IPA_SSA); | 721 gcc_assert (symtab->state == IPA_SSA); |
659 | 722 |
660 init_node_map (true); | 723 init_node_map (true); |
724 parse_profile_file_filtering (); | |
661 | 725 |
662 FOR_EACH_DEFINED_FUNCTION (node) | 726 FOR_EACH_DEFINED_FUNCTION (node) |
663 { | 727 { |
664 if (!gimple_has_body_p (node->decl)) | 728 bool thunk = false; |
729 if (!gimple_has_body_p (node->decl) && !node->thunk.thunk_p) | |
665 continue; | 730 continue; |
666 | 731 |
667 /* Don't profile functions produced for builtin stuff. */ | 732 /* Don't profile functions produced for builtin stuff. */ |
668 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) | 733 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
669 continue; | 734 continue; |
676 will get acocunted), testsuite expects that. */ | 741 will get acocunted), testsuite expects that. */ |
677 if (DECL_EXTERNAL (node->decl) | 742 if (DECL_EXTERNAL (node->decl) |
678 && flag_test_coverage) | 743 && flag_test_coverage) |
679 continue; | 744 continue; |
680 | 745 |
746 const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl)); | |
747 if (!include_source_file_for_profile (file)) | |
748 continue; | |
749 | |
750 if (node->thunk.thunk_p) | |
751 { | |
752 /* We cannot expand variadic thunks to Gimple. */ | |
753 if (stdarg_p (TREE_TYPE (node->decl))) | |
754 continue; | |
755 thunk = true; | |
756 /* When generate profile, expand thunk to gimple so it can be | |
757 instrumented same way as other functions. */ | |
758 if (profile_arc_flag) | |
759 node->expand_thunk (false, true); | |
760 /* Read cgraph profile but keep function as thunk at profile-use | |
761 time. */ | |
762 else | |
763 { | |
764 read_thunk_profile (node); | |
765 continue; | |
766 } | |
767 } | |
768 | |
681 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); | 769 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
682 | 770 |
683 if (dump_file) | 771 if (dump_file) |
684 dump_function_header (dump_file, cfun->decl, dump_flags); | 772 dump_function_header (dump_file, cfun->decl, dump_flags); |
685 | 773 |
686 /* Local pure-const may imply need to fixup the cfg. */ | 774 /* Local pure-const may imply need to fixup the cfg. */ |
687 if (execute_fixup_cfg () & TODO_cleanup_cfg) | 775 if (gimple_has_body_p (node->decl) |
776 && (execute_fixup_cfg () & TODO_cleanup_cfg)) | |
688 cleanup_tree_cfg (); | 777 cleanup_tree_cfg (); |
689 | 778 |
690 branch_prob (); | 779 branch_prob (thunk); |
691 | 780 |
692 if (! flag_branch_probabilities | 781 if (! flag_branch_probabilities |
693 && flag_profile_values) | 782 && flag_profile_values) |
694 gimple_gen_ic_func_profiler (); | 783 gimple_gen_ic_func_profiler (); |
695 | 784 |
696 if (flag_branch_probabilities | 785 if (flag_branch_probabilities |
786 && !thunk | |
697 && flag_profile_values | 787 && flag_profile_values |
698 && flag_value_profile_transformations) | 788 && flag_value_profile_transformations |
789 && profile_status_for_fn (cfun) == PROFILE_READ) | |
699 gimple_value_profile_transformations (); | 790 gimple_value_profile_transformations (); |
700 | 791 |
701 /* The above could hose dominator info. Currently there is | 792 /* The above could hose dominator info. Currently there is |
702 none coming in, this is a safety valve. It should be | 793 none coming in, this is a safety valve. It should be |
703 easy to adjust it, if and when there is some. */ | 794 easy to adjust it, if and when there is some. */ |
704 free_dominance_info (CDI_DOMINATORS); | 795 free_dominance_info (CDI_DOMINATORS); |
705 free_dominance_info (CDI_POST_DOMINATORS); | 796 free_dominance_info (CDI_POST_DOMINATORS); |
706 pop_cfun (); | 797 pop_cfun (); |
707 } | 798 } |
799 | |
800 release_profile_file_filtering (); | |
708 | 801 |
709 /* Drop pure/const flags from instrumented functions. */ | 802 /* Drop pure/const flags from instrumented functions. */ |
710 if (profile_arc_flag || flag_test_coverage) | 803 if (profile_arc_flag || flag_test_coverage) |
711 FOR_EACH_DEFINED_FUNCTION (node) | 804 FOR_EACH_DEFINED_FUNCTION (node) |
712 { | 805 { |
796 bool | 889 bool |
797 pass_ipa_tree_profile::gate (function *) | 890 pass_ipa_tree_profile::gate (function *) |
798 { | 891 { |
799 /* When profile instrumentation, use or test coverage shall be performed. | 892 /* When profile instrumentation, use or test coverage shall be performed. |
800 But for AutoFDO, this there is no instrumentation, thus this pass is | 893 But for AutoFDO, this there is no instrumentation, thus this pass is |
801 diabled. */ | 894 disabled. */ |
802 return (!in_lto_p && !flag_auto_profile | 895 return (!in_lto_p && !flag_auto_profile |
803 && (flag_branch_probabilities || flag_test_coverage | 896 && (flag_branch_probabilities || flag_test_coverage |
804 || profile_arc_flag)); | 897 || profile_arc_flag)); |
805 } | 898 } |
806 | 899 |