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 : 14429950 : record_reference (tree *tp, int *walk_subtrees, void *data)
50 : : {
51 : 14429974 : tree t = *tp;
52 : 14429974 : tree decl;
53 : 14429974 : record_reference_ctx *ctx = (record_reference_ctx *)data;
54 : :
55 : 14429974 : t = canonicalize_constructor_val (t, NULL);
56 : 14429974 : if (!t)
57 : 143 : t = *tp;
58 : 14429831 : else if (t != *tp)
59 : 4451845 : *tp = t;
60 : :
61 : 14429974 : switch (TREE_CODE (t))
62 : : {
63 : 0 : case VAR_DECL:
64 : 0 : case FUNCTION_DECL:
65 : 0 : gcc_unreachable ();
66 : 4633933 : break;
67 : :
68 : 4633933 : case FDESC_EXPR:
69 : 4633933 : case ADDR_EXPR:
70 : : /* Record dereferences to the functions. This makes the
71 : : functions reachable unconditionally. */
72 : 4633933 : decl = get_base_var (*tp);
73 : 4633933 : if (TREE_CODE (decl) == FUNCTION_DECL)
74 : : {
75 : 1132466 : cgraph_node *node = cgraph_node::get_create (decl);
76 : 1132466 : if (!ctx->only_vars)
77 : 1132466 : node->mark_address_taken ();
78 : 1132466 : ctx->varpool_node->create_reference (node, IPA_REF_ADDR);
79 : : }
80 : :
81 : 4633933 : 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 : 2601303 : 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 : 2601279 : varpool_node *vnode = varpool_node::get_create (decl);
95 : 2601279 : ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR);
96 : : }
97 : 4633909 : *walk_subtrees = 0;
98 : 4633909 : break;
99 : :
100 : 9796041 : default:
101 : : /* Save some cycles by not walking types and declaration as we
102 : : won't find anything useful there anyway. */
103 : 9796041 : 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 : 197566 : record_type_list (cgraph_node *node, tree list)
118 : : {
119 : 220139 : for (; list; list = TREE_CHAIN (list))
120 : : {
121 : 22573 : tree type = TREE_VALUE (list);
122 : :
123 : 22573 : if (TYPE_P (type))
124 : 22131 : type = lookup_type_for_runtime (type);
125 : 22573 : STRIP_NOPS (type);
126 : 22573 : if (TREE_CODE (type) == ADDR_EXPR)
127 : : {
128 : 22573 : type = TREE_OPERAND (type, 0);
129 : 22573 : if (VAR_P (type))
130 : : {
131 : 22573 : varpool_node *vnode = varpool_node::get_create (type);
132 : 22573 : node->create_reference (vnode, IPA_REF_ADDR);
133 : : }
134 : : }
135 : : }
136 : 197566 : }
137 : :
138 : : /* Record all references we will introduce by producing EH tables
139 : : for NODE. */
140 : :
141 : : static void
142 : 10999041 : record_eh_tables (cgraph_node *node, function *fun)
143 : : {
144 : 10999041 : eh_region i;
145 : :
146 : 10999041 : if (DECL_FUNCTION_PERSONALITY (node->decl))
147 : : {
148 : 2178667 : tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl);
149 : 2178667 : cgraph_node *per_node = cgraph_node::get_create (per_decl);
150 : :
151 : 2178667 : node->create_reference (per_node, IPA_REF_ADDR);
152 : 2178667 : per_node->mark_address_taken ();
153 : : }
154 : :
155 : 10999041 : i = fun->eh->region_tree;
156 : 10999041 : if (!i)
157 : : return;
158 : :
159 : 7011037 : while (1)
160 : : {
161 : 7011037 : switch (i->type)
162 : : {
163 : : case ERT_CLEANUP:
164 : : case ERT_MUST_NOT_THROW:
165 : : break;
166 : :
167 : 182763 : case ERT_TRY:
168 : 182763 : {
169 : 182763 : eh_catch c;
170 : 362946 : for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
171 : 180183 : record_type_list (node, c->type_list);
172 : : }
173 : : break;
174 : :
175 : 17383 : case ERT_ALLOWED_EXCEPTIONS:
176 : 17383 : record_type_list (node, i->u.allowed.type_list);
177 : 17383 : break;
178 : : }
179 : : /* If there are sub-regions, process them. */
180 : 7011037 : if (i->inner)
181 : : i = i->inner;
182 : : /* If there are peers, process them. */
183 : 5411825 : 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 : 4710806 : do
189 : : {
190 : 4710806 : i = i->outer;
191 : 4710806 : if (i == NULL)
192 : : return;
193 : : }
194 : 1599212 : 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 : 29427043 : mark_address (gimple *stmt, tree addr, tree, void *data)
213 : : {
214 : 29427043 : addr = get_base_address (addr);
215 : 29427043 : if (TREE_CODE (addr) == FUNCTION_DECL)
216 : : {
217 : 1051252 : cgraph_node *node = cgraph_node::get_create (addr);
218 : 1051252 : node->mark_address_taken ();
219 : 1051252 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
220 : : }
221 : 28375791 : else if (addr && VAR_P (addr)
222 : 17477368 : && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
223 : : {
224 : 7787749 : varpool_node *vnode = varpool_node::get_create (addr);
225 : :
226 : 7787749 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_ADDR, stmt);
227 : : }
228 : :
229 : 29427043 : return false;
230 : : }
231 : :
232 : : /* Mark load of T. */
233 : :
234 : : static bool
235 : 57198596 : mark_load (gimple *stmt, tree t, tree, void *data)
236 : : {
237 : 57198596 : t = get_base_address (t);
238 : 57198596 : 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 : 100 : cgraph_node *node = cgraph_node::get_create (t);
243 : 100 : node->mark_address_taken ();
244 : 100 : ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
245 : 100 : }
246 : 57198496 : else if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
247 : : {
248 : 10885444 : varpool_node *vnode = varpool_node::get_create (t);
249 : :
250 : 10885444 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_LOAD, stmt);
251 : : }
252 : 57198596 : return false;
253 : : }
254 : :
255 : : /* Mark store of T. */
256 : :
257 : : static bool
258 : 56681124 : mark_store (gimple *stmt, tree t, tree, void *data)
259 : : {
260 : 56681124 : t = get_base_address (t);
261 : 56681124 : if (t && VAR_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
262 : : {
263 : 5555003 : varpool_node *vnode = varpool_node::get_create (t);
264 : :
265 : 5555003 : ((symtab_node *)data)->create_reference (vnode, IPA_REF_STORE, stmt);
266 : : }
267 : 56681124 : return false;
268 : : }
269 : :
270 : : /* Record all references from cgraph_node that are taken in statement STMT. */
271 : :
272 : : void
273 : 278209515 : cgraph_node::record_stmt_references (gimple *stmt)
274 : : {
275 : 278209515 : walk_stmt_load_store_addr_ops (stmt, this, mark_load, mark_store,
276 : : mark_address);
277 : 278209515 : }
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 : 281914 : pass_build_cgraph_edges (gcc::context *ctxt)
301 : 563828 : : 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 : 2688902 : pass_build_cgraph_edges::execute (function *fun)
311 : : {
312 : 2688902 : basic_block bb;
313 : 2688902 : cgraph_node *node = cgraph_node::get (current_function_decl);
314 : 2688902 : gimple_stmt_iterator gsi;
315 : 2688902 : tree decl;
316 : 2688902 : unsigned ix;
317 : :
318 : : /* Create the callgraph edges and record the nodes referenced by the function.
319 : : body. */
320 : 18507786 : FOR_EACH_BB_FN (bb, fun)
321 : : {
322 : 91744058 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
323 : : {
324 : 60106290 : gimple *stmt = gsi_stmt (gsi);
325 : 60106290 : tree decl;
326 : :
327 : 60106290 : if (is_gimple_debug (stmt))
328 : 2434795 : continue;
329 : :
330 : 57671495 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
331 : : {
332 : 9257655 : decl = gimple_call_fndecl (call_stmt);
333 : 9257655 : if (decl)
334 : 8883628 : node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
335 : 374027 : else if (gimple_call_internal_p (call_stmt))
336 : : ;
337 : : else
338 : 159886 : node->create_indirect_edge (call_stmt,
339 : : gimple_call_flags (call_stmt),
340 : : bb->count);
341 : : }
342 : 57671495 : node->record_stmt_references (stmt);
343 : 57671495 : 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 : 57671495 : 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 : 15818884 : 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 : 18980046 : FOR_EACH_LOCAL_DECL (fun, ix, decl)
367 : 14311986 : if (VAR_P (decl)
368 : 14311986 : && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
369 : 249020 : && !DECL_HAS_VALUE_EXPR_P (decl)
370 : 14534957 : && TREE_TYPE (decl) != error_mark_node)
371 : 222964 : varpool_node::finalize_decl (decl);
372 : 2688902 : record_eh_tables (node, fun);
373 : :
374 : 2688902 : return 0;
375 : : }
376 : :
377 : : } // anon namespace
378 : :
379 : : gimple_opt_pass *
380 : 281914 : make_pass_build_cgraph_edges (gcc::context *ctxt)
381 : : {
382 : 281914 : 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 : 1995562 : record_references_in_initializer (tree decl, bool only_vars)
391 : : {
392 : 1995562 : varpool_node *node = varpool_node::get_create (decl);
393 : 1995562 : hash_set<tree> visited_nodes;
394 : 1995562 : record_reference_ctx ctx = {false, NULL};
395 : :
396 : 1995562 : ctx.varpool_node = node;
397 : 1995562 : ctx.only_vars = only_vars;
398 : 1995562 : walk_tree (&DECL_INITIAL (decl), record_reference,
399 : : &ctx, &visited_nodes);
400 : 1995562 : }
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 : 8113064 : cgraph_edge::rebuild_edges (void)
407 : : {
408 : 8113064 : basic_block bb;
409 : 8113064 : cgraph_node *node = cgraph_node::get (current_function_decl);
410 : 8113064 : gimple_stmt_iterator gsi;
411 : :
412 : 8113064 : node->remove_callees ();
413 : 8113064 : node->remove_all_references ();
414 : :
415 : 8113064 : node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
416 : :
417 : 54427824 : FOR_EACH_BB_FN (bb, cfun)
418 : : {
419 : 292361010 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
420 : : {
421 : 199731490 : gimple *stmt = gsi_stmt (gsi);
422 : 199731490 : tree decl;
423 : :
424 : 199731490 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
425 : : {
426 : 26443822 : decl = gimple_call_fndecl (call_stmt);
427 : 26443822 : if (decl)
428 : 24662953 : node->create_edge (cgraph_node::get_create (decl), call_stmt,
429 : : bb->count);
430 : 1780869 : else if (gimple_call_internal_p (call_stmt))
431 : : ;
432 : : else
433 : 494780 : node->create_indirect_edge (call_stmt,
434 : : gimple_call_flags (call_stmt),
435 : : bb->count);
436 : : }
437 : 199731490 : node->record_stmt_references (stmt);
438 : : }
439 : 58579953 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
440 : 12265193 : node->record_stmt_references (gsi_stmt (gsi));
441 : : }
442 : 8113064 : record_eh_tables (node, cfun);
443 : 8113064 : gcc_assert (!node->inlined_to);
444 : 8113064 : 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 : 197075 : cgraph_edge::rebuild_references (void)
452 : : {
453 : 197075 : basic_block bb;
454 : 197075 : cgraph_node *node = cgraph_node::get (current_function_decl);
455 : 197075 : gimple_stmt_iterator gsi;
456 : 197075 : ipa_ref *ref = NULL;
457 : 197075 : int i;
458 : :
459 : : /* Keep speculative references for further cgraph edge expansion. */
460 : 550594 : for (i = 0; node->iterate_reference (i, ref);)
461 : 156444 : if (!ref->speculative)
462 : 155952 : ref->remove_reference ();
463 : : else
464 : 492 : i++;
465 : :
466 : 1849853 : FOR_EACH_BB_FN (bb, cfun)
467 : : {
468 : 11571062 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
469 : 8265506 : node->record_stmt_references (gsi_stmt (gsi));
470 : 1928609 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
471 : 275831 : node->record_stmt_references (gsi_stmt (gsi));
472 : : }
473 : 197075 : record_eh_tables (node, cfun);
474 : 197075 : }
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 : 1127656 : pass_rebuild_cgraph_edges (gcc::context *ctxt)
495 : 2255312 : : gimple_opt_pass (pass_data_rebuild_cgraph_edges, ctxt)
496 : : {}
497 : :
498 : : /* opt_pass methods: */
499 : 845742 : opt_pass * clone () final override
500 : : {
501 : 845742 : return new pass_rebuild_cgraph_edges (m_ctxt);
502 : : }
503 : 8010844 : unsigned int execute (function *) final override
504 : : {
505 : 8010844 : return cgraph_edge::rebuild_edges ();
506 : : }
507 : :
508 : : }; // class pass_rebuild_cgraph_edges
509 : :
510 : : } // anon namespace
511 : :
512 : : gimple_opt_pass *
513 : 281914 : make_pass_rebuild_cgraph_edges (gcc::context *ctxt)
514 : : {
515 : 281914 : 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 : 845742 : pass_remove_cgraph_callee_edges (gcc::context *ctxt)
538 : 1691484 : : gimple_opt_pass (pass_data_remove_cgraph_callee_edges, ctxt)
539 : : {}
540 : :
541 : : /* opt_pass methods: */
542 : 563828 : opt_pass * clone () final override {
543 : 563828 : 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 : 3213356 : pass_remove_cgraph_callee_edges::execute (function *)
551 : : {
552 : 3213356 : cgraph_node *node = cgraph_node::get (current_function_decl);
553 : 3213356 : node->remove_callees ();
554 : 3213356 : node->remove_all_references ();
555 : 3213356 : return 0;
556 : : }
557 : :
558 : : } // anon namespace
559 : :
560 : : gimple_opt_pass *
561 : 281914 : make_pass_remove_cgraph_callee_edges (gcc::context *ctxt)
562 : : {
563 : 281914 : return new pass_remove_cgraph_callee_edges (ctxt);
564 : : }
|