Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-profile.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Calculate branch probabilities, and basic block execution counts. | 1 /* Calculate branch probabilities, and basic block execution counts. |
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, | 2 Copyright (C) 1990-2017 Free Software Foundation, Inc. |
3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 | |
4 Free Software Foundation, Inc. | |
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; | 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support; |
6 based on some ideas from Dain Samples of UC Berkeley. | 4 based on some ideas from Dain Samples of UC Berkeley. |
7 Further mangling by Bob Manson, Cygnus Support. | 5 Further mangling by Bob Manson, Cygnus Support. |
8 Converted to use trees by Dale Johannesen, Apple Computer. | 6 Converted to use trees by Dale Johannesen, Apple Computer. |
9 | 7 |
27 Tree-based version. See profile.c for overview. */ | 25 Tree-based version. See profile.c for overview. */ |
28 | 26 |
29 #include "config.h" | 27 #include "config.h" |
30 #include "system.h" | 28 #include "system.h" |
31 #include "coretypes.h" | 29 #include "coretypes.h" |
32 #include "tm.h" | 30 #include "memmodel.h" |
33 #include "flags.h" | 31 #include "backend.h" |
34 #include "regs.h" | 32 #include "target.h" |
35 #include "function.h" | 33 #include "tree.h" |
36 #include "basic-block.h" | 34 #include "gimple.h" |
35 #include "cfghooks.h" | |
36 #include "tree-pass.h" | |
37 #include "ssa.h" | |
38 #include "cgraph.h" | |
39 #include "coverage.h" | |
37 #include "diagnostic-core.h" | 40 #include "diagnostic-core.h" |
38 #include "coverage.h" | 41 #include "fold-const.h" |
39 #include "tree.h" | 42 #include "varasm.h" |
40 #include "tree-flow.h" | 43 #include "tree-nested.h" |
41 #include "tree-dump.h" | 44 #include "gimplify.h" |
42 #include "tree-pass.h" | 45 #include "gimple-iterator.h" |
43 #include "timevar.h" | 46 #include "gimplify-me.h" |
47 #include "tree-cfg.h" | |
48 #include "tree-into-ssa.h" | |
44 #include "value-prof.h" | 49 #include "value-prof.h" |
45 #include "cgraph.h" | 50 #include "profile.h" |
51 #include "tree-cfgcleanup.h" | |
52 #include "params.h" | |
53 #include "stringpool.h" | |
54 #include "attribs.h" | |
46 | 55 |
47 static GTY(()) tree gcov_type_node; | 56 static GTY(()) tree gcov_type_node; |
48 static GTY(()) tree gcov_type_tmp_var; | |
49 static GTY(()) tree tree_interval_profiler_fn; | 57 static GTY(()) tree tree_interval_profiler_fn; |
50 static GTY(()) tree tree_pow2_profiler_fn; | 58 static GTY(()) tree tree_pow2_profiler_fn; |
51 static GTY(()) tree tree_one_value_profiler_fn; | 59 static GTY(()) tree tree_one_value_profiler_fn; |
52 static GTY(()) tree tree_indirect_call_profiler_fn; | 60 static GTY(()) tree tree_indirect_call_profiler_fn; |
53 static GTY(()) tree tree_average_profiler_fn; | 61 static GTY(()) tree tree_average_profiler_fn; |
54 static GTY(()) tree tree_ior_profiler_fn; | 62 static GTY(()) tree tree_ior_profiler_fn; |
55 | 63 static GTY(()) tree tree_time_profiler_counter; |
64 | |
56 | 65 |
57 static GTY(()) tree ic_void_ptr_var; | 66 static GTY(()) tree ic_void_ptr_var; |
58 static GTY(()) tree ic_gcov_type_ptr_var; | 67 static GTY(()) tree ic_gcov_type_ptr_var; |
59 static GTY(()) tree ptr_void; | 68 static GTY(()) tree ptr_void; |
60 | 69 |
61 /* Do initialization work for the edge profiler. */ | 70 /* Do initialization work for the edge profiler. */ |
62 | 71 |
63 /* Add code: | 72 /* Add code: |
64 static gcov* __gcov_indirect_call_counters; // pointer to actual counter | 73 __thread gcov* __gcov_indirect_call_counters; // pointer to actual counter |
65 static void* __gcov_indirect_call_callee; // actual callee address | 74 __thread void* __gcov_indirect_call_callee; // actual callee address |
75 __thread int __gcov_function_counter; // time profiler function counter | |
66 */ | 76 */ |
67 static void | 77 static void |
68 init_ic_make_global_vars (void) | 78 init_ic_make_global_vars (void) |
69 { | 79 { |
70 tree gcov_type_ptr; | 80 tree gcov_type_ptr; |
71 | 81 |
72 ptr_void = build_pointer_type (void_type_node); | 82 ptr_void = build_pointer_type (void_type_node); |
73 | 83 |
74 ic_void_ptr_var | 84 ic_void_ptr_var |
75 = build_decl (UNKNOWN_LOCATION, VAR_DECL, | 85 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
76 get_identifier ("__gcov_indirect_call_callee"), | 86 get_identifier ( |
87 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ? | |
88 "__gcov_indirect_call_topn_callee" : | |
89 "__gcov_indirect_call_callee")), | |
77 ptr_void); | 90 ptr_void); |
91 TREE_PUBLIC (ic_void_ptr_var) = 1; | |
92 DECL_EXTERNAL (ic_void_ptr_var) = 1; | |
78 TREE_STATIC (ic_void_ptr_var) = 1; | 93 TREE_STATIC (ic_void_ptr_var) = 1; |
79 TREE_PUBLIC (ic_void_ptr_var) = 0; | |
80 DECL_ARTIFICIAL (ic_void_ptr_var) = 1; | 94 DECL_ARTIFICIAL (ic_void_ptr_var) = 1; |
81 DECL_INITIAL (ic_void_ptr_var) = NULL; | 95 DECL_INITIAL (ic_void_ptr_var) = NULL; |
82 varpool_finalize_decl (ic_void_ptr_var); | 96 if (targetm.have_tls) |
83 varpool_mark_needed_node (varpool_node (ic_void_ptr_var)); | 97 set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var)); |
84 | 98 |
85 gcov_type_ptr = build_pointer_type (get_gcov_type ()); | 99 gcov_type_ptr = build_pointer_type (get_gcov_type ()); |
100 | |
86 ic_gcov_type_ptr_var | 101 ic_gcov_type_ptr_var |
87 = build_decl (UNKNOWN_LOCATION, VAR_DECL, | 102 = build_decl (UNKNOWN_LOCATION, VAR_DECL, |
88 get_identifier ("__gcov_indirect_call_counters"), | 103 get_identifier ( |
104 (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ? | |
105 "__gcov_indirect_call_topn_counters" : | |
106 "__gcov_indirect_call_counters")), | |
89 gcov_type_ptr); | 107 gcov_type_ptr); |
108 TREE_PUBLIC (ic_gcov_type_ptr_var) = 1; | |
109 DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1; | |
90 TREE_STATIC (ic_gcov_type_ptr_var) = 1; | 110 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; | 111 DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1; |
93 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; | 112 DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; |
94 varpool_finalize_decl (ic_gcov_type_ptr_var); | 113 if (targetm.have_tls) |
95 varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var)); | 114 set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var)); |
96 } | 115 } |
97 | 116 |
98 void | 117 /* Create the type and function decls for the interface with gcov. */ |
99 gimple_init_edge_profiler (void) | 118 |
119 void | |
120 gimple_init_gcov_profiler (void) | |
100 { | 121 { |
101 tree interval_profiler_fn_type; | 122 tree interval_profiler_fn_type; |
102 tree pow2_profiler_fn_type; | 123 tree pow2_profiler_fn_type; |
103 tree one_value_profiler_fn_type; | 124 tree one_value_profiler_fn_type; |
104 tree gcov_type_ptr; | 125 tree gcov_type_ptr; |
105 tree ic_profiler_fn_type; | 126 tree ic_profiler_fn_type; |
106 tree average_profiler_fn_type; | 127 tree average_profiler_fn_type; |
128 const char *profiler_fn_name; | |
129 const char *fn_name; | |
107 | 130 |
108 if (!gcov_type_node) | 131 if (!gcov_type_node) |
109 { | 132 { |
133 const char *fn_suffix | |
134 = flag_profile_update == PROFILE_UPDATE_ATOMIC ? "_atomic" : ""; | |
135 | |
110 gcov_type_node = get_gcov_type (); | 136 gcov_type_node = get_gcov_type (); |
111 gcov_type_ptr = build_pointer_type (gcov_type_node); | 137 gcov_type_ptr = build_pointer_type (gcov_type_node); |
112 | 138 |
113 /* void (*) (gcov_type *, gcov_type, int, unsigned) */ | 139 /* void (*) (gcov_type *, gcov_type, int, unsigned) */ |
114 interval_profiler_fn_type | 140 interval_profiler_fn_type |
115 = build_function_type_list (void_type_node, | 141 = build_function_type_list (void_type_node, |
116 gcov_type_ptr, gcov_type_node, | 142 gcov_type_ptr, gcov_type_node, |
117 integer_type_node, | 143 integer_type_node, |
118 unsigned_type_node, NULL_TREE); | 144 unsigned_type_node, NULL_TREE); |
119 tree_interval_profiler_fn | 145 fn_name = concat ("__gcov_interval_profiler", fn_suffix, NULL); |
120 = build_fn_decl ("__gcov_interval_profiler", | 146 tree_interval_profiler_fn = build_fn_decl (fn_name, |
121 interval_profiler_fn_type); | 147 interval_profiler_fn_type); |
148 free (CONST_CAST (char *, fn_name)); | |
122 TREE_NOTHROW (tree_interval_profiler_fn) = 1; | 149 TREE_NOTHROW (tree_interval_profiler_fn) = 1; |
123 DECL_ATTRIBUTES (tree_interval_profiler_fn) | 150 DECL_ATTRIBUTES (tree_interval_profiler_fn) |
124 = tree_cons (get_identifier ("leaf"), NULL, | 151 = tree_cons (get_identifier ("leaf"), NULL, |
125 DECL_ATTRIBUTES (tree_interval_profiler_fn)); | 152 DECL_ATTRIBUTES (tree_interval_profiler_fn)); |
126 | 153 |
127 /* void (*) (gcov_type *, gcov_type) */ | 154 /* void (*) (gcov_type *, gcov_type) */ |
128 pow2_profiler_fn_type | 155 pow2_profiler_fn_type |
129 = build_function_type_list (void_type_node, | 156 = build_function_type_list (void_type_node, |
130 gcov_type_ptr, gcov_type_node, | 157 gcov_type_ptr, gcov_type_node, |
131 NULL_TREE); | 158 NULL_TREE); |
132 tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", | 159 fn_name = concat ("__gcov_pow2_profiler", fn_suffix, NULL); |
133 pow2_profiler_fn_type); | 160 tree_pow2_profiler_fn = build_fn_decl (fn_name, pow2_profiler_fn_type); |
161 free (CONST_CAST (char *, fn_name)); | |
134 TREE_NOTHROW (tree_pow2_profiler_fn) = 1; | 162 TREE_NOTHROW (tree_pow2_profiler_fn) = 1; |
135 DECL_ATTRIBUTES (tree_pow2_profiler_fn) | 163 DECL_ATTRIBUTES (tree_pow2_profiler_fn) |
136 = tree_cons (get_identifier ("leaf"), NULL, | 164 = tree_cons (get_identifier ("leaf"), NULL, |
137 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); | 165 DECL_ATTRIBUTES (tree_pow2_profiler_fn)); |
138 | 166 |
139 /* void (*) (gcov_type *, gcov_type) */ | 167 /* void (*) (gcov_type *, gcov_type) */ |
140 one_value_profiler_fn_type | 168 one_value_profiler_fn_type |
141 = build_function_type_list (void_type_node, | 169 = build_function_type_list (void_type_node, |
142 gcov_type_ptr, gcov_type_node, | 170 gcov_type_ptr, gcov_type_node, |
143 NULL_TREE); | 171 NULL_TREE); |
144 tree_one_value_profiler_fn | 172 fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL); |
145 = build_fn_decl ("__gcov_one_value_profiler", | 173 tree_one_value_profiler_fn = build_fn_decl (fn_name, |
146 one_value_profiler_fn_type); | 174 one_value_profiler_fn_type); |
175 free (CONST_CAST (char *, fn_name)); | |
147 TREE_NOTHROW (tree_one_value_profiler_fn) = 1; | 176 TREE_NOTHROW (tree_one_value_profiler_fn) = 1; |
148 DECL_ATTRIBUTES (tree_one_value_profiler_fn) | 177 DECL_ATTRIBUTES (tree_one_value_profiler_fn) |
149 = tree_cons (get_identifier ("leaf"), NULL, | 178 = tree_cons (get_identifier ("leaf"), NULL, |
150 DECL_ATTRIBUTES (tree_one_value_profiler_fn)); | 179 DECL_ATTRIBUTES (tree_one_value_profiler_fn)); |
151 | 180 |
152 init_ic_make_global_vars (); | 181 init_ic_make_global_vars (); |
153 | 182 |
154 /* void (*) (gcov_type *, gcov_type, void *, void *) */ | 183 /* void (*) (gcov_type, void *) */ |
155 ic_profiler_fn_type | 184 ic_profiler_fn_type |
156 = build_function_type_list (void_type_node, | 185 = build_function_type_list (void_type_node, |
157 gcov_type_ptr, gcov_type_node, | 186 gcov_type_node, |
158 ptr_void, | 187 ptr_void, |
159 ptr_void, NULL_TREE); | 188 NULL_TREE); |
189 profiler_fn_name = "__gcov_indirect_call_profiler_v2"; | |
190 if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE)) | |
191 profiler_fn_name = "__gcov_indirect_call_topn_profiler"; | |
192 | |
160 tree_indirect_call_profiler_fn | 193 tree_indirect_call_profiler_fn |
161 = build_fn_decl ("__gcov_indirect_call_profiler", | 194 = build_fn_decl (profiler_fn_name, ic_profiler_fn_type); |
162 ic_profiler_fn_type); | 195 |
163 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; | 196 TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; |
164 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) | 197 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) |
165 = tree_cons (get_identifier ("leaf"), NULL, | 198 = tree_cons (get_identifier ("leaf"), NULL, |
166 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); | 199 DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); |
167 | 200 |
201 tree_time_profiler_counter | |
202 = build_decl (UNKNOWN_LOCATION, VAR_DECL, | |
203 get_identifier ("__gcov_time_profiler_counter"), | |
204 get_gcov_type ()); | |
205 TREE_PUBLIC (tree_time_profiler_counter) = 1; | |
206 DECL_EXTERNAL (tree_time_profiler_counter) = 1; | |
207 TREE_STATIC (tree_time_profiler_counter) = 1; | |
208 DECL_ARTIFICIAL (tree_time_profiler_counter) = 1; | |
209 DECL_INITIAL (tree_time_profiler_counter) = NULL; | |
210 | |
168 /* void (*) (gcov_type *, gcov_type) */ | 211 /* void (*) (gcov_type *, gcov_type) */ |
169 average_profiler_fn_type | 212 average_profiler_fn_type |
170 = build_function_type_list (void_type_node, | 213 = build_function_type_list (void_type_node, |
171 gcov_type_ptr, gcov_type_node, NULL_TREE); | 214 gcov_type_ptr, gcov_type_node, NULL_TREE); |
172 tree_average_profiler_fn | 215 fn_name = concat ("__gcov_average_profiler", fn_suffix, NULL); |
173 = build_fn_decl ("__gcov_average_profiler", | 216 tree_average_profiler_fn = build_fn_decl (fn_name, |
174 average_profiler_fn_type); | 217 average_profiler_fn_type); |
218 free (CONST_CAST (char *, fn_name)); | |
175 TREE_NOTHROW (tree_average_profiler_fn) = 1; | 219 TREE_NOTHROW (tree_average_profiler_fn) = 1; |
176 DECL_ATTRIBUTES (tree_average_profiler_fn) | 220 DECL_ATTRIBUTES (tree_average_profiler_fn) |
177 = tree_cons (get_identifier ("leaf"), NULL, | 221 = tree_cons (get_identifier ("leaf"), NULL, |
178 DECL_ATTRIBUTES (tree_average_profiler_fn)); | 222 DECL_ATTRIBUTES (tree_average_profiler_fn)); |
179 tree_ior_profiler_fn | 223 fn_name = concat ("__gcov_ior_profiler", fn_suffix, NULL); |
180 = build_fn_decl ("__gcov_ior_profiler", | 224 tree_ior_profiler_fn = build_fn_decl (fn_name, average_profiler_fn_type); |
181 average_profiler_fn_type); | 225 free (CONST_CAST (char *, fn_name)); |
182 TREE_NOTHROW (tree_ior_profiler_fn) = 1; | 226 TREE_NOTHROW (tree_ior_profiler_fn) = 1; |
183 DECL_ATTRIBUTES (tree_ior_profiler_fn) | 227 DECL_ATTRIBUTES (tree_ior_profiler_fn) |
184 = tree_cons (get_identifier ("leaf"), NULL, | 228 = tree_cons (get_identifier ("leaf"), NULL, |
185 DECL_ATTRIBUTES (tree_ior_profiler_fn)); | 229 DECL_ATTRIBUTES (tree_ior_profiler_fn)); |
186 | 230 |
200 gsi_insert_on_edge to preserve the order. */ | 244 gsi_insert_on_edge to preserve the order. */ |
201 | 245 |
202 void | 246 void |
203 gimple_gen_edge_profiler (int edgeno, edge e) | 247 gimple_gen_edge_profiler (int edgeno, edge e) |
204 { | 248 { |
205 tree ref, one; | 249 tree one; |
206 gimple stmt1, stmt2, stmt3; | 250 |
207 | |
208 /* We share one temporary variable declaration per function. This | |
209 gets re-set in tree_profiling. */ | |
210 if (gcov_type_tmp_var == NULL_TREE) | |
211 gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter"); | |
212 ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); | |
213 one = build_int_cst (gcov_type_node, 1); | 251 one = build_int_cst (gcov_type_node, 1); |
214 stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); | 252 |
215 gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1)); | 253 if (flag_profile_update == PROFILE_UPDATE_ATOMIC) |
216 stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var, | 254 { |
217 gimple_assign_lhs (stmt1), one); | 255 /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */ |
218 gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2)); | 256 tree addr = tree_coverage_counter_addr (GCOV_COUNTER_ARCS, edgeno); |
219 stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2)); | 257 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32 |
220 gsi_insert_on_edge (e, stmt1); | 258 ? BUILT_IN_ATOMIC_FETCH_ADD_8: |
221 gsi_insert_on_edge (e, stmt2); | 259 BUILT_IN_ATOMIC_FETCH_ADD_4); |
222 gsi_insert_on_edge (e, stmt3); | 260 gcall *stmt = gimple_build_call (f, 3, addr, one, |
261 build_int_cst (integer_type_node, | |
262 MEMMODEL_RELAXED)); | |
263 gsi_insert_on_edge (e, stmt); | |
264 } | |
265 else | |
266 { | |
267 tree ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); | |
268 tree gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, | |
269 NULL, "PROF_edge_counter"); | |
270 gassign *stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); | |
271 gcov_type_tmp_var = make_temp_ssa_name (gcov_type_node, | |
272 NULL, "PROF_edge_counter"); | |
273 gassign *stmt2 = gimple_build_assign (gcov_type_tmp_var, PLUS_EXPR, | |
274 gimple_assign_lhs (stmt1), one); | |
275 gassign *stmt3 = gimple_build_assign (unshare_expr (ref), | |
276 gimple_assign_lhs (stmt2)); | |
277 gsi_insert_on_edge (e, stmt1); | |
278 gsi_insert_on_edge (e, stmt2); | |
279 gsi_insert_on_edge (e, stmt3); | |
280 } | |
223 } | 281 } |
224 | 282 |
225 /* Emits code to get VALUE to instrument at GSI, and returns the | 283 /* Emits code to get VALUE to instrument at GSI, and returns the |
226 variable containing the value. */ | 284 variable containing the value. */ |
227 | 285 |
228 static tree | 286 static tree |
229 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value) | 287 prepare_instrumented_value (gimple_stmt_iterator *gsi, histogram_value value) |
230 { | 288 { |
231 tree val = value->hvalue.value; | 289 tree val = value->hvalue.value; |
232 if (POINTER_TYPE_P (TREE_TYPE (val))) | 290 if (POINTER_TYPE_P (TREE_TYPE (val))) |
233 val = fold_convert (sizetype, val); | 291 val = fold_convert (build_nonstandard_integer_type |
292 (TYPE_PRECISION (TREE_TYPE (val)), 1), val); | |
234 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val), | 293 return force_gimple_operand_gsi (gsi, fold_convert (gcov_type_node, val), |
235 true, NULL_TREE, true, GSI_SAME_STMT); | 294 true, NULL_TREE, true, GSI_SAME_STMT); |
236 } | 295 } |
237 | 296 |
238 /* Output instructions as GIMPLE trees to increment the interval histogram | 297 /* Output instructions as GIMPLE trees to increment the interval histogram |
240 tag of the section for counters, BASE is offset of the counter position. */ | 299 tag of the section for counters, BASE is offset of the counter position. */ |
241 | 300 |
242 void | 301 void |
243 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) | 302 gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) |
244 { | 303 { |
245 gimple stmt = value->hvalue.stmt; | 304 gimple *stmt = value->hvalue.stmt; |
246 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 305 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
247 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; | 306 tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; |
248 gimple call; | 307 gcall *call; |
249 tree val; | 308 tree val; |
250 tree start = build_int_cst_type (integer_type_node, | 309 tree start = build_int_cst_type (integer_type_node, |
251 value->hdata.intvl.int_start); | 310 value->hdata.intvl.int_start); |
252 tree steps = build_int_cst_type (unsigned_type_node, | 311 tree steps = build_int_cst_type (unsigned_type_node, |
253 value->hdata.intvl.steps); | 312 value->hdata.intvl.steps); |
254 | 313 |
255 ref_ptr = force_gimple_operand_gsi (&gsi, | 314 ref_ptr = force_gimple_operand_gsi (&gsi, |
256 build_addr (ref, current_function_decl), | 315 build_addr (ref), |
257 true, NULL_TREE, true, GSI_SAME_STMT); | 316 true, NULL_TREE, true, GSI_SAME_STMT); |
258 val = prepare_instrumented_value (&gsi, value); | 317 val = prepare_instrumented_value (&gsi, value); |
259 call = gimple_build_call (tree_interval_profiler_fn, 4, | 318 call = gimple_build_call (tree_interval_profiler_fn, 4, |
260 ref_ptr, val, start, steps); | 319 ref_ptr, val, start, steps); |
261 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 320 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
266 of the section for counters, BASE is offset of the counter position. */ | 325 of the section for counters, BASE is offset of the counter position. */ |
267 | 326 |
268 void | 327 void |
269 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) | 328 gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) |
270 { | 329 { |
271 gimple stmt = value->hvalue.stmt; | 330 gimple *stmt = value->hvalue.stmt; |
272 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 331 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
273 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 332 tree ref_ptr = tree_coverage_counter_addr (tag, base); |
274 gimple call; | 333 gcall *call; |
275 tree val; | 334 tree val; |
276 | 335 |
277 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 336 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
278 true, NULL_TREE, true, GSI_SAME_STMT); | 337 true, NULL_TREE, true, GSI_SAME_STMT); |
279 val = prepare_instrumented_value (&gsi, value); | 338 val = prepare_instrumented_value (&gsi, value); |
286 section for counters, BASE is offset of the counter position. */ | 345 section for counters, BASE is offset of the counter position. */ |
287 | 346 |
288 void | 347 void |
289 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) | 348 gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) |
290 { | 349 { |
291 gimple stmt = value->hvalue.stmt; | 350 gimple *stmt = value->hvalue.stmt; |
292 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 351 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
293 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 352 tree ref_ptr = tree_coverage_counter_addr (tag, base); |
294 gimple call; | 353 gcall *call; |
295 tree val; | 354 tree val; |
296 | 355 |
297 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 356 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
298 true, NULL_TREE, true, GSI_SAME_STMT); | 357 true, NULL_TREE, true, GSI_SAME_STMT); |
299 val = prepare_instrumented_value (&gsi, value); | 358 val = prepare_instrumented_value (&gsi, value); |
310 | 369 |
311 void | 370 void |
312 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) | 371 gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) |
313 { | 372 { |
314 tree tmp1; | 373 tree tmp1; |
315 gimple stmt1, stmt2, stmt3; | 374 gassign *stmt1, *stmt2, *stmt3; |
316 gimple stmt = value->hvalue.stmt; | 375 gimple *stmt = value->hvalue.stmt; |
317 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 376 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
318 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 377 tree ref_ptr = tree_coverage_counter_addr (tag, base); |
319 | 378 |
379 if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && | |
380 tag == GCOV_COUNTER_V_INDIR) || | |
381 (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) && | |
382 tag == GCOV_COUNTER_ICALL_TOPNV)) | |
383 return; | |
384 | |
320 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 385 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
321 true, NULL_TREE, true, GSI_SAME_STMT); | 386 true, NULL_TREE, true, GSI_SAME_STMT); |
322 | 387 |
323 /* Insert code: | 388 /* Insert code: |
324 | 389 |
325 __gcov_indirect_call_counters = get_relevant_counter_ptr (); | 390 stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr (); |
326 __gcov_indirect_call_callee = (void *) indirect call argument; | 391 stmt2: tmp1 = (void *) (indirect call argument value) |
392 stmt3: __gcov_indirect_call_callee = tmp1; | |
393 | |
394 Example: | |
395 f_1 = foo; | |
396 __gcov_indirect_call_counters = &__gcov4.main[0]; | |
397 PROF_9 = f_1; | |
398 __gcov_indirect_call_callee = PROF_9; | |
399 _4 = f_1 (); | |
327 */ | 400 */ |
328 | 401 |
329 tmp1 = create_tmp_reg (ptr_void, "PROF"); | |
330 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); | 402 stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); |
403 tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF"); | |
331 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); | 404 stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); |
332 gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2)); | |
333 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2)); | 405 stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2)); |
334 | 406 |
335 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); | 407 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); |
336 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); | 408 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); |
337 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); | 409 gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); |
344 */ | 416 */ |
345 | 417 |
346 void | 418 void |
347 gimple_gen_ic_func_profiler (void) | 419 gimple_gen_ic_func_profiler (void) |
348 { | 420 { |
349 struct cgraph_node * c_node = cgraph_node (current_function_decl); | 421 struct cgraph_node * c_node = cgraph_node::get (current_function_decl); |
350 gimple_stmt_iterator gsi; | 422 gcall *stmt1; |
351 gimple stmt1, stmt2; | 423 tree tree_uid, cur_func, void0; |
352 tree tree_uid, cur_func, counter_ptr, ptr_var, void0; | 424 |
353 | 425 if (c_node->only_called_directly_p ()) |
354 if (cgraph_only_called_directly_p (c_node)) | |
355 return; | 426 return; |
356 | 427 |
357 gimple_init_edge_profiler (); | 428 gimple_init_gcov_profiler (); |
358 | 429 |
359 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); | 430 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); |
431 basic_block cond_bb = split_edge (single_succ_edge (entry)); | |
432 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); | |
433 | |
434 /* We need to do an extra split in order to not create an input | |
435 for a possible PHI node. */ | |
436 split_edge (single_succ_edge (update_bb)); | |
437 | |
438 edge true_edge = single_succ_edge (cond_bb); | |
439 true_edge->flags = EDGE_TRUE_VALUE; | |
440 | |
441 profile_probability probability; | |
442 if (DECL_VIRTUAL_P (current_function_decl)) | |
443 probability = profile_probability::very_likely (); | |
444 else | |
445 probability = profile_probability::unlikely (); | |
446 | |
447 true_edge->probability = probability; | |
448 edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest, | |
449 EDGE_FALSE_VALUE); | |
450 e->probability = true_edge->probability.invert (); | |
451 | |
452 /* Insert code: | |
453 | |
454 if (__gcov_indirect_call_callee != NULL) | |
455 __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl); | |
456 | |
457 The function __gcov_indirect_call_profiler_v2 is responsible for | |
458 resetting __gcov_indirect_call_callee to NULL. */ | |
459 | |
460 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | |
461 void0 = build_int_cst (build_pointer_type (void_type_node), 0); | |
462 | |
463 tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE, | |
464 true, GSI_SAME_STMT); | |
465 | |
466 gcond *cond = gimple_build_cond (NE_EXPR, ref, | |
467 void0, NULL, NULL); | |
468 gsi_insert_before (&gsi, cond, GSI_NEW_STMT); | |
469 | |
470 gsi = gsi_after_labels (update_bb); | |
360 | 471 |
361 cur_func = force_gimple_operand_gsi (&gsi, | 472 cur_func = force_gimple_operand_gsi (&gsi, |
362 build_addr (current_function_decl, | 473 build_addr (current_function_decl), |
363 current_function_decl), | |
364 true, NULL_TREE, | 474 true, NULL_TREE, |
365 true, GSI_SAME_STMT); | 475 true, GSI_SAME_STMT); |
366 counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var, | 476 tree_uid = build_int_cst |
367 true, NULL_TREE, true, | 477 (gcov_type_node, |
368 GSI_SAME_STMT); | 478 cgraph_node::get (current_function_decl)->profile_id); |
369 ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, | 479 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2, |
370 true, NULL_TREE, true, | 480 tree_uid, cur_func); |
371 GSI_SAME_STMT); | |
372 tree_uid = build_int_cst (gcov_type_node, c_node->pid); | |
373 stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4, | |
374 counter_ptr, tree_uid, cur_func, ptr_var); | |
375 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); | 481 gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); |
376 | 482 } |
377 /* Set __gcov_indirect_call_callee to 0, | 483 |
378 so that calls from other modules won't get misattributed | 484 /* Output instructions as GIMPLE tree at the beginning for each function. |
379 to the last caller of the current callee. */ | 485 TAG is the tag of the section for counters, BASE is offset of the |
380 void0 = build_int_cst (build_pointer_type (void_type_node), 0); | 486 counter position and GSI is the iterator we place the counter. */ |
381 stmt2 = gimple_build_assign (ic_void_ptr_var, void0); | 487 |
382 gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); | 488 void |
383 } | 489 gimple_gen_time_profiler (unsigned tag, unsigned base) |
384 | 490 { |
385 /* Output instructions as GIMPLE trees for code to find the most common value | 491 tree type = get_gcov_type (); |
386 of a difference between two evaluations of an expression. | 492 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); |
387 VALUE is the expression whose value is profiled. TAG is the tag of the | 493 basic_block cond_bb = split_edge (single_succ_edge (entry)); |
388 section for counters, BASE is offset of the counter position. */ | 494 basic_block update_bb = split_edge (single_succ_edge (cond_bb)); |
389 | 495 |
390 void | 496 /* We need to do an extra split in order to not create an input |
391 gimple_gen_const_delta_profiler (histogram_value value ATTRIBUTE_UNUSED, | 497 for a possible PHI node. */ |
392 unsigned tag ATTRIBUTE_UNUSED, | 498 split_edge (single_succ_edge (update_bb)); |
393 unsigned base ATTRIBUTE_UNUSED) | 499 |
394 { | 500 edge true_edge = single_succ_edge (cond_bb); |
395 /* FIXME implement this. */ | 501 true_edge->flags = EDGE_TRUE_VALUE; |
396 #ifdef ENABLE_CHECKING | 502 true_edge->probability = profile_probability::unlikely (); |
397 internal_error ("unimplemented functionality"); | 503 edge e |
398 #endif | 504 = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE); |
399 gcc_unreachable (); | 505 e->probability = true_edge->probability.invert (); |
506 | |
507 gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); | |
508 tree original_ref = tree_coverage_counter_ref (tag, base); | |
509 tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE, | |
510 true, GSI_SAME_STMT); | |
511 tree one = build_int_cst (type, 1); | |
512 | |
513 /* Emit: if (counters[0] != 0). */ | |
514 gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0), | |
515 NULL, NULL); | |
516 gsi_insert_before (&gsi, cond, GSI_NEW_STMT); | |
517 | |
518 gsi = gsi_start_bb (update_bb); | |
519 | |
520 /* Emit: counters[0] = ++__gcov_time_profiler_counter. */ | |
521 if (flag_profile_update == PROFILE_UPDATE_ATOMIC) | |
522 { | |
523 tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL, | |
524 "time_profiler_counter_ptr"); | |
525 tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr), | |
526 tree_time_profiler_counter); | |
527 gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr); | |
528 gsi_insert_before (&gsi, assign, GSI_NEW_STMT); | |
529 tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32 | |
530 ? BUILT_IN_ATOMIC_ADD_FETCH_8: | |
531 BUILT_IN_ATOMIC_ADD_FETCH_4); | |
532 gcall *stmt = gimple_build_call (f, 3, ptr, one, | |
533 build_int_cst (integer_type_node, | |
534 MEMMODEL_RELAXED)); | |
535 tree result_type = TREE_TYPE (TREE_TYPE (f)); | |
536 tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile"); | |
537 gimple_set_lhs (stmt, tmp); | |
538 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); | |
539 tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
540 assign = gimple_build_assign (tmp, NOP_EXPR, | |
541 gimple_call_lhs (stmt)); | |
542 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
543 assign = gimple_build_assign (original_ref, tmp); | |
544 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
545 } | |
546 else | |
547 { | |
548 tree tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
549 gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter); | |
550 gsi_insert_before (&gsi, assign, GSI_NEW_STMT); | |
551 | |
552 tmp = make_temp_ssa_name (type, NULL, "time_profile"); | |
553 assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign), | |
554 one); | |
555 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
556 assign = gimple_build_assign (original_ref, tmp); | |
557 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
558 assign = gimple_build_assign (tree_time_profiler_counter, tmp); | |
559 gsi_insert_after (&gsi, assign, GSI_NEW_STMT); | |
560 } | |
400 } | 561 } |
401 | 562 |
402 /* Output instructions as GIMPLE trees to increment the average histogram | 563 /* Output instructions as GIMPLE trees to increment the average histogram |
403 counter. VALUE is the expression whose value is profiled. TAG is the | 564 counter. VALUE is the expression whose value is profiled. TAG is the |
404 tag of the section for counters, BASE is offset of the counter position. */ | 565 tag of the section for counters, BASE is offset of the counter position. */ |
405 | 566 |
406 void | 567 void |
407 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) | 568 gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) |
408 { | 569 { |
409 gimple stmt = value->hvalue.stmt; | 570 gimple *stmt = value->hvalue.stmt; |
410 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 571 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
411 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 572 tree ref_ptr = tree_coverage_counter_addr (tag, base); |
412 gimple call; | 573 gcall *call; |
413 tree val; | 574 tree val; |
414 | 575 |
415 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 576 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
416 true, NULL_TREE, | 577 true, NULL_TREE, |
417 true, GSI_SAME_STMT); | 578 true, GSI_SAME_STMT); |
425 tag of the section for counters, BASE is offset of the counter position. */ | 586 tag of the section for counters, BASE is offset of the counter position. */ |
426 | 587 |
427 void | 588 void |
428 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) | 589 gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) |
429 { | 590 { |
430 gimple stmt = value->hvalue.stmt; | 591 gimple *stmt = value->hvalue.stmt; |
431 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | 592 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); |
432 tree ref_ptr = tree_coverage_counter_addr (tag, base); | 593 tree ref_ptr = tree_coverage_counter_addr (tag, base); |
433 gimple call; | 594 gcall *call; |
434 tree val; | 595 tree val; |
435 | 596 |
436 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, | 597 ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, |
437 true, NULL_TREE, true, GSI_SAME_STMT); | 598 true, NULL_TREE, true, GSI_SAME_STMT); |
438 val = prepare_instrumented_value (&gsi, value); | 599 val = prepare_instrumented_value (&gsi, value); |
439 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); | 600 call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); |
440 gsi_insert_before (&gsi, call, GSI_NEW_STMT); | 601 gsi_insert_before (&gsi, call, GSI_NEW_STMT); |
441 } | 602 } |
442 | 603 |
604 #ifndef HAVE_sync_compare_and_swapsi | |
605 #define HAVE_sync_compare_and_swapsi 0 | |
606 #endif | |
607 #ifndef HAVE_atomic_compare_and_swapsi | |
608 #define HAVE_atomic_compare_and_swapsi 0 | |
609 #endif | |
610 | |
611 #ifndef HAVE_sync_compare_and_swapdi | |
612 #define HAVE_sync_compare_and_swapdi 0 | |
613 #endif | |
614 #ifndef HAVE_atomic_compare_and_swapdi | |
615 #define HAVE_atomic_compare_and_swapdi 0 | |
616 #endif | |
617 | |
443 /* Profile all functions in the callgraph. */ | 618 /* Profile all functions in the callgraph. */ |
444 | 619 |
445 static unsigned int | 620 static unsigned int |
446 tree_profiling (void) | 621 tree_profiling (void) |
447 { | 622 { |
448 struct cgraph_node *node; | 623 struct cgraph_node *node; |
449 | 624 |
450 /* Don't profile functions produced at destruction time, particularly | 625 /* Verify whether we can utilize atomic update operations. */ |
451 the gcov datastructure initializer. Don't profile if it has been | 626 bool can_support_atomic = false; |
452 already instrumented either (when OpenMP expansion creates | 627 unsigned HOST_WIDE_INT gcov_type_size |
453 child function from already instrumented body). */ | 628 = tree_to_uhwi (TYPE_SIZE_UNIT (get_gcov_type ())); |
454 if (cgraph_state == CGRAPH_STATE_FINISHED) | 629 if (gcov_type_size == 4) |
455 return 0; | 630 can_support_atomic |
456 | 631 = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi; |
457 for (node = cgraph_nodes; node; node = node->next) | 632 else if (gcov_type_size == 8) |
633 can_support_atomic | |
634 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi; | |
635 | |
636 if (flag_profile_update == PROFILE_UPDATE_ATOMIC | |
637 && !can_support_atomic) | |
458 { | 638 { |
459 if (!node->analyzed | 639 warning (0, "target does not support atomic profile update, " |
460 || !gimple_has_body_p (node->decl) | 640 "single mode is selected"); |
461 || !(!node->clone_of || node->decl != node->clone_of->decl)) | 641 flag_profile_update = PROFILE_UPDATE_SINGLE; |
642 } | |
643 else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC) | |
644 flag_profile_update = can_support_atomic | |
645 ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE; | |
646 | |
647 /* This is a small-ipa pass that gets called only once, from | |
648 cgraphunit.c:ipa_passes(). */ | |
649 gcc_assert (symtab->state == IPA_SSA); | |
650 | |
651 init_node_map (true); | |
652 | |
653 FOR_EACH_DEFINED_FUNCTION (node) | |
654 { | |
655 if (!gimple_has_body_p (node->decl)) | |
462 continue; | 656 continue; |
463 | 657 |
464 /* Don't profile functions produced for builtin stuff. */ | 658 /* Don't profile functions produced for builtin stuff. */ |
465 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION | 659 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
466 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile) | |
467 continue; | 660 continue; |
468 | 661 |
662 if (lookup_attribute ("no_profile_instrument_function", | |
663 DECL_ATTRIBUTES (node->decl))) | |
664 continue; | |
665 /* Do not instrument extern inline functions when testing coverage. | |
666 While this is not perfectly consistent (early inlined extern inlines | |
667 will get acocunted), testsuite expects that. */ | |
668 if (DECL_EXTERNAL (node->decl) | |
669 && flag_test_coverage) | |
670 continue; | |
671 | |
469 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); | 672 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
470 current_function_decl = node->decl; | 673 |
471 | 674 /* Local pure-const may imply need to fixup the cfg. */ |
472 /* Re-set global shared temporary variable for edge-counters. */ | 675 if (execute_fixup_cfg () & TODO_cleanup_cfg) |
473 gcov_type_tmp_var = NULL_TREE; | 676 cleanup_tree_cfg (); |
474 | 677 |
475 branch_prob (); | 678 branch_prob (); |
476 | 679 |
477 if (! flag_branch_probabilities | 680 if (! flag_branch_probabilities |
478 && flag_profile_values) | 681 && flag_profile_values) |
486 /* The above could hose dominator info. Currently there is | 689 /* The above could hose dominator info. Currently there is |
487 none coming in, this is a safety valve. It should be | 690 none coming in, this is a safety valve. It should be |
488 easy to adjust it, if and when there is some. */ | 691 easy to adjust it, if and when there is some. */ |
489 free_dominance_info (CDI_DOMINATORS); | 692 free_dominance_info (CDI_DOMINATORS); |
490 free_dominance_info (CDI_POST_DOMINATORS); | 693 free_dominance_info (CDI_POST_DOMINATORS); |
491 | |
492 current_function_decl = NULL; | |
493 pop_cfun (); | 694 pop_cfun (); |
494 } | 695 } |
495 | 696 |
496 /* Drop pure/const flags from instrumented functions. */ | 697 /* Drop pure/const flags from instrumented functions. */ |
497 for (node = cgraph_nodes; node; node = node->next) | 698 if (profile_arc_flag || flag_test_coverage) |
498 { | 699 FOR_EACH_DEFINED_FUNCTION (node) |
499 if (!node->analyzed | 700 { |
500 || !gimple_has_body_p (node->decl) | 701 if (!gimple_has_body_p (node->decl) |
501 || !(!node->clone_of || node->decl != node->clone_of->decl)) | 702 || !(!node->clone_of |
502 continue; | 703 || node->decl != node->clone_of->decl)) |
503 | 704 continue; |
504 /* Don't profile functions produced for builtin stuff. */ | 705 |
505 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION | 706 /* Don't profile functions produced for builtin stuff. */ |
506 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile) | 707 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
507 continue; | 708 continue; |
508 | 709 |
509 cgraph_set_const_flag (node, false, false); | 710 node->set_const_flag (false, false); |
510 cgraph_set_pure_flag (node, false, false); | 711 node->set_pure_flag (false, false); |
511 } | 712 } |
512 | 713 |
513 /* Update call statements and rebuild the cgraph. */ | 714 /* Update call statements and rebuild the cgraph. */ |
514 for (node = cgraph_nodes; node; node = node->next) | 715 FOR_EACH_DEFINED_FUNCTION (node) |
515 { | 716 { |
516 basic_block bb; | 717 basic_block bb; |
517 | 718 |
518 if (!node->analyzed | 719 if (!gimple_has_body_p (node->decl) |
519 || !gimple_has_body_p (node->decl) | 720 || !(!node->clone_of |
520 || !(!node->clone_of || node->decl != node->clone_of->decl)) | 721 || node->decl != node->clone_of->decl)) |
521 continue; | 722 continue; |
522 | 723 |
523 /* Don't profile functions produced for builtin stuff. */ | 724 /* Don't profile functions produced for builtin stuff. */ |
524 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION | 725 if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) |
525 || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile) | |
526 continue; | 726 continue; |
527 | 727 |
528 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); | 728 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
529 current_function_decl = node->decl; | 729 |
530 | 730 FOR_EACH_BB_FN (bb, cfun) |
531 FOR_EACH_BB (bb) | |
532 { | 731 { |
533 gimple_stmt_iterator gsi; | 732 gimple_stmt_iterator gsi; |
534 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 733 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
535 { | 734 { |
536 gimple stmt = gsi_stmt (gsi); | 735 gimple *stmt = gsi_stmt (gsi); |
537 if (is_gimple_call (stmt)) | 736 if (is_gimple_call (stmt)) |
538 update_stmt (stmt); | 737 update_stmt (stmt); |
539 } | 738 } |
540 } | 739 } |
541 | 740 |
542 cfun->after_tree_profile = 1; | 741 /* re-merge split blocks. */ |
742 cleanup_tree_cfg (); | |
543 update_ssa (TODO_update_ssa); | 743 update_ssa (TODO_update_ssa); |
544 | 744 |
545 rebuild_cgraph_edges (); | 745 cgraph_edge::rebuild_edges (); |
546 | 746 |
547 current_function_decl = NULL; | |
548 pop_cfun (); | 747 pop_cfun (); |
549 } | 748 } |
550 | 749 |
750 handle_missing_profiles (); | |
751 | |
752 del_node_map (); | |
551 return 0; | 753 return 0; |
552 } | 754 } |
553 | 755 |
554 /* When profile instrumentation, use or test coverage shall be performed. */ | 756 namespace { |
555 | 757 |
556 static bool | 758 const pass_data pass_data_ipa_tree_profile = |
557 gate_tree_profile_ipa (void) | 759 { |
558 { | 760 SIMPLE_IPA_PASS, /* type */ |
559 return (!in_lto_p | 761 "profile", /* name */ |
762 OPTGROUP_NONE, /* optinfo_flags */ | |
763 TV_IPA_PROFILE, /* tv_id */ | |
764 0, /* properties_required */ | |
765 0, /* properties_provided */ | |
766 0, /* properties_destroyed */ | |
767 0, /* todo_flags_start */ | |
768 TODO_dump_symtab, /* todo_flags_finish */ | |
769 }; | |
770 | |
771 class pass_ipa_tree_profile : public simple_ipa_opt_pass | |
772 { | |
773 public: | |
774 pass_ipa_tree_profile (gcc::context *ctxt) | |
775 : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt) | |
776 {} | |
777 | |
778 /* opt_pass methods: */ | |
779 virtual bool gate (function *); | |
780 virtual unsigned int execute (function *) { return tree_profiling (); } | |
781 | |
782 }; // class pass_ipa_tree_profile | |
783 | |
784 bool | |
785 pass_ipa_tree_profile::gate (function *) | |
786 { | |
787 /* When profile instrumentation, use or test coverage shall be performed. | |
788 But for AutoFDO, this there is no instrumentation, thus this pass is | |
789 diabled. */ | |
790 return (!in_lto_p && !flag_auto_profile | |
560 && (flag_branch_probabilities || flag_test_coverage | 791 && (flag_branch_probabilities || flag_test_coverage |
561 || profile_arc_flag)); | 792 || profile_arc_flag)); |
562 } | 793 } |
563 | 794 |
564 struct simple_ipa_opt_pass pass_ipa_tree_profile = | 795 } // anon namespace |
565 { | 796 |
566 { | 797 simple_ipa_opt_pass * |
567 SIMPLE_IPA_PASS, | 798 make_pass_ipa_tree_profile (gcc::context *ctxt) |
568 "tree_profile_ipa", /* name */ | 799 { |
569 gate_tree_profile_ipa, /* gate */ | 800 return new pass_ipa_tree_profile (ctxt); |
570 tree_profiling, /* execute */ | 801 } |
571 NULL, /* sub */ | |
572 NULL, /* next */ | |
573 0, /* static_pass_number */ | |
574 TV_IPA_PROFILE, /* tv_id */ | |
575 0, /* properties_required */ | |
576 0, /* properties_provided */ | |
577 0, /* properties_destroyed */ | |
578 0, /* todo_flags_start */ | |
579 TODO_dump_func /* todo_flags_finish */ | |
580 } | |
581 }; | |
582 | 802 |
583 #include "gt-tree-profile.h" | 803 #include "gt-tree-profile.h" |