Branch data Line data Source code
1 : : /* Callgraph construction.
2 : : Copyright (C) 2003-2024 Free Software Foundation, Inc.
3 : : Contributed by Jan Hubicka
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "backend.h"
25 : : #include "tree.h"
26 : : #include "gimple.h"
27 : : #include "tree-pass.h"
28 : : #include "cgraph.h"
29 : : #include "gimple-iterator.h"
30 : : #include "gimple-fold.h"
31 : : #include "gimple-walk.h"
32 : : #include "ipa-utils.h"
33 : : #include "except.h"
34 : : #include "gimplify.h"
35 : :
36 : : /* Context of record_reference. */
37 : : struct record_reference_ctx
38 : : {
39 : : bool only_vars;
40 : : struct varpool_node *varpool_node;
41 : : };
42 : :
43 : : /* Walk tree and record all calls and references to functions/variables.
44 : : Called via walk_tree: TP is pointer to tree to be examined.
45 : : When DATA is non-null, record references to callgraph.
46 : : */
47 : :
48 : : static tree
49 : 14491608 : record_reference (tree *tp, int *walk_subtrees, void *data)
50 : : {
51 : 14491632 : tree t = *tp;
52 : 14491632 : tree decl;
53 : 14491632 : record_reference_ctx *ctx = (record_reference_ctx *)data;
54 : :
55 : 14491632 : t = canonicalize_constructor_val (t, NULL);
56 : 14491632 : if (!t)
57 : 117 : t = *tp;
58 : 14491515 : else if (t != *tp)
59 : 4420481 : *tp = t;
60 : :
61 : 14491632 : switch (TREE_CODE (t))
62 : : {
63 : 0 : case VAR_DECL:
64 : 0 : case FUNCTION_DECL:
65 : 0 : gcc_unreachable ();
66 : 4605385 : break;
67 : :
68 : 4605385 : case FDESC_EXPR:
69 : 4605385 : case ADDR_EXPR:
70 : : /* Record dereferences to the functions. This makes the
71 : : functions reachable unconditionally. */
72 : 4605385 : decl = get_base_var (*tp);
73 : 4605385 : if (TREE_CODE (decl) == FUNCTION_DECL)
74 : : {
75 : 1120778 : cgraph_node *node = cgraph_node::get_create (decl);
76 : 1120778 : if (!ctx->only_vars)
77 : 1120778 : node->mark_address_taken ();
78 : 1120778 : ctx->varpool_node->create_reference (node, IPA_REF_ADDR);
79 : : }
80 : :
81 : 4605385 : if (VAR_P (decl))
82 : : {
83 : : /* Replace vars with their DECL_VALUE_EXPR if any.
84 : : This is normally done during gimplification, but
85 : : static var initializers are never gimplified. */
86 : 2583038 : if (DECL_HAS_VALUE_EXPR_P (decl))
87 : : {
88 : : tree *p;
89 : 48 : for (p = tp; *p != decl; p = &TREE_OPERAND (*p, 0))
90 : : ;
91 : 24 : *p = unshare_expr (DECL_VALUE_EXPR (decl));
92 : 24 : return record_reference (tp, walk_subtrees, data);
93 : : }
94 : 2583014 : varpool_node *vnode = varpool_node::get_create (decl);
95 : 2583014 : ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR);
96 : : }
97 : 4605361 : *walk_subtrees = 0;
98 : 4605361 : break;
99 : :
100 : 9886247 : default:
101 : : /* Save some cycles by not walking types and declaration as we
102 : : won't find anything useful there anyway. */
103 : 9886247 : if (IS_TYPE_OR_DECL_P (*tp))
104 : : {
105 : 0 : *walk_subtrees = 0;
106 : 0 : break;
107 : : }
108 : : break;
109 : : }
110 : :
111 : : return NULL_TREE;
112 : : }
113 : :
114 : : /* Record references to typeinfos in the type list LIST. */
115 : :
116 : : static void
117 : 184740 : record_type_list (cgraph_node *node, tree list)
118 : : {
119 : 204804 : for (; list; list = TREE_CHAIN (list))
120 : : {
121 : 20064 : tree type = TREE_VALUE (list);
122 : :
123 : 20064 : if (TYPE_P (type))
124 : 19616 : type = lookup_type_for_runtime (type);
125 : 20064 : STRIP_NOPS (type);
126 : 20064 : if (TREE_CODE (type) == ADDR_EXPR)
127 : : {
128 : 20064 : type = TREE_OPERAND (type, 0);
129 : 20064 : if (VAR_P (type))
130 : : {
131 : 20064 : varpool_node *vnode = varpool_node::get_create (type);
132 : 20064 : node->create_reference (vnode, IPA_REF_ADDR);
133 : : }
134 : : }
135 : : }
136 : 184740 : }
137 : :
138 : : /* Record all references we will introduce by producing EH tables
139 : : for NODE. */
140 : :
141 : : static void
142 : 10968089 : record_eh_tables (cgraph_node *node, function *fun)
143 : : {
144 : 10968089 : eh_region i;
145 : :
146 : 10968089 : if (DECL_FUNCTION_PERSONALITY (node->decl))
147 : : {
148 : 2213430 : tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl);
149 : 2213430 : cgraph_node *per_node = cgraph_node::get_create (per_decl);
150 : :
151 : 2213430 : node->create_reference (per_node, IPA_REF_ADDR);
152 : 2213430 : per_node->mark_address_taken ();
153 : : }
154 : :
155 : 10968089 : i = fun->eh->region_tree;
156 : 10968089 : if (!i)
157 : : return;
158 : :
159 : 7119123 : while (1)
160 : : {
161 : 7119123 : switch (i->type)
162 : : {
163 : : case ERT_CLEANUP:
164 : : case ERT_MUST_NOT_THROW:
165 : : break;
166 : :
167 : 172627 : case ERT_TRY:
168 : 172627 : {
169 : 172627 : eh_catch c;
170 : 343058 : for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
171 : 170431 : record_type_list (node, c->type_list);
172 : : }
173 : : break;
174 : :
175 : 14309 : case ERT_ALLOWED_EXCEPTIONS:
176 : 14309 : record_type_list (node, i->u.allowed.type_list);
177 : 14309 : break;
178 : : }
179 : : /* If there are sub-regions, process them. */
180 : 7119123 : if (i->inner)
181 : : i = i->inner;
182 : : /* If there are peers, process them. */
183 : 5499293 : else if (i->next_peer)
184 : : i = i->next_peer;
185 : : /* Otherwise, step back up the tree to the next peer. */
186 : : else
187 : : {
188 : 4756287 : do
189 : : {
190 : 4756287 : i = i->outer;
191 : 4756287 : if (i == NULL)
192 : : return;
193 : : }
194 : 1619830 : while (i->next_peer == NULL);
195 : : i = i->next_peer;
196 : : }
197 : : }
198 : : }
199 : :
200 : : /* Computes the frequency of the call statement so that it can be stored in
201 : : cgraph_edge. BB is the basic block of the call statement. */
202 : : int
203 : 0 : compute_call_stmt_bb_frequency (tree decl, basic_block bb)
204 : : {
205 : 0 : return bb->count.to_cgraph_frequency
206 : 0 : (ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (decl))->count);
207 : : }
208 : :
209 : : /* Mark address taken in STMT. */
210 : :
211 : : static bool
212 : 29898777 : mark_address (gimple *stmt, tree addr, tree, void *data)
213 : : {
214 : 29898777 : addr = get_base_address (addr);
215 : 29898777 : if (TREE_CODE (addr) == FUNCTION_DECL)
216 : : {
217 : 1007601 : cgraph_node *node = cgraph_node::get_create (addr);
218 : 1007601 : node->mark_address_taken ();
219 : 1007601 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
220 : : }
221 : 28891176 : else if (addr && VAR_P (addr)
222 : 17895947 : && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
223 : : {
224 : 7732977 : varpool_node *vnode = varpool_node::get_create (addr);
225 : :
226 : 7732977 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_ADDR, stmt);
227 : : }
228 : :
229 : 29898777 : return false;
230 : : }
231 : :
232 : : /* Mark load of T. */
233 : :
234 : : static bool
235 : 58121706 : mark_load (gimple *stmt, tree t, tree, void *data)
236 : : {
237 : 58121706 : t = get_base_address (t);
238 : 58121706 : if (t && TREE_CODE (t) == FUNCTION_DECL)
239 : : {
240 : : /* ??? This can happen on platforms with descriptors when these are
241 : : directly manipulated in the code. Pretend that it's an address. */
242 : 101 : cgraph_node *node = cgraph_node::get_create (t);
243 : 101 : node->mark_address_taken ();
244 : 101 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
245 : 101 : }
246 : 58121605 : else if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
247 : : {
248 : 10975023 : varpool_node *vnode = varpool_node::get_create (t);
249 : :
250 : 10975023 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_LOAD, stmt);
251 : : }
252 : 58121706 : return false;
253 : : }
254 : :
255 : : /* Mark store of T. */
256 : :
257 : : static bool
258 : 58149141 : mark_store (gimple *stmt, tree t, tree, void *data)
259 : : {
260 : 58149141 : t = get_base_address (t);
261 : 58149141 : if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
262 : : {
263 : 5568835 : varpool_node *vnode = varpool_node::get_create (t);
264 : :
265 : 5568835 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_STORE, stmt);
266 : : }
267 : 58149141 : return false;
268 : : }
269 : :
270 : : /* Record all references from cgraph_node that are taken in statement STMT. */
271 : :
272 : : void
273 : 284366108 : cgraph_node::record_stmt_references (gimple *stmt)
274 : : {
275 : 284366108 : walk_stmt_load_store_addr_ops (stmt, this, mark_load, mark_store,
276 : : mark_address);
277 : 284366108 : }
278 : :
279 : : /* Create cgraph edges for function calls.
280 : : Also look for functions and variables having addresses taken. */
281 : :
282 : : namespace {
283 : :
284 : : const pass_data pass_data_build_cgraph_edges =
285 : : {
286 : : GIMPLE_PASS, /* type */
287 : : "*build_cgraph_edges", /* name */
288 : : OPTGROUP_NONE, /* optinfo_flags */
289 : : TV_NONE, /* tv_id */
290 : : PROP_cfg, /* properties_required */
291 : : 0, /* properties_provided */
292 : : 0, /* properties_destroyed */
293 : : 0, /* todo_flags_start */
294 : : 0, /* todo_flags_finish */
295 : : };
296 : :
297 : : class pass_build_cgraph_edges : public gimple_opt_pass
298 : : {
299 : : public:
300 : 280114 : pass_build_cgraph_edges (gcc::context *ctxt)
301 : 560228 : : gimple_opt_pass (pass_data_build_cgraph_edges, ctxt)
302 : : {}
303 : :
304 : : /* opt_pass methods: */
305 : : unsigned int execute (function *) final override;
306 : :
307 : : }; // class pass_build_cgraph_edges
308 : :
309 : : unsigned int
310 : 2682174 : pass_build_cgraph_edges::execute (function *fun)
311 : : {
312 : 2682174 : basic_block bb;
313 : 2682174 : cgraph_node *node = cgraph_node::get (current_function_decl);
314 : 2682174 : gimple_stmt_iterator gsi;
315 : 2682174 : tree decl;
316 : 2682174 : unsigned ix;
317 : :
318 : : /* Create the callgraph edges and record the nodes referenced by the function.
319 : : body. */
320 : 18733251 : FOR_EACH_BB_FN (bb, fun)
321 : : {
322 : 93488800 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
323 : : {
324 : 61386646 : gimple *stmt = gsi_stmt (gsi);
325 : 61386646 : tree decl;
326 : :
327 : 61386646 : if (is_gimple_debug (stmt))
328 : 2469672 : continue;
329 : :
330 : 58916974 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
331 : : {
332 : 9347306 : decl = gimple_call_fndecl (call_stmt);
333 : 9347306 : if (decl)
334 : 8968727 : node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
335 : 378579 : else if (gimple_call_internal_p (call_stmt))
336 : : ;
337 : : else
338 : 159874 : node->create_indirect_edge (call_stmt,
339 : : gimple_call_flags (call_stmt),
340 : : bb->count);
341 : : }
342 : 58916974 : node->record_stmt_references (stmt);
343 : 58916974 : if (gomp_parallel *omp_par_stmt = dyn_cast <gomp_parallel *> (stmt))
344 : : {
345 : 0 : tree fn = gimple_omp_parallel_child_fn (omp_par_stmt);
346 : 0 : node->create_reference (cgraph_node::get_create (fn),
347 : : IPA_REF_ADDR, stmt);
348 : : }
349 : 58916974 : if (gimple_code (stmt) == GIMPLE_OMP_TASK)
350 : : {
351 : 0 : tree fn = gimple_omp_task_child_fn (stmt);
352 : 0 : if (fn)
353 : 0 : node->create_reference (cgraph_node::get_create (fn),
354 : : IPA_REF_ADDR, stmt);
355 : 0 : fn = gimple_omp_task_copy_fn (stmt);
356 : 0 : if (fn)
357 : 0 : node->create_reference (cgraph_node::get_create (fn),
358 : : IPA_REF_ADDR, stmt);
359 : : }
360 : : }
361 : 16051077 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
362 : 0 : node->record_stmt_references (gsi_stmt (gsi));
363 : : }
364 : :
365 : : /* Look for initializers of constant variables and private statics. */
366 : 19060118 : FOR_EACH_LOCAL_DECL (fun, ix, decl)
367 : 14399519 : if (VAR_P (decl)
368 : 14399519 : && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
369 : 257442 : && !DECL_HAS_VALUE_EXPR_P (decl)
370 : 14627992 : && TREE_TYPE (decl) != error_mark_node)
371 : 228461 : varpool_node::finalize_decl (decl);
372 : 2682174 : record_eh_tables (node, fun);
373 : :
374 : 2682174 : return 0;
375 : : }
376 : :
377 : : } // anon namespace
378 : :
379 : : gimple_opt_pass *
380 : 280114 : make_pass_build_cgraph_edges (gcc::context *ctxt)
381 : : {
382 : 280114 : return new pass_build_cgraph_edges (ctxt);
383 : : }
384 : :
385 : : /* Record references to functions and other variables present in the
386 : : initial value of DECL, a variable.
387 : : When ONLY_VARS is true, we mark needed only variables, not functions. */
388 : :
389 : : void
390 : 1980191 : record_references_in_initializer (tree decl, bool only_vars)
391 : : {
392 : 1980191 : varpool_node *node = varpool_node::get_create (decl);
393 : 1980191 : hash_set<tree> visited_nodes;
394 : 1980191 : record_reference_ctx ctx = {false, NULL};
395 : :
396 : 1980191 : ctx.varpool_node = node;
397 : 1980191 : ctx.only_vars = only_vars;
398 : 1980191 : walk_tree (&DECL_INITIAL (decl), record_reference,
399 : : &ctx, &visited_nodes);
400 : 1980191 : }
401 : :
402 : : /* Rebuild cgraph edges for current function node. This needs to be run after
403 : : passes that don't update the cgraph. */
404 : :
405 : : unsigned int
406 : 8091153 : cgraph_edge::rebuild_edges (void)
407 : : {
408 : 8091153 : basic_block bb;
409 : 8091153 : cgraph_node *node = cgraph_node::get (current_function_decl);
410 : 8091153 : gimple_stmt_iterator gsi;
411 : :
412 : 8091153 : node->remove_callees ();
413 : 8091153 : node->remove_all_references ();
414 : :
415 : 8091153 : node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
416 : :
417 : 55017230 : FOR_EACH_BB_FN (bb, cfun)
418 : : {
419 : 297901971 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
420 : : {
421 : 204049817 : gimple *stmt = gsi_stmt (gsi);
422 : 204049817 : tree decl;
423 : :
424 : 204049817 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
425 : : {
426 : 26617333 : decl = gimple_call_fndecl (call_stmt);
427 : 26617333 : if (decl)
428 : 24865407 : node->create_edge (cgraph_node::get_create (decl), call_stmt,
429 : : bb->count);
430 : 1751926 : else if (gimple_call_internal_p (call_stmt))
431 : : ;
432 : : else
433 : 495211 : node->create_indirect_edge (call_stmt,
434 : : gimple_call_flags (call_stmt),
435 : : bb->count);
436 : : }
437 : 204049817 : node->record_stmt_references (stmt);
438 : : }
439 : 59412822 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
440 : 12486745 : node->record_stmt_references (gsi_stmt (gsi));
441 : : }
442 : 8091153 : record_eh_tables (node, cfun);
443 : 8091153 : gcc_assert (!node->inlined_to);
444 : 8091153 : return 0;
445 : : }
446 : :
447 : : /* Rebuild cgraph references for current function node. This needs to be run
448 : : after passes that don't update the cgraph. */
449 : :
450 : : void
451 : 194762 : cgraph_edge::rebuild_references (void)
452 : : {
453 : 194762 : basic_block bb;
454 : 194762 : cgraph_node *node = cgraph_node::get (current_function_decl);
455 : 194762 : gimple_stmt_iterator gsi;
456 : 194762 : ipa_ref *ref = NULL;
457 : 194762 : int i;
458 : :
459 : : /* Keep speculative references for further cgraph edge expansion. */
460 : 546616 : for (i = 0; node->iterate_reference (i, ref);)
461 : 157092 : if (!ref->speculative)
462 : 156654 : ref->remove_reference ();
463 : : else
464 : 438 : i++;
465 : :
466 : 1882685 : FOR_EACH_BB_FN (bb, cfun)
467 : : {
468 : 12009908 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
469 : 8634062 : node->record_stmt_references (gsi_stmt (gsi));
470 : 1966433 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
471 : 278510 : node->record_stmt_references (gsi_stmt (gsi));
472 : : }
473 : 194762 : record_eh_tables (node, cfun);
474 : 194762 : }
475 : :
476 : : namespace {
477 : :
478 : : const pass_data pass_data_rebuild_cgraph_edges =
479 : : {
480 : : GIMPLE_PASS, /* type */
481 : : "*rebuild_cgraph_edges", /* name */
482 : : OPTGROUP_NONE, /* optinfo_flags */
483 : : TV_CGRAPH, /* tv_id */
484 : : PROP_cfg, /* properties_required */
485 : : 0, /* properties_provided */
486 : : 0, /* properties_destroyed */
487 : : 0, /* todo_flags_start */
488 : : 0, /* todo_flags_finish */
489 : : };
490 : :
491 : : class pass_rebuild_cgraph_edges : public gimple_opt_pass
492 : : {
493 : : public:
494 : 1120456 : pass_rebuild_cgraph_edges (gcc::context *ctxt)
495 : 2240912 : : gimple_opt_pass (pass_data_rebuild_cgraph_edges, ctxt)
496 : : {}
497 : :
498 : : /* opt_pass methods: */
499 : 840342 : opt_pass * clone () final override
500 : : {
501 : 840342 : return new pass_rebuild_cgraph_edges (m_ctxt);
502 : : }
503 : 7991036 : unsigned int execute (function *) final override
504 : : {
505 : 7991036 : return cgraph_edge::rebuild_edges ();
506 : : }
507 : :
508 : : }; // class pass_rebuild_cgraph_edges
509 : :
510 : : } // anon namespace
511 : :
512 : : gimple_opt_pass *
513 : 280114 : make_pass_rebuild_cgraph_edges (gcc::context *ctxt)
514 : : {
515 : 280114 : return new pass_rebuild_cgraph_edges (ctxt);
516 : : }
517 : :
518 : :
519 : : namespace {
520 : :
521 : : const pass_data pass_data_remove_cgraph_callee_edges =
522 : : {
523 : : GIMPLE_PASS, /* type */
524 : : "*remove_cgraph_callee_edges", /* name */
525 : : OPTGROUP_NONE, /* optinfo_flags */
526 : : TV_NONE, /* tv_id */
527 : : 0, /* properties_required */
528 : : 0, /* properties_provided */
529 : : 0, /* properties_destroyed */
530 : : 0, /* todo_flags_start */
531 : : 0, /* todo_flags_finish */
532 : : };
533 : :
534 : : class pass_remove_cgraph_callee_edges : public gimple_opt_pass
535 : : {
536 : : public:
537 : 840342 : pass_remove_cgraph_callee_edges (gcc::context *ctxt)
538 : 1680684 : : gimple_opt_pass (pass_data_remove_cgraph_callee_edges, ctxt)
539 : : {}
540 : :
541 : : /* opt_pass methods: */
542 : 560228 : opt_pass * clone () final override {
543 : 560228 : return new pass_remove_cgraph_callee_edges (m_ctxt);
544 : : }
545 : : unsigned int execute (function *) final override;
546 : :
547 : : }; // class pass_remove_cgraph_callee_edges
548 : :
549 : : unsigned int
550 : 3237592 : pass_remove_cgraph_callee_edges::execute (function *)
551 : : {
552 : 3237592 : cgraph_node *node = cgraph_node::get (current_function_decl);
553 : 3237592 : node->remove_callees ();
554 : 3237592 : node->remove_all_references ();
555 : 3237592 : return 0;
556 : : }
557 : :
558 : : } // anon namespace
559 : :
560 : : gimple_opt_pass *
561 : 280114 : make_pass_remove_cgraph_callee_edges (gcc::context *ctxt)
562 : : {
563 : 280114 : return new pass_remove_cgraph_callee_edges (ctxt);
564 : : }
|