Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-profile.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Calculate branch probabilities, and basic block execution counts. |
145 | 2 Copyright (C) 1990-2020 Free Software Foundation, Inc. |
0 | 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; |
4 based on some ideas from Dain Samples of UC Berkeley. | |
5 Further mangling by Bob Manson, Cygnus Support. | |
6 Converted to use trees by Dale Johannesen, Apple Computer. | |
7 | |
8 This file is part of GCC. | |
9 | |
10 GCC is free software; you can redistribute it and/or modify it under | |
11 the terms of the GNU General Public License as published by the Free | |
12 Software Foundation; either version 3, or (at your option) any later | |
13 version. | |
14 | |
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with GCC; see the file COPYING3. If not see | |
22 <http://www.gnu.org/licenses/>. */ | |
23 | |
24 /* Generate basic block profile instrumentation and auxiliary files. | |
25 Tree-based version. See profile.c for overview. */ | |
26 | |
27 #include "config.h" | |
28 #include "system.h" | |
29 #include "coretypes.h" | |
111 | 30 #include "memmodel.h" |
31 #include "backend.h" | |
32 #include "target.h" | |
33 #include "tree.h" | |
34 #include "gimple.h" | |
35 #include "cfghooks.h" | |
36 #include "tree-pass.h" | |
37 #include "ssa.h" | |
38 #include "cgraph.h" | |
0 | 39 #include "coverage.h" |
111 | 40 #include "diagnostic-core.h" |
41 #include "fold-const.h" | |
42 #include "varasm.h" | |
43 #include "tree-nested.h" | |
44 #include "gimplify.h" | |
45 #include "gimple-iterator.h" | |
46 #include "gimplify-me.h" | |
47 #include "tree-cfg.h" | |
48 #include "tree-into-ssa.h" | |
0 | 49 #include "value-prof.h" |
111 | 50 #include "profile.h" |
51 #include "tree-cfgcleanup.h" | |
52 #include "stringpool.h" | |
53 #include "attribs.h" | |
131 | 54 #include "tree-pretty-print.h" |
55 #include "langhooks.h" | |
56 #include "stor-layout.h" | |
145 | 57 #include "xregex.h" |
0 | 58 |
59 static GTY(()) tree gcov_type_node; | |
60 static GTY(()) tree tree_interval_profiler_fn; | |
61 static GTY(()) tree tree_pow2_profiler_fn; | |
145 | 62 static GTY(()) tree tree_topn_values_profiler_fn; |
0 | 63 static GTY(()) tree tree_indirect_call_profiler_fn; |
64 static GTY(()) tree tree_average_profiler_fn; | |
65 static GTY(()) tree tree_ior_profiler_fn; | |
111 | 66 static GTY(()) tree tree_time_profiler_counter; |
67 | |
0 | 68 |
131 | 69 static GTY(()) tree ic_tuple_var; |
70 static GTY(()) tree ic_tuple_counters_field; | |
71 static GTY(()) tree ic_tuple_callee_field; | |
0 | 72 |
73 /* Do initialization work for the edge profiler. */ | |
74 | |
75 /* Add code: | |
145 | 76 __thread gcov* __gcov_indirect_call.counters; // pointer to actual counter |
77 __thread void* __gcov_indirect_call.callee; // actual callee address | |
111 | 78 __thread int __gcov_function_counter; // time profiler function counter |
0 | 79 */ |
80 static void | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
81 init_ic_make_global_vars (void) |
0 | 82 { |
111 | 83 tree gcov_type_ptr; |
0 | 84 |
131 | 85 gcov_type_ptr = build_pointer_type (get_gcov_type ()); |
86 | |
87 tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE); | |
88 | |
89 /* callee */ | |
90 ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, | |
91 ptr_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
|
92 |
131 | 93 /* counters */ |
94 ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, | |
95 NULL_TREE, gcov_type_ptr); | |
96 DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field; | |
97 | |
98 finish_builtin_struct (tuple_type, "indirect_call_tuple", | |
99 ic_tuple_counters_field, NULL_TREE); | |
100 | |
101 ic_tuple_var | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
102 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
145 | 103 get_identifier ("__gcov_indirect_call"), tuple_type); |
131 | 104 TREE_PUBLIC (ic_tuple_var) = 1; |
105 DECL_ARTIFICIAL (ic_tuple_var) = 1; | |
106 DECL_INITIAL (ic_tuple_var) = NULL; | |
107 DECL_EXTERNAL (ic_tuple_var) = 1; | |
111 | 108 if (targetm.have_tls) |
145 | 109 set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var)); |
0 | 110 } |
111 | |
111 | 112 /* Create the type and function decls for the interface with gcov. */ |
113 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
114 void |
111 | 115 gimple_init_gcov_profiler (void) |
0 | 116 { |
117 tree interval_profiler_fn_type; | |
118 tree pow2_profiler_fn_type; | |
145 | 119 tree topn_values_profiler_fn_type; |
0 | 120 tree gcov_type_ptr; |
121 tree ic_profiler_fn_type; | |
122 tree average_profiler_fn_type; | |
111 | 123 const char *fn_name; |
0 | 124 |
125 if (!gcov_type_node) | |
126 { | |
111 | 127 const char *fn_suffix |
128 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : ""; | |
129 | |
0 | 130 gcov_type_node = get_gcov_type (); |
131 gcov_type_ptr = build_pointer_type (gcov_type_node); | |
132 | |
133 /* void (*) (gcov_type *, gcov_type, int, unsigned) */ | |
134 interval_profiler_fn_type | |
135 = build_function_type_list (void_type_node, | |
136 gcov_type_ptr, gcov_type_node, | |
137 integer_type_node, | |
138 unsigned_type_node, NULL_TREE); | |
111 | 139 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL); |
140 tree_interval_profiler_fn = build_fn_decl (fn_name, | |
141 interval_profiler_fn_type); | |
142 free (CONST_CAST (char *, fn_name)); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
143 TREE_NOTHROW (tree_interval_profiler_fn) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
144 DECL_ATTRIBUTES (tree_interval_profiler_fn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
145 = tree_cons (get_identifier ("leaf"), NULL, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
146 DECL_ATTRIBUTES (tree_interval_profiler_fn)); |
0 | 147 |
148 /* void (*) (gcov_type *, gcov_type) */ | |
149 pow2_profiler_fn_type | |
150 = build_function_type_list (void_type_node, | |
151 gcov_type_ptr, gcov_type_node, | |
152 NULL_TREE); | |
111 | 153 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL); |
154 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type); | |
155 free (CONST_CAST (char *, fn_name)); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
156 TREE_NOTHROW (tree_pow2_profiler_fn) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
157 DECL_ATTRIBUTES (tree_pow2_profiler_fn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
158 = tree_cons (get_identifier ("leaf"), NULL, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
159 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); |
0 | 160 |
161 /* void (*) (gcov_type *, gcov_type) */ | |
145 | 162 topn_values_profiler_fn_type |
0 | 163 = build_function_type_list (void_type_node, |
164 gcov_type_ptr, gcov_type_node, | |
165 NULL_TREE); | |
145 | 166 fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL); |
167 tree_topn_values_profiler_fn | |
168 = build_fn_decl (fn_name, topn_values_profiler_fn_type); | |
111 | 169 free (CONST_CAST (char *, fn_name)); |
145 | 170 |
171 TREE_NOTHROW (tree_topn_values_profiler_fn) = 1; | |
172 DECL_ATTRIBUTES (tree_topn_values_profiler_fn) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
173 = tree_cons (get_identifier ("leaf"), NULL, |
145 | 174 DECL_ATTRIBUTES (tree_topn_values_profiler_fn)); |
0 | 175 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
176 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
|
177 |
111 | 178 /* void (*) (gcov_type, void *) */ |
0 | 179 ic_profiler_fn_type |
180 = build_function_type_list (void_type_node, | |
111 | 181 gcov_type_node, |
131 | 182 ptr_type_node, |
111 | 183 NULL_TREE); |
145 | 184 fn_name = concat ("__gcov_indirect_call_profiler_v4", fn_suffix, NULL); |
0 | 185 tree_indirect_call_profiler_fn |
145 | 186 = build_fn_decl (fn_name, ic_profiler_fn_type); |
187 free (CONST_CAST (char *, fn_name)); | |
111 | 188 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
189 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
190 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
191 = tree_cons (get_identifier ("leaf"), NULL, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
192 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
193 |
111 | 194 tree_time_profiler_counter |
195 = build_decl (UNKNOWN_LOCATION, VAR_DECL, | |
196 get_identifier ("__gcov_time_profiler_counter"), | |
197 get_gcov_type ()); | |
198 TREE_PUBLIC (tree_time_profiler_counter) = 1; | |
199 DECL_EXTERNAL (tree_time_profiler_counter) = 1; | |
200 TREE_STATIC (tree_time_profiler_counter) = 1; | |
201 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1; | |
202 DECL_INITIAL (tree_time_profiler_counter) = NULL; | |
203 | |
0 | 204 /* void (*) (gcov_type *, gcov_type) */ |
205 average_profiler_fn_type | |
206 = build_function_type_list (void_type_node, | |
207 gcov_type_ptr, gcov_type_node, NULL_TREE); | |
111 | 208 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL); |
209 tree_average_profiler_fn = build_fn_decl (fn_name, | |
210 average_profiler_fn_type); | |
211 free (CONST_CAST (char *, fn_name)); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
212 TREE_NOTHROW (tree_average_profiler_fn) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
213 DECL_ATTRIBUTES (tree_average_profiler_fn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
214 = tree_cons (get_identifier ("leaf"), NULL, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
215 DECL_ATTRIBUTES (tree_average_profiler_fn)); |
111 | 216 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL); |
217 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type); | |
218 free (CONST_CAST (char *, fn_name)); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
219 TREE_NOTHROW (tree_ior_profiler_fn) = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
220 DECL_ATTRIBUTES (tree_ior_profiler_fn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
221 = tree_cons (get_identifier ("leaf"), NULL, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
222 DECL_ATTRIBUTES (tree_ior_profiler_fn)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
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 /* 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
|
225 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
|
226 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
|
227 DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); |
145 | 228 DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
229 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
|
230 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
|
231 DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); |
0 | 232 } |
233 } | |
234 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
235 /* 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
|
236 execution count, and insert them on E. We rely on |
0 | 237 gsi_insert_on_edge to preserve the order. */ |
238 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
239 void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
240 gimple_gen_edge_profiler (int edgeno, edge e) |
0 | 241 { |
111 | 242 tree one; |
0 | 243 |
244 one = build_int_cst (gcov_type_node, 1); | |
111 | 245 |
246 if (flag_profile_update == PROFILE_UPDATE_ATOMIC) | |
247 { | |
248 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */ | |
249 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno); | |
250 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32 | |
251 ? BUILT_IN_ATOMIC_FETCH_ADD_8: | |
252 BUILT_IN_ATOMIC_FETCH_ADD_4); | |
253 gcall *stmt = gimple_build_call (f, 3, addr, one, | |
254 build_int_cst (integer_type_node, | |
255 MEMMODEL_RELAXED)); | |
256 gsi_insert_on_edge (e, stmt); | |
257 } | |
258 else | |
259 { | |
260 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); | |
261 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, | |
262 NULL, "PROF_edge_counter"); | |
263 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); | |
264 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, | |
265 NULL, "PROF_edge_counter"); | |
266 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR, | |
267 gimple_assign_lhs (stmt1), one); | |
268 gassign *stmt3 = gimple_build_assign (unshare_expr (ref), | |
269 gimple_assign_lhs (stmt2)); | |
270 gsi_insert_on_edge (e, stmt1); | |
271 gsi_insert_on_edge (e, stmt2); | |
272 gsi_insert_on_edge (e, stmt3); | |
273 } | |
0 | 274 } |
275 | |
276 /* Emits code to get VALUE to instrument at GSI, and returns the | |
277 variable containing the value. */ | |
278 | |
279 static tree | |
280 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value) | |
281 { | |
282 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
|
283 if (POINTER_TYPE_P (TREE_TYPE (val))) |
111 | 284 val = fold_convert (build_nonstandard_integer_type |
285 (TYPE_PRECISION (TREE_TYPE (val)), 1), val); | |
0 | 286 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val), |
287 true, NULL_TREE, true, GSI_SAME_STMT); | |
288 } | |
289 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
290 /* 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
|
291 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 292 tag of the section for counters, BASE is offset of the counter position. */ |
293 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
294 void |
145 | 295 gimple_gen_interval_profiler (histogram_value value, unsigned tag) |
0 | 296 { |
111 | 297 gimple *stmt = value->hvalue.stmt; |
0 | 298 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 299 tree ref = tree_coverage_counter_ref (tag, 0), ref_ptr; |
111 | 300 gcall *call; |
0 | 301 tree val; |
302 tree start = build_int_cst_type (integer_type_node, | |
303 value->hdata.intvl.int_start); | |
304 tree steps = build_int_cst_type (unsigned_type_node, | |
305 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
|
306 |
0 | 307 ref_ptr = force_gimple_operand_gsi (&gsi, |
111 | 308 build_addr (ref), |
0 | 309 true, NULL_TREE, true, GSI_SAME_STMT); |
310 val = prepare_instrumented_value (&gsi, value); | |
311 call = gimple_build_call (tree_interval_profiler_fn, 4, | |
312 ref_ptr, val, start, steps); | |
313 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
314 } | |
315 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
316 /* 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
|
317 counter. VALUE is the expression whose value is profiled. TAG is the tag |
145 | 318 of the section for counters. */ |
0 | 319 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
320 void |
145 | 321 gimple_gen_pow2_profiler (histogram_value value, unsigned tag) |
0 | 322 { |
111 | 323 gimple *stmt = value->hvalue.stmt; |
0 | 324 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 325 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
111 | 326 gcall *call; |
0 | 327 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
|
328 |
0 | 329 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
330 true, NULL_TREE, true, GSI_SAME_STMT); | |
331 val = prepare_instrumented_value (&gsi, value); | |
332 call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); | |
333 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
334 } | |
335 | |
145 | 336 /* Output instructions as GIMPLE trees for code to find the most N common |
337 values. VALUE is the expression whose value is profiled. TAG is the tag | |
338 of the section for counters. */ | |
0 | 339 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
340 void |
145 | 341 gimple_gen_topn_values_profiler (histogram_value value, unsigned tag) |
0 | 342 { |
111 | 343 gimple *stmt = value->hvalue.stmt; |
0 | 344 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 345 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
111 | 346 gcall *call; |
0 | 347 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
|
348 |
0 | 349 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
350 true, NULL_TREE, true, GSI_SAME_STMT); | |
351 val = prepare_instrumented_value (&gsi, value); | |
145 | 352 call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val); |
0 | 353 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
354 } | |
355 | |
356 | |
357 /* 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
|
358 common called function in indirect call. |
0 | 359 VALUE is the call expression whose indirect callee is profiled. |
145 | 360 TAG is the tag of the section for counters. */ |
0 | 361 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
362 void |
145 | 363 gimple_gen_ic_profiler (histogram_value value, unsigned tag) |
0 | 364 { |
365 tree tmp1; | |
111 | 366 gassign *stmt1, *stmt2, *stmt3; |
367 gimple *stmt = value->hvalue.stmt; | |
0 | 368 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 369 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
111 | 370 |
0 | 371 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
372 true, NULL_TREE, true, GSI_SAME_STMT); | |
373 | |
374 /* 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
|
375 |
131 | 376 stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr (); |
111 | 377 stmt2: tmp1 = (void *) (indirect call argument value) |
131 | 378 stmt3: __gcov_indirect_call.callee = tmp1; |
111 | 379 |
380 Example: | |
381 f_1 = foo; | |
131 | 382 __gcov_indirect_call.counters = &__gcov4.main[0]; |
111 | 383 PROF_9 = f_1; |
145 | 384 __gcov_indirect_call.callee = PROF_9; |
111 | 385 _4 = f_1 (); |
0 | 386 */ |
387 | |
131 | 388 tree gcov_type_ptr = build_pointer_type (get_gcov_type ()); |
389 | |
390 tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr, | |
391 ic_tuple_var, ic_tuple_counters_field, NULL_TREE); | |
392 | |
393 stmt1 = gimple_build_assign (counter_ref, ref_ptr); | |
394 tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF"); | |
0 | 395 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); |
131 | 396 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node, |
397 ic_tuple_var, ic_tuple_callee_field, NULL_TREE); | |
398 stmt3 = gimple_build_assign (callee_ref, tmp1); | |
0 | 399 |
400 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); | |
401 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); | |
402 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); | |
403 } | |
404 | |
405 | |
406 /* Output instructions as GIMPLE trees for code to find the most | |
407 common called function in indirect call. Insert instructions at the | |
408 beginning of every possible called function. | |
409 */ | |
410 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
411 void |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
412 gimple_gen_ic_func_profiler (void) |
0 | 413 { |
111 | 414 struct cgraph_node * c_node = cgraph_node::get (current_function_decl); |
415 gcall *stmt1; | |
416 tree tree_uid, cur_func, void0; | |
0 | 417 |
111 | 418 if (c_node->only_called_directly_p ()) |
0 | 419 return; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
420 |
111 | 421 gimple_init_gcov_profiler (); |
422 | |
423 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); | |
424 basic_block cond_bb = split_edge (single_succ_edge (entry)); | |
425 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); | |
426 | |
427 /* We need to do an extra split in order to not create an input | |
428 for a possible PHI node. */ | |
429 split_edge (single_succ_edge (update_bb)); | |
430 | |
431 edge true_edge = single_succ_edge (cond_bb); | |
432 true_edge->flags = EDGE_TRUE_VALUE; | |
433 | |
434 profile_probability probability; | |
435 if (DECL_VIRTUAL_P (current_function_decl)) | |
436 probability = profile_probability::very_likely (); | |
437 else | |
438 probability = profile_probability::unlikely (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
439 |
111 | 440 true_edge->probability = probability; |
441 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest, | |
442 EDGE_FALSE_VALUE); | |
443 e->probability = true_edge->probability.invert (); | |
444 | |
445 /* Insert code: | |
446 | |
145 | 447 if (__gcov_indirect_call.callee != NULL) |
448 __gcov_indirect_call_profiler_v3 (profile_id, ¤t_function_decl); | |
111 | 449 |
145 | 450 The function __gcov_indirect_call_profiler_v3 is responsible for |
451 resetting __gcov_indirect_call.callee to NULL. */ | |
111 | 452 |
453 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | |
131 | 454 void0 = build_int_cst (ptr_type_node, 0); |
111 | 455 |
131 | 456 tree callee_ref = build3 (COMPONENT_REF, ptr_type_node, |
457 ic_tuple_var, ic_tuple_callee_field, NULL_TREE); | |
458 | |
459 tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE, | |
111 | 460 true, GSI_SAME_STMT); |
461 | |
462 gcond *cond = gimple_build_cond (NE_EXPR, ref, | |
463 void0, NULL, NULL); | |
464 gsi_insert_before (&gsi, cond, GSI_NEW_STMT); | |
465 | |
466 gsi = gsi_after_labels (update_bb); | |
0 | 467 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
468 cur_func = force_gimple_operand_gsi (&gsi, |
111 | 469 build_addr (current_function_decl), |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
470 true, NULL_TREE, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
471 true, GSI_SAME_STMT); |
111 | 472 tree_uid = build_int_cst |
473 (gcov_type_node, | |
474 cgraph_node::get (current_function_decl)->profile_id); | |
475 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2, | |
476 tree_uid, cur_func); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
477 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); |
0 | 478 } |
479 | |
111 | 480 /* Output instructions as GIMPLE tree at the beginning for each function. |
481 TAG is the tag of the section for counters, BASE is offset of the | |
482 counter position and GSI is the iterator we place the counter. */ | |
0 | 483 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
484 void |
145 | 485 gimple_gen_time_profiler (unsigned tag) |
0 | 486 { |
111 | 487 tree type = get_gcov_type (); |
488 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); | |
489 basic_block cond_bb = split_edge (single_succ_edge (entry)); | |
490 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); | |
491 | |
492 /* We need to do an extra split in order to not create an input | |
493 for a possible PHI node. */ | |
494 split_edge (single_succ_edge (update_bb)); | |
495 | |
496 edge true_edge = single_succ_edge (cond_bb); | |
497 true_edge->flags = EDGE_TRUE_VALUE; | |
498 true_edge->probability = profile_probability::unlikely (); | |
499 edge e | |
500 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE); | |
501 e->probability = true_edge->probability.invert (); | |
502 | |
503 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | |
145 | 504 tree original_ref = tree_coverage_counter_ref (tag, 0); |
111 | 505 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE, |
506 true, GSI_SAME_STMT); | |
507 tree one = build_int_cst (type, 1); | |
508 | |
509 /* Emit: if (counters[0] != 0). */ | |
510 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0), | |
511 NULL, NULL); | |
512 gsi_insert_before (&gsi, cond, GSI_NEW_STMT); | |
513 | |
514 gsi = gsi_start_bb (update_bb); | |
515 | |
516 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */ | |
517 if (flag_profile_update == PROFILE_UPDATE_ATOMIC) | |
518 { | |
519 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL, | |
520 "time_profiler_counter_ptr"); | |
521 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr), | |
522 tree_time_profiler_counter); | |
523 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr); | |
524 gsi_insert_before (&gsi, assign, GSI_NEW_STMT); | |
525 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32 | |
526 ? BUILT_IN_ATOMIC_ADD_FETCH_8: | |
527 BUILT_IN_ATOMIC_ADD_FETCH_4); | |
528 gcall *stmt = gimple_build_call (f, 3, ptr, one, | |
529 build_int_cst (integer_type_node, | |
530 MEMMODEL_RELAXED)); | |
531 tree result_type = TREE_TYPE (TREE_TYPE (f)); | |
532 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile"); | |
533 gimple_set_lhs (stmt, tmp); | |
534 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); | |
535 tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
536 assign = gimple_build_assign (tmp, NOP_EXPR, | |
537 gimple_call_lhs (stmt)); | |
538 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
539 assign = gimple_build_assign (original_ref, tmp); | |
540 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
541 } | |
542 else | |
543 { | |
544 tree tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
545 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter); | |
546 gsi_insert_before (&gsi, assign, GSI_NEW_STMT); | |
547 | |
548 tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
549 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign), | |
550 one); | |
551 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
552 assign = gimple_build_assign (original_ref, tmp); | |
553 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
554 assign = gimple_build_assign (tree_time_profiler_counter, tmp); | |
555 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
556 } | |
0 | 557 } |
558 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
559 /* 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
|
560 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 561 tag of the section for counters, BASE is offset of the counter position. */ |
562 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
563 void |
145 | 564 gimple_gen_average_profiler (histogram_value value, unsigned tag) |
0 | 565 { |
111 | 566 gimple *stmt = value->hvalue.stmt; |
0 | 567 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 568 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
111 | 569 gcall *call; |
0 | 570 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
|
571 |
0 | 572 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
573 true, NULL_TREE, | |
574 true, GSI_SAME_STMT); | |
575 val = prepare_instrumented_value (&gsi, value); | |
576 call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val); | |
577 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
578 } | |
579 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
580 /* 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
|
581 counter. VALUE is the expression whose value is profiled. TAG is the |
0 | 582 tag of the section for counters, BASE is offset of the counter position. */ |
583 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
584 void |
145 | 585 gimple_gen_ior_profiler (histogram_value value, unsigned tag) |
0 | 586 { |
111 | 587 gimple *stmt = value->hvalue.stmt; |
0 | 588 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
145 | 589 tree ref_ptr = tree_coverage_counter_addr (tag, 0); |
111 | 590 gcall *call; |
0 | 591 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
|
592 |
0 | 593 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
594 true, NULL_TREE, true, GSI_SAME_STMT); | |
595 val = prepare_instrumented_value (&gsi, value); | |
596 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); | |
597 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | |
598 } | |
599 | |
145 | 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; | |
674 } | |
675 | |
111 | 676 #ifndef HAVE_sync_compare_and_swapsi |
677 #define HAVE_sync_compare_and_swapsi 0 | |
678 #endif | |
679 #ifndef HAVE_atomic_compare_and_swapsi | |
680 #define HAVE_atomic_compare_and_swapsi 0 | |
681 #endif | |
682 | |
683 #ifndef HAVE_sync_compare_and_swapdi | |
684 #define HAVE_sync_compare_and_swapdi 0 | |
685 #endif | |
686 #ifndef HAVE_atomic_compare_and_swapdi | |
687 #define HAVE_atomic_compare_and_swapdi 0 | |
688 #endif | |
689 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
690 /* Profile all functions in the callgraph. */ |
0 | 691 |
692 static unsigned int | |
693 tree_profiling (void) | |
694 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
695 struct cgraph_node *node; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
696 |
111 | 697 /* Verify whether we can utilize atomic update operations. */ |
698 bool can_support_atomic = false; | |
699 unsigned HOST_WIDE_INT gcov_type_size | |
700 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ())); | |
701 if (gcov_type_size == 4) | |
702 can_support_atomic | |
703 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi; | |
704 else if (gcov_type_size == 8) | |
705 can_support_atomic | |
706 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi; | |
0 | 707 |
111 | 708 if (flag_profile_update == PROFILE_UPDATE_ATOMIC |
709 && !can_support_atomic) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
710 { |
111 | 711 warning (0, "target does not support atomic profile update, " |
712 "single mode is selected"); | |
713 flag_profile_update = PROFILE_UPDATE_SINGLE; | |
714 } | |
715 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC) | |
716 flag_profile_update = can_support_atomic | |
717 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE; | |
718 | |
719 /* This is a small-ipa pass that gets called only once, from | |
720 cgraphunit.c:ipa_passes(). */ | |
721 gcc_assert (symtab->state == IPA_SSA); | |
722 | |
723 init_node_map (true); | |
145 | 724 parse_profile_file_filtering (); |
111 | 725 |
726 FOR_EACH_DEFINED_FUNCTION (node) | |
727 { | |
145 | 728 bool thunk = false; |
729 if (!gimple_has_body_p (node->decl) && !node->thunk.thunk_p) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
730 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
731 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
732 /* Don't profile functions produced for builtin stuff. */ |
111 | 733 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
734 continue; | |
735 | |
736 if (lookup_attribute ("no_profile_instrument_function", | |
737 DECL_ATTRIBUTES (node->decl))) | |
738 continue; | |
739 /* Do not instrument extern inline functions when testing coverage. | |
740 While this is not perfectly consistent (early inlined extern inlines | |
741 will get acocunted), testsuite expects that. */ | |
742 if (DECL_EXTERNAL (node->decl) | |
743 && flag_test_coverage) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
744 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
745 |
145 | 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 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
769 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
770 |
131 | 771 if (dump_file) |
772 dump_function_header (dump_file, cfun->decl, dump_flags); | |
773 | |
111 | 774 /* Local pure-const may imply need to fixup the cfg. */ |
145 | 775 if (gimple_has_body_p (node->decl) |
776 && (execute_fixup_cfg () & TODO_cleanup_cfg)) | |
111 | 777 cleanup_tree_cfg (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
778 |
145 | 779 branch_prob (thunk); |
0 | 780 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
781 if (! flag_branch_probabilities |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
782 && flag_profile_values) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
783 gimple_gen_ic_func_profiler (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
784 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
785 if (flag_branch_probabilities |
145 | 786 && !thunk |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
787 && flag_profile_values |
145 | 788 && flag_value_profile_transformations |
789 && profile_status_for_fn (cfun) == PROFILE_READ) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
790 gimple_value_profile_transformations (); |
0 | 791 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
792 /* The above could hose dominator info. Currently there is |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
793 none coming in, this is a safety valve. It should be |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
794 easy to adjust it, if and when there is some. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
795 free_dominance_info (CDI_DOMINATORS); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
796 free_dominance_info (CDI_POST_DOMINATORS); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
797 pop_cfun (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
798 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
799 |
145 | 800 release_profile_file_filtering (); |
801 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
802 /* Drop pure/const flags from instrumented functions. */ |
111 | 803 if (profile_arc_flag || flag_test_coverage) |
804 FOR_EACH_DEFINED_FUNCTION (node) | |
805 { | |
806 if (!gimple_has_body_p (node->decl) | |
807 || !(!node->clone_of | |
808 || node->decl != node->clone_of->decl)) | |
809 continue; | |
810 | |
811 /* Don't profile functions produced for builtin stuff. */ | |
812 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) | |
813 continue; | |
814 | |
815 node->set_const_flag (false, false); | |
816 node->set_pure_flag (false, false); | |
817 } | |
818 | |
819 /* Update call statements and rebuild the cgraph. */ | |
820 FOR_EACH_DEFINED_FUNCTION (node) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
821 { |
111 | 822 basic_block bb; |
823 | |
824 if (!gimple_has_body_p (node->decl) | |
825 || !(!node->clone_of | |
826 || node->decl != node->clone_of->decl)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
827 continue; |
0 | 828 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
829 /* Don't profile functions produced for builtin stuff. */ |
111 | 830 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
831 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
832 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
833 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
834 |
111 | 835 FOR_EACH_BB_FN (bb, cfun) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
836 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
837 gimple_stmt_iterator gsi; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
838 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
839 { |
111 | 840 gimple *stmt = gsi_stmt (gsi); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
841 if (is_gimple_call (stmt)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
842 update_stmt (stmt); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
843 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
844 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
845 |
111 | 846 /* re-merge split blocks. */ |
847 cleanup_tree_cfg (); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
848 update_ssa (TODO_update_ssa); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
849 |
111 | 850 cgraph_edge::rebuild_edges (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
851 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
852 pop_cfun (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
853 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
854 |
111 | 855 handle_missing_profiles (); |
856 | |
857 del_node_map (); | |
0 | 858 return 0; |
859 } | |
860 | |
111 | 861 namespace { |
862 | |
863 const pass_data pass_data_ipa_tree_profile = | |
864 { | |
865 SIMPLE_IPA_PASS, /* type */ | |
866 "profile", /* name */ | |
867 OPTGROUP_NONE, /* optinfo_flags */ | |
868 TV_IPA_PROFILE, /* tv_id */ | |
869 0, /* properties_required */ | |
870 0, /* properties_provided */ | |
871 0, /* properties_destroyed */ | |
872 0, /* todo_flags_start */ | |
873 TODO_dump_symtab, /* todo_flags_finish */ | |
874 }; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
875 |
111 | 876 class pass_ipa_tree_profile : public simple_ipa_opt_pass |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
877 { |
111 | 878 public: |
879 pass_ipa_tree_profile (gcc::context *ctxt) | |
880 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt) | |
881 {} | |
882 | |
883 /* opt_pass methods: */ | |
884 virtual bool gate (function *); | |
885 virtual unsigned int execute (function *) { return tree_profiling (); } | |
886 | |
887 }; // class pass_ipa_tree_profile | |
888 | |
889 bool | |
890 pass_ipa_tree_profile::gate (function *) | |
891 { | |
892 /* When profile instrumentation, use or test coverage shall be performed. | |
893 But for AutoFDO, this there is no instrumentation, thus this pass is | |
145 | 894 disabled. */ |
111 | 895 return (!in_lto_p && !flag_auto_profile |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
896 && (flag_branch_probabilities || flag_test_coverage |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
897 || profile_arc_flag)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
898 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
899 |
111 | 900 } // anon namespace |
901 | |
902 simple_ipa_opt_pass * | |
903 make_pass_ipa_tree_profile (gcc::context *ctxt) | |
0 | 904 { |
111 | 905 return new pass_ipa_tree_profile (ctxt); |
906 } | |
0 | 907 |
908 #include "gt-tree-profile.h" |