ipa.c 45.2 KB
Newer Older
1
/* Basic IPA optimizations and utilities.
2
   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
3
   Free Software Foundation, Inc.
4 5 6 7 8

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
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 11 12 13 14 15 16 17
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
18 19
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
20 21 22 23 24 25

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#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 32
#include "target.h"
#include "tree-iterator.h"
33
#include "ipa-utils.h"
34
#include "pointer-set.h"
35
#include "ipa-inline.h"
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
/* Look for all functions inlined to NODE and update their inlined_to pointers
   to INLINED_TO.  */

static void
update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
{
  struct cgraph_edge *e;
  for (e = node->callees; e; e = e->next_callee)
    if (e->callee->global.inlined_to)
      {
        e->callee->global.inlined_to = inlined_to;
	update_inlined_to_pointer (e->callee, inlined_to);
      }
}

52
/* Add symtab NODE to queue starting at FIRST.
53 54 55 56 57 58

   The queue is linked via AUX pointers and terminated by pointer to 1.
   We enqueue nodes at two occasions: when we find them reachable or when we find
   their bodies needed for further clonning.  In the second case we mark them
   by pointer to 2 after processing so they are re-queue when they become
   reachable.  */
59 60

static void
61 62
enqueue_node (symtab_node node, symtab_node *first,
	      struct pointer_set_t *reachable)
63
{
64
  /* Node is still in queue; do nothing.  */
65
  if (node->symbol.aux && node->symbol.aux != (void *) 2)
66 67 68
    return;
  /* Node was already processed as unreachable, re-enqueue
     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 73 74 75 76 77 78
  *first = node;
}

/* Process references.  */

static void
process_references (struct ipa_ref_list *list,
79
		    symtab_node *first,
80 81
		    bool before_inlining_p,
		    struct pointer_set_t *reachable)
82 83 84 85 86
{
  int i;
  struct ipa_ref *ref;
  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
    {
87
      if (symtab_function_p (ref->referred))
88 89
	{
	  struct cgraph_node *node = ipa_ref_node (ref);
90

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);
97 98 99 100
	}
      else
	{
	  struct varpool_node *node = ipa_ref_varpool_node (ref);
101

102 103 104 105
	  if (node->analyzed
	      && (!DECL_EXTERNAL (node->symbol.decl)
		  || node->alias
		  || before_inlining_p))
106 107
	    pointer_set_insert (reachable, node);
	  enqueue_node ((symtab_node) node, first, reachable);
108 109 110 111
	}
    }
}

112 113 114 115 116 117

/* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */

static bool
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 123 124 125
	    && !DECL_EXTERNAL (node->symbol.decl)
	    && !node->symbol.externally_visible
	    && !node->symbol.used_from_other_partition
	    && !node->symbol.in_other_partition);
126 127
}

128 129 130 131 132
/* Return true when function can be marked local.  */

static bool
cgraph_local_node_p (struct cgraph_node *node)
{
133 134 135 136 137 138 139
   struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);

   /* FIXME: thunks can be considered local, but we need prevent i386
      from attempting to change calling convention of them.  */
   if (n->thunk.thunk_p)
     return false;
   return !cgraph_for_node_and_aliases (n,
140 141 142 143 144 145 146 147 148 149 150 151 152
					cgraph_non_local_node_p_1, NULL, true);
					
}

/* Return true when NODE has ADDR reference.  */

static bool
has_addr_references_p (struct cgraph_node *node,
		       void *data ATTRIBUTE_UNUSED)
{
  int i;
  struct ipa_ref *ref;

153
  for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
154
					     i, ref); i++)
155 156 157
    if (ref->use == IPA_REF_ADDR)
      return true;
  return false;
158 159
}

160
/* Perform reachability analysis and reclaim all unreachable nodes.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

   The algorithm is basically mark&sweep but with some extra refinements:

   - reachable extern inline functions needs special handling; the bodies needs
     to stay in memory until inlining in hope that they will be inlined.
     After inlining we release their bodies and turn them into unanalyzed
     nodes even when they are reachable.

     BEFORE_INLINING_P specify whether we are before or after inlining.

   - virtual functions are kept in callgraph even if they seem unreachable in
     hope calls to them will be devirtualized. 

     Again we remove them after inlining.  In late optimization some
     devirtualization may happen, but it is not importnat since we won't inline
     the call. In theory early opts and IPA should work out all important cases.

   - virtual clones needs bodies of their origins for later materialization;
     this means that we want to keep the body even if the origin is unreachable
     otherwise.  To avoid origin from sitting in the callgraph and being
     walked by IPA passes, we turn them into unanalyzed nodes with body
     defined.

     We maintain set of function declaration where body needs to stay in
     body_needed_for_clonning

     Inline clones represent special case: their declaration match the
     declaration of origin and cgraph_remove_node already knows how to
     reshape callgraph and preserve body when offline copy of function or
     inline clone is being removed.

192 193 194 195 196 197
   - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
     variables with DECL_INITIAL set.  We finalize these and keep reachable
     ones around for constant folding purposes.  After inlining we however
     stop walking their references to let everything static referneced by them
     to be removed when it is otherwise unreachable.

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
   We maintain queue of both reachable symbols (i.e. defined symbols that needs
   to stay) and symbols that are in boundary (i.e. external symbols referenced
   by reachable symbols or origins of clones).  The queue is represented
   as linked list by AUX pointer terminated by 1.

   A the end we keep all reachable symbols. For symbols in boundary we always
   turn definition into a declaration, but we may keep function body around
   based on body_needed_for_clonning

   All symbols that enter the queue have AUX pointer non-zero and are in the
   boundary.  Pointer set REACHABLE is used to track reachable symbols.

   Every symbol can be visited twice - once as part of boundary and once
   as real reachable symbol. enqueue_node needs to decide whether the
   node needs to be re-queued for second processing.  For this purpose
   we set AUX pointer of processed symbols in the boundary to constant 2.  */
214 215

bool
216
symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
217
{
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 ();
224 225

#ifdef ENABLE_CHECKING
226
  verify_symtab ();
227
#endif
228 229
  if (file)
    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 237 238 239
  /* Mark functions whose bodies are obviously needed.
     This is mostly when they can be referenced externally.  Inline clones
     are special since their declarations are shared with master clone and thus
     cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them.  */
240 241
  FOR_EACH_DEFINED_FUNCTION (node)
    if (!node->global.inlined_to
242 243 244
	&& (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
	    /* Keep around virtual functions for possible devirtualization.  */
	    || (before_inlining_p
245 246
		&& DECL_VIRTUAL_P (node->symbol.decl)
		&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
247
      {
248
        gcc_assert (!node->global.inlined_to);
249
	pointer_set_insert (reachable, node);
250
	enqueue_node ((symtab_node)node, &first, reachable);
251 252
      }
    else
253
      gcc_assert (!node->symbol.aux);
254 255

  /* Mark variables that are obviously needed.  */
256 257 258 259 260 261 262 263 264
  FOR_EACH_DEFINED_VARIABLE (vnode)
    if (!varpool_can_remove_if_no_refs (vnode))
      {
	pointer_set_insert (reachable, vnode);
	enqueue_node ((symtab_node)vnode, &first, reachable);
      }

  /* Perform reachability analysis.  */
  while (first != (symtab_node) (void *) 1)
265
    {
266 267
      bool in_boundary_p = !pointer_set_contains (reachable, first);
      symtab_node node = first;
268

269
      first = (symtab_node)first->symbol.aux;
270

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
      /* If we are processing symbol in boundary, mark its AUX pointer for
	 possible later re-processing in enqueue_node.  */
      if (in_boundary_p)
	node->symbol.aux = (void *)2;
      else
	{
	  /* If any symbol in a comdat group is reachable, force
	     all other in the same comdat group to be also reachable.  */
	  if (node->symbol.same_comdat_group)
	    {
	      symtab_node next;
	      for (next = node->symbol.same_comdat_group;
		   next != node;
		   next = next->symbol.same_comdat_group)
		if (!pointer_set_insert (reachable, next))
		  enqueue_node ((symtab_node) next, &first, reachable);
	    }
	  /* Mark references as reachable.  */
	  process_references (&node->symbol.ref_list, &first,
			      before_inlining_p, reachable);
	}
292

293
      if (symtab_function_p (node))
294
	{
295 296 297 298 299
	  struct cgraph_node *cnode = cgraph (node);

	  /* Mark the callees reachable unless they are direct calls to extern
 	     inline functions we decided to not inline.  */
	  if (!in_boundary_p)
300
	    {
301 302
	      struct cgraph_edge *e;
	      for (e = cnode->callees; e; e = e->next_callee)
303
		{
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);
311
		}
312 313 314 315 316

	      /* When inline clone exists, mark body to be preserved so when removing
		 offline copy of the function we don't kill it.  */
	      if (!cnode->alias && cnode->global.inlined_to)
	        pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
317
	    }
318

319 320
	  /* For non-inline clones, force their origins to the boundary and ensure
	     that body is not removed.  */
321
	  while (cnode->clone_of
322
	         && !gimple_has_body_p (cnode->symbol.decl))
323
	    {
324 325
	      bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
	      cnode = cnode->clone_of;
326
	      if (noninline)
327
	      	{
328 329
	          pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
		  enqueue_node ((symtab_node)cnode, &first, reachable);
330 331
		  break;
		}
332
	    }
333
	}
334 335 336 337 338 339 340 341 342 343 344 345 346
      /* When we see constructor of external variable, keep referred nodes in the
	 boundary.  This will also hold initializers of the external vars NODE
	 reffers to.  */
      if (symtab_variable_p (node)
	  && DECL_EXTERNAL (node->symbol.decl)
	  && !varpool (node)->alias
	  && in_boundary_p)
        {
	  int i;
	  struct ipa_ref *ref;
	  for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
	    enqueue_node (ref->referred, &first, reachable);
        }
347 348
    }

349
  /* Remove unreachable functions.   */
350
  for (node = cgraph_first_function (); node; node = next)
351
    {
352
      next = cgraph_next_function (node);
353
      if (!node->symbol.aux)
354
	{
355 356
	  if (file)
	    fprintf (file, " %s", cgraph_node_name (node));
357 358 359 360 361 362
	  cgraph_remove_node (node);
	  changed = true;
	}
      else if (!pointer_set_contains (reachable, node))
        {
	  if (node->analyzed)
363
	    {
364 365 366 367
	      if (file)
		fprintf (file, " %s", cgraph_node_name (node));
	      cgraph_node_remove_callees (node);
	      ipa_remove_all_references (&node->symbol.ref_list);
368 369
	      changed = true;
	    }
370
	  if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
371
	      && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
372 373
	    cgraph_release_function_body (node);
	  node->analyzed = false;
374 375
	}
    }
376 377 378 379

  /* Inline clones might be kept around so their materializing allows further
     cloning.  If the function the clone is inlined into is removed, we need
     to turn it into normal cone.  */
380
  FOR_EACH_FUNCTION (node)
381 382 383 384 385
    {
      if (node->global.inlined_to
	  && !node->callers)
	{
	  gcc_assert (node->clones);
386 387
	  node->global.inlined_to = NULL;
	  update_inlined_to_pointer (node, node);
388
	}
389
      node->symbol.aux = NULL;
390
    }
391

392
  /* Remove unreachable variables.  */
393
  if (file)
394
    fprintf (file, "\nReclaiming variables:");
395
  for (vnode = varpool_first_variable (); vnode; vnode = vnext)
396
    {
397
      vnext = varpool_next_variable (vnode);
398 399
      if (!vnode->symbol.aux)
	{
400 401 402 403
	  if (file)
	    fprintf (file, " %s", varpool_node_name (vnode));
	  varpool_remove_node (vnode);
	  changed = true;
404
	}
405 406 407 408 409 410 411 412 413 414 415 416 417
      else if (!pointer_set_contains (reachable, vnode))
        {
	  if (vnode->analyzed)
	    {
	      if (file)
		fprintf (file, " %s", varpool_node_name (vnode));
	      changed = true;
	    }
	  vnode->analyzed = false;
	  vnode->symbol.aux = NULL;
	}
      else
	vnode->symbol.aux = NULL;
418
    }
419

420 421
  pointer_set_destroy (reachable);
  pointer_set_destroy (body_needed_for_clonning);
422

423
  /* Now update address_taken flags and try to promote functions to be local.  */
424 425
  if (file)
    fprintf (file, "\nClearing address taken flags:");
426
  FOR_EACH_DEFINED_FUNCTION (node)
427 428
    if (node->symbol.address_taken
	&& !node->symbol.used_from_other_partition)
429
      {
430
	if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
431 432 433
	  {
	    if (file)
	      fprintf (file, " %s", cgraph_node_name (node));
434
	    node->symbol.address_taken = false;
435 436 437 438 439 440 441
	    changed = true;
	    if (cgraph_local_node_p (node))
	      {
		node->local.local = true;
		if (file)
		  fprintf (file, " (local)");
	      }
442 443
	  }
      }
444 445
  if (file)
    fprintf (file, "\n");
446

447
#ifdef ENABLE_CHECKING
448
  verify_symtab ();
449
#endif
Diego Novillo committed
450

451 452 453 454 455
  /* If we removed something, perhaps profile could be improved.  */
  if (changed && optimize && inline_edge_summary_vec)
    FOR_EACH_DEFINED_FUNCTION (node)
      cgraph_propagate_frequency (node);

456 457
  return changed;
}
458

459 460 461 462 463
/* Discover variables that have no longer address taken or that are read only
   and update their flags.

   FIXME: This can not be done in between gimplify and omp_expand since
   readonly flag plays role on what is shared and what is not.  Currently we do
464 465 466
   this transformation as part of whole program visibility and re-do at
   ipa-reference pass (to take into account clonning), but it would
   make sense to do it before early optimizations.  */
467 468 469 470 471 472 473

void
ipa_discover_readonly_nonaddressable_vars (void)
{
  struct varpool_node *vnode;
  if (dump_file)
    fprintf (dump_file, "Clearing variable flags:");
474
  FOR_EACH_VARIABLE (vnode)
475
    if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
476 477
	&& (TREE_ADDRESSABLE (vnode->symbol.decl)
	    || !TREE_READONLY (vnode->symbol.decl)))
478 479 480 481 482
      {
	bool written = false;
	bool address_taken = false;
	int i;
        struct ipa_ref *ref;
483
        for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
484
						   i, ref)
485 486 487 488 489 490 491 492 493 494 495 496
		    && (!written || !address_taken); i++)
	  switch (ref->use)
	    {
	    case IPA_REF_ADDR:
	      address_taken = true;
	      break;
	    case IPA_REF_LOAD:
	      break;
	    case IPA_REF_STORE:
	      written = true;
	      break;
	    }
497
	if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
498 499 500
	  {
	    if (dump_file)
	      fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
501
	    TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
502
	  }
503
	if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
504 505 506
	    /* Making variable in explicit section readonly can cause section
	       type conflict. 
	       See e.g. gcc.c-torture/compile/pr23237.c */
507
	    && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
508 509 510
	  {
	    if (dump_file)
	      fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
511
	    TREE_READONLY (vnode->symbol.decl) = 1;
512 513 514 515 516 517
	  }
      }
  if (dump_file)
    fprintf (dump_file, "\n");
}

518 519 520 521 522 523
/* Return true when there is a reference to node and it is not vtable.  */
static bool
cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
{
  int i;
  struct ipa_ref *ref;
524
  for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
525
					     i, ref); i++)
526 527 528
    if (ref->use == IPA_REF_ADDR)
      {
	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 534
	  return true;
      }
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
  return false;
}

/* COMDAT functions must be shared only if they have address taken,
   otherwise we can produce our own private implementation with
   -fwhole-program.  
   Return true when turning COMDAT functoin static can not lead to wrong
   code when the resulting object links with a library defining same COMDAT.

   Virtual functions do have their addresses taken from the vtables,
   but in C++ there is no way to compare their addresses for equality.  */

bool
cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
{
  if ((cgraph_address_taken_from_non_vtable_p (node)
551
       && !DECL_VIRTUAL_P (node->symbol.decl))
552 553
      || !node->analyzed)
    return false;
554
  if (node->symbol.same_comdat_group)
555 556 557 558 559 560
    {
      struct cgraph_node *next;

      /* If more than one function is in the same COMDAT group, it must
         be shared even if just one function in the comdat group has
         address taken.  */
561 562
      for (next = cgraph (node->symbol.same_comdat_group);
	   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 566 567 568 569
	  return false;
    }
  return true;
}

570 571
/* Return true when function NODE should be considered externally visible.  */

572
static bool
573 574
cgraph_externally_visible_p (struct cgraph_node *node,
			     bool whole_program, bool aliased)
575
{
576 577
  if (!node->local.finalized)
    return false;
578 579 580
  if (!DECL_COMDAT (node->symbol.decl)
      && (!TREE_PUBLIC (node->symbol.decl)
	  || DECL_EXTERNAL (node->symbol.decl)))
581
    return false;
582 583 584 585

  /* Do not even try to be smart about aliased nodes.  Until we properly
     represent everything by same body alias, these are just evil.  */
  if (aliased)
586
    return true;
587

588 589 590 591 592
  /* Do not try to localize built-in functions yet.  One of problems is that we
     end up mangling their asm for WHOPR that makes it impossible to call them
     using the implicit built-in declarations anymore.  Similarly this enables
     us to remove them as unreachable before actual calls may appear during
     expansion or folding.  */
593
  if (DECL_BUILT_IN (node->symbol.decl))
594 595
    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 602
  if (lookup_attribute ("externally_visible",
			DECL_ATTRIBUTES (node->symbol.decl)))
603
    return true;
604
  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
605 606
      && lookup_attribute ("dllexport",
			   DECL_ATTRIBUTES (node->symbol.decl)))
607
    return true;
608
  if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
609
    return false;
610 611 612 613 614
  /* When doing LTO or whole program, we can bring COMDAT functoins static.
     This improves code quality and we know we will duplicate them at most twice
     (in the case that we are not using plugin and link with object file
      implementing same COMDAT)  */
  if ((in_lto_p || whole_program)
615
      && DECL_COMDAT (node->symbol.decl)
616 617 618
      && cgraph_comdat_can_be_unshared_p (node))
    return false;

619
  /* When doing link time optimizations, hidden symbols become local.  */
620
  if (in_lto_p
621 622
      && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
	  || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
623 624 625
      /* Be sure that node is defined in IR file, not in other object
	 file.  In that case we don't set used_from_other_object_file.  */
      && node->analyzed)
626 627
    ;
  else if (!whole_program)
628
    return true;
629

630
  if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
631
    return true;
632 633 634 635 636 637

  return false;
}

/* Return true when variable VNODE should be considered externally visible.  */

638
bool
639 640
varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
{
641 642 643 644 645 646
  /* Do not touch weakrefs; while they are not externally visible,
     dropping their DECL_EXTERNAL flags confuse most
     of code handling them.  */
  if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
    return true;

647 648 649
  if (DECL_EXTERNAL (vnode->symbol.decl))
    return true;

650
  if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
651 652 653 654 655 656 657 658
    return false;

  /* Do not even try to be smart about aliased nodes.  Until we properly
     represent everything by same body alias, these are just evil.  */
  if (aliased)
    return true;

  /* If linker counts on us, we must preserve the function.  */
659
  if (symtab_used_from_object_file_p ((symtab_node) vnode))
660 661
    return true;

662
  if (DECL_HARD_REGISTER (vnode->symbol.decl))
663
    return true;
664
  if (DECL_PRESERVE_P (vnode->symbol.decl))
665 666
    return true;
  if (lookup_attribute ("externally_visible",
667
			DECL_ATTRIBUTES (vnode->symbol.decl)))
668
    return true;
669 670
  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
      && lookup_attribute ("dllexport",
671
			   DECL_ATTRIBUTES (vnode->symbol.decl)))
672
    return true;
673 674 675 676 677 678 679

  /* See if we have linker information about symbol not being used or
     if we need to make guess based on the declaration.

     Even if the linker clams the symbol is unused, never bring internal
     symbols that are declared by user as used or externally visible.
     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;
684

Joseph Myers committed
685
  /* As a special case, the COMDAT virtual tables can be unshared.
686 687 688 689 690
     In LTO mode turn vtables into static variables.  The variable is readonly,
     so this does not enable more optimization, but referring static var
     is faster for dynamic linking.  Also this match logic hidding vtables
     from LTO symbol tables.  */
  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 694
    return false;

695 696
  /* When doing link time optimizations, hidden symbols become local.  */
  if (in_lto_p
697 698
      && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
	  || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
699 700 701 702 703 704 705 706 707 708 709 710 711 712
      /* Be sure that node is defined in IR file, not in other object
	 file.  In that case we don't set used_from_other_object_file.  */
      && vnode->finalized)
    ;
  else if (!flag_whole_program)
    return true;

  /* Do not attempt to privatize COMDATS by default.
     This would break linking with C++ libraries sharing
     inline definitions.

     FIXME: We can do so for readonly vars with no address taken and
     possibly also for vtables since no direct pointer comparsion is done.
     It might be interesting to do so to reduce linking overhead.  */
713
  if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
714 715 716 717
    return true;
  return false;
}

718 719 720 721 722 723 724 725 726 727 728
/* Mark visibility of all functions.

   A local function is one whose calls can occur only in the current
   compilation unit and all its calls are explicit, so we can change
   its calling convention.  We simply mark all static functions whose
   address is not taken as local.

   We also change the TREE_PUBLIC flag of all declarations that are public
   in language point of view but we want to overwrite this default
   via visibilities for the backend point of view.  */

729
static unsigned int
730
function_and_variable_visibility (bool whole_program)
731 732 733
{
  struct cgraph_node *node;
  struct varpool_node *vnode;
734 735 736 737 738 739
  struct pointer_set_t *aliased_nodes = pointer_set_create ();
  struct pointer_set_t *aliased_vnodes = pointer_set_create ();
  unsigned i;
  alias_pair *p;

  /* Discover aliased nodes.  */
740
  FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
741 742 743 744 745 746
    {
      if (dump_file)
       fprintf (dump_file, "Alias %s->%s",
		IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
		IDENTIFIER_POINTER (p->target));
		
747
      if ((node = cgraph_node_for_asm (p->target)) != NULL
748
	  && !DECL_EXTERNAL (node->symbol.decl))
749
        {
750 751
	  if (!node->analyzed)
	    continue;
752
	  cgraph_mark_force_output_node (node);
753 754 755 756 757
	  pointer_set_insert (aliased_nodes, node);
	  if (dump_file)
	    fprintf (dump_file, "  node %s/%i",
		     cgraph_node_name (node), node->uid);
        }
758
      else if ((vnode = varpool_node_for_asm (p->target)) != NULL
759
	       && !DECL_EXTERNAL (vnode->symbol.decl))
760
        {
761
	  vnode->symbol.force_output = 1;
762 763 764 765 766 767 768 769
	  pointer_set_insert (aliased_vnodes, vnode);
	  if (dump_file)
	    fprintf (dump_file, "  varpool node %s",
		     varpool_node_name (vnode));
        }
      if (dump_file)
       fprintf (dump_file, "\n");
    }
770

771
  FOR_EACH_FUNCTION (node)
772
    {
773
      int flags = flags_from_decl_or_type (node->symbol.decl);
774 775

      /* Optimize away PURE and CONST constructors and destructors.  */
776 777 778 779
      if (optimize
	  && (flags & (ECF_CONST | ECF_PURE))
	  && !(flags & ECF_LOOPING_CONST_OR_PURE))
	{
780 781
	  DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
	  DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
782 783
	}

784 785 786
      /* Frontends and alias code marks nodes as needed before parsing is finished.
	 We may end up marking as node external nodes where this flag is meaningless
	 strip it.  */
787
      if (node->symbol.force_output
788
	  && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
789
	node->symbol.force_output = 0;
790

791 792
      /* C++ FE on lack of COMDAT support create local COMDAT functions
	 (that ought to be shared but can not due to object format
Joseph Myers committed
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 796
      if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
        DECL_COMDAT (node->symbol.decl) = 0;
797 798 799
      /* For external decls stop tracking same_comdat_group, it doesn't matter
	 what comdat group they are in when they won't be emitted in this TU,
	 and simplifies later passes.  */
800
      if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
801
	{
802
#ifdef ENABLE_CHECKING
803
	  symtab_node n;
804

805 806 807
	  for (n = node->symbol.same_comdat_group;
	       n != (symtab_node)node;
	       n = n->symbol.same_comdat_group)
808 809
	      /* If at least one of same comdat group functions is external,
		 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);
813
	}
814 815 816 817
      gcc_assert ((!DECL_WEAK (node->symbol.decl)
		  && !DECL_COMDAT (node->symbol.decl))
      	          || TREE_PUBLIC (node->symbol.decl)
		  || DECL_EXTERNAL (node->symbol.decl));
818 819 820
      if (cgraph_externally_visible_p (node, whole_program,
				       pointer_set_contains (aliased_nodes,
							     node)))
821 822
        {
	  gcc_assert (!node->global.inlined_to);
823
	  node->symbol.externally_visible = true;
824 825
	}
      else
826 827 828
	node->symbol.externally_visible = false;
      if (!node->symbol.externally_visible && node->analyzed
	  && !DECL_EXTERNAL (node->symbol.decl))
829
	{
830 831
	  gcc_assert (whole_program || in_lto_p
		      || !TREE_PUBLIC (node->symbol.decl));
832
	  symtab_make_decl_local (node->symbol.decl);
833 834
	  node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
	  if (node->symbol.same_comdat_group)
835 836 837 838
	    /* cgraph_externally_visible_p has already checked all other nodes
	       in the group and they will all be made local.  We need to
	       dissolve the group at once so that the predicate does not
	       segfault though. */
839
	    symtab_dissolve_same_comdat_group_list ((symtab_node) node);
840
	}
841 842

      if (node->thunk.thunk_p
843
	  && TREE_PUBLIC (node->symbol.decl))
844 845 846
	{
	  struct cgraph_node *decl_node = node;

847
	  decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
848 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))
852
	    {
853 854 855 856 857
	      gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
				   == DECL_COMDAT (decl_node->symbol.decl));
	      gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
				   == DECL_COMDAT_GROUP (decl_node->symbol.decl));
	      gcc_checking_assert (node->symbol.same_comdat_group);
858
	    }
859 860
	  if (DECL_EXTERNAL (decl_node->symbol.decl))
	    DECL_EXTERNAL (node->symbol.decl) = 1;
861
	}
862
    }
863
  FOR_EACH_DEFINED_FUNCTION (node)
864
    node->local.local = cgraph_local_node_p (node);
865
  FOR_EACH_VARIABLE (vnode)
866 867
    {
      /* weak flag makes no sense on local variables.  */
868 869 870
      gcc_assert (!DECL_WEAK (vnode->symbol.decl)
      		  || TREE_PUBLIC (vnode->symbol.decl)
		  || DECL_EXTERNAL (vnode->symbol.decl));
871 872 873 874 875 876 877 878 879 880 881 882 883
      /* In several cases declarations can not be common:

	 - when declaration has initializer
	 - when it is in weak
	 - when it has specific section
	 - when it resides in non-generic address space.
	 - if declaration is local, it will get into .local common section
	   so common flag is not needed.  Frontends still produce these in
	   certain cases, such as for:

	     static int a __attribute__ ((common))

	 Canonicalize things here and clear the redundant flag.  */
884 885 886 887 888 889 890
      if (DECL_COMMON (vnode->symbol.decl)
	  && (!(TREE_PUBLIC (vnode->symbol.decl)
	      || DECL_EXTERNAL (vnode->symbol.decl))
	      || (DECL_INITIAL (vnode->symbol.decl)
		  && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
	      || DECL_WEAK (vnode->symbol.decl)
	      || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
891
	      || ! (ADDR_SPACE_GENERIC_P
892 893
		    (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
	DECL_COMMON (vnode->symbol.decl) = 0;
894
    }
895
  FOR_EACH_DEFINED_VARIABLE (vnode)
896
    {
897 898
      if (!vnode->finalized)
        continue;
899 900 901
      if (varpool_externally_visible_p
	    (vnode, 
	     pointer_set_contains (aliased_vnodes, vnode)))
902
	vnode->symbol.externally_visible = true;
903
      else
904 905
        vnode->symbol.externally_visible = false;
      if (!vnode->symbol.externally_visible)
906
	{
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;
912 913
	}
    }
914 915
  pointer_set_destroy (aliased_nodes);
  pointer_set_destroy (aliased_vnodes);
916 917 918 919

  if (dump_file)
    {
      fprintf (dump_file, "\nMarking local functions:");
920
      FOR_EACH_DEFINED_FUNCTION (node)
921 922 923 924
	if (node->local.local)
	  fprintf (dump_file, " %s", cgraph_node_name (node));
      fprintf (dump_file, "\n\n");
      fprintf (dump_file, "\nMarking externally visible functions:");
925
      FOR_EACH_DEFINED_FUNCTION (node)
926
	if (node->symbol.externally_visible)
927 928
	  fprintf (dump_file, " %s", cgraph_node_name (node));
      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 933
	  fprintf (dump_file, " %s", varpool_node_name (vnode));
      fprintf (dump_file, "\n\n");
934 935
    }
  cgraph_function_flags_ready = true;
936
  return 0;
937 938
}

939 940 941 942 943 944
/* Local function pass handling visibilities.  This happens before LTO streaming
   so in particular -fwhole-program should be ignored at this level.  */

static unsigned int
local_function_and_variable_visibility (void)
{
945
  return function_and_variable_visibility (flag_whole_program && !flag_lto);
946 947
}

H.J. Lu committed
948
struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
949
{
950 951
 {
  SIMPLE_IPA_PASS,
952 953
  "visibility",				/* name */
  NULL,					/* gate */
954
  local_function_and_variable_visibility,/* execute */
955 956 957 958 959 960 961 962
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
  TV_CGRAPHOPT,				/* tv_id */
  0,	                                /* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
963
  TODO_remove_functions | TODO_dump_symtab
964
  | TODO_ggc_collect			/* todo_flags_finish */
965
 }
966
};
967

968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
/* Free inline summary.  */

static unsigned
free_inline_summary (void)
{
  inline_free_summary ();
  return 0;
}

struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
{
 {
  SIMPLE_IPA_PASS,
  "*free_inline_summary",		/* name */
  NULL,					/* gate */
  free_inline_summary,			/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
  TV_IPA_FREE_INLINE_SUMMARY,		/* tv_id */
  0,	                                /* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
  TODO_ggc_collect			/* todo_flags_finish */
 }
};

996 997 998 999 1000 1001 1002 1003
/* Do not re-run on ltrans stage.  */

static bool
gate_whole_program_function_and_variable_visibility (void)
{
  return !flag_ltrans;
}

Joseph Myers committed
1004
/* Bring functionss local at LTO time with -fwhole-program.  */
1005 1006 1007 1008 1009

static unsigned int
whole_program_function_and_variable_visibility (void)
{
  function_and_variable_visibility (flag_whole_program);
1010 1011
  if (optimize)
    ipa_discover_readonly_nonaddressable_vars ();
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
  return 0;
}

struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
{
 {
  IPA_PASS,
  "whole-program",			/* name */
  gate_whole_program_function_and_variable_visibility,/* gate */
  whole_program_function_and_variable_visibility,/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
  TV_CGRAPHOPT,				/* tv_id */
  0,	                                /* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
1030
  TODO_remove_functions | TODO_dump_symtab
1031
  | TODO_ggc_collect			/* todo_flags_finish */
1032 1033 1034 1035
 },
 NULL,					/* generate_summary */
 NULL,					/* write_summary */
 NULL,					/* read_summary */
1036 1037
 NULL,					/* write_optimization_summary */
 NULL,					/* read_optimization_summary */
1038
 NULL,					/* stmt_fixup */
1039 1040 1041 1042
 0,					/* TODOs */
 NULL,					/* function_transform */
 NULL,					/* variable_transform */
};
1043

1044

1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
/* Simple ipa profile pass propagating frequencies across the callgraph.  */

static unsigned int
ipa_profile (void)
{
  struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
  struct cgraph_edge *e;
  int order_pos;
  bool something_changed = false;
  int i;

1056
  order_pos = ipa_reverse_postorder (order);
1057 1058 1059 1060 1061
  for (i = order_pos - 1; i >= 0; i--)
    {
      if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
	{
	  for (e = order[i]->callees; e; e = e->next_callee)
1062
	    if (e->callee->local.local && !e->callee->symbol.aux)
1063 1064
	      {
	        something_changed = true;
1065
	        e->callee->symbol.aux = (void *)1;
1066 1067
	      }
	}
1068
      order[i]->symbol.aux = NULL;
1069 1070 1071 1072 1073 1074 1075
    }

  while (something_changed)
    {
      something_changed = false;
      for (i = order_pos - 1; i >= 0; i--)
	{
1076
	  if (order[i]->symbol.aux && cgraph_propagate_frequency (order[i]))
1077 1078
	    {
	      for (e = order[i]->callees; e; e = e->next_callee)
1079
		if (e->callee->local.local && !e->callee->symbol.aux)
1080 1081
		  {
		    something_changed = true;
1082
		    e->callee->symbol.aux = (void *)1;
1083 1084
		  }
	    }
1085
	  order[i]->symbol.aux = NULL;
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
	}
    }
  free (order);
  return 0;
}

static bool
gate_ipa_profile (void)
{
  return flag_ipa_profile;
}

struct ipa_opt_pass_d pass_ipa_profile =
{
 {
  IPA_PASS,
David Li committed
1102
  "profile_estimate",			/* name */
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
  gate_ipa_profile,			/* gate */
  ipa_profile,			        /* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
  TV_IPA_PROFILE,		        /* tv_id */
  0,	                                /* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
  0                                     /* todo_flags_finish */
 },
 NULL,				        /* generate_summary */
 NULL,					/* write_summary */
 NULL,					/* read_summary */
 NULL,					/* write_optimization_summary */
 NULL,					/* read_optimization_summary */
 NULL,					/* stmt_fixup */
 0,					/* TODOs */
 NULL,			                /* function_transform */
 NULL					/* variable_transform */
};
1125 1126 1127 1128

/* Generate and emit a static constructor or destructor.  WHICH must
   be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
   is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
1129
   initialization priority for this constructor or destructor. 
1130

1131 1132 1133 1134 1135
   FINAL specify whether the externally visible name for collect2 should
   be produced. */

static void
cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1136 1137 1138 1139 1140 1141 1142 1143
{
  static int counter = 0;
  char which_buf[16];
  tree decl, name, resdecl;

  /* The priority is encoded in the constructor or destructor name.
     collect2 will sort the names and arrange that they are called at
     program startup.  */
1144 1145 1146 1147 1148 1149
  if (final)
    sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
  else
  /* Proudce sane name but one not recognizable by collect2, just for the
     case we fail to inline the function.  */
    sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
  name = get_file_function_name (which_buf);

  decl = build_decl (input_location, FUNCTION_DECL, name,
		     build_function_type_list (void_type_node, NULL_TREE));
  current_function_decl = decl;

  resdecl = build_decl (input_location,
			RESULT_DECL, NULL_TREE, void_type_node);
  DECL_ARTIFICIAL (resdecl) = 1;
  DECL_RESULT (decl) = resdecl;
  DECL_CONTEXT (resdecl) = decl;

  allocate_struct_function (decl, false);

  TREE_STATIC (decl) = 1;
  TREE_USED (decl) = 1;
  DECL_ARTIFICIAL (decl) = 1;
  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
  DECL_SAVED_TREE (decl) = body;
1169
  if (!targetm.have_ctors_dtors && final)
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
    {
      TREE_PUBLIC (decl) = 1;
      DECL_PRESERVE_P (decl) = 1;
    }
  DECL_UNINLINABLE (decl) = 1;

  DECL_INITIAL (decl) = make_node (BLOCK);
  TREE_USED (DECL_INITIAL (decl)) = 1;

  DECL_SOURCE_LOCATION (decl) = input_location;
  cfun->function_end_locus = input_location;

  switch (which)
    {
    case 'I':
      DECL_STATIC_CONSTRUCTOR (decl) = 1;
      decl_init_priority_insert (decl, priority);
      break;
    case 'D':
      DECL_STATIC_DESTRUCTOR (decl) = 1;
      decl_fini_priority_insert (decl, priority);
      break;
    default:
      gcc_unreachable ();
    }

  gimplify_function_tree (decl);

  cgraph_add_new_function (decl, false);

  set_cfun (NULL);
  current_function_decl = NULL;
}

1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
/* Generate and emit a static constructor or destructor.  WHICH must
   be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
   is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
   initialization priority for this constructor or destructor.  */

void
cgraph_build_static_cdtor (char which, tree body, int priority)
{
  cgraph_build_static_cdtor_1 (which, body, priority, false);
}
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229

/* A vector of FUNCTION_DECLs declared as static constructors.  */
static VEC(tree, heap) *static_ctors;
/* A vector of FUNCTION_DECLs declared as static destructors.  */
static VEC(tree, heap) *static_dtors;

/* When target does not have ctors and dtors, we call all constructor
   and destructor by special initialization/destruction function
   recognized by collect2.

   When we are going to build this function, collect all constructors and
   destructors and turn them into normal functions.  */

static void
record_cdtor_fn (struct cgraph_node *node)
{
1230 1231 1232 1233 1234 1235
  if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
    VEC_safe_push (tree, heap, static_ctors, node->symbol.decl);
  if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
    VEC_safe_push (tree, heap, static_dtors, node->symbol.decl);
  node = cgraph_get_node (node->symbol.decl);
  DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1236 1237 1238 1239 1240 1241 1242 1243
}

/* Define global constructors/destructor functions for the CDTORS, of
   which they are LEN.  The CDTORS are sorted by initialization
   priority.  If CTOR_P is true, these are constructors; otherwise,
   they are destructors.  */

static void
1244
build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1245 1246
{
  size_t i,j;
1247
  size_t len = VEC_length (tree, cdtors);
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261

  i = 0;
  while (i < len)
    {
      tree body;
      tree fn;
      priority_type priority;

      priority = 0;
      body = NULL_TREE;
      j = i;
      do
	{
	  priority_type p;
1262
	  fn = VEC_index (tree, cdtors, j);
1263 1264 1265 1266 1267 1268 1269 1270 1271
	  p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
	  if (j == i)
	    priority = p;
	  else if (p != priority)
	    break;
	  j++;
	}
      while (j < len);

1272
      /* When there is only one cdtor and target supports them, do nothing.  */
1273 1274 1275 1276 1277 1278 1279 1280
      if (j == i + 1
	  && targetm.have_ctors_dtors)
	{
	  i++;
	  continue;
	}
      /* Find the next batch of constructors/destructors with the same
	 initialization priority.  */
1281
      for (;i < j; i++)
1282 1283
	{
	  tree call;
1284
	  fn = VEC_index (tree, cdtors, i);
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
	  call = build_call_expr (fn, 0);
	  if (ctor_p)
	    DECL_STATIC_CONSTRUCTOR (fn) = 0;
	  else
	    DECL_STATIC_DESTRUCTOR (fn) = 0;
	  /* We do not want to optimize away pure/const calls here.
	     When optimizing, these should be already removed, when not
	     optimizing, we want user to be able to breakpoint in them.  */
	  TREE_SIDE_EFFECTS (call) = 1;
	  append_to_statement_list (call, &body);
	}
      gcc_assert (body != NULL_TREE);
      /* Generate a function to call all the function of like
	 priority.  */
1299
      cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
    }
}

/* Comparison function for qsort.  P1 and P2 are actually of type
   "tree *" and point to static constructors.  DECL_INIT_PRIORITY is
   used to determine the sort order.  */

static int
compare_ctor (const void *p1, const void *p2)
{
  tree f1;
  tree f2;
  int priority1;
  int priority2;

  f1 = *(const tree *)p1;
  f2 = *(const tree *)p2;
  priority1 = DECL_INIT_PRIORITY (f1);
  priority2 = DECL_INIT_PRIORITY (f2);

  if (priority1 < priority2)
    return -1;
  else if (priority1 > priority2)
    return 1;
  else
    /* Ensure a stable sort.  Constructors are executed in backwarding
       order to make LTO initialize braries first.  */
    return DECL_UID (f2) - DECL_UID (f1);
}

/* Comparison function for qsort.  P1 and P2 are actually of type
   "tree *" and point to static destructors.  DECL_FINI_PRIORITY is
   used to determine the sort order.  */

static int
compare_dtor (const void *p1, const void *p2)
{
  tree f1;
  tree f2;
  int priority1;
  int priority2;

  f1 = *(const tree *)p1;
  f2 = *(const tree *)p2;
  priority1 = DECL_FINI_PRIORITY (f1);
  priority2 = DECL_FINI_PRIORITY (f2);

  if (priority1 < priority2)
    return -1;
  else if (priority1 > priority2)
    return 1;
  else
    /* Ensure a stable sort.  */
    return DECL_UID (f1) - DECL_UID (f2);
}

/* Generate functions to call static constructors and destructors
   for targets that do not support .ctors/.dtors sections.  These
   functions have magic names which are detected by collect2.  */

static void
build_cdtor_fns (void)
{
  if (!VEC_empty (tree, static_ctors))
    {
      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);
1368 1369 1370 1371 1372
    }

  if (!VEC_empty (tree, static_dtors))
    {
      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);
1375 1376 1377 1378 1379
    }
}

/* Look for constructors and destructors and produce function calling them.
   This is needed for targets not supporting ctors or dtors, but we perform the
Joseph Myers committed
1380
   transformation also at linktime to merge possibly numerous
1381 1382 1383 1384 1385 1386 1387
   constructors/destructors into single function to improve code locality and
   reduce size.  */

static unsigned int
ipa_cdtor_merge (void)
{
  struct cgraph_node *node;
1388 1389 1390
  FOR_EACH_DEFINED_FUNCTION (node)
    if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
	|| DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
       record_cdtor_fn (node);
  build_cdtor_fns ();
  VEC_free (tree, heap, static_ctors);
  VEC_free (tree, heap, static_dtors);
  return 0;
}

/* Perform the pass when we have no ctors/dtors support
   or at LTO time to merge multiple constructors into single
   function.  */

static bool
gate_ipa_cdtor_merge (void)
{
  return !targetm.have_ctors_dtors || (optimize && in_lto_p);
}

struct ipa_opt_pass_d pass_ipa_cdtor_merge =
{
 {
  IPA_PASS,
  "cdtor",				/* name */
  gate_ipa_cdtor_merge,			/* gate */
  ipa_cdtor_merge,		        /* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
  TV_CGRAPHOPT,			        /* tv_id */
  0,	                                /* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
  0                                     /* todo_flags_finish */
 },
 NULL,				        /* generate_summary */
 NULL,					/* write_summary */
 NULL,					/* read_summary */
 NULL,					/* write_optimization_summary */
 NULL,					/* read_optimization_summary */
 NULL,					/* stmt_fixup */
 0,					/* TODOs */
 NULL,			                /* function_transform */
 NULL					/* variable_transform */
};