Line data Source code
1 : /* Callgraph construction.
2 : Copyright (C) 2003-2026 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 14730006 : record_reference (tree *tp, int *walk_subtrees, void *data)
50 : {
51 14730038 : tree t = *tp;
52 14730038 : tree decl;
53 14730038 : record_reference_ctx *ctx = (record_reference_ctx *)data;
54 :
55 14730038 : t = canonicalize_constructor_val (t, NULL);
56 14730038 : if (!t)
57 77 : t = *tp;
58 14729961 : else if (t != *tp)
59 4431468 : *tp = t;
60 :
61 14730038 : switch (TREE_CODE (t))
62 : {
63 0 : case VAR_DECL:
64 0 : case FUNCTION_DECL:
65 0 : gcc_unreachable ();
66 4625297 : break;
67 :
68 4625297 : case FDESC_EXPR:
69 4625297 : case ADDR_EXPR:
70 : /* Record dereferences to the functions. This makes the
71 : functions reachable unconditionally. */
72 4625297 : decl = get_base_var (*tp);
73 4625297 : if (TREE_CODE (decl) == FUNCTION_DECL)
74 : {
75 1122129 : cgraph_node *node = cgraph_node::get_create (decl);
76 1122129 : if (!ctx->only_vars)
77 1122129 : node->mark_address_taken ();
78 1122129 : ctx->varpool_node->create_reference (node, IPA_REF_ADDR);
79 : }
80 :
81 4625297 : 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 2593210 : if (DECL_HAS_VALUE_EXPR_P (decl))
87 : {
88 : tree *p;
89 64 : for (p = tp; *p != decl; p = &TREE_OPERAND (*p, 0))
90 : ;
91 32 : *p = unshare_expr (DECL_VALUE_EXPR (decl));
92 32 : return record_reference (tp, walk_subtrees, data);
93 : }
94 2593178 : varpool_node *vnode = varpool_node::get_create (decl);
95 2593178 : ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR);
96 : }
97 4625265 : *walk_subtrees = 0;
98 4625265 : break;
99 :
100 10104741 : default:
101 : /* Save some cycles by not walking types and declaration as we
102 : won't find anything useful there anyway. */
103 10104741 : 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 191971 : record_type_list (cgraph_node *node, tree list)
118 : {
119 216099 : for (; list; list = TREE_CHAIN (list))
120 : {
121 24128 : tree type = TREE_VALUE (list);
122 :
123 24128 : if (TYPE_P (type))
124 23511 : type = lookup_type_for_runtime (type);
125 24128 : STRIP_NOPS (type);
126 24128 : if (TREE_CODE (type) == ADDR_EXPR)
127 : {
128 24128 : type = TREE_OPERAND (type, 0);
129 24128 : if (VAR_P (type))
130 : {
131 24128 : varpool_node *vnode = varpool_node::get_create (type);
132 24128 : node->create_reference (vnode, IPA_REF_ADDR);
133 : }
134 : }
135 : }
136 191971 : }
137 :
138 : /* Record all references we will introduce by producing EH tables
139 : for NODE. */
140 :
141 : static void
142 11767677 : record_eh_tables (cgraph_node *node, function *fun)
143 : {
144 11767677 : eh_region i;
145 :
146 11767677 : if (DECL_FUNCTION_PERSONALITY (node->decl))
147 : {
148 2361138 : tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl);
149 2361138 : cgraph_node *per_node = cgraph_node::get_create (per_decl);
150 :
151 2361138 : node->create_reference (per_node, IPA_REF_ADDR);
152 2361138 : per_node->mark_address_taken ();
153 : }
154 :
155 11767677 : i = fun->eh->region_tree;
156 11767677 : if (!i)
157 : return;
158 :
159 7802038 : while (1)
160 : {
161 7802038 : switch (i->type)
162 : {
163 : case ERT_CLEANUP:
164 : case ERT_MUST_NOT_THROW:
165 : break;
166 :
167 178715 : case ERT_TRY:
168 178715 : {
169 178715 : eh_catch c;
170 355082 : for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
171 176367 : record_type_list (node, c->type_list);
172 : }
173 : break;
174 :
175 15604 : case ERT_ALLOWED_EXCEPTIONS:
176 15604 : record_type_list (node, i->u.allowed.type_list);
177 15604 : break;
178 : }
179 : /* If there are sub-regions, process them. */
180 7802038 : if (i->inner)
181 : i = i->inner;
182 : /* If there are peers, process them. */
183 6056232 : 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 5079029 : do
189 : {
190 5079029 : i = i->outer;
191 5079029 : if (i == NULL)
192 : return;
193 : }
194 1745806 : 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 32506224 : mark_address (gimple *stmt, tree addr, tree, void *data)
213 : {
214 32506224 : addr = get_base_address (addr);
215 32506224 : if (TREE_CODE (addr) == FUNCTION_DECL)
216 : {
217 1107634 : cgraph_node *node = cgraph_node::get_create (addr);
218 1107634 : node->mark_address_taken ();
219 1107634 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
220 : }
221 31398590 : else if (addr && VAR_P (addr)
222 18874284 : && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
223 : {
224 7929071 : varpool_node *vnode = varpool_node::get_create (addr);
225 :
226 7929071 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_ADDR, stmt);
227 : }
228 :
229 32506224 : return false;
230 : }
231 :
232 : /* Mark load of T. */
233 :
234 : static bool
235 61200601 : mark_load (gimple *stmt, tree t, tree, void *data)
236 : {
237 61200601 : t = get_base_address (t);
238 61200601 : 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 105 : cgraph_node *node = cgraph_node::get_create (t);
243 105 : node->mark_address_taken ();
244 105 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
245 105 : }
246 61200496 : else if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
247 : {
248 11300345 : varpool_node *vnode = varpool_node::get_create (t);
249 :
250 11300345 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_LOAD, stmt);
251 : }
252 61200601 : return false;
253 : }
254 :
255 : /* Mark store of T. */
256 :
257 : static bool
258 61785407 : mark_store (gimple *stmt, tree t, tree, void *data)
259 : {
260 61785407 : t = get_base_address (t);
261 61785407 : if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
262 : {
263 5787011 : varpool_node *vnode = varpool_node::get_create (t);
264 :
265 5787011 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_STORE, stmt);
266 : }
267 61785407 : return false;
268 : }
269 :
270 : /* Record all references from cgraph_node that are taken in statement STMT. */
271 :
272 : void
273 306133238 : cgraph_node::record_stmt_references (gimple *stmt)
274 : {
275 306133238 : walk_stmt_load_store_addr_ops (stmt, this, mark_load, mark_store,
276 : mark_address);
277 306133238 : }
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 287872 : pass_build_cgraph_edges (gcc::context *ctxt)
301 575744 : : 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 2873796 : pass_build_cgraph_edges::execute (function *fun)
311 : {
312 2873796 : basic_block bb;
313 2873796 : cgraph_node *node = cgraph_node::get (current_function_decl);
314 2873796 : gimple_stmt_iterator gsi;
315 2873796 : tree decl;
316 2873796 : unsigned ix;
317 :
318 : /* Create the callgraph edges and record the nodes referenced by the function.
319 : body. */
320 19952599 : FOR_EACH_BB_FN (bb, fun)
321 : {
322 98921764 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
323 : {
324 64764158 : gimple *stmt = gsi_stmt (gsi);
325 64764158 : tree decl;
326 :
327 64764158 : if (is_gimple_debug (stmt))
328 2310887 : continue;
329 :
330 62453271 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
331 : {
332 10147021 : decl = gimple_call_fndecl (call_stmt);
333 10147021 : if (decl)
334 9642401 : node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
335 504620 : else if (gimple_call_internal_p (call_stmt))
336 : ;
337 : else
338 162718 : node->create_indirect_edge (call_stmt,
339 : gimple_call_flags (call_stmt),
340 : bb->count);
341 : }
342 62453271 : node->record_stmt_references (stmt);
343 62453271 : 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 62453271 : 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 17078803 : 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 20388267 : FOR_EACH_LOCAL_DECL (fun, ix, decl)
367 15387009 : if (VAR_P (decl)
368 15387009 : && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
369 286977 : && !DECL_HAS_VALUE_EXPR_P (decl)
370 15629795 : && TREE_TYPE (decl) != error_mark_node)
371 242713 : varpool_node::finalize_decl (decl);
372 2873796 : record_eh_tables (node, fun);
373 :
374 2873796 : return 0;
375 : }
376 :
377 : } // anon namespace
378 :
379 : gimple_opt_pass *
380 287872 : make_pass_build_cgraph_edges (gcc::context *ctxt)
381 : {
382 287872 : 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 2006475 : record_references_in_initializer (tree decl, bool only_vars)
391 : {
392 2006475 : varpool_node *node = varpool_node::get_create (decl);
393 2006475 : hash_set<tree> visited_nodes;
394 2006475 : record_reference_ctx ctx = {false, NULL};
395 :
396 2006475 : ctx.varpool_node = node;
397 2006475 : ctx.only_vars = only_vars;
398 2006475 : walk_tree (&DECL_INITIAL (decl), record_reference,
399 : &ctx, &visited_nodes);
400 2006475 : }
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 8667707 : cgraph_edge::rebuild_edges (void)
407 : {
408 8667707 : basic_block bb;
409 8667707 : cgraph_node *node = cgraph_node::get (current_function_decl);
410 8667707 : gimple_stmt_iterator gsi;
411 :
412 8667707 : node->remove_callees ();
413 8667707 : node->remove_all_references ();
414 :
415 8667707 : node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
416 :
417 58539976 : FOR_EACH_BB_FN (bb, cfun)
418 : {
419 318862344 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
420 : {
421 219117806 : gimple *stmt = gsi_stmt (gsi);
422 219117806 : tree decl;
423 :
424 219117806 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
425 : {
426 28911492 : decl = gimple_call_fndecl (call_stmt);
427 28911492 : if (decl)
428 26730142 : node->create_edge (cgraph_node::get_create (decl), call_stmt,
429 : bb->count);
430 2181350 : else if (gimple_call_internal_p (call_stmt))
431 : ;
432 : else
433 504486 : node->create_indirect_edge (call_stmt,
434 : gimple_call_flags (call_stmt),
435 : bb->count);
436 : }
437 219117806 : node->record_stmt_references (stmt);
438 : }
439 62962334 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
440 13090065 : node->record_stmt_references (gsi_stmt (gsi));
441 : }
442 8667707 : record_eh_tables (node, cfun);
443 8667707 : gcc_assert (!node->inlined_to);
444 8667707 : 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 226174 : cgraph_edge::rebuild_references (void)
452 : {
453 226174 : basic_block bb;
454 226174 : cgraph_node *node = cgraph_node::get (current_function_decl);
455 226174 : gimple_stmt_iterator gsi;
456 226174 : ipa_ref *ref = NULL;
457 226174 : int i;
458 :
459 : /* Keep speculative references for further cgraph edge expansion. */
460 637364 : for (i = 0; node->iterate_reference (i, ref);)
461 185016 : if (!ref->speculative)
462 182098 : ref->remove_reference ();
463 : else
464 2918 : i++;
465 :
466 2170701 : FOR_EACH_BB_FN (bb, cfun)
467 : {
468 15042110 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
469 11153056 : node->record_stmt_references (gsi_stmt (gsi));
470 2263567 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
471 319040 : node->record_stmt_references (gsi_stmt (gsi));
472 : }
473 226174 : record_eh_tables (node, cfun);
474 226174 : }
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 1151488 : pass_rebuild_cgraph_edges (gcc::context *ctxt)
495 2302976 : : gimple_opt_pass (pass_data_rebuild_cgraph_edges, ctxt)
496 : {}
497 :
498 : /* opt_pass methods: */
499 863616 : opt_pass * clone () final override
500 : {
501 863616 : return new pass_rebuild_cgraph_edges (m_ctxt);
502 : }
503 8560605 : unsigned int execute (function *) final override
504 : {
505 8560605 : return cgraph_edge::rebuild_edges ();
506 : }
507 :
508 : }; // class pass_rebuild_cgraph_edges
509 :
510 : } // anon namespace
511 :
512 : gimple_opt_pass *
513 287872 : make_pass_rebuild_cgraph_edges (gcc::context *ctxt)
514 : {
515 287872 : 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 863616 : pass_remove_cgraph_callee_edges (gcc::context *ctxt)
538 1727232 : : gimple_opt_pass (pass_data_remove_cgraph_callee_edges, ctxt)
539 : {}
540 :
541 : /* opt_pass methods: */
542 575744 : opt_pass * clone () final override {
543 575744 : 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 3444446 : pass_remove_cgraph_callee_edges::execute (function *)
551 : {
552 3444446 : cgraph_node *node = cgraph_node::get (current_function_decl);
553 3444446 : node->remove_callees ();
554 3444446 : node->remove_all_references ();
555 3444446 : return 0;
556 : }
557 :
558 : } // anon namespace
559 :
560 : gimple_opt_pass *
561 287872 : make_pass_remove_cgraph_callee_edges (gcc::context *ctxt)
562 : {
563 287872 : return new pass_remove_cgraph_callee_edges (ctxt);
564 : }
|