Mercurial > hg > CbC > CbC_gcc
comparison gcc/cgraphbuild.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 /* Callgraph construction. | 1 /* Callgraph construction. |
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 | 2 Copyright (C) 2003-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 Contributed by Jan Hubicka | 3 Contributed by Jan Hubicka |
5 | 4 |
6 This file is part of GCC. | 5 This file is part of GCC. |
7 | 6 |
8 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
20 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
21 | 20 |
22 #include "config.h" | 21 #include "config.h" |
23 #include "system.h" | 22 #include "system.h" |
24 #include "coretypes.h" | 23 #include "coretypes.h" |
25 #include "tm.h" | 24 #include "backend.h" |
26 #include "tree.h" | 25 #include "tree.h" |
27 #include "tree-flow.h" | |
28 #include "langhooks.h" | |
29 #include "pointer-set.h" | |
30 #include "cgraph.h" | |
31 #include "intl.h" | |
32 #include "gimple.h" | 26 #include "gimple.h" |
33 #include "tree-pass.h" | 27 #include "tree-pass.h" |
28 #include "cgraph.h" | |
29 #include "gimple-fold.h" | |
30 #include "gimple-iterator.h" | |
31 #include "gimple-walk.h" | |
34 #include "ipa-utils.h" | 32 #include "ipa-utils.h" |
35 #include "except.h" | 33 #include "except.h" |
36 | 34 |
37 /* Context of record_reference. */ | 35 /* Context of record_reference. */ |
38 struct record_reference_ctx | 36 struct record_reference_ctx |
39 { | 37 { |
40 bool only_vars; | 38 bool only_vars; |
41 struct varpool_node *varpool_node; | 39 class varpool_node *varpool_node; |
42 }; | 40 }; |
43 | 41 |
44 /* Walk tree and record all calls and references to functions/variables. | 42 /* Walk tree and record all calls and references to functions/variables. |
45 Called via walk_tree: TP is pointer to tree to be examined. | 43 Called via walk_tree: TP is pointer to tree to be examined. |
46 When DATA is non-null, record references to callgraph. | 44 When DATA is non-null, record references to callgraph. |
49 static tree | 47 static tree |
50 record_reference (tree *tp, int *walk_subtrees, void *data) | 48 record_reference (tree *tp, int *walk_subtrees, void *data) |
51 { | 49 { |
52 tree t = *tp; | 50 tree t = *tp; |
53 tree decl; | 51 tree decl; |
54 struct record_reference_ctx *ctx = (struct record_reference_ctx *)data; | 52 record_reference_ctx *ctx = (record_reference_ctx *)data; |
53 | |
54 t = canonicalize_constructor_val (t, NULL); | |
55 if (!t) | |
56 t = *tp; | |
57 else if (t != *tp) | |
58 *tp = t; | |
55 | 59 |
56 switch (TREE_CODE (t)) | 60 switch (TREE_CODE (t)) |
57 { | 61 { |
58 case VAR_DECL: | 62 case VAR_DECL: |
59 case FUNCTION_DECL: | 63 case FUNCTION_DECL: |
65 /* Record dereferences to the functions. This makes the | 69 /* Record dereferences to the functions. This makes the |
66 functions reachable unconditionally. */ | 70 functions reachable unconditionally. */ |
67 decl = get_base_var (*tp); | 71 decl = get_base_var (*tp); |
68 if (TREE_CODE (decl) == FUNCTION_DECL) | 72 if (TREE_CODE (decl) == FUNCTION_DECL) |
69 { | 73 { |
74 cgraph_node *node = cgraph_node::get_create (decl); | |
70 if (!ctx->only_vars) | 75 if (!ctx->only_vars) |
71 cgraph_mark_address_taken_node (cgraph_node (decl)); | 76 node->mark_address_taken (); |
72 ipa_record_reference (NULL, ctx->varpool_node, | 77 ctx->varpool_node->create_reference (node, IPA_REF_ADDR); |
73 cgraph_node (decl), NULL, | 78 } |
74 IPA_REF_ADDR, NULL); | 79 |
75 } | 80 if (VAR_P (decl)) |
76 | 81 { |
77 if (TREE_CODE (decl) == VAR_DECL) | 82 varpool_node *vnode = varpool_node::get_create (decl); |
78 { | 83 ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR); |
79 struct varpool_node *vnode = varpool_node (decl); | |
80 if (lang_hooks.callgraph.analyze_expr) | |
81 lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); | |
82 varpool_mark_needed_node (vnode); | |
83 if (vnode->alias && vnode->extra_name) | |
84 vnode = vnode->extra_name; | |
85 ipa_record_reference (NULL, ctx->varpool_node, | |
86 NULL, vnode, | |
87 IPA_REF_ADDR, NULL); | |
88 } | 84 } |
89 *walk_subtrees = 0; | 85 *walk_subtrees = 0; |
90 break; | 86 break; |
91 | 87 |
92 default: | 88 default: |
95 if (IS_TYPE_OR_DECL_P (*tp)) | 91 if (IS_TYPE_OR_DECL_P (*tp)) |
96 { | 92 { |
97 *walk_subtrees = 0; | 93 *walk_subtrees = 0; |
98 break; | 94 break; |
99 } | 95 } |
100 | |
101 if ((unsigned int) TREE_CODE (t) >= LAST_AND_UNUSED_TREE_CODE) | |
102 return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees); | |
103 break; | 96 break; |
104 } | 97 } |
105 | 98 |
106 return NULL_TREE; | 99 return NULL_TREE; |
107 } | 100 } |
108 | 101 |
109 /* Record references to typeinfos in the type list LIST. */ | 102 /* Record references to typeinfos in the type list LIST. */ |
110 | 103 |
111 static void | 104 static void |
112 record_type_list (struct cgraph_node *node, tree list) | 105 record_type_list (cgraph_node *node, tree list) |
113 { | 106 { |
114 for (; list; list = TREE_CHAIN (list)) | 107 for (; list; list = TREE_CHAIN (list)) |
115 { | 108 { |
116 tree type = TREE_VALUE (list); | 109 tree type = TREE_VALUE (list); |
117 | 110 |
119 type = lookup_type_for_runtime (type); | 112 type = lookup_type_for_runtime (type); |
120 STRIP_NOPS (type); | 113 STRIP_NOPS (type); |
121 if (TREE_CODE (type) == ADDR_EXPR) | 114 if (TREE_CODE (type) == ADDR_EXPR) |
122 { | 115 { |
123 type = TREE_OPERAND (type, 0); | 116 type = TREE_OPERAND (type, 0); |
124 if (TREE_CODE (type) == VAR_DECL) | 117 if (VAR_P (type)) |
125 { | 118 { |
126 struct varpool_node *vnode = varpool_node (type); | 119 varpool_node *vnode = varpool_node::get_create (type); |
127 varpool_mark_needed_node (vnode); | 120 node->create_reference (vnode, IPA_REF_ADDR); |
128 ipa_record_reference (node, NULL, | |
129 NULL, vnode, | |
130 IPA_REF_ADDR, NULL); | |
131 } | 121 } |
132 } | 122 } |
133 } | 123 } |
134 } | 124 } |
135 | 125 |
136 /* Record all references we will introduce by producing EH tables | 126 /* Record all references we will introduce by producing EH tables |
137 for NODE. */ | 127 for NODE. */ |
138 | 128 |
139 static void | 129 static void |
140 record_eh_tables (struct cgraph_node *node, struct function *fun) | 130 record_eh_tables (cgraph_node *node, function *fun) |
141 { | 131 { |
142 eh_region i; | 132 eh_region i; |
143 | 133 |
144 if (DECL_FUNCTION_PERSONALITY (node->decl)) | 134 if (DECL_FUNCTION_PERSONALITY (node->decl)) |
145 ipa_record_reference (node, NULL, | 135 { |
146 cgraph_node (DECL_FUNCTION_PERSONALITY (node->decl)), | 136 tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl); |
147 NULL, IPA_REF_ADDR, NULL); | 137 cgraph_node *per_node = cgraph_node::get_create (per_decl); |
138 | |
139 node->create_reference (per_node, IPA_REF_ADDR); | |
140 per_node->mark_address_taken (); | |
141 } | |
148 | 142 |
149 i = fun->eh->region_tree; | 143 i = fun->eh->region_tree; |
150 if (!i) | 144 if (!i) |
151 return; | 145 return; |
152 | 146 |
189 i = i->next_peer; | 183 i = i->next_peer; |
190 } | 184 } |
191 } | 185 } |
192 } | 186 } |
193 | 187 |
194 /* Reset inlining information of all incoming call edges of NODE. */ | |
195 | |
196 void | |
197 reset_inline_failed (struct cgraph_node *node) | |
198 { | |
199 struct cgraph_edge *e; | |
200 | |
201 for (e = node->callers; e; e = e->next_caller) | |
202 { | |
203 e->callee->global.inlined_to = NULL; | |
204 if (!node->analyzed) | |
205 e->inline_failed = CIF_BODY_NOT_AVAILABLE; | |
206 else if (node->local.redefined_extern_inline) | |
207 e->inline_failed = CIF_REDEFINED_EXTERN_INLINE; | |
208 else if (!node->local.inlinable) | |
209 e->inline_failed = CIF_FUNCTION_NOT_INLINABLE; | |
210 else if (e->call_stmt_cannot_inline_p) | |
211 e->inline_failed = CIF_MISMATCHED_ARGUMENTS; | |
212 else | |
213 e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED; | |
214 } | |
215 } | |
216 | |
217 /* Computes the frequency of the call statement so that it can be stored in | 188 /* Computes the frequency of the call statement so that it can be stored in |
218 cgraph_edge. BB is the basic block of the call statement. */ | 189 cgraph_edge. BB is the basic block of the call statement. */ |
219 int | 190 int |
220 compute_call_stmt_bb_frequency (tree decl, basic_block bb) | 191 compute_call_stmt_bb_frequency (tree decl, basic_block bb) |
221 { | 192 { |
222 int entry_freq = ENTRY_BLOCK_PTR_FOR_FUNCTION | 193 int entry_freq = ENTRY_BLOCK_PTR_FOR_FN |
223 (DECL_STRUCT_FUNCTION (decl))->frequency; | 194 (DECL_STRUCT_FUNCTION (decl))->frequency; |
224 int freq = bb->frequency; | 195 int freq = bb->frequency; |
225 | 196 |
226 if (profile_status_for_function (DECL_STRUCT_FUNCTION (decl)) == PROFILE_ABSENT) | 197 if (profile_status_for_fn (DECL_STRUCT_FUNCTION (decl)) == PROFILE_ABSENT) |
227 return CGRAPH_FREQ_BASE; | 198 return CGRAPH_FREQ_BASE; |
228 | 199 |
229 if (!entry_freq) | 200 if (!entry_freq) |
230 entry_freq = 1, freq++; | 201 entry_freq = 1, freq++; |
231 | 202 |
237 } | 208 } |
238 | 209 |
239 /* Mark address taken in STMT. */ | 210 /* Mark address taken in STMT. */ |
240 | 211 |
241 static bool | 212 static bool |
242 mark_address (gimple stmt, tree addr, void *data) | 213 mark_address (gimple *stmt, tree addr, tree, void *data) |
243 { | 214 { |
244 addr = get_base_address (addr); | 215 addr = get_base_address (addr); |
245 if (TREE_CODE (addr) == FUNCTION_DECL) | 216 if (TREE_CODE (addr) == FUNCTION_DECL) |
246 { | 217 { |
247 struct cgraph_node *node = cgraph_node (addr); | 218 cgraph_node *node = cgraph_node::get_create (addr); |
248 cgraph_mark_address_taken_node (node); | 219 node->mark_address_taken (); |
249 ipa_record_reference ((struct cgraph_node *)data, NULL, | 220 ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt); |
250 node, NULL, | 221 } |
251 IPA_REF_ADDR, stmt); | 222 else if (addr && VAR_P (addr) |
252 } | |
253 else if (addr && TREE_CODE (addr) == VAR_DECL | |
254 && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) | 223 && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) |
255 { | 224 { |
256 struct varpool_node *vnode = varpool_node (addr); | 225 varpool_node *vnode = varpool_node::get_create (addr); |
257 int walk_subtrees; | 226 |
258 | 227 ((symtab_node *)data)->create_reference (vnode, IPA_REF_ADDR, stmt); |
259 if (lang_hooks.callgraph.analyze_expr) | |
260 lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); | |
261 varpool_mark_needed_node (vnode); | |
262 if (vnode->alias && vnode->extra_name) | |
263 vnode = vnode->extra_name; | |
264 ipa_record_reference ((struct cgraph_node *)data, NULL, | |
265 NULL, vnode, | |
266 IPA_REF_ADDR, stmt); | |
267 } | 228 } |
268 | 229 |
269 return false; | 230 return false; |
270 } | 231 } |
271 | 232 |
272 /* Mark load of T. */ | 233 /* Mark load of T. */ |
273 | 234 |
274 static bool | 235 static bool |
275 mark_load (gimple stmt, tree t, void *data) | 236 mark_load (gimple *stmt, tree t, tree, void *data) |
276 { | 237 { |
277 t = get_base_address (t); | 238 t = get_base_address (t); |
278 if (t && TREE_CODE (t) == FUNCTION_DECL) | 239 if (t && TREE_CODE (t) == FUNCTION_DECL) |
279 { | 240 { |
280 /* ??? This can happen on platforms with descriptors when these are | 241 /* ??? This can happen on platforms with descriptors when these are |
281 directly manipulated in the code. Pretend that it's an address. */ | 242 directly manipulated in the code. Pretend that it's an address. */ |
282 struct cgraph_node *node = cgraph_node (t); | 243 cgraph_node *node = cgraph_node::get_create (t); |
283 cgraph_mark_address_taken_node (node); | 244 node->mark_address_taken (); |
284 ipa_record_reference ((struct cgraph_node *)data, NULL, | 245 ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt); |
285 node, NULL, | 246 } |
286 IPA_REF_ADDR, stmt); | 247 else if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t))) |
287 } | 248 { |
288 else if (t && TREE_CODE (t) == VAR_DECL | 249 varpool_node *vnode = varpool_node::get_create (t); |
289 && (TREE_STATIC (t) || DECL_EXTERNAL (t))) | 250 |
290 { | 251 ((symtab_node *)data)->create_reference (vnode, IPA_REF_LOAD, stmt); |
291 struct varpool_node *vnode = varpool_node (t); | |
292 int walk_subtrees; | |
293 | |
294 if (lang_hooks.callgraph.analyze_expr) | |
295 lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); | |
296 varpool_mark_needed_node (vnode); | |
297 if (vnode->alias && vnode->extra_name) | |
298 vnode = vnode->extra_name; | |
299 ipa_record_reference ((struct cgraph_node *)data, NULL, | |
300 NULL, vnode, | |
301 IPA_REF_LOAD, stmt); | |
302 } | 252 } |
303 return false; | 253 return false; |
304 } | 254 } |
305 | 255 |
306 /* Mark store of T. */ | 256 /* Mark store of T. */ |
307 | 257 |
308 static bool | 258 static bool |
309 mark_store (gimple stmt, tree t, void *data) | 259 mark_store (gimple *stmt, tree t, tree, void *data) |
310 { | 260 { |
311 t = get_base_address (t); | 261 t = get_base_address (t); |
312 if (t && TREE_CODE (t) == VAR_DECL | 262 if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t))) |
313 && (TREE_STATIC (t) || DECL_EXTERNAL (t))) | 263 { |
314 { | 264 varpool_node *vnode = varpool_node::get_create (t); |
315 struct varpool_node *vnode = varpool_node (t); | 265 |
316 int walk_subtrees; | 266 ((symtab_node *)data)->create_reference (vnode, IPA_REF_STORE, stmt); |
317 | |
318 if (lang_hooks.callgraph.analyze_expr) | |
319 lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); | |
320 varpool_mark_needed_node (vnode); | |
321 if (vnode->alias && vnode->extra_name) | |
322 vnode = vnode->extra_name; | |
323 ipa_record_reference ((struct cgraph_node *)data, NULL, | |
324 NULL, vnode, | |
325 IPA_REF_STORE, stmt); | |
326 } | 267 } |
327 return false; | 268 return false; |
328 } | 269 } |
329 | 270 |
271 /* Record all references from cgraph_node that are taken in statement STMT. */ | |
272 | |
273 void | |
274 cgraph_node::record_stmt_references (gimple *stmt) | |
275 { | |
276 walk_stmt_load_store_addr_ops (stmt, this, mark_load, mark_store, | |
277 mark_address); | |
278 } | |
279 | |
330 /* Create cgraph edges for function calls. | 280 /* Create cgraph edges for function calls. |
331 Also look for functions and variables having addresses taken. */ | 281 Also look for functions and variables having addresses taken. */ |
332 | 282 |
333 static unsigned int | 283 namespace { |
334 build_cgraph_edges (void) | 284 |
285 const pass_data pass_data_build_cgraph_edges = | |
286 { | |
287 GIMPLE_PASS, /* type */ | |
288 "*build_cgraph_edges", /* name */ | |
289 OPTGROUP_NONE, /* optinfo_flags */ | |
290 TV_NONE, /* tv_id */ | |
291 PROP_cfg, /* properties_required */ | |
292 0, /* properties_provided */ | |
293 0, /* properties_destroyed */ | |
294 0, /* todo_flags_start */ | |
295 0, /* todo_flags_finish */ | |
296 }; | |
297 | |
298 class pass_build_cgraph_edges : public gimple_opt_pass | |
299 { | |
300 public: | |
301 pass_build_cgraph_edges (gcc::context *ctxt) | |
302 : gimple_opt_pass (pass_data_build_cgraph_edges, ctxt) | |
303 {} | |
304 | |
305 /* opt_pass methods: */ | |
306 virtual unsigned int execute (function *); | |
307 | |
308 }; // class pass_build_cgraph_edges | |
309 | |
310 unsigned int | |
311 pass_build_cgraph_edges::execute (function *fun) | |
335 { | 312 { |
336 basic_block bb; | 313 basic_block bb; |
337 struct cgraph_node *node = cgraph_node (current_function_decl); | 314 cgraph_node *node = cgraph_node::get (current_function_decl); |
338 struct pointer_set_t *visited_nodes = pointer_set_create (); | |
339 gimple_stmt_iterator gsi; | 315 gimple_stmt_iterator gsi; |
340 tree decl; | 316 tree decl; |
341 unsigned ix; | 317 unsigned ix; |
342 | 318 |
343 /* Create the callgraph edges and record the nodes referenced by the function. | 319 /* Create the callgraph edges and record the nodes referenced by the function. |
344 body. */ | 320 body. */ |
345 FOR_EACH_BB (bb) | 321 FOR_EACH_BB_FN (bb, fun) |
346 { | 322 { |
347 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 323 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
348 { | 324 { |
349 gimple stmt = gsi_stmt (gsi); | 325 gimple *stmt = gsi_stmt (gsi); |
350 tree decl; | 326 tree decl; |
351 | 327 |
352 if (is_gimple_call (stmt)) | 328 if (is_gimple_debug (stmt)) |
329 continue; | |
330 | |
331 if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) | |
353 { | 332 { |
354 int freq = compute_call_stmt_bb_frequency (current_function_decl, | 333 int freq = compute_call_stmt_bb_frequency (current_function_decl, |
355 bb); | 334 bb); |
356 decl = gimple_call_fndecl (stmt); | 335 decl = gimple_call_fndecl (call_stmt); |
357 if (decl) | 336 if (decl) |
358 cgraph_create_edge (node, cgraph_node (decl), stmt, | 337 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count, freq); |
359 bb->count, freq, | 338 else if (gimple_call_internal_p (call_stmt)) |
360 bb->loop_depth); | 339 ; |
361 else | 340 else |
362 cgraph_create_indirect_edge (node, stmt, | 341 node->create_indirect_edge (call_stmt, |
363 gimple_call_flags (stmt), | 342 gimple_call_flags (call_stmt), |
364 bb->count, freq, | 343 bb->count, freq); |
365 bb->loop_depth); | |
366 } | 344 } |
367 walk_stmt_load_store_addr_ops (stmt, node, mark_load, | 345 node->record_stmt_references (stmt); |
368 mark_store, mark_address); | 346 if (gomp_parallel *omp_par_stmt = dyn_cast <gomp_parallel *> (stmt)) |
369 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL | |
370 && gimple_omp_parallel_child_fn (stmt)) | |
371 { | 347 { |
372 tree fn = gimple_omp_parallel_child_fn (stmt); | 348 tree fn = gimple_omp_parallel_child_fn (omp_par_stmt); |
373 ipa_record_reference (node, NULL, cgraph_node (fn), | 349 node->create_reference (cgraph_node::get_create (fn), |
374 NULL, IPA_REF_ADDR, stmt); | 350 IPA_REF_ADDR, stmt); |
375 } | 351 } |
376 if (gimple_code (stmt) == GIMPLE_OMP_TASK) | 352 if (gimple_code (stmt) == GIMPLE_OMP_TASK) |
377 { | 353 { |
378 tree fn = gimple_omp_task_child_fn (stmt); | 354 tree fn = gimple_omp_task_child_fn (stmt); |
379 if (fn) | 355 if (fn) |
380 ipa_record_reference (node, NULL, cgraph_node (fn), | 356 node->create_reference (cgraph_node::get_create (fn), |
381 NULL, IPA_REF_ADDR, stmt); | 357 IPA_REF_ADDR, stmt); |
382 fn = gimple_omp_task_copy_fn (stmt); | 358 fn = gimple_omp_task_copy_fn (stmt); |
383 if (fn) | 359 if (fn) |
384 ipa_record_reference (node, NULL, cgraph_node (fn), | 360 node->create_reference (cgraph_node::get_create (fn), |
385 NULL, IPA_REF_ADDR, stmt); | 361 IPA_REF_ADDR, stmt); |
386 } | 362 } |
387 } | 363 } |
388 for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) | 364 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
389 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node, | 365 node->record_stmt_references (gsi_stmt (gsi)); |
390 mark_load, mark_store, mark_address); | |
391 } | 366 } |
392 | 367 |
393 /* Look for initializers of constant variables and private statics. */ | 368 /* Look for initializers of constant variables and private statics. */ |
394 FOR_EACH_LOCAL_DECL (cfun, ix, decl) | 369 FOR_EACH_LOCAL_DECL (fun, ix, decl) |
395 if (TREE_CODE (decl) == VAR_DECL | 370 if (VAR_P (decl) |
396 && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))) | 371 && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) |
397 varpool_finalize_decl (decl); | 372 && !DECL_HAS_VALUE_EXPR_P (decl) |
398 record_eh_tables (node, cfun); | 373 && TREE_TYPE (decl) != error_mark_node) |
399 | 374 varpool_node::finalize_decl (decl); |
400 pointer_set_destroy (visited_nodes); | 375 record_eh_tables (node, fun); |
376 | |
401 return 0; | 377 return 0; |
402 } | 378 } |
403 | 379 |
404 struct gimple_opt_pass pass_build_cgraph_edges = | 380 } // anon namespace |
405 { | 381 |
406 { | 382 gimple_opt_pass * |
407 GIMPLE_PASS, | 383 make_pass_build_cgraph_edges (gcc::context *ctxt) |
408 "*build_cgraph_edges", /* name */ | 384 { |
409 NULL, /* gate */ | 385 return new pass_build_cgraph_edges (ctxt); |
410 build_cgraph_edges, /* execute */ | 386 } |
411 NULL, /* sub */ | |
412 NULL, /* next */ | |
413 0, /* static_pass_number */ | |
414 TV_NONE, /* tv_id */ | |
415 PROP_cfg, /* properties_required */ | |
416 0, /* properties_provided */ | |
417 0, /* properties_destroyed */ | |
418 0, /* todo_flags_start */ | |
419 0 /* todo_flags_finish */ | |
420 } | |
421 }; | |
422 | 387 |
423 /* Record references to functions and other variables present in the | 388 /* Record references to functions and other variables present in the |
424 initial value of DECL, a variable. | 389 initial value of DECL, a variable. |
425 When ONLY_VARS is true, we mark needed only variables, not functions. */ | 390 When ONLY_VARS is true, we mark needed only variables, not functions. */ |
426 | 391 |
427 void | 392 void |
428 record_references_in_initializer (tree decl, bool only_vars) | 393 record_references_in_initializer (tree decl, bool only_vars) |
429 { | 394 { |
430 struct pointer_set_t *visited_nodes = pointer_set_create (); | 395 varpool_node *node = varpool_node::get_create (decl); |
431 struct varpool_node *node = varpool_node (decl); | 396 hash_set<tree> visited_nodes; |
432 struct record_reference_ctx ctx = {false, NULL}; | 397 record_reference_ctx ctx = {false, NULL}; |
433 | 398 |
434 ctx.varpool_node = node; | 399 ctx.varpool_node = node; |
435 ctx.only_vars = only_vars; | 400 ctx.only_vars = only_vars; |
436 walk_tree (&DECL_INITIAL (decl), record_reference, | 401 walk_tree (&DECL_INITIAL (decl), record_reference, |
437 &ctx, visited_nodes); | 402 &ctx, &visited_nodes); |
438 pointer_set_destroy (visited_nodes); | |
439 } | 403 } |
440 | 404 |
441 /* Rebuild cgraph edges for current function node. This needs to be run after | 405 /* Rebuild cgraph edges for current function node. This needs to be run after |
442 passes that don't update the cgraph. */ | 406 passes that don't update the cgraph. */ |
443 | 407 |
444 unsigned int | 408 unsigned int |
445 rebuild_cgraph_edges (void) | 409 cgraph_edge::rebuild_edges (void) |
446 { | 410 { |
447 basic_block bb; | 411 basic_block bb; |
448 struct cgraph_node *node = cgraph_node (current_function_decl); | 412 cgraph_node *node = cgraph_node::get (current_function_decl); |
449 gimple_stmt_iterator gsi; | 413 gimple_stmt_iterator gsi; |
450 | 414 |
451 cgraph_node_remove_callees (node); | 415 node->remove_callees (); |
452 ipa_remove_all_references (&node->ref_list); | 416 node->remove_all_references (); |
453 | 417 |
454 node->count = ENTRY_BLOCK_PTR->count; | 418 node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; |
455 | 419 |
456 FOR_EACH_BB (bb) | 420 FOR_EACH_BB_FN (bb, cfun) |
457 { | 421 { |
458 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 422 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
459 { | 423 { |
460 gimple stmt = gsi_stmt (gsi); | 424 gimple *stmt = gsi_stmt (gsi); |
461 tree decl; | 425 tree decl; |
462 | 426 |
463 if (is_gimple_call (stmt)) | 427 if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) |
464 { | 428 { |
465 int freq = compute_call_stmt_bb_frequency (current_function_decl, | 429 int freq = compute_call_stmt_bb_frequency (current_function_decl, |
466 bb); | 430 bb); |
467 decl = gimple_call_fndecl (stmt); | 431 decl = gimple_call_fndecl (call_stmt); |
468 if (decl) | 432 if (decl) |
469 cgraph_create_edge (node, cgraph_node (decl), stmt, | 433 node->create_edge (cgraph_node::get_create (decl), call_stmt, |
470 bb->count, freq, | 434 bb->count, freq); |
471 bb->loop_depth); | 435 else if (gimple_call_internal_p (call_stmt)) |
436 ; | |
472 else | 437 else |
473 cgraph_create_indirect_edge (node, stmt, | 438 node->create_indirect_edge (call_stmt, |
474 gimple_call_flags (stmt), | 439 gimple_call_flags (call_stmt), |
475 bb->count, freq, | 440 bb->count, freq); |
476 bb->loop_depth); | |
477 } | 441 } |
478 walk_stmt_load_store_addr_ops (stmt, node, mark_load, | 442 node->record_stmt_references (stmt); |
479 mark_store, mark_address); | 443 } |
480 | 444 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
481 } | 445 node->record_stmt_references (gsi_stmt (gsi)); |
482 for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) | |
483 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node, | |
484 mark_load, mark_store, mark_address); | |
485 } | 446 } |
486 record_eh_tables (node, cfun); | 447 record_eh_tables (node, cfun); |
487 gcc_assert (!node->global.inlined_to); | 448 gcc_assert (!node->global.inlined_to); |
488 | 449 |
450 if (node->instrumented_version | |
451 && !node->instrumentation_clone) | |
452 node->create_reference (node->instrumented_version, IPA_REF_CHKP, NULL); | |
453 | |
489 return 0; | 454 return 0; |
490 } | 455 } |
491 | 456 |
492 /* Rebuild cgraph edges for current function node. This needs to be run after | 457 /* Rebuild cgraph references for current function node. This needs to be run |
493 passes that don't update the cgraph. */ | 458 after passes that don't update the cgraph. */ |
494 | 459 |
495 void | 460 void |
496 cgraph_rebuild_references (void) | 461 cgraph_edge::rebuild_references (void) |
497 { | 462 { |
498 basic_block bb; | 463 basic_block bb; |
499 struct cgraph_node *node = cgraph_node (current_function_decl); | 464 cgraph_node *node = cgraph_node::get (current_function_decl); |
500 gimple_stmt_iterator gsi; | 465 gimple_stmt_iterator gsi; |
501 | 466 ipa_ref *ref = NULL; |
502 ipa_remove_all_references (&node->ref_list); | 467 int i; |
503 | 468 |
504 node->count = ENTRY_BLOCK_PTR->count; | 469 /* Keep speculative references for further cgraph edge expansion. */ |
505 | 470 for (i = 0; node->iterate_reference (i, ref);) |
506 FOR_EACH_BB (bb) | 471 if (!ref->speculative) |
472 ref->remove_reference (); | |
473 else | |
474 i++; | |
475 | |
476 FOR_EACH_BB_FN (bb, cfun) | |
507 { | 477 { |
508 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 478 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
509 { | 479 node->record_stmt_references (gsi_stmt (gsi)); |
510 gimple stmt = gsi_stmt (gsi); | 480 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
511 | 481 node->record_stmt_references (gsi_stmt (gsi)); |
512 walk_stmt_load_store_addr_ops (stmt, node, mark_load, | |
513 mark_store, mark_address); | |
514 | |
515 } | |
516 for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) | |
517 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node, | |
518 mark_load, mark_store, mark_address); | |
519 } | 482 } |
520 record_eh_tables (node, cfun); | 483 record_eh_tables (node, cfun); |
521 } | 484 |
522 | 485 if (node->instrumented_version |
523 struct gimple_opt_pass pass_rebuild_cgraph_edges = | 486 && !node->instrumentation_clone) |
524 { | 487 node->create_reference (node->instrumented_version, IPA_REF_CHKP, NULL); |
525 { | 488 } |
526 GIMPLE_PASS, | 489 |
527 "*rebuild_cgraph_edges", /* name */ | 490 namespace { |
528 NULL, /* gate */ | 491 |
529 rebuild_cgraph_edges, /* execute */ | 492 const pass_data pass_data_rebuild_cgraph_edges = |
530 NULL, /* sub */ | 493 { |
531 NULL, /* next */ | 494 GIMPLE_PASS, /* type */ |
532 0, /* static_pass_number */ | 495 "*rebuild_cgraph_edges", /* name */ |
533 TV_CGRAPH, /* tv_id */ | 496 OPTGROUP_NONE, /* optinfo_flags */ |
534 PROP_cfg, /* properties_required */ | 497 TV_CGRAPH, /* tv_id */ |
535 0, /* properties_provided */ | 498 PROP_cfg, /* properties_required */ |
536 0, /* properties_destroyed */ | 499 0, /* properties_provided */ |
537 0, /* todo_flags_start */ | 500 0, /* properties_destroyed */ |
538 0, /* todo_flags_finish */ | 501 0, /* todo_flags_start */ |
539 } | 502 0, /* todo_flags_finish */ |
540 }; | 503 }; |
541 | 504 |
542 | 505 class pass_rebuild_cgraph_edges : public gimple_opt_pass |
543 static unsigned int | 506 { |
544 remove_cgraph_callee_edges (void) | 507 public: |
545 { | 508 pass_rebuild_cgraph_edges (gcc::context *ctxt) |
546 cgraph_node_remove_callees (cgraph_node (current_function_decl)); | 509 : gimple_opt_pass (pass_data_rebuild_cgraph_edges, ctxt) |
510 {} | |
511 | |
512 /* opt_pass methods: */ | |
513 opt_pass * clone () { return new pass_rebuild_cgraph_edges (m_ctxt); } | |
514 virtual unsigned int execute (function *) | |
515 { | |
516 return cgraph_edge::rebuild_edges (); | |
517 } | |
518 | |
519 }; // class pass_rebuild_cgraph_edges | |
520 | |
521 } // anon namespace | |
522 | |
523 gimple_opt_pass * | |
524 make_pass_rebuild_cgraph_edges (gcc::context *ctxt) | |
525 { | |
526 return new pass_rebuild_cgraph_edges (ctxt); | |
527 } | |
528 | |
529 | |
530 namespace { | |
531 | |
532 const pass_data pass_data_remove_cgraph_callee_edges = | |
533 { | |
534 GIMPLE_PASS, /* type */ | |
535 "*remove_cgraph_callee_edges", /* name */ | |
536 OPTGROUP_NONE, /* optinfo_flags */ | |
537 TV_NONE, /* tv_id */ | |
538 0, /* properties_required */ | |
539 0, /* properties_provided */ | |
540 0, /* properties_destroyed */ | |
541 0, /* todo_flags_start */ | |
542 0, /* todo_flags_finish */ | |
543 }; | |
544 | |
545 class pass_remove_cgraph_callee_edges : public gimple_opt_pass | |
546 { | |
547 public: | |
548 pass_remove_cgraph_callee_edges (gcc::context *ctxt) | |
549 : gimple_opt_pass (pass_data_remove_cgraph_callee_edges, ctxt) | |
550 {} | |
551 | |
552 /* opt_pass methods: */ | |
553 opt_pass * clone () { | |
554 return new pass_remove_cgraph_callee_edges (m_ctxt); | |
555 } | |
556 virtual unsigned int execute (function *); | |
557 | |
558 }; // class pass_remove_cgraph_callee_edges | |
559 | |
560 unsigned int | |
561 pass_remove_cgraph_callee_edges::execute (function *) | |
562 { | |
563 cgraph_node *node = cgraph_node::get (current_function_decl); | |
564 node->remove_callees (); | |
565 node->remove_all_references (); | |
547 return 0; | 566 return 0; |
548 } | 567 } |
549 | 568 |
550 struct gimple_opt_pass pass_remove_cgraph_callee_edges = | 569 } // anon namespace |
551 { | 570 |
552 { | 571 gimple_opt_pass * |
553 GIMPLE_PASS, | 572 make_pass_remove_cgraph_callee_edges (gcc::context *ctxt) |
554 "*remove_cgraph_callee_edges", /* name */ | 573 { |
555 NULL, /* gate */ | 574 return new pass_remove_cgraph_callee_edges (ctxt); |
556 remove_cgraph_callee_edges, /* execute */ | 575 } |
557 NULL, /* sub */ | |
558 NULL, /* next */ | |
559 0, /* static_pass_number */ | |
560 TV_NONE, /* tv_id */ | |
561 0, /* properties_required */ | |
562 0, /* properties_provided */ | |
563 0, /* properties_destroyed */ | |
564 0, /* todo_flags_start */ | |
565 0, /* todo_flags_finish */ | |
566 } | |
567 }; |