0
|
1 /* Calculate branch probabilities, and basic block execution counts.
|
|
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
|
|
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
|
4 Free Software Foundation, Inc.
|
|
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
|
|
6 based on some ideas from Dain Samples of UC Berkeley.
|
|
7 Further mangling by Bob Manson, Cygnus Support.
|
|
8 Converted to use trees by Dale Johannesen, Apple Computer.
|
|
9
|
|
10 This file is part of GCC.
|
|
11
|
|
12 GCC is free software; you can redistribute it and/or modify it under
|
|
13 the terms of the GNU General Public License as published by the Free
|
|
14 Software Foundation; either version 3, or (at your option) any later
|
|
15 version.
|
|
16
|
|
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
20 for more details.
|
|
21
|
|
22 You should have received a copy of the GNU General Public License
|
|
23 along with GCC; see the file COPYING3. If not see
|
|
24 <http://www.gnu.org/licenses/>. */
|
|
25
|
|
26 /* Generate basic block profile instrumentation and auxiliary files.
|
|
27 Tree-based version. See profile.c for overview. */
|
|
28
|
|
29 #include "config.h"
|
|
30 #include "system.h"
|
|
31 #include "coretypes.h"
|
|
32 #include "tm.h"
|
|
33 #include "rtl.h"
|
|
34 #include "flags.h"
|
|
35 #include "output.h"
|
|
36 #include "regs.h"
|
|
37 #include "expr.h"
|
|
38 #include "function.h"
|
|
39 #include "toplev.h"
|
|
40 #include "coverage.h"
|
|
41 #include "tree.h"
|
|
42 #include "tree-flow.h"
|
|
43 #include "tree-dump.h"
|
|
44 #include "tree-pass.h"
|
|
45 #include "timevar.h"
|
|
46 #include "value-prof.h"
|
|
47 #include "ggc.h"
|
|
48 #include "cgraph.h"
|
|
49
|
|
50 static GTY(()) tree gcov_type_node;
|
|
51 static GTY(()) tree gcov_type_tmp_var;
|
|
52 static GTY(()) tree tree_interval_profiler_fn;
|
|
53 static GTY(()) tree tree_pow2_profiler_fn;
|
|
54 static GTY(()) tree tree_one_value_profiler_fn;
|
|
55 static GTY(()) tree tree_indirect_call_profiler_fn;
|
|
56 static GTY(()) tree tree_average_profiler_fn;
|
|
57 static GTY(()) tree tree_ior_profiler_fn;
|
|
58
|
|
59
|
|
60 static GTY(()) tree ic_void_ptr_var;
|
|
61 static GTY(()) tree ic_gcov_type_ptr_var;
|
|
62 static GTY(()) tree ptr_void;
|
|
63
|
|
64 /* Do initialization work for the edge profiler. */
|
|
65
|
|
66 /* Add code:
|
|
67 static gcov* __gcov_indirect_call_counters; // pointer to actual counter
|
|
68 static void* __gcov_indirect_call_callee; // actual callee address
|
|
69 */
|
|
70 static void
|
|
71 tree_init_ic_make_global_vars (void)
|
|
72 {
|
|
73 tree gcov_type_ptr;
|
|
74
|
|
75 ptr_void = build_pointer_type (void_type_node);
|
|
76
|
|
77 ic_void_ptr_var
|
|
78 = build_decl (VAR_DECL,
|
|
79 get_identifier ("__gcov_indirect_call_callee"),
|
|
80 ptr_void);
|
|
81 TREE_STATIC (ic_void_ptr_var) = 1;
|
|
82 TREE_PUBLIC (ic_void_ptr_var) = 0;
|
|
83 DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
|
|
84 DECL_INITIAL (ic_void_ptr_var) = NULL;
|
|
85 assemble_variable (ic_void_ptr_var, 0, 0, 0);
|
|
86
|
|
87 gcov_type_ptr = build_pointer_type (get_gcov_type ());
|
|
88 ic_gcov_type_ptr_var
|
|
89 = build_decl (VAR_DECL,
|
|
90 get_identifier ("__gcov_indirect_call_counters"),
|
|
91 gcov_type_ptr);
|
|
92 TREE_STATIC (ic_gcov_type_ptr_var) = 1;
|
|
93 TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
|
|
94 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
|
|
95 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
|
|
96 assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
|
|
97 }
|
|
98
|
|
99 static void
|
|
100 tree_init_edge_profiler (void)
|
|
101 {
|
|
102 tree interval_profiler_fn_type;
|
|
103 tree pow2_profiler_fn_type;
|
|
104 tree one_value_profiler_fn_type;
|
|
105 tree gcov_type_ptr;
|
|
106 tree ic_profiler_fn_type;
|
|
107 tree average_profiler_fn_type;
|
|
108
|
|
109 if (!gcov_type_node)
|
|
110 {
|
|
111 gcov_type_node = get_gcov_type ();
|
|
112 gcov_type_ptr = build_pointer_type (gcov_type_node);
|
|
113
|
|
114 /* void (*) (gcov_type *, gcov_type, int, unsigned) */
|
|
115 interval_profiler_fn_type
|
|
116 = build_function_type_list (void_type_node,
|
|
117 gcov_type_ptr, gcov_type_node,
|
|
118 integer_type_node,
|
|
119 unsigned_type_node, NULL_TREE);
|
|
120 tree_interval_profiler_fn
|
|
121 = build_fn_decl ("__gcov_interval_profiler",
|
|
122 interval_profiler_fn_type);
|
|
123
|
|
124 /* void (*) (gcov_type *, gcov_type) */
|
|
125 pow2_profiler_fn_type
|
|
126 = build_function_type_list (void_type_node,
|
|
127 gcov_type_ptr, gcov_type_node,
|
|
128 NULL_TREE);
|
|
129 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
|
|
130 pow2_profiler_fn_type);
|
|
131
|
|
132 /* void (*) (gcov_type *, gcov_type) */
|
|
133 one_value_profiler_fn_type
|
|
134 = build_function_type_list (void_type_node,
|
|
135 gcov_type_ptr, gcov_type_node,
|
|
136 NULL_TREE);
|
|
137 tree_one_value_profiler_fn
|
|
138 = build_fn_decl ("__gcov_one_value_profiler",
|
|
139 one_value_profiler_fn_type);
|
|
140
|
|
141 tree_init_ic_make_global_vars ();
|
|
142
|
|
143 /* void (*) (gcov_type *, gcov_type, void *, void *) */
|
|
144 ic_profiler_fn_type
|
|
145 = build_function_type_list (void_type_node,
|
|
146 gcov_type_ptr, gcov_type_node,
|
|
147 ptr_void,
|
|
148 ptr_void, NULL_TREE);
|
|
149 tree_indirect_call_profiler_fn
|
|
150 = build_fn_decl ("__gcov_indirect_call_profiler",
|
|
151 ic_profiler_fn_type);
|
|
152 /* void (*) (gcov_type *, gcov_type) */
|
|
153 average_profiler_fn_type
|
|
154 = build_function_type_list (void_type_node,
|
|
155 gcov_type_ptr, gcov_type_node, NULL_TREE);
|
|
156 tree_average_profiler_fn
|
|
157 = build_fn_decl ("__gcov_average_profiler",
|
|
158 average_profiler_fn_type);
|
|
159 tree_ior_profiler_fn
|
|
160 = build_fn_decl ("__gcov_ior_profiler",
|
|
161 average_profiler_fn_type);
|
|
162 }
|
|
163 }
|
|
164
|
|
165 /* New call was added, make goto call edges if neccesary. */
|
|
166
|
|
167 static void
|
|
168 add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
|
|
169 {
|
|
170 gimple stmt = gsi_stmt (gsi);
|
|
171
|
|
172 if (!stmt_can_make_abnormal_goto (stmt))
|
|
173 return;
|
|
174 if (!gsi_end_p (gsi))
|
|
175 split_block (gimple_bb (stmt), stmt);
|
|
176 make_abnormal_goto_edges (gimple_bb (stmt), true);
|
|
177 }
|
|
178
|
|
179 /* Output instructions as GIMPLE trees to increment the edge
|
|
180 execution count, and insert them on E. We rely on
|
|
181 gsi_insert_on_edge to preserve the order. */
|
|
182
|
|
183 static void
|
|
184 tree_gen_edge_profiler (int edgeno, edge e)
|
|
185 {
|
|
186 tree ref, one;
|
|
187 gimple stmt1, stmt2, stmt3;
|
|
188
|
|
189 /* We share one temporary variable declaration per function. This
|
|
190 gets re-set in tree_profiling. */
|
|
191 if (gcov_type_tmp_var == NULL_TREE)
|
|
192 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
|
|
193 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
|
|
194 one = build_int_cst (gcov_type_node, 1);
|
|
195 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
|
|
196 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
|
|
197 gcov_type_tmp_var, one);
|
|
198 stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
|
|
199 gsi_insert_on_edge (e, stmt1);
|
|
200 gsi_insert_on_edge (e, stmt2);
|
|
201 gsi_insert_on_edge (e, stmt3);
|
|
202 }
|
|
203
|
|
204 /* Emits code to get VALUE to instrument at GSI, and returns the
|
|
205 variable containing the value. */
|
|
206
|
|
207 static tree
|
|
208 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value)
|
|
209 {
|
|
210 tree val = value->hvalue.value;
|
|
211 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val),
|
|
212 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
213 }
|
|
214
|
|
215 /* Output instructions as GIMPLE trees to increment the interval histogram
|
|
216 counter. VALUE is the expression whose value is profiled. TAG is the
|
|
217 tag of the section for counters, BASE is offset of the counter position. */
|
|
218
|
|
219 static void
|
|
220 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
221 {
|
|
222 gimple stmt = value->hvalue.stmt;
|
|
223 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
224 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr;
|
|
225 gimple call;
|
|
226 tree val;
|
|
227 tree start = build_int_cst_type (integer_type_node,
|
|
228 value->hdata.intvl.int_start);
|
|
229 tree steps = build_int_cst_type (unsigned_type_node,
|
|
230 value->hdata.intvl.steps);
|
|
231
|
|
232 ref_ptr = force_gimple_operand_gsi (&gsi,
|
|
233 build_addr (ref, current_function_decl),
|
|
234 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
235 val = prepare_instrumented_value (&gsi, value);
|
|
236 call = gimple_build_call (tree_interval_profiler_fn, 4,
|
|
237 ref_ptr, val, start, steps);
|
|
238 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
239 add_abnormal_goto_call_edges (gsi);
|
|
240 }
|
|
241
|
|
242 /* Output instructions as GIMPLE trees to increment the power of two histogram
|
|
243 counter. VALUE is the expression whose value is profiled. TAG is the tag
|
|
244 of the section for counters, BASE is offset of the counter position. */
|
|
245
|
|
246 static void
|
|
247 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
248 {
|
|
249 gimple stmt = value->hvalue.stmt;
|
|
250 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
251 tree ref_ptr = tree_coverage_counter_addr (tag, base);
|
|
252 gimple call;
|
|
253 tree val;
|
|
254
|
|
255 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
|
|
256 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
257 val = prepare_instrumented_value (&gsi, value);
|
|
258 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
|
|
259 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
260 add_abnormal_goto_call_edges (gsi);
|
|
261 }
|
|
262
|
|
263 /* Output instructions as GIMPLE trees for code to find the most common value.
|
|
264 VALUE is the expression whose value is profiled. TAG is the tag of the
|
|
265 section for counters, BASE is offset of the counter position. */
|
|
266
|
|
267 static void
|
|
268 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
269 {
|
|
270 gimple stmt = value->hvalue.stmt;
|
|
271 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
272 tree ref_ptr = tree_coverage_counter_addr (tag, base);
|
|
273 gimple call;
|
|
274 tree val;
|
|
275
|
|
276 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
|
|
277 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
278 val = prepare_instrumented_value (&gsi, value);
|
|
279 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
|
|
280 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
281 add_abnormal_goto_call_edges (gsi);
|
|
282 }
|
|
283
|
|
284
|
|
285 /* Output instructions as GIMPLE trees for code to find the most
|
|
286 common called function in indirect call.
|
|
287 VALUE is the call expression whose indirect callee is profiled.
|
|
288 TAG is the tag of the section for counters, BASE is offset of the
|
|
289 counter position. */
|
|
290
|
|
291 static void
|
|
292 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
293 {
|
|
294 tree tmp1;
|
|
295 gimple stmt1, stmt2, stmt3;
|
|
296 gimple stmt = value->hvalue.stmt;
|
|
297 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
298 tree ref_ptr = tree_coverage_counter_addr (tag, base);
|
|
299
|
|
300 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
|
|
301 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
302
|
|
303 /* Insert code:
|
|
304
|
|
305 __gcov_indirect_call_counters = get_relevant_counter_ptr ();
|
|
306 __gcov_indirect_call_callee = (void *) indirect call argument;
|
|
307 */
|
|
308
|
|
309 tmp1 = create_tmp_var (ptr_void, "PROF");
|
|
310 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
|
|
311 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
|
|
312 stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
|
|
313
|
|
314 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
|
|
315 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
|
|
316 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
|
|
317 }
|
|
318
|
|
319
|
|
320 /* Output instructions as GIMPLE trees for code to find the most
|
|
321 common called function in indirect call. Insert instructions at the
|
|
322 beginning of every possible called function.
|
|
323 */
|
|
324
|
|
325 static void
|
|
326 tree_gen_ic_func_profiler (void)
|
|
327 {
|
|
328 struct cgraph_node * c_node = cgraph_node (current_function_decl);
|
|
329 gimple_stmt_iterator gsi;
|
|
330 edge e;
|
|
331 basic_block bb;
|
|
332 edge_iterator ei;
|
|
333 gimple stmt1, stmt2;
|
|
334 tree tree_uid, cur_func;
|
|
335
|
|
336 if (!c_node->needed)
|
|
337 return;
|
|
338
|
|
339 tree_init_edge_profiler ();
|
|
340
|
|
341 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
|
|
342 {
|
|
343 tree void0;
|
|
344
|
|
345 bb = split_edge (e);
|
|
346 gsi = gsi_start_bb (bb);
|
|
347
|
|
348 cur_func = force_gimple_operand_gsi (&gsi,
|
|
349 build_addr (current_function_decl,
|
|
350 current_function_decl),
|
|
351 true, NULL_TREE,
|
|
352 true, GSI_SAME_STMT);
|
|
353 tree_uid = build_int_cst (gcov_type_node, c_node->pid);
|
|
354 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
|
|
355 ic_gcov_type_ptr_var,
|
|
356 tree_uid,
|
|
357 cur_func,
|
|
358 ic_void_ptr_var);
|
|
359 gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
|
|
360 gcc_assert (EDGE_COUNT (bb->succs) == 1);
|
|
361 bb = split_edge (EDGE_I (bb->succs, 0));
|
|
362 add_abnormal_goto_call_edges (gsi);
|
|
363
|
|
364 gsi = gsi_start_bb (bb);
|
|
365 /* Set __gcov_indirect_call_callee to 0,
|
|
366 so that calls from other modules won't get misattributed
|
|
367 to the last caller of the current callee. */
|
|
368 void0 = build_int_cst (build_pointer_type (void_type_node), 0);
|
|
369 stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
|
|
370 gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
|
|
371 }
|
|
372 }
|
|
373
|
|
374 /* Output instructions as GIMPLE trees for code to find the most common value
|
|
375 of a difference between two evaluations of an expression.
|
|
376 VALUE is the expression whose value is profiled. TAG is the tag of the
|
|
377 section for counters, BASE is offset of the counter position. */
|
|
378
|
|
379 static void
|
|
380 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED,
|
|
381 unsigned tag ATTRIBUTE_UNUSED,
|
|
382 unsigned base ATTRIBUTE_UNUSED)
|
|
383 {
|
|
384 /* FIXME implement this. */
|
|
385 #ifdef ENABLE_CHECKING
|
|
386 internal_error ("unimplemented functionality");
|
|
387 #endif
|
|
388 gcc_unreachable ();
|
|
389 }
|
|
390
|
|
391 /* Output instructions as GIMPLE trees to increment the average histogram
|
|
392 counter. VALUE is the expression whose value is profiled. TAG is the
|
|
393 tag of the section for counters, BASE is offset of the counter position. */
|
|
394
|
|
395 static void
|
|
396 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
397 {
|
|
398 gimple stmt = value->hvalue.stmt;
|
|
399 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
400 tree ref_ptr = tree_coverage_counter_addr (tag, base);
|
|
401 gimple call;
|
|
402 tree val;
|
|
403
|
|
404 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
|
|
405 true, NULL_TREE,
|
|
406 true, GSI_SAME_STMT);
|
|
407 val = prepare_instrumented_value (&gsi, value);
|
|
408 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
|
|
409 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
410 add_abnormal_goto_call_edges (gsi);
|
|
411 }
|
|
412
|
|
413 /* Output instructions as GIMPLE trees to increment the ior histogram
|
|
414 counter. VALUE is the expression whose value is profiled. TAG is the
|
|
415 tag of the section for counters, BASE is offset of the counter position. */
|
|
416
|
|
417 static void
|
|
418 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
|
|
419 {
|
|
420 gimple stmt = value->hvalue.stmt;
|
|
421 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
|
|
422 tree ref_ptr = tree_coverage_counter_addr (tag, base);
|
|
423 gimple call;
|
|
424 tree val;
|
|
425
|
|
426 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
|
|
427 true, NULL_TREE, true, GSI_SAME_STMT);
|
|
428 val = prepare_instrumented_value (&gsi, value);
|
|
429 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
|
|
430 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
431 add_abnormal_goto_call_edges (gsi);
|
|
432 }
|
|
433
|
|
434 /* Return 1 if tree-based profiling is in effect, else 0.
|
|
435 If it is, set up hooks for tree-based profiling.
|
|
436 Gate for pass_tree_profile. */
|
|
437
|
|
438 static bool
|
|
439 do_tree_profiling (void)
|
|
440 {
|
|
441 if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
|
|
442 {
|
|
443 tree_register_profile_hooks ();
|
|
444 gimple_register_value_prof_hooks ();
|
|
445 return true;
|
|
446 }
|
|
447 return false;
|
|
448 }
|
|
449
|
|
450 static unsigned int
|
|
451 tree_profiling (void)
|
|
452 {
|
|
453 /* Don't profile functions produced at destruction time, particularly
|
|
454 the gcov datastructure initializer. Don't profile if it has been
|
|
455 already instrumented either (when OpenMP expansion creates
|
|
456 child function from already instrumented body). */
|
|
457 if (cgraph_state == CGRAPH_STATE_FINISHED
|
|
458 || cfun->after_tree_profile)
|
|
459 return 0;
|
|
460
|
|
461 /* Re-set global shared temporary variable for edge-counters. */
|
|
462 gcov_type_tmp_var = NULL_TREE;
|
|
463
|
|
464 branch_prob ();
|
|
465
|
|
466 if (! flag_branch_probabilities
|
|
467 && flag_profile_values)
|
|
468 tree_gen_ic_func_profiler ();
|
|
469
|
|
470 if (flag_branch_probabilities
|
|
471 && flag_profile_values
|
|
472 && flag_value_profile_transformations)
|
|
473 value_profile_transformations ();
|
|
474 /* The above could hose dominator info. Currently there is
|
|
475 none coming in, this is a safety valve. It should be
|
|
476 easy to adjust it, if and when there is some. */
|
|
477 free_dominance_info (CDI_DOMINATORS);
|
|
478 free_dominance_info (CDI_POST_DOMINATORS);
|
|
479 cfun->after_tree_profile = 1;
|
|
480 return 0;
|
|
481 }
|
|
482
|
|
483 struct gimple_opt_pass pass_tree_profile =
|
|
484 {
|
|
485 {
|
|
486 GIMPLE_PASS,
|
|
487 "tree_profile", /* name */
|
|
488 do_tree_profiling, /* gate */
|
|
489 tree_profiling, /* execute */
|
|
490 NULL, /* sub */
|
|
491 NULL, /* next */
|
|
492 0, /* static_pass_number */
|
|
493 TV_BRANCH_PROB, /* tv_id */
|
|
494 PROP_gimple_leh | PROP_cfg, /* properties_required */
|
|
495 PROP_gimple_leh | PROP_cfg, /* properties_provided */
|
|
496 0, /* properties_destroyed */
|
|
497 0, /* todo_flags_start */
|
|
498 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */
|
|
499 }
|
|
500 };
|
|
501
|
|
502 struct profile_hooks tree_profile_hooks =
|
|
503 {
|
|
504 tree_init_edge_profiler, /* init_edge_profiler */
|
|
505 tree_gen_edge_profiler, /* gen_edge_profiler */
|
|
506 tree_gen_interval_profiler, /* gen_interval_profiler */
|
|
507 tree_gen_pow2_profiler, /* gen_pow2_profiler */
|
|
508 tree_gen_one_value_profiler, /* gen_one_value_profiler */
|
|
509 tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
|
|
510 tree_gen_ic_profiler, /* gen_ic_profiler */
|
|
511 tree_gen_average_profiler, /* gen_average_profiler */
|
|
512 tree_gen_ior_profiler /* gen_ior_profiler */
|
|
513 };
|
|
514
|
|
515 #include "gt-tree-profile.h"
|