Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-profile.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Calculate branch probabilities, and basic block execution counts. |
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 |
0 | 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 "flags.h" | |
34 #include "regs.h" | |
35 #include "expr.h" | |
36 #include "function.h" | |
37 #include "toplev.h" | |
38 #include "coverage.h" | |
39 #include "tree.h" | |
40 #include "tree-flow.h" | |
41 #include "tree-dump.h" | |
42 #include "tree-pass.h" | |
43 #include "timevar.h" | |
44 #include "value-prof.h" | |
45 #include "cgraph.h" | |
46 | |
47 static GTY(()) tree gcov_type_node; | |
48 static GTY(()) tree gcov_type_tmp_var; | |
49 static GTY(()) tree tree_interval_profiler_fn; | |
50 static GTY(()) tree tree_pow2_profiler_fn; | |
51 static GTY(()) tree tree_one_value_profiler_fn; | |
52 static GTY(()) tree tree_indirect_call_profiler_fn; | |
53 static GTY(()) tree tree_average_profiler_fn; | |
54 static GTY(()) tree tree_ior_profiler_fn; | |
55 | |
56 | |
57 static GTY(()) tree ic_void_ptr_var; | |
58 static GTY(()) tree ic_gcov_type_ptr_var; | |
59 static GTY(()) tree ptr_void; | |
60 | |
61 /* Do initialization work for the edge profiler. */ | |
62 | |
63 /* Add code: | |
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter | |
65 static void* __gcov_indirect_call_callee; // actual callee address | |
66 */ | |
67 static void | |
68 tree_init_ic_make_global_vars (void) | |
69 { | |
70 tree gcov_type_ptr; | |
71 | |
72 ptr_void = build_pointer_type (void_type_node); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
73 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
74 ic_void_ptr_var |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
75 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
76 get_identifier ("__gcov_indirect_call_callee"), |
0 | 77 ptr_void); |
78 TREE_STATIC (ic_void_ptr_var) = 1; | |
79 TREE_PUBLIC (ic_void_ptr_var) = 0; | |
80 DECL_ARTIFICIAL (ic_void_ptr_var) = 1; | |
81 DECL_INITIAL (ic_void_ptr_var) = NULL; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
82 varpool_finalize_decl (ic_void_ptr_var); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
83 varpool_mark_needed_node (varpool_node (ic_void_ptr_var)); |
0 | 84 |
85 gcov_type_ptr = build_pointer_type (get_gcov_type ()); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
86 ic_gcov_type_ptr_var |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
87 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
88 get_identifier ("__gcov_indirect_call_counters"), |
0 | 89 gcov_type_ptr); |
90 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; | |
93 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
94 varpool_finalize_decl (ic_gcov_type_ptr_var); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
95 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var)); |
0 | 96 } |
97 | |
98 static void | |
99 tree_init_edge_profiler (void) | |
100 { | |
101 tree interval_profiler_fn_type; | |
102 tree pow2_profiler_fn_type; | |
103 tree one_value_profiler_fn_type; | |
104 tree gcov_type_ptr; | |
105 tree ic_profiler_fn_type; | |
106 tree average_profiler_fn_type; | |
107 | |
108 if (!gcov_type_node) | |
109 { | |
110 gcov_type_node = get_gcov_type (); | |
111 gcov_type_ptr = build_pointer_type (gcov_type_node); | |
112 | |
113 /* void (*) (gcov_type *, gcov_type, int, unsigned) */ | |
114 interval_profiler_fn_type | |
115 = build_function_type_list (void_type_node, | |
116 gcov_type_ptr, gcov_type_node, | |
117 integer_type_node, | |
118 unsigned_type_node, NULL_TREE); | |
119 tree_interval_profiler_fn | |
120 = build_fn_decl ("__gcov_interval_profiler", | |
121 interval_profiler_fn_type); | |
122 | |
123 /* void (*) (gcov_type *, gcov_type) */ | |
124 pow2_profiler_fn_type | |
125 = build_function_type_list (void_type_node, | |
126 gcov_type_ptr, gcov_type_node, | |
127 NULL_TREE); | |
128 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", | |
129 pow2_profiler_fn_type); | |
130 | |
131 /* void (*) (gcov_type *, gcov_type) */ | |
132 one_value_profiler_fn_type | |
133 = build_function_type_list (void_type_node, | |
134 gcov_type_ptr, gcov_type_node, | |
135 NULL_TREE); | |
136 tree_one_value_profiler_fn | |
137 = build_fn_decl ("__gcov_one_value_profiler", | |
138 one_value_profiler_fn_type); | |
139 | |
140 tree_init_ic_make_global_vars (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
141 |
0 | 142 /* void (*) (gcov_type *, gcov_type, void *, void *) */ |
143 ic_profiler_fn_type | |
144 = build_function_type_list (void_type_node, | |
145 gcov_type_ptr, gcov_type_node, | |
146 ptr_void, | |
147 ptr_void, NULL_TREE); | |
148 tree_indirect_call_profiler_fn | |
149 = build_fn_decl ("__gcov_indirect_call_profiler", | |
150 ic_profiler_fn_type); | |
151 /* void (*) (gcov_type *, gcov_type) */ | |
152 average_profiler_fn_type | |
153 = build_function_type_list (void_type_node, | |
154 gcov_type_ptr, gcov_type_node, NULL_TREE); | |
155 tree_average_profiler_fn | |
156 = build_fn_decl ("__gcov_average_profiler", | |
157 average_profiler_fn_type); | |
158 tree_ior_profiler_fn | |
159 = build_fn_decl ("__gcov_ior_profiler", | |
160 average_profiler_fn_type); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
161 /* LTO streamer needs assembler names. Because we create these decls |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
162 late, we need to initialize them by hand. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
163 DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
164 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
165 DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
166 DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
167 DECL_ASSEMBLER_NAME (tree_average_profiler_fn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
168 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); |
0 | 169 } |
170 } | |
171 | |
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 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
186 /* Output instructions as GIMPLE trees to increment the edge |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
187 execution count, and insert them on E. We rely on |
0 | 188 gsi_insert_on_edge to preserve the order. */ |
189 | |
190 static void | |
191 tree_gen_edge_profiler (int edgeno, edge e) | |
192 { | |
193 tree ref, one; | |
194 gimple stmt1, stmt2, stmt3; | |
195 | |
196 /* We share one temporary variable declaration per function. This | |
197 gets re-set in tree_profiling. */ | |
198 if (gcov_type_tmp_var == NULL_TREE) | |
199 gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter"); | |
200 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); | |
201 one = build_int_cst (gcov_type_node, 1); | |
202 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); | |
203 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var, | |
204 gcov_type_tmp_var, one); | |
205 stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var); | |
206 gsi_insert_on_edge (e, stmt1); | |
207 gsi_insert_on_edge (e, stmt2); | |
208 gsi_insert_on_edge (e, stmt3); | |
209 } | |
210 | |
211 /* Emits code to get VALUE to instrument at GSI, and returns the | |
212 variable containing the value. */ | |
213 | |
214 static tree | |
215 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value) | |
216 { | |
217 tree val = value->hvalue.value; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
218 if (POINTER_TYPE_P (TREE_TYPE (val))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
219 val = fold_convert (sizetype, val); |
0 | 220 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val), |
221 true, NULL_TREE, true, GSI_SAME_STMT); | |
222 } | |
223 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
224 /* Output instructions as GIMPLE trees to increment the interval histogram |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
225 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 226 tag of the section for counters, BASE is offset of the counter position. */ |
227 | |
228 static void | |
229 tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) | |
230 { | |
231 gimple stmt = value->hvalue.stmt; | |
232 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
233 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; | |
234 gimple call; | |
235 tree val; | |
236 tree start = build_int_cst_type (integer_type_node, | |
237 value->hdata.intvl.int_start); | |
238 tree steps = build_int_cst_type (unsigned_type_node, | |
239 value->hdata.intvl.steps); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
240 |
0 | 241 ref_ptr = force_gimple_operand_gsi (&gsi, |
242 build_addr (ref, current_function_decl), | |
243 true, NULL_TREE, true, GSI_SAME_STMT); | |
244 val = prepare_instrumented_value (&gsi, value); | |
245 call = gimple_build_call (tree_interval_profiler_fn, 4, | |
246 ref_ptr, val, start, steps); | |
247 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
248 add_abnormal_goto_call_edges (gsi); | |
249 } | |
250 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
251 /* Output instructions as GIMPLE trees to increment the power of two histogram |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
252 counter. VALUE is the expression whose value is profiled. TAG is the tag |
0 | 253 of the section for counters, BASE is offset of the counter position. */ |
254 | |
255 static void | |
256 tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) | |
257 { | |
258 gimple stmt = value->hvalue.stmt; | |
259 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
260 tree ref_ptr = tree_coverage_counter_addr (tag, base); | |
261 gimple call; | |
262 tree val; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
263 |
0 | 264 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
265 true, NULL_TREE, true, GSI_SAME_STMT); | |
266 val = prepare_instrumented_value (&gsi, value); | |
267 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); | |
268 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
269 add_abnormal_goto_call_edges (gsi); | |
270 } | |
271 | |
272 /* 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 | |
274 section for counters, BASE is offset of the counter position. */ | |
275 | |
276 static void | |
277 tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) | |
278 { | |
279 gimple stmt = value->hvalue.stmt; | |
280 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
281 tree ref_ptr = tree_coverage_counter_addr (tag, base); | |
282 gimple call; | |
283 tree val; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
284 |
0 | 285 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
286 true, NULL_TREE, true, GSI_SAME_STMT); | |
287 val = prepare_instrumented_value (&gsi, value); | |
288 call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val); | |
289 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
290 add_abnormal_goto_call_edges (gsi); | |
291 } | |
292 | |
293 | |
294 /* Output instructions as GIMPLE trees for code to find the most | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
295 common called function in indirect call. |
0 | 296 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 | |
298 counter position. */ | |
299 | |
300 static void | |
301 tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) | |
302 { | |
303 tree tmp1; | |
304 gimple stmt1, stmt2, stmt3; | |
305 gimple stmt = value->hvalue.stmt; | |
306 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
307 tree ref_ptr = tree_coverage_counter_addr (tag, base); | |
308 | |
309 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | |
310 true, NULL_TREE, true, GSI_SAME_STMT); | |
311 | |
312 /* Insert code: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
313 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
314 __gcov_indirect_call_counters = get_relevant_counter_ptr (); |
0 | 315 __gcov_indirect_call_callee = (void *) indirect call argument; |
316 */ | |
317 | |
318 tmp1 = create_tmp_var (ptr_void, "PROF"); | |
319 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); | |
320 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); | |
321 stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1); | |
322 | |
323 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); | |
324 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); | |
325 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); | |
326 } | |
327 | |
328 | |
329 /* Output instructions as GIMPLE trees for code to find the most | |
330 common called function in indirect call. Insert instructions at the | |
331 beginning of every possible called function. | |
332 */ | |
333 | |
334 static void | |
335 tree_gen_ic_func_profiler (void) | |
336 { | |
337 struct cgraph_node * c_node = cgraph_node (current_function_decl); | |
338 gimple_stmt_iterator gsi; | |
339 edge e; | |
340 basic_block bb; | |
341 edge_iterator ei; | |
342 gimple stmt1, stmt2; | |
343 tree tree_uid, cur_func; | |
344 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
345 if (cgraph_only_called_directly_p (c_node)) |
0 | 346 return; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
347 |
0 | 348 tree_init_edge_profiler (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
349 |
0 | 350 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) |
351 { | |
352 tree void0; | |
353 | |
354 bb = split_edge (e); | |
355 gsi = gsi_start_bb (bb); | |
356 | |
357 cur_func = force_gimple_operand_gsi (&gsi, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
358 build_addr (current_function_decl, |
0 | 359 current_function_decl), |
360 true, NULL_TREE, | |
361 true, GSI_SAME_STMT); | |
362 tree_uid = build_int_cst (gcov_type_node, c_node->pid); | |
363 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4, | |
364 ic_gcov_type_ptr_var, | |
365 tree_uid, | |
366 cur_func, | |
367 ic_void_ptr_var); | |
368 gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT); | |
369 gcc_assert (EDGE_COUNT (bb->succs) == 1); | |
370 bb = split_edge (EDGE_I (bb->succs, 0)); | |
371 add_abnormal_goto_call_edges (gsi); | |
372 | |
373 gsi = gsi_start_bb (bb); | |
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 } | |
382 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
383 /* Output instructions as GIMPLE trees for code to find the most common value |
0 | 384 of a difference between two evaluations of an expression. |
385 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. */ | |
387 | |
388 static void | |
389 tree_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, | |
390 unsigned tag ATTRIBUTE_UNUSED, | |
391 unsigned base ATTRIBUTE_UNUSED) | |
392 { | |
393 /* FIXME implement this. */ | |
394 #ifdef ENABLE_CHECKING | |
395 internal_error ("unimplemented functionality"); | |
396 #endif | |
397 gcc_unreachable (); | |
398 } | |
399 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
400 /* Output instructions as GIMPLE trees to increment the average histogram |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
401 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 402 tag of the section for counters, BASE is offset of the counter position. */ |
403 | |
404 static void | |
405 tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) | |
406 { | |
407 gimple stmt = value->hvalue.stmt; | |
408 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
409 tree ref_ptr = tree_coverage_counter_addr (tag, base); | |
410 gimple call; | |
411 tree val; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
412 |
0 | 413 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
414 true, NULL_TREE, | |
415 true, GSI_SAME_STMT); | |
416 val = prepare_instrumented_value (&gsi, value); | |
417 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val); | |
418 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
419 add_abnormal_goto_call_edges (gsi); | |
420 } | |
421 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
422 /* Output instructions as GIMPLE trees to increment the ior histogram |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
423 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 424 tag of the section for counters, BASE is offset of the counter position. */ |
425 | |
426 static void | |
427 tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) | |
428 { | |
429 gimple stmt = value->hvalue.stmt; | |
430 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
431 tree ref_ptr = tree_coverage_counter_addr (tag, base); | |
432 gimple call; | |
433 tree val; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
434 |
0 | 435 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
436 true, NULL_TREE, true, GSI_SAME_STMT); | |
437 val = prepare_instrumented_value (&gsi, value); | |
438 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); | |
439 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
440 add_abnormal_goto_call_edges (gsi); | |
441 } | |
442 | |
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 | |
459 static unsigned int | |
460 tree_profiling (void) | |
461 { | |
462 /* Don't profile functions produced at destruction time, particularly | |
463 the gcov datastructure initializer. Don't profile if it has been | |
464 already instrumented either (when OpenMP expansion creates | |
465 child function from already instrumented body). */ | |
466 if (cgraph_state == CGRAPH_STATE_FINISHED | |
467 || cfun->after_tree_profile) | |
468 return 0; | |
469 | |
470 /* Re-set global shared temporary variable for edge-counters. */ | |
471 gcov_type_tmp_var = NULL_TREE; | |
472 | |
473 branch_prob (); | |
474 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
475 if (! flag_branch_probabilities |
0 | 476 && flag_profile_values) |
477 tree_gen_ic_func_profiler (); | |
478 | |
479 if (flag_branch_probabilities | |
480 && flag_profile_values | |
481 && flag_value_profile_transformations) | |
482 value_profile_transformations (); | |
483 /* The above could hose dominator info. Currently there is | |
484 none coming in, this is a safety valve. It should be | |
485 easy to adjust it, if and when there is some. */ | |
486 free_dominance_info (CDI_DOMINATORS); | |
487 free_dominance_info (CDI_POST_DOMINATORS); | |
488 cfun->after_tree_profile = 1; | |
489 return 0; | |
490 } | |
491 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
492 struct gimple_opt_pass pass_tree_profile = |
0 | 493 { |
494 { | |
495 GIMPLE_PASS, | |
496 "tree_profile", /* name */ | |
497 do_tree_profiling, /* gate */ | |
498 tree_profiling, /* execute */ | |
499 NULL, /* sub */ | |
500 NULL, /* next */ | |
501 0, /* static_pass_number */ | |
502 TV_BRANCH_PROB, /* tv_id */ | |
503 PROP_gimple_leh | PROP_cfg, /* properties_required */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
504 0, /* properties_provided */ |
0 | 505 0, /* properties_destroyed */ |
506 0, /* todo_flags_start */ | |
507 TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */ | |
508 } | |
509 }; | |
510 | |
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" |