* Tippo
[official-gcc.git] / gcc / ipa.c
blobe270591807711f7cde661500867695c67cbc8d9d
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cgraph.h"
26 #include "tree-pass.h"
27 #include "gimple.h"
28 #include "ggc.h"
29 #include "flags.h"
30 #include "pointer-set.h"
31 #include "target.h"
32 #include "tree-iterator.h"
33 #include "ipa-utils.h"
34 #include "pointer-set.h"
35 #include "ipa-inline.h"
37 /* Look for all functions inlined to NODE and update their inlined_to pointers
38 to INLINED_TO. */
40 static void
41 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
43 struct cgraph_edge *e;
44 for (e = node->callees; e; e = e->next_callee)
45 if (e->callee->global.inlined_to)
47 e->callee->global.inlined_to = inlined_to;
48 update_inlined_to_pointer (e->callee, inlined_to);
52 /* Add symtab NODE to queue starting at FIRST.
54 The queue is linked via AUX pointers and terminated by pointer to 1.
55 We enqueue nodes at two occasions: when we find them reachable or when we find
56 their bodies needed for further clonning. In the second case we mark them
57 by pointer to 2 after processing so they are re-queue when they become
58 reachable. */
60 static void
61 enqueue_node (symtab_node node, symtab_node *first,
62 struct pointer_set_t *reachable)
64 /* Node is still in queue; do nothing. */
65 if (node->symbol.aux && node->symbol.aux != (void *) 2)
66 return;
67 /* Node was already processed as unreachable, re-enqueue
68 only if it became reachable now. */
69 if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
70 return;
71 node->symbol.aux = *first;
72 *first = node;
75 /* Process references. */
77 static void
78 process_references (struct ipa_ref_list *list,
79 symtab_node *first,
80 bool before_inlining_p,
81 struct pointer_set_t *reachable)
83 int i;
84 struct ipa_ref *ref;
85 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
87 if (symtab_function_p (ref->referred))
89 struct cgraph_node *node = ipa_ref_node (ref);
91 if (node->analyzed
92 && (!DECL_EXTERNAL (node->symbol.decl)
93 || node->alias
94 || before_inlining_p))
95 pointer_set_insert (reachable, node);
96 enqueue_node ((symtab_node) node, first, reachable);
98 else
100 struct varpool_node *node = ipa_ref_varpool_node (ref);
102 if (node->analyzed
103 && (!DECL_EXTERNAL (node->symbol.decl)
104 || node->alias
105 || before_inlining_p))
106 pointer_set_insert (reachable, node);
107 enqueue_node ((symtab_node) node, first, reachable);
113 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
115 static bool
116 cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
118 /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
119 return !(cgraph_only_called_directly_or_aliased_p (node)
120 && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
121 && node->analyzed
122 && !DECL_EXTERNAL (node->symbol.decl)
123 && !node->symbol.externally_visible
124 && !node->symbol.used_from_other_partition
125 && !node->symbol.in_other_partition);
128 /* Return true when function can be marked local. */
130 static bool
131 cgraph_local_node_p (struct cgraph_node *node)
133 struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
135 /* FIXME: thunks can be considered local, but we need prevent i386
136 from attempting to change calling convention of them. */
137 if (n->thunk.thunk_p)
138 return false;
139 return !cgraph_for_node_and_aliases (n,
140 cgraph_non_local_node_p_1, NULL, true);
144 /* Return true when NODE has ADDR reference. */
146 static bool
147 has_addr_references_p (struct cgraph_node *node,
148 void *data ATTRIBUTE_UNUSED)
150 int i;
151 struct ipa_ref *ref;
153 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
154 i, ref); i++)
155 if (ref->use == IPA_REF_ADDR)
156 return true;
157 return false;
160 /* Perform reachability analysis and reclaim all unreachable nodes.
162 The algorithm is basically mark&sweep but with some extra refinements:
164 - reachable extern inline functions needs special handling; the bodies needs
165 to stay in memory until inlining in hope that they will be inlined.
166 After inlining we release their bodies and turn them into unanalyzed
167 nodes even when they are reachable.
169 BEFORE_INLINING_P specify whether we are before or after inlining.
171 - virtual functions are kept in callgraph even if they seem unreachable in
172 hope calls to them will be devirtualized.
174 Again we remove them after inlining. In late optimization some
175 devirtualization may happen, but it is not importnat since we won't inline
176 the call. In theory early opts and IPA should work out all important cases.
178 - virtual clones needs bodies of their origins for later materialization;
179 this means that we want to keep the body even if the origin is unreachable
180 otherwise. To avoid origin from sitting in the callgraph and being
181 walked by IPA passes, we turn them into unanalyzed nodes with body
182 defined.
184 We maintain set of function declaration where body needs to stay in
185 body_needed_for_clonning
187 Inline clones represent special case: their declaration match the
188 declaration of origin and cgraph_remove_node already knows how to
189 reshape callgraph and preserve body when offline copy of function or
190 inline clone is being removed.
192 - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
193 variables with DECL_INITIAL set. We finalize these and keep reachable
194 ones around for constant folding purposes. After inlining we however
195 stop walking their references to let everything static referneced by them
196 to be removed when it is otherwise unreachable.
198 We maintain queue of both reachable symbols (i.e. defined symbols that needs
199 to stay) and symbols that are in boundary (i.e. external symbols referenced
200 by reachable symbols or origins of clones). The queue is represented
201 as linked list by AUX pointer terminated by 1.
203 A the end we keep all reachable symbols. For symbols in boundary we always
204 turn definition into a declaration, but we may keep function body around
205 based on body_needed_for_clonning
207 All symbols that enter the queue have AUX pointer non-zero and are in the
208 boundary. Pointer set REACHABLE is used to track reachable symbols.
210 Every symbol can be visited twice - once as part of boundary and once
211 as real reachable symbol. enqueue_node needs to decide whether the
212 node needs to be re-queued for second processing. For this purpose
213 we set AUX pointer of processed symbols in the boundary to constant 2. */
215 bool
216 symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
218 symtab_node first = (symtab_node) (void *) 1;
219 struct cgraph_node *node, *next;
220 struct varpool_node *vnode, *vnext;
221 bool changed = false;
222 struct pointer_set_t *reachable = pointer_set_create ();
223 struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
225 #ifdef ENABLE_CHECKING
226 verify_symtab ();
227 #endif
228 if (file)
229 fprintf (file, "\nReclaiming functions:");
230 #ifdef ENABLE_CHECKING
231 FOR_EACH_FUNCTION (node)
232 gcc_assert (!node->symbol.aux);
233 FOR_EACH_VARIABLE (vnode)
234 gcc_assert (!vnode->symbol.aux);
235 #endif
236 /* Mark functions whose bodies are obviously needed.
237 This is mostly when they can be referenced externally. Inline clones
238 are special since their declarations are shared with master clone and thus
239 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
240 FOR_EACH_DEFINED_FUNCTION (node)
241 if (!node->global.inlined_to
242 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
243 /* Keep around virtual functions for possible devirtualization. */
244 || (before_inlining_p
245 && DECL_VIRTUAL_P (node->symbol.decl)
246 && (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
248 gcc_assert (!node->global.inlined_to);
249 pointer_set_insert (reachable, node);
250 enqueue_node ((symtab_node)node, &first, reachable);
252 else
253 gcc_assert (!node->symbol.aux);
255 /* Mark variables that are obviously needed. */
256 FOR_EACH_DEFINED_VARIABLE (vnode)
257 if (!varpool_can_remove_if_no_refs (vnode))
259 pointer_set_insert (reachable, vnode);
260 enqueue_node ((symtab_node)vnode, &first, reachable);
263 /* Perform reachability analysis. */
264 while (first != (symtab_node) (void *) 1)
266 bool in_boundary_p = !pointer_set_contains (reachable, first);
267 symtab_node node = first;
269 first = (symtab_node)first->symbol.aux;
271 /* If we are processing symbol in boundary, mark its AUX pointer for
272 possible later re-processing in enqueue_node. */
273 if (in_boundary_p)
274 node->symbol.aux = (void *)2;
275 else
277 /* If any symbol in a comdat group is reachable, force
278 all other in the same comdat group to be also reachable. */
279 if (node->symbol.same_comdat_group)
281 symtab_node next;
282 for (next = node->symbol.same_comdat_group;
283 next != node;
284 next = next->symbol.same_comdat_group)
285 if (!pointer_set_insert (reachable, next))
286 enqueue_node ((symtab_node) next, &first, reachable);
288 /* Mark references as reachable. */
289 process_references (&node->symbol.ref_list, &first,
290 before_inlining_p, reachable);
293 if (symtab_function_p (node))
295 struct cgraph_node *cnode = cgraph (node);
297 /* Mark the callees reachable unless they are direct calls to extern
298 inline functions we decided to not inline. */
299 if (!in_boundary_p)
301 struct cgraph_edge *e;
302 for (e = cnode->callees; e; e = e->next_callee)
304 if (e->callee->analyzed
305 && (!e->inline_failed
306 || !DECL_EXTERNAL (e->callee->symbol.decl)
307 || cnode->alias
308 || before_inlining_p))
309 pointer_set_insert (reachable, e->callee);
310 enqueue_node ((symtab_node) e->callee, &first, reachable);
313 /* When inline clone exists, mark body to be preserved so when removing
314 offline copy of the function we don't kill it. */
315 if (!cnode->alias && cnode->global.inlined_to)
316 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
319 /* For non-inline clones, force their origins to the boundary and ensure
320 that body is not removed. */
321 while (cnode->clone_of
322 && !gimple_has_body_p (cnode->symbol.decl))
324 bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
325 cnode = cnode->clone_of;
326 if (noninline)
328 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
329 enqueue_node ((symtab_node)cnode, &first, reachable);
330 break;
334 /* When we see constructor of external variable, keep referred nodes in the
335 boundary. This will also hold initializers of the external vars NODE
336 reffers to. */
337 if (symtab_variable_p (node)
338 && DECL_EXTERNAL (node->symbol.decl)
339 && !varpool (node)->alias
340 && in_boundary_p)
342 int i;
343 struct ipa_ref *ref;
344 for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
345 enqueue_node (ref->referred, &first, reachable);
349 /* Remove unreachable functions. */
350 for (node = cgraph_first_function (); node; node = next)
352 next = cgraph_next_function (node);
353 if (!node->symbol.aux)
355 if (file)
356 fprintf (file, " %s", cgraph_node_name (node));
357 cgraph_remove_node (node);
358 changed = true;
360 else if (!pointer_set_contains (reachable, node))
362 if (node->analyzed)
364 if (file)
365 fprintf (file, " %s", cgraph_node_name (node));
366 cgraph_node_remove_callees (node);
367 ipa_remove_all_references (&node->symbol.ref_list);
368 changed = true;
370 if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
371 && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
372 cgraph_release_function_body (node);
373 node->analyzed = false;
377 /* Inline clones might be kept around so their materializing allows further
378 cloning. If the function the clone is inlined into is removed, we need
379 to turn it into normal cone. */
380 FOR_EACH_FUNCTION (node)
382 if (node->global.inlined_to
383 && !node->callers)
385 gcc_assert (node->clones);
386 node->global.inlined_to = NULL;
387 update_inlined_to_pointer (node, node);
389 node->symbol.aux = NULL;
392 /* Remove unreachable variables. */
393 if (file)
394 fprintf (file, "\nReclaiming variables:");
395 for (vnode = varpool_first_variable (); vnode; vnode = vnext)
397 vnext = varpool_next_variable (vnode);
398 if (!vnode->symbol.aux)
400 if (file)
401 fprintf (file, " %s", varpool_node_name (vnode));
402 varpool_remove_node (vnode);
403 changed = true;
405 else if (!pointer_set_contains (reachable, vnode))
407 if (vnode->analyzed)
409 if (file)
410 fprintf (file, " %s", varpool_node_name (vnode));
411 changed = true;
413 vnode->analyzed = false;
414 vnode->symbol.aux = NULL;
416 else
417 vnode->symbol.aux = NULL;
420 pointer_set_destroy (reachable);
421 pointer_set_destroy (body_needed_for_clonning);
423 /* Now update address_taken flags and try to promote functions to be local. */
424 if (file)
425 fprintf (file, "\nClearing address taken flags:");
426 FOR_EACH_DEFINED_FUNCTION (node)
427 if (node->symbol.address_taken
428 && !node->symbol.used_from_other_partition)
430 if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
432 if (file)
433 fprintf (file, " %s", cgraph_node_name (node));
434 node->symbol.address_taken = false;
435 changed = true;
436 if (cgraph_local_node_p (node))
438 node->local.local = true;
439 if (file)
440 fprintf (file, " (local)");
444 if (file)
445 fprintf (file, "\n");
447 #ifdef ENABLE_CHECKING
448 verify_symtab ();
449 #endif
451 /* If we removed something, perhaps profile could be improved. */
452 if (changed && optimize && inline_edge_summary_vec)
453 FOR_EACH_DEFINED_FUNCTION (node)
454 cgraph_propagate_frequency (node);
456 return changed;
459 /* Discover variables that have no longer address taken or that are read only
460 and update their flags.
462 FIXME: This can not be done in between gimplify and omp_expand since
463 readonly flag plays role on what is shared and what is not. Currently we do
464 this transformation as part of whole program visibility and re-do at
465 ipa-reference pass (to take into account clonning), but it would
466 make sense to do it before early optimizations. */
468 void
469 ipa_discover_readonly_nonaddressable_vars (void)
471 struct varpool_node *vnode;
472 if (dump_file)
473 fprintf (dump_file, "Clearing variable flags:");
474 FOR_EACH_VARIABLE (vnode)
475 if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
476 && (TREE_ADDRESSABLE (vnode->symbol.decl)
477 || !TREE_READONLY (vnode->symbol.decl)))
479 bool written = false;
480 bool address_taken = false;
481 int i;
482 struct ipa_ref *ref;
483 for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
484 i, ref)
485 && (!written || !address_taken); i++)
486 switch (ref->use)
488 case IPA_REF_ADDR:
489 address_taken = true;
490 break;
491 case IPA_REF_LOAD:
492 break;
493 case IPA_REF_STORE:
494 written = true;
495 break;
497 if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
499 if (dump_file)
500 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
501 TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
503 if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
504 /* Making variable in explicit section readonly can cause section
505 type conflict.
506 See e.g. gcc.c-torture/compile/pr23237.c */
507 && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
509 if (dump_file)
510 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
511 TREE_READONLY (vnode->symbol.decl) = 1;
514 if (dump_file)
515 fprintf (dump_file, "\n");
518 /* Return true when there is a reference to node and it is not vtable. */
519 static bool
520 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
522 int i;
523 struct ipa_ref *ref;
524 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
525 i, ref); i++)
526 if (ref->use == IPA_REF_ADDR)
528 struct varpool_node *node;
529 if (symtab_function_p (ref->referring))
530 return true;
531 node = ipa_ref_referring_varpool_node (ref);
532 if (!DECL_VIRTUAL_P (node->symbol.decl))
533 return true;
535 return false;
538 /* COMDAT functions must be shared only if they have address taken,
539 otherwise we can produce our own private implementation with
540 -fwhole-program.
541 Return true when turning COMDAT functoin static can not lead to wrong
542 code when the resulting object links with a library defining same COMDAT.
544 Virtual functions do have their addresses taken from the vtables,
545 but in C++ there is no way to compare their addresses for equality. */
547 bool
548 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
550 if ((cgraph_address_taken_from_non_vtable_p (node)
551 && !DECL_VIRTUAL_P (node->symbol.decl))
552 || !node->analyzed)
553 return false;
554 if (node->symbol.same_comdat_group)
556 struct cgraph_node *next;
558 /* If more than one function is in the same COMDAT group, it must
559 be shared even if just one function in the comdat group has
560 address taken. */
561 for (next = cgraph (node->symbol.same_comdat_group);
562 next != node; next = cgraph (next->symbol.same_comdat_group))
563 if (cgraph_address_taken_from_non_vtable_p (next)
564 && !DECL_VIRTUAL_P (next->symbol.decl))
565 return false;
567 return true;
570 /* Return true when function NODE should be considered externally visible. */
572 static bool
573 cgraph_externally_visible_p (struct cgraph_node *node,
574 bool whole_program, bool aliased)
576 if (!node->local.finalized)
577 return false;
578 if (!DECL_COMDAT (node->symbol.decl)
579 && (!TREE_PUBLIC (node->symbol.decl)
580 || DECL_EXTERNAL (node->symbol.decl)))
581 return false;
583 /* Do not even try to be smart about aliased nodes. Until we properly
584 represent everything by same body alias, these are just evil. */
585 if (aliased)
586 return true;
588 /* Do not try to localize built-in functions yet. One of problems is that we
589 end up mangling their asm for WHOPR that makes it impossible to call them
590 using the implicit built-in declarations anymore. Similarly this enables
591 us to remove them as unreachable before actual calls may appear during
592 expansion or folding. */
593 if (DECL_BUILT_IN (node->symbol.decl))
594 return true;
596 /* If linker counts on us, we must preserve the function. */
597 if (symtab_used_from_object_file_p ((symtab_node) node))
598 return true;
599 if (DECL_PRESERVE_P (node->symbol.decl))
600 return true;
601 if (lookup_attribute ("externally_visible",
602 DECL_ATTRIBUTES (node->symbol.decl)))
603 return true;
604 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
605 && lookup_attribute ("dllexport",
606 DECL_ATTRIBUTES (node->symbol.decl)))
607 return true;
608 if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
609 return false;
610 /* When doing LTO or whole program, we can bring COMDAT functoins static.
611 This improves code quality and we know we will duplicate them at most twice
612 (in the case that we are not using plugin and link with object file
613 implementing same COMDAT) */
614 if ((in_lto_p || whole_program)
615 && DECL_COMDAT (node->symbol.decl)
616 && cgraph_comdat_can_be_unshared_p (node))
617 return false;
619 /* When doing link time optimizations, hidden symbols become local. */
620 if (in_lto_p
621 && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
622 || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
623 /* Be sure that node is defined in IR file, not in other object
624 file. In that case we don't set used_from_other_object_file. */
625 && node->analyzed)
627 else if (!whole_program)
628 return true;
630 if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
631 return true;
633 return false;
636 /* Return true when variable VNODE should be considered externally visible. */
638 bool
639 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
641 /* Do not touch weakrefs; while they are not externally visible,
642 dropping their DECL_EXTERNAL flags confuse most
643 of code handling them. */
644 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
645 return true;
647 if (DECL_EXTERNAL (vnode->symbol.decl))
648 return true;
650 if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
651 return false;
653 /* Do not even try to be smart about aliased nodes. Until we properly
654 represent everything by same body alias, these are just evil. */
655 if (aliased)
656 return true;
658 /* If linker counts on us, we must preserve the function. */
659 if (symtab_used_from_object_file_p ((symtab_node) vnode))
660 return true;
662 if (DECL_HARD_REGISTER (vnode->symbol.decl))
663 return true;
664 if (DECL_PRESERVE_P (vnode->symbol.decl))
665 return true;
666 if (lookup_attribute ("externally_visible",
667 DECL_ATTRIBUTES (vnode->symbol.decl)))
668 return true;
669 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
670 && lookup_attribute ("dllexport",
671 DECL_ATTRIBUTES (vnode->symbol.decl)))
672 return true;
674 /* See if we have linker information about symbol not being used or
675 if we need to make guess based on the declaration.
677 Even if the linker clams the symbol is unused, never bring internal
678 symbols that are declared by user as used or externally visible.
679 This is needed for i.e. references from asm statements. */
680 if (symtab_used_from_object_file_p ((symtab_node) vnode))
681 return true;
682 if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
683 return false;
685 /* As a special case, the COMDAT virtual tables can be unshared.
686 In LTO mode turn vtables into static variables. The variable is readonly,
687 so this does not enable more optimization, but referring static var
688 is faster for dynamic linking. Also this match logic hidding vtables
689 from LTO symbol tables. */
690 if ((in_lto_p || flag_whole_program)
691 && !vnode->symbol.force_output
692 && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
693 return false;
695 /* When doing link time optimizations, hidden symbols become local. */
696 if (in_lto_p
697 && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
698 || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
699 /* Be sure that node is defined in IR file, not in other object
700 file. In that case we don't set used_from_other_object_file. */
701 && vnode->finalized)
703 else if (!flag_whole_program)
704 return true;
706 /* Do not attempt to privatize COMDATS by default.
707 This would break linking with C++ libraries sharing
708 inline definitions.
710 FIXME: We can do so for readonly vars with no address taken and
711 possibly also for vtables since no direct pointer comparsion is done.
712 It might be interesting to do so to reduce linking overhead. */
713 if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
714 return true;
715 return false;
718 /* Mark visibility of all functions.
720 A local function is one whose calls can occur only in the current
721 compilation unit and all its calls are explicit, so we can change
722 its calling convention. We simply mark all static functions whose
723 address is not taken as local.
725 We also change the TREE_PUBLIC flag of all declarations that are public
726 in language point of view but we want to overwrite this default
727 via visibilities for the backend point of view. */
729 static unsigned int
730 function_and_variable_visibility (bool whole_program)
732 struct cgraph_node *node;
733 struct varpool_node *vnode;
734 struct pointer_set_t *aliased_nodes = pointer_set_create ();
735 struct pointer_set_t *aliased_vnodes = pointer_set_create ();
736 unsigned i;
737 alias_pair *p;
739 /* Discover aliased nodes. */
740 FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
742 if (dump_file)
743 fprintf (dump_file, "Alias %s->%s",
744 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
745 IDENTIFIER_POINTER (p->target));
747 if ((node = cgraph_node_for_asm (p->target)) != NULL
748 && !DECL_EXTERNAL (node->symbol.decl))
750 if (!node->analyzed)
751 continue;
752 cgraph_mark_force_output_node (node);
753 pointer_set_insert (aliased_nodes, node);
754 if (dump_file)
755 fprintf (dump_file, " node %s/%i",
756 cgraph_node_name (node), node->uid);
758 else if ((vnode = varpool_node_for_asm (p->target)) != NULL
759 && !DECL_EXTERNAL (vnode->symbol.decl))
761 vnode->symbol.force_output = 1;
762 pointer_set_insert (aliased_vnodes, vnode);
763 if (dump_file)
764 fprintf (dump_file, " varpool node %s",
765 varpool_node_name (vnode));
767 if (dump_file)
768 fprintf (dump_file, "\n");
771 FOR_EACH_FUNCTION (node)
773 int flags = flags_from_decl_or_type (node->symbol.decl);
775 /* Optimize away PURE and CONST constructors and destructors. */
776 if (optimize
777 && (flags & (ECF_CONST | ECF_PURE))
778 && !(flags & ECF_LOOPING_CONST_OR_PURE))
780 DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
781 DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
784 /* Frontends and alias code marks nodes as needed before parsing is finished.
785 We may end up marking as node external nodes where this flag is meaningless
786 strip it. */
787 if (node->symbol.force_output
788 && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
789 node->symbol.force_output = 0;
791 /* C++ FE on lack of COMDAT support create local COMDAT functions
792 (that ought to be shared but can not due to object format
793 limitations). It is necessary to keep the flag to make rest of C++ FE
794 happy. Clear the flag here to avoid confusion in middle-end. */
795 if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
796 DECL_COMDAT (node->symbol.decl) = 0;
797 /* For external decls stop tracking same_comdat_group, it doesn't matter
798 what comdat group they are in when they won't be emitted in this TU,
799 and simplifies later passes. */
800 if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
802 #ifdef ENABLE_CHECKING
803 symtab_node n;
805 for (n = node->symbol.same_comdat_group;
806 n != (symtab_node)node;
807 n = n->symbol.same_comdat_group)
808 /* If at least one of same comdat group functions is external,
809 all of them have to be, otherwise it is a front-end bug. */
810 gcc_assert (DECL_EXTERNAL (n->symbol.decl));
811 #endif
812 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
814 gcc_assert ((!DECL_WEAK (node->symbol.decl)
815 && !DECL_COMDAT (node->symbol.decl))
816 || TREE_PUBLIC (node->symbol.decl)
817 || DECL_EXTERNAL (node->symbol.decl));
818 if (cgraph_externally_visible_p (node, whole_program,
819 pointer_set_contains (aliased_nodes,
820 node)))
822 gcc_assert (!node->global.inlined_to);
823 node->symbol.externally_visible = true;
825 else
826 node->symbol.externally_visible = false;
827 if (!node->symbol.externally_visible && node->analyzed
828 && !DECL_EXTERNAL (node->symbol.decl))
830 gcc_assert (whole_program || in_lto_p
831 || !TREE_PUBLIC (node->symbol.decl));
832 symtab_make_decl_local (node->symbol.decl);
833 node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
834 if (node->symbol.same_comdat_group)
835 /* cgraph_externally_visible_p has already checked all other nodes
836 in the group and they will all be made local. We need to
837 dissolve the group at once so that the predicate does not
838 segfault though. */
839 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
842 if (node->thunk.thunk_p
843 && TREE_PUBLIC (node->symbol.decl))
845 struct cgraph_node *decl_node = node;
847 decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
849 /* Thunks have the same visibility as function they are attached to.
850 Make sure the C++ front end set this up properly. */
851 if (DECL_ONE_ONLY (decl_node->symbol.decl))
853 gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
854 == DECL_COMDAT (decl_node->symbol.decl));
855 gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
856 == DECL_COMDAT_GROUP (decl_node->symbol.decl));
857 gcc_checking_assert (node->symbol.same_comdat_group);
859 if (DECL_EXTERNAL (decl_node->symbol.decl))
860 DECL_EXTERNAL (node->symbol.decl) = 1;
863 FOR_EACH_DEFINED_FUNCTION (node)
864 node->local.local = cgraph_local_node_p (node);
865 FOR_EACH_VARIABLE (vnode)
867 /* weak flag makes no sense on local variables. */
868 gcc_assert (!DECL_WEAK (vnode->symbol.decl)
869 || TREE_PUBLIC (vnode->symbol.decl)
870 || DECL_EXTERNAL (vnode->symbol.decl));
871 /* In several cases declarations can not be common:
873 - when declaration has initializer
874 - when it is in weak
875 - when it has specific section
876 - when it resides in non-generic address space.
877 - if declaration is local, it will get into .local common section
878 so common flag is not needed. Frontends still produce these in
879 certain cases, such as for:
881 static int a __attribute__ ((common))
883 Canonicalize things here and clear the redundant flag. */
884 if (DECL_COMMON (vnode->symbol.decl)
885 && (!(TREE_PUBLIC (vnode->symbol.decl)
886 || DECL_EXTERNAL (vnode->symbol.decl))
887 || (DECL_INITIAL (vnode->symbol.decl)
888 && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
889 || DECL_WEAK (vnode->symbol.decl)
890 || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
891 || ! (ADDR_SPACE_GENERIC_P
892 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
893 DECL_COMMON (vnode->symbol.decl) = 0;
895 FOR_EACH_DEFINED_VARIABLE (vnode)
897 if (!vnode->finalized)
898 continue;
899 if (varpool_externally_visible_p
900 (vnode,
901 pointer_set_contains (aliased_vnodes, vnode)))
902 vnode->symbol.externally_visible = true;
903 else
904 vnode->symbol.externally_visible = false;
905 if (!vnode->symbol.externally_visible)
907 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
908 symtab_make_decl_local (vnode->symbol.decl);
909 if (vnode->symbol.same_comdat_group)
910 symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
911 vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
914 pointer_set_destroy (aliased_nodes);
915 pointer_set_destroy (aliased_vnodes);
917 if (dump_file)
919 fprintf (dump_file, "\nMarking local functions:");
920 FOR_EACH_DEFINED_FUNCTION (node)
921 if (node->local.local)
922 fprintf (dump_file, " %s", cgraph_node_name (node));
923 fprintf (dump_file, "\n\n");
924 fprintf (dump_file, "\nMarking externally visible functions:");
925 FOR_EACH_DEFINED_FUNCTION (node)
926 if (node->symbol.externally_visible)
927 fprintf (dump_file, " %s", cgraph_node_name (node));
928 fprintf (dump_file, "\n\n");
929 fprintf (dump_file, "\nMarking externally visible variables:");
930 FOR_EACH_DEFINED_VARIABLE (vnode)
931 if (vnode->symbol.externally_visible)
932 fprintf (dump_file, " %s", varpool_node_name (vnode));
933 fprintf (dump_file, "\n\n");
935 cgraph_function_flags_ready = true;
936 return 0;
939 /* Local function pass handling visibilities. This happens before LTO streaming
940 so in particular -fwhole-program should be ignored at this level. */
942 static unsigned int
943 local_function_and_variable_visibility (void)
945 return function_and_variable_visibility (flag_whole_program && !flag_lto);
948 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
951 SIMPLE_IPA_PASS,
952 "visibility", /* name */
953 NULL, /* gate */
954 local_function_and_variable_visibility,/* execute */
955 NULL, /* sub */
956 NULL, /* next */
957 0, /* static_pass_number */
958 TV_CGRAPHOPT, /* tv_id */
959 0, /* properties_required */
960 0, /* properties_provided */
961 0, /* properties_destroyed */
962 0, /* todo_flags_start */
963 TODO_remove_functions | TODO_dump_symtab
964 | TODO_ggc_collect /* todo_flags_finish */
968 /* Free inline summary. */
970 static unsigned
971 free_inline_summary (void)
973 inline_free_summary ();
974 return 0;
977 struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
980 SIMPLE_IPA_PASS,
981 "*free_inline_summary", /* name */
982 NULL, /* gate */
983 free_inline_summary, /* execute */
984 NULL, /* sub */
985 NULL, /* next */
986 0, /* static_pass_number */
987 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
988 0, /* properties_required */
989 0, /* properties_provided */
990 0, /* properties_destroyed */
991 0, /* todo_flags_start */
992 TODO_ggc_collect /* todo_flags_finish */
996 /* Do not re-run on ltrans stage. */
998 static bool
999 gate_whole_program_function_and_variable_visibility (void)
1001 return !flag_ltrans;
1004 /* Bring functionss local at LTO time with -fwhole-program. */
1006 static unsigned int
1007 whole_program_function_and_variable_visibility (void)
1009 function_and_variable_visibility (flag_whole_program);
1010 if (optimize)
1011 ipa_discover_readonly_nonaddressable_vars ();
1012 return 0;
1015 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1018 IPA_PASS,
1019 "whole-program", /* name */
1020 gate_whole_program_function_and_variable_visibility,/* gate */
1021 whole_program_function_and_variable_visibility,/* execute */
1022 NULL, /* sub */
1023 NULL, /* next */
1024 0, /* static_pass_number */
1025 TV_CGRAPHOPT, /* tv_id */
1026 0, /* properties_required */
1027 0, /* properties_provided */
1028 0, /* properties_destroyed */
1029 0, /* todo_flags_start */
1030 TODO_remove_functions | TODO_dump_symtab
1031 | TODO_ggc_collect /* todo_flags_finish */
1033 NULL, /* generate_summary */
1034 NULL, /* write_summary */
1035 NULL, /* read_summary */
1036 NULL, /* write_optimization_summary */
1037 NULL, /* read_optimization_summary */
1038 NULL, /* stmt_fixup */
1039 0, /* TODOs */
1040 NULL, /* function_transform */
1041 NULL, /* variable_transform */
1045 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1047 static unsigned int
1048 ipa_profile (void)
1050 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1051 struct cgraph_edge *e;
1052 int order_pos;
1053 bool something_changed = false;
1054 int i;
1056 order_pos = ipa_reverse_postorder (order);
1057 for (i = order_pos - 1; i >= 0; i--)
1059 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1061 for (e = order[i]->callees; e; e = e->next_callee)
1062 if (e->callee->local.local && !e->callee->symbol.aux)
1064 something_changed = true;
1065 e->callee->symbol.aux = (void *)1;
1068 order[i]->symbol.aux = NULL;
1071 while (something_changed)
1073 something_changed = false;
1074 for (i = order_pos - 1; i >= 0; i--)
1076 if (order[i]->symbol.aux && cgraph_propagate_frequency (order[i]))
1078 for (e = order[i]->callees; e; e = e->next_callee)
1079 if (e->callee->local.local && !e->callee->symbol.aux)
1081 something_changed = true;
1082 e->callee->symbol.aux = (void *)1;
1085 order[i]->symbol.aux = NULL;
1088 free (order);
1089 return 0;
1092 static bool
1093 gate_ipa_profile (void)
1095 return flag_ipa_profile;
1098 struct ipa_opt_pass_d pass_ipa_profile =
1101 IPA_PASS,
1102 "profile_estimate", /* name */
1103 gate_ipa_profile, /* gate */
1104 ipa_profile, /* execute */
1105 NULL, /* sub */
1106 NULL, /* next */
1107 0, /* static_pass_number */
1108 TV_IPA_PROFILE, /* tv_id */
1109 0, /* properties_required */
1110 0, /* properties_provided */
1111 0, /* properties_destroyed */
1112 0, /* todo_flags_start */
1113 0 /* todo_flags_finish */
1115 NULL, /* generate_summary */
1116 NULL, /* write_summary */
1117 NULL, /* read_summary */
1118 NULL, /* write_optimization_summary */
1119 NULL, /* read_optimization_summary */
1120 NULL, /* stmt_fixup */
1121 0, /* TODOs */
1122 NULL, /* function_transform */
1123 NULL /* variable_transform */
1126 /* Generate and emit a static constructor or destructor. WHICH must
1127 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1128 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1129 initialization priority for this constructor or destructor.
1131 FINAL specify whether the externally visible name for collect2 should
1132 be produced. */
1134 static void
1135 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1137 static int counter = 0;
1138 char which_buf[16];
1139 tree decl, name, resdecl;
1141 /* The priority is encoded in the constructor or destructor name.
1142 collect2 will sort the names and arrange that they are called at
1143 program startup. */
1144 if (final)
1145 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1146 else
1147 /* Proudce sane name but one not recognizable by collect2, just for the
1148 case we fail to inline the function. */
1149 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1150 name = get_file_function_name (which_buf);
1152 decl = build_decl (input_location, FUNCTION_DECL, name,
1153 build_function_type_list (void_type_node, NULL_TREE));
1154 current_function_decl = decl;
1156 resdecl = build_decl (input_location,
1157 RESULT_DECL, NULL_TREE, void_type_node);
1158 DECL_ARTIFICIAL (resdecl) = 1;
1159 DECL_RESULT (decl) = resdecl;
1160 DECL_CONTEXT (resdecl) = decl;
1162 allocate_struct_function (decl, false);
1164 TREE_STATIC (decl) = 1;
1165 TREE_USED (decl) = 1;
1166 DECL_ARTIFICIAL (decl) = 1;
1167 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1168 DECL_SAVED_TREE (decl) = body;
1169 if (!targetm.have_ctors_dtors && final)
1171 TREE_PUBLIC (decl) = 1;
1172 DECL_PRESERVE_P (decl) = 1;
1174 DECL_UNINLINABLE (decl) = 1;
1176 DECL_INITIAL (decl) = make_node (BLOCK);
1177 TREE_USED (DECL_INITIAL (decl)) = 1;
1179 DECL_SOURCE_LOCATION (decl) = input_location;
1180 cfun->function_end_locus = input_location;
1182 switch (which)
1184 case 'I':
1185 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1186 decl_init_priority_insert (decl, priority);
1187 break;
1188 case 'D':
1189 DECL_STATIC_DESTRUCTOR (decl) = 1;
1190 decl_fini_priority_insert (decl, priority);
1191 break;
1192 default:
1193 gcc_unreachable ();
1196 gimplify_function_tree (decl);
1198 cgraph_add_new_function (decl, false);
1200 set_cfun (NULL);
1201 current_function_decl = NULL;
1204 /* Generate and emit a static constructor or destructor. WHICH must
1205 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1206 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1207 initialization priority for this constructor or destructor. */
1209 void
1210 cgraph_build_static_cdtor (char which, tree body, int priority)
1212 cgraph_build_static_cdtor_1 (which, body, priority, false);
1215 /* A vector of FUNCTION_DECLs declared as static constructors. */
1216 static VEC(tree, heap) *static_ctors;
1217 /* A vector of FUNCTION_DECLs declared as static destructors. */
1218 static VEC(tree, heap) *static_dtors;
1220 /* When target does not have ctors and dtors, we call all constructor
1221 and destructor by special initialization/destruction function
1222 recognized by collect2.
1224 When we are going to build this function, collect all constructors and
1225 destructors and turn them into normal functions. */
1227 static void
1228 record_cdtor_fn (struct cgraph_node *node)
1230 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
1231 VEC_safe_push (tree, heap, static_ctors, node->symbol.decl);
1232 if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1233 VEC_safe_push (tree, heap, static_dtors, node->symbol.decl);
1234 node = cgraph_get_node (node->symbol.decl);
1235 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1238 /* Define global constructors/destructor functions for the CDTORS, of
1239 which they are LEN. The CDTORS are sorted by initialization
1240 priority. If CTOR_P is true, these are constructors; otherwise,
1241 they are destructors. */
1243 static void
1244 build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1246 size_t i,j;
1247 size_t len = VEC_length (tree, cdtors);
1249 i = 0;
1250 while (i < len)
1252 tree body;
1253 tree fn;
1254 priority_type priority;
1256 priority = 0;
1257 body = NULL_TREE;
1258 j = i;
1261 priority_type p;
1262 fn = VEC_index (tree, cdtors, j);
1263 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1264 if (j == i)
1265 priority = p;
1266 else if (p != priority)
1267 break;
1268 j++;
1270 while (j < len);
1272 /* When there is only one cdtor and target supports them, do nothing. */
1273 if (j == i + 1
1274 && targetm.have_ctors_dtors)
1276 i++;
1277 continue;
1279 /* Find the next batch of constructors/destructors with the same
1280 initialization priority. */
1281 for (;i < j; i++)
1283 tree call;
1284 fn = VEC_index (tree, cdtors, i);
1285 call = build_call_expr (fn, 0);
1286 if (ctor_p)
1287 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1288 else
1289 DECL_STATIC_DESTRUCTOR (fn) = 0;
1290 /* We do not want to optimize away pure/const calls here.
1291 When optimizing, these should be already removed, when not
1292 optimizing, we want user to be able to breakpoint in them. */
1293 TREE_SIDE_EFFECTS (call) = 1;
1294 append_to_statement_list (call, &body);
1296 gcc_assert (body != NULL_TREE);
1297 /* Generate a function to call all the function of like
1298 priority. */
1299 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1303 /* Comparison function for qsort. P1 and P2 are actually of type
1304 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1305 used to determine the sort order. */
1307 static int
1308 compare_ctor (const void *p1, const void *p2)
1310 tree f1;
1311 tree f2;
1312 int priority1;
1313 int priority2;
1315 f1 = *(const tree *)p1;
1316 f2 = *(const tree *)p2;
1317 priority1 = DECL_INIT_PRIORITY (f1);
1318 priority2 = DECL_INIT_PRIORITY (f2);
1320 if (priority1 < priority2)
1321 return -1;
1322 else if (priority1 > priority2)
1323 return 1;
1324 else
1325 /* Ensure a stable sort. Constructors are executed in backwarding
1326 order to make LTO initialize braries first. */
1327 return DECL_UID (f2) - DECL_UID (f1);
1330 /* Comparison function for qsort. P1 and P2 are actually of type
1331 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1332 used to determine the sort order. */
1334 static int
1335 compare_dtor (const void *p1, const void *p2)
1337 tree f1;
1338 tree f2;
1339 int priority1;
1340 int priority2;
1342 f1 = *(const tree *)p1;
1343 f2 = *(const tree *)p2;
1344 priority1 = DECL_FINI_PRIORITY (f1);
1345 priority2 = DECL_FINI_PRIORITY (f2);
1347 if (priority1 < priority2)
1348 return -1;
1349 else if (priority1 > priority2)
1350 return 1;
1351 else
1352 /* Ensure a stable sort. */
1353 return DECL_UID (f1) - DECL_UID (f2);
1356 /* Generate functions to call static constructors and destructors
1357 for targets that do not support .ctors/.dtors sections. These
1358 functions have magic names which are detected by collect2. */
1360 static void
1361 build_cdtor_fns (void)
1363 if (!VEC_empty (tree, static_ctors))
1365 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1366 VEC_qsort (tree, static_ctors, compare_ctor);
1367 build_cdtor (/*ctor_p=*/true, static_ctors);
1370 if (!VEC_empty (tree, static_dtors))
1372 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1373 VEC_qsort (tree, static_dtors, compare_dtor);
1374 build_cdtor (/*ctor_p=*/false, static_dtors);
1378 /* Look for constructors and destructors and produce function calling them.
1379 This is needed for targets not supporting ctors or dtors, but we perform the
1380 transformation also at linktime to merge possibly numerous
1381 constructors/destructors into single function to improve code locality and
1382 reduce size. */
1384 static unsigned int
1385 ipa_cdtor_merge (void)
1387 struct cgraph_node *node;
1388 FOR_EACH_DEFINED_FUNCTION (node)
1389 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
1390 || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1391 record_cdtor_fn (node);
1392 build_cdtor_fns ();
1393 VEC_free (tree, heap, static_ctors);
1394 VEC_free (tree, heap, static_dtors);
1395 return 0;
1398 /* Perform the pass when we have no ctors/dtors support
1399 or at LTO time to merge multiple constructors into single
1400 function. */
1402 static bool
1403 gate_ipa_cdtor_merge (void)
1405 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1408 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1411 IPA_PASS,
1412 "cdtor", /* name */
1413 gate_ipa_cdtor_merge, /* gate */
1414 ipa_cdtor_merge, /* execute */
1415 NULL, /* sub */
1416 NULL, /* next */
1417 0, /* static_pass_number */
1418 TV_CGRAPHOPT, /* tv_id */
1419 0, /* properties_required */
1420 0, /* properties_provided */
1421 0, /* properties_destroyed */
1422 0, /* todo_flags_start */
1423 0 /* todo_flags_finish */
1425 NULL, /* generate_summary */
1426 NULL, /* write_summary */
1427 NULL, /* read_summary */
1428 NULL, /* write_optimization_summary */
1429 NULL, /* read_optimization_summary */
1430 NULL, /* stmt_fixup */
1431 0, /* TODOs */
1432 NULL, /* function_transform */
1433 NULL /* variable_transform */