1/* Basic IPA optimizations and utilities.
2   Copyright (C) 2003-2022 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "backend.h"
24#include "target.h"
25#include "tree.h"
26#include "gimple.h"
27#include "alloc-pool.h"
28#include "tree-pass.h"
29#include "stringpool.h"
30#include "cgraph.h"
31#include "gimplify.h"
32#include "tree-iterator.h"
33#include "ipa-utils.h"
34#include "symbol-summary.h"
35#include "tree-vrp.h"
36#include "ipa-prop.h"
37#include "ipa-fnsummary.h"
38#include "dbgcnt.h"
39#include "debug.h"
40#include "stringpool.h"
41#include "attribs.h"
42
43/* Return true when NODE has ADDR reference.  */
44
45static bool
46has_addr_references_p (struct cgraph_node *node,
47		       void *)
48{
49  int i;
50  struct ipa_ref *ref = NULL;
51
52  for (i = 0; node->iterate_referring (i, ref); i++)
53    if (ref->use == IPA_REF_ADDR)
54      return true;
55  return false;
56}
57
58/* Return true when NODE can be target of an indirect call.  */
59
60static bool
61is_indirect_call_target_p (struct cgraph_node *node, void *)
62{
63  return node->indirect_call_target;
64}
65
66/* Look for all functions inlined to NODE and update their inlined_to pointers
67   to INLINED_TO.  */
68
69static void
70update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
71{
72  struct cgraph_edge *e;
73  for (e = node->callees; e; e = e->next_callee)
74    if (e->callee->inlined_to)
75      {
76	e->callee->inlined_to = inlined_to;
77	update_inlined_to_pointer (e->callee, inlined_to);
78      }
79}
80
81/* Add symtab NODE to queue starting at FIRST.
82
83   The queue is linked via AUX pointers and terminated by pointer to 1.
84   We enqueue nodes at two occasions: when we find them reachable or when we find
85   their bodies needed for further clonning.  In the second case we mark them
86   by pointer to 2 after processing so they are re-queue when they become
87   reachable.  */
88
89static void
90enqueue_node (symtab_node *node, symtab_node **first,
91	      hash_set<symtab_node *> *reachable)
92{
93  /* Node is still in queue; do nothing.  */
94  if (node->aux && node->aux != (void *) 2)
95    return;
96  /* Node was already processed as unreachable, re-enqueue
97     only if it became reachable now.  */
98  if (node->aux == (void *)2 && !reachable->contains (node))
99    return;
100  node->aux = *first;
101  *first = node;
102}
103
104/* Return true if NODE may get inlined later.
105   This is used to keep DECL_EXTERNAL function bodies around long enough
106   so inliner can proces them.  */
107
108static bool
109possible_inline_candidate_p (symtab_node *node)
110{
111  if (symtab->state >= IPA_SSA_AFTER_INLINING)
112    return false;
113  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
114  if (!cnode)
115    return false;
116  if (DECL_UNINLINABLE (cnode->decl))
117    return false;
118  if (opt_for_fn (cnode->decl, optimize))
119    return true;
120  if (symtab->state >= IPA_SSA)
121    return false;
122  return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
123}
124
125/* Process references.  */
126
127static void
128process_references (symtab_node *snode,
129		    symtab_node **first,
130		    hash_set<symtab_node *> *reachable)
131{
132  int i;
133  struct ipa_ref *ref = NULL;
134  for (i = 0; snode->iterate_reference (i, ref); i++)
135    {
136      symtab_node *node = ref->referred;
137      symtab_node *body = node->ultimate_alias_target ();
138
139      if (node->definition && !node->in_other_partition
140	  && ((!DECL_EXTERNAL (node->decl) || node->alias)
141	      || (possible_inline_candidate_p (node)
142		  /* We use variable constructors during late compilation for
143		     constant folding.  Keep references alive so partitioning
144		     knows about potential references.  */
145		  || (VAR_P (node->decl)
146		      && (flag_wpa
147			  || flag_incremental_link
148			 	 == INCREMENTAL_LINK_LTO)
149		      && dyn_cast <varpool_node *> (node)
150		      	   ->ctor_useable_for_folding_p ()))))
151	{
152	  /* Be sure that we will not optimize out alias target
153	     body.  */
154	  if (DECL_EXTERNAL (node->decl)
155	      && node->alias
156	      && symtab->state < IPA_SSA_AFTER_INLINING)
157	    reachable->add (body);
158	  reachable->add (node);
159	}
160      enqueue_node (node, first, reachable);
161    }
162}
163
164/* EDGE is an polymorphic call.  If BEFORE_INLINING_P is set, mark
165   all its potential targets as reachable to permit later inlining if
166   devirtualization happens.  After inlining still keep their declarations
167   around, so we can devirtualize to a direct call.
168
169   Also try to make trivial devirutalization when no or only one target is
170   possible.  */
171
172static void
173walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
174			       struct cgraph_edge *edge,
175			       symtab_node **first,
176			       hash_set<symtab_node *> *reachable)
177{
178  unsigned int i;
179  void *cache_token;
180  bool final;
181  vec <cgraph_node *>targets
182    = possible_polymorphic_call_targets
183	(edge, &final, &cache_token);
184
185  if (!reachable_call_targets->add (cache_token))
186    {
187      for (i = 0; i < targets.length (); i++)
188	{
189	  struct cgraph_node *n = targets[i];
190
191	  /* Do not bother to mark virtual methods in anonymous namespace;
192	     either we will find use of virtual table defining it, or it is
193	     unused.  */
194	  if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE
195	      && type_in_anonymous_namespace_p
196		    (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl))))
197	    continue;
198
199	  n->indirect_call_target = true;
200	  symtab_node *body = n->function_symbol ();
201
202	  /* Prior inlining, keep alive bodies of possible targets for
203	     devirtualization.  */
204	  if (n->definition
205	      && (possible_inline_candidate_p (body)
206		  && opt_for_fn (body->decl, flag_devirtualize)))
207	     {
208		/* Be sure that we will not optimize out alias target
209		   body.  */
210		if (DECL_EXTERNAL (n->decl)
211		    && n->alias
212		    && symtab->state < IPA_SSA_AFTER_INLINING)
213		  reachable->add (body);
214	       reachable->add (n);
215	     }
216	  /* Even after inlining we want to keep the possible targets in the
217	     boundary, so late passes can still produce direct call even if
218	     the chance for inlining is lost.  */
219	  enqueue_node (n, first, reachable);
220	}
221    }
222
223  /* Very trivial devirtualization; when the type is
224     final or anonymous (so we know all its derivation)
225     and there is only one possible virtual call target,
226     make the edge direct.  */
227  if (final)
228    {
229      if (targets.length () <= 1 && dbg_cnt (devirt))
230	{
231	  cgraph_node *target, *node = edge->caller;
232	  if (targets.length () == 1)
233	    target = targets[0];
234	  else
235	    target = cgraph_node::get_create
236		       (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
237
238	  if (dump_enabled_p ())
239	    {
240	      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt,
241			       "devirtualizing call in %s to %s\n",
242			       edge->caller->dump_name (),
243			       target->dump_name ());
244	    }
245	  edge = cgraph_edge::make_direct (edge, target);
246	  if (ipa_fn_summaries)
247	    ipa_update_overall_fn_summary (node->inlined_to
248					   ? node->inlined_to : node);
249	  else if (edge->call_stmt)
250	    cgraph_edge::redirect_call_stmt_to_callee (edge);
251	}
252    }
253}
254
255/* Perform reachability analysis and reclaim all unreachable nodes.
256
257   The algorithm is basically mark&sweep but with some extra refinements:
258
259   - reachable extern inline functions needs special handling; the bodies needs
260     to stay in memory until inlining in hope that they will be inlined.
261     After inlining we release their bodies and turn them into unanalyzed
262     nodes even when they are reachable.
263
264   - virtual functions are kept in callgraph even if they seem unreachable in
265     hope calls to them will be devirtualized.
266
267     Again we remove them after inlining.  In late optimization some
268     devirtualization may happen, but it is not important since we won't inline
269     the call. In theory early opts and IPA should work out all important cases.
270
271   - virtual clones needs bodies of their origins for later materialization;
272     this means that we want to keep the body even if the origin is unreachable
273     otherwise.  To avoid origin from sitting in the callgraph and being
274     walked by IPA passes, we turn them into unanalyzed nodes with body
275     defined.
276
277     We maintain set of function declaration where body needs to stay in
278     body_needed_for_clonning
279
280     Inline clones represent special case: their declaration match the
281     declaration of origin and cgraph_remove_node already knows how to
282     reshape callgraph and preserve body when offline copy of function or
283     inline clone is being removed.
284
285   - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
286     variables with DECL_INITIAL set.  We finalize these and keep reachable
287     ones around for constant folding purposes.  After inlining we however
288     stop walking their references to let everything static referenced by them
289     to be removed when it is otherwise unreachable.
290
291   We maintain queue of both reachable symbols (i.e. defined symbols that needs
292   to stay) and symbols that are in boundary (i.e. external symbols referenced
293   by reachable symbols or origins of clones).  The queue is represented
294   as linked list by AUX pointer terminated by 1.
295
296   At the end we keep all reachable symbols. For symbols in boundary we always
297   turn definition into a declaration, but we may keep function body around
298   based on body_needed_for_clonning
299
300   All symbols that enter the queue have AUX pointer non-zero and are in the
301   boundary.  Pointer set REACHABLE is used to track reachable symbols.
302
303   Every symbol can be visited twice - once as part of boundary and once
304   as real reachable symbol. enqueue_node needs to decide whether the
305   node needs to be re-queued for second processing.  For this purpose
306   we set AUX pointer of processed symbols in the boundary to constant 2.  */
307
308bool
309symbol_table::remove_unreachable_nodes (FILE *file)
310{
311  symtab_node *first = (symtab_node *) (void *) 1;
312  struct cgraph_node *node, *next;
313  varpool_node *vnode, *vnext;
314  bool changed = false;
315  hash_set<symtab_node *> reachable;
316  hash_set<tree> body_needed_for_clonning;
317  hash_set<void *> reachable_call_targets;
318
319  timevar_push (TV_IPA_UNREACHABLE);
320  build_type_inheritance_graph ();
321  if (file)
322    fprintf (file, "\nReclaiming functions:");
323  if (flag_checking)
324    {
325      FOR_EACH_FUNCTION (node)
326	gcc_assert (!node->aux);
327      FOR_EACH_VARIABLE (vnode)
328	gcc_assert (!vnode->aux);
329    }
330  /* Mark functions whose bodies are obviously needed.
331     This is mostly when they can be referenced externally.  Inline clones
332     are special since their declarations are shared with master clone and thus
333     cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them.  */
334  FOR_EACH_FUNCTION (node)
335    {
336      node->used_as_abstract_origin = false;
337      node->indirect_call_target = false;
338      if (node->definition
339	  && !node->inlined_to
340	  && !node->in_other_partition
341	  && !node->can_remove_if_no_direct_calls_and_refs_p ())
342	{
343	  gcc_assert (!node->inlined_to);
344	  reachable.add (node);
345	  enqueue_node (node, &first, &reachable);
346	}
347      else
348	gcc_assert (!node->aux);
349     }
350
351  /* Mark variables that are obviously needed.  */
352  FOR_EACH_DEFINED_VARIABLE (vnode)
353    if (!vnode->can_remove_if_no_refs_p()
354	&& !vnode->in_other_partition)
355      {
356	reachable.add (vnode);
357	enqueue_node (vnode, &first, &reachable);
358      }
359
360  /* Perform reachability analysis.  */
361  while (first != (symtab_node *) (void *) 1)
362    {
363      bool in_boundary_p = !reachable.contains (first);
364      symtab_node *node = first;
365
366      first = (symtab_node *)first->aux;
367
368      /* If we are processing symbol in boundary, mark its AUX pointer for
369	 possible later re-processing in enqueue_node.  */
370      if (in_boundary_p)
371	{
372	  node->aux = (void *)2;
373	  if (node->alias && node->analyzed)
374	    enqueue_node (node->get_alias_target (), &first, &reachable);
375	}
376      else
377	{
378	  if (TREE_CODE (node->decl) == FUNCTION_DECL
379	      && DECL_ABSTRACT_ORIGIN (node->decl))
380	    {
381	      struct cgraph_node *origin_node
382	      = cgraph_node::get (DECL_ABSTRACT_ORIGIN (node->decl));
383	      if (origin_node && !origin_node->used_as_abstract_origin)
384		{
385	          origin_node->used_as_abstract_origin = true;
386		  gcc_assert (!origin_node->prev_sibling_clone);
387		  gcc_assert (!origin_node->next_sibling_clone);
388		  for (cgraph_node *n = origin_node->clones; n;
389		       n = n->next_sibling_clone)
390		    if (n->decl == DECL_ABSTRACT_ORIGIN (node->decl))
391		      n->used_as_abstract_origin = true;
392		}
393	    }
394	  /* If any non-external and non-local symbol in a comdat group is
395 	     reachable, force all externally visible symbols in the same comdat
396	     group to be reachable as well.  Comdat-local symbols
397	     can be discarded if all uses were inlined.  */
398	  if (node->same_comdat_group
399	      && node->externally_visible
400	      && !DECL_EXTERNAL (node->decl))
401	    {
402	      symtab_node *next;
403	      for (next = node->same_comdat_group;
404		   next != node;
405		   next = next->same_comdat_group)
406		if (!next->comdat_local_p ()
407		    && !DECL_EXTERNAL (next->decl)
408		    && !reachable.add (next))
409		  enqueue_node (next, &first, &reachable);
410	    }
411	  /* Mark references as reachable.  */
412	  process_references (node, &first, &reachable);
413	}
414
415      if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
416	{
417	  /* Mark the callees reachable unless they are direct calls to extern
418 	     inline functions we decided to not inline.  */
419	  if (!in_boundary_p)
420	    {
421	      struct cgraph_edge *e;
422	      /* Keep alive possible targets for devirtualization.  */
423	      if (opt_for_fn (cnode->decl, optimize)
424		  && opt_for_fn (cnode->decl, flag_devirtualize))
425		{
426		  struct cgraph_edge *next;
427		  for (e = cnode->indirect_calls; e; e = next)
428		    {
429		      next = e->next_callee;
430		      if (e->indirect_info->polymorphic)
431			walk_polymorphic_call_targets (&reachable_call_targets,
432						       e, &first, &reachable);
433		    }
434		}
435	      for (e = cnode->callees; e; e = e->next_callee)
436		{
437	          symtab_node *body = e->callee->function_symbol ();
438		  if (e->callee->definition
439		      && !e->callee->in_other_partition
440		      && (!e->inline_failed
441			  || !DECL_EXTERNAL (e->callee->decl)
442			  || e->callee->alias
443			  || possible_inline_candidate_p (e->callee)))
444		    {
445		      /* Be sure that we will not optimize out alias target
446			 body.  */
447		      if (DECL_EXTERNAL (e->callee->decl)
448			  && e->callee->alias
449			  && symtab->state < IPA_SSA_AFTER_INLINING)
450			reachable.add (body);
451		      reachable.add (e->callee);
452		    }
453		  else if (e->callee->declare_variant_alt
454			   && !e->callee->in_other_partition)
455		    reachable.add (e->callee);
456		  enqueue_node (e->callee, &first, &reachable);
457		}
458
459	      /* When inline clone exists, mark body to be preserved so when removing
460		 offline copy of the function we don't kill it.  */
461	      if (cnode->inlined_to)
462	        body_needed_for_clonning.add (cnode->decl);
463
464	      /* For non-inline clones, force their origins to the boundary and ensure
465		 that body is not removed.  */
466	      while (cnode->clone_of)
467		{
468		  bool noninline = cnode->clone_of->decl != cnode->decl;
469		  cnode = cnode->clone_of;
470		  if (noninline)
471		    {
472		      body_needed_for_clonning.add (cnode->decl);
473		      enqueue_node (cnode, &first, &reachable);
474		    }
475		}
476
477	    }
478	  else if (cnode->thunk)
479	    enqueue_node (cnode->callees->callee, &first, &reachable);
480
481	  /* If any reachable function has simd clones, mark them as
482	     reachable as well.  */
483	  if (cnode->simd_clones)
484	    {
485	      cgraph_node *next;
486	      for (next = cnode->simd_clones;
487		   next;
488		   next = next->simdclone->next_clone)
489		if (in_boundary_p
490		    || !reachable.add (next))
491		  enqueue_node (next, &first, &reachable);
492	    }
493	}
494      /* When we see constructor of external variable, keep referred nodes in the
495	boundary.  This will also hold initializers of the external vars NODE
496	refers to.  */
497      varpool_node *vnode = dyn_cast <varpool_node *> (node);
498      if (vnode
499	  && DECL_EXTERNAL (node->decl)
500	  && !vnode->alias
501	  && in_boundary_p)
502	{
503	  struct ipa_ref *ref = NULL;
504	  for (int i = 0; node->iterate_reference (i, ref); i++)
505	    enqueue_node (ref->referred, &first, &reachable);
506	}
507    }
508
509  /* Remove unreachable functions.   */
510  for (node = first_function (); node; node = next)
511    {
512      next = next_function (node);
513
514      /* If node is not needed at all, remove it.  */
515      if (!node->aux)
516	{
517	  if (file)
518	    fprintf (file, " %s", node->dump_name ());
519	  node->remove ();
520	  changed = true;
521	}
522      /* If node is unreachable, remove its body.  */
523      else if (!reachable.contains (node))
524        {
525	  /* We keep definitions of thunks and aliases in the boundary so
526	     we can walk to the ultimate alias targets and function symbols
527	     reliably.  */
528	  if (node->alias || node->thunk)
529	    ;
530	  else if (!body_needed_for_clonning.contains (node->decl))
531	    {
532	      /* Make the node a non-clone so that we do not attempt to
533		 materialize it later.  */
534	      if (node->clone_of)
535		node->remove_from_clone_tree ();
536	      node->release_body ();
537	    }
538	  else if (!node->clone_of)
539	    gcc_assert (in_lto_p || DECL_RESULT (node->decl));
540	  if (node->definition && !node->alias && !node->thunk)
541	    {
542	      if (file)
543		fprintf (file, " %s", node->dump_name ());
544	      node->body_removed = true;
545	      node->analyzed = false;
546	      node->definition = false;
547	      node->cpp_implicit_alias = false;
548	      node->alias = false;
549	      node->transparent_alias = false;
550	      node->thunk = false;
551	      node->weakref = false;
552	      /* After early inlining we drop always_inline attributes on
553		 bodies of functions that are still referenced (have their
554		 address taken).  */
555	      DECL_ATTRIBUTES (node->decl)
556		= remove_attribute ("always_inline",
557				    DECL_ATTRIBUTES (node->decl));
558	      if (!node->in_other_partition)
559		node->local = false;
560	      node->remove_callees ();
561	      node->remove_all_references ();
562	      changed = true;
563	    }
564	}
565      else
566	gcc_assert (node->clone_of || !node->has_gimple_body_p ()
567		    || in_lto_p || DECL_RESULT (node->decl));
568    }
569
570  /* Inline clones might be kept around so their materializing allows further
571     cloning.  If the function the clone is inlined into is removed, we need
572     to turn it into normal cone.  */
573  FOR_EACH_FUNCTION (node)
574    {
575      if (node->inlined_to
576	  && !node->callers)
577	{
578	  gcc_assert (node->clones);
579	  node->inlined_to = NULL;
580	  update_inlined_to_pointer (node, node);
581	}
582      node->aux = NULL;
583    }
584
585  /* Remove unreachable variables.  */
586  if (file)
587    fprintf (file, "\nReclaiming variables:");
588  for (vnode = first_variable (); vnode; vnode = vnext)
589    {
590      vnext = next_variable (vnode);
591      if (!vnode->aux
592	  /* For can_refer_decl_in_current_unit_p we want to track for
593	     all external variables if they are defined in other partition
594	     or not.  */
595	  && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl)))
596	{
597	  struct ipa_ref *ref = NULL;
598
599	  /* First remove the aliases, so varpool::remove can possibly lookup
600	     the constructor and save it for future use.  */
601	  while (vnode->iterate_direct_aliases (0, ref))
602	    {
603	      if (file)
604		fprintf (file, " %s", ref->referred->dump_name ());
605	      ref->referring->remove ();
606	    }
607	  if (file)
608	    fprintf (file, " %s", vnode->dump_name ());
609          vnext = next_variable (vnode);
610	  /* Signal removal to the debug machinery.  */
611	  if (! flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
612	    {
613	      vnode->definition = false;
614	      (*debug_hooks->late_global_decl) (vnode->decl);
615	    }
616	  vnode->remove ();
617	  changed = true;
618	}
619      else if (!reachable.contains (vnode) && !vnode->alias)
620        {
621	  tree init;
622	  if (vnode->definition)
623	    {
624	      if (file)
625		fprintf (file, " %s", vnode->dump_name ());
626	      changed = true;
627	    }
628	  /* Keep body if it may be useful for constant folding.  */
629	  if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
630	      || ((init = ctor_for_folding (vnode->decl)) == error_mark_node))
631	    vnode->remove_initializer ();
632	  else
633	    DECL_INITIAL (vnode->decl) = init;
634	  vnode->body_removed = true;
635	  vnode->definition = false;
636	  vnode->analyzed = false;
637	  vnode->aux = NULL;
638
639	  vnode->remove_from_same_comdat_group ();
640
641	  vnode->remove_all_references ();
642	}
643      else
644	vnode->aux = NULL;
645    }
646
647  /* Now update address_taken flags and try to promote functions to be local.  */
648  if (file)
649    fprintf (file, "\nClearing address taken flags:");
650  FOR_EACH_DEFINED_FUNCTION (node)
651    if (node->address_taken
652	&& !node->used_from_other_partition)
653      {
654	if (!node->call_for_symbol_and_aliases
655	    (has_addr_references_p, NULL, true))
656	  {
657	    if (file)
658	      fprintf (file, " %s", node->dump_name ());
659	    node->address_taken = false;
660	    changed = true;
661	    if (node->local_p ()
662		/* Virtual functions may be kept in cgraph just because
663		   of possible later devirtualization.  Do not mark them as
664		   local too early so we won't optimize them out before
665		   we are done with polymorphic call analysis.  */
666		&& (symtab->state >= IPA_SSA_AFTER_INLINING
667		    || !node->call_for_symbol_and_aliases
668		       (is_indirect_call_target_p, NULL, true)))
669	      {
670		node->local = true;
671		if (file)
672		  fprintf (file, " (local)");
673	      }
674	  }
675      }
676  if (file)
677    fprintf (file, "\n");
678
679  symtab_node::checking_verify_symtab_nodes ();
680
681  /* If we removed something, perhaps profile could be improved.  */
682  if (changed && (optimize || in_lto_p) && ipa_call_summaries)
683    FOR_EACH_DEFINED_FUNCTION (node)
684      ipa_propagate_frequency (node);
685
686  timevar_pop (TV_IPA_UNREACHABLE);
687  return changed;
688}
689
690/* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ
691   as needed, also clear EXPLICIT_REFS if the references to given variable
692   do not need to be explicit.  */
693
694void
695process_references (varpool_node *vnode,
696		    bool *written, bool *address_taken,
697		    bool *read, bool *explicit_refs)
698{
699  int i;
700  struct ipa_ref *ref;
701
702  if (!vnode->all_refs_explicit_p ()
703      || TREE_THIS_VOLATILE (vnode->decl))
704    *explicit_refs = false;
705
706  for (i = 0; vnode->iterate_referring (i, ref)
707	      && *explicit_refs && (!*written || !*address_taken || !*read); i++)
708    switch (ref->use)
709      {
710      case IPA_REF_ADDR:
711	*address_taken = true;
712	break;
713      case IPA_REF_LOAD:
714	*read = true;
715	break;
716      case IPA_REF_STORE:
717	*written = true;
718	break;
719      case IPA_REF_ALIAS:
720	process_references (dyn_cast<varpool_node *> (ref->referring), written,
721			    address_taken, read, explicit_refs);
722	break;
723      }
724}
725
726/* Set TREE_READONLY bit.  */
727
728bool
729set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
730{
731  TREE_READONLY (vnode->decl) = true;
732  return false;
733}
734
735/* Set writeonly bit and clear the initalizer, since it will not be needed.  */
736
737bool
738set_writeonly_bit (varpool_node *vnode, void *data)
739{
740  vnode->writeonly = true;
741  if (optimize || in_lto_p)
742    {
743      DECL_INITIAL (vnode->decl) = NULL;
744      if (!vnode->alias)
745	{
746	  if (vnode->num_references ())
747	    *(bool *)data = true;
748	  vnode->remove_all_references ();
749	}
750    }
751  return false;
752}
753
754/* Clear addressale bit of VNODE.  */
755
756bool
757clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
758{
759  vnode->address_taken = false;
760  TREE_ADDRESSABLE (vnode->decl) = 0;
761  return false;
762}
763
764/* Discover variables that have no longer address taken, are read-only or
765   write-only and update their flags.
766
767   Return true when unreachable symbol removal should be done.
768
769   FIXME: This cannot be done in between gimplify and omp_expand since
770   readonly flag plays role on what is shared and what is not.  Currently we do
771   this transformation as part of whole program visibility and re-do at
772   ipa-reference pass (to take into account clonning), but it would
773   make sense to do it before early optimizations.  */
774
775bool
776ipa_discover_variable_flags (void)
777{
778  if (!flag_ipa_reference_addressable)
779    return false;
780
781  bool remove_p = false;
782  varpool_node *vnode;
783  if (dump_file)
784    fprintf (dump_file, "Clearing variable flags:");
785  FOR_EACH_VARIABLE (vnode)
786    if (!vnode->alias
787	&& (TREE_ADDRESSABLE (vnode->decl)
788	    || !vnode->writeonly
789	    || !TREE_READONLY (vnode->decl)))
790      {
791	bool written = false;
792	bool address_taken = false;
793	bool read = false;
794	bool explicit_refs = true;
795
796	process_references (vnode, &written, &address_taken, &read,
797			    &explicit_refs);
798	if (!explicit_refs)
799	  continue;
800	if (!address_taken)
801	  {
802	    if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
803	      fprintf (dump_file, " %s (non-addressable)",
804		       vnode->dump_name ());
805	    vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
806					        true);
807	  }
808	if (!address_taken && !written
809	    /* Making variable in explicit section readonly can cause section
810	       type conflict.
811	       See e.g. gcc.c-torture/compile/pr23237.c */
812	    && vnode->get_section () == NULL)
813	  {
814	    if (!TREE_READONLY (vnode->decl) && dump_file)
815	      fprintf (dump_file, " %s (read-only)", vnode->dump_name ());
816	    vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
817	  }
818	if (!vnode->writeonly && !read && !address_taken && written)
819	  {
820	    if (dump_file)
821	      fprintf (dump_file, " %s (write-only)", vnode->dump_name ());
822	    vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p,
823					        true);
824	  }
825      }
826  if (dump_file)
827    fprintf (dump_file, "\n");
828  return remove_p;
829}
830
831/* Generate and emit a static constructor or destructor.  WHICH must
832   be one of 'I' (for a constructor), 'D' (for a destructor).
833   BODY is a STATEMENT_LIST containing GENERIC
834   statements.  PRIORITY is the initialization priority for this
835   constructor or destructor.
836
837   FINAL specify whether the externally visible name for collect2 should
838   be produced. */
839
840static tree
841cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final,
842			     tree optimization,
843			     tree target)
844{
845  static int counter = 0;
846  char which_buf[16];
847  tree decl, name, resdecl;
848
849  /* The priority is encoded in the constructor or destructor name.
850     collect2 will sort the names and arrange that they are called at
851     program startup.  */
852  if (!targetm.have_ctors_dtors && final)
853    {
854      sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
855      name = get_file_function_name (which_buf);
856    }
857  else
858    {
859      /* Proudce sane name but one not recognizable by collect2, just for the
860	 case we fail to inline the function.  */
861      sprintf (which_buf, "_sub_%c_%.5d_%d", which, priority, counter++);
862      name = get_identifier (which_buf);
863    }
864
865  decl = build_decl (input_location, FUNCTION_DECL, name,
866		     build_function_type_list (void_type_node, NULL_TREE));
867  current_function_decl = decl;
868
869  resdecl = build_decl (input_location,
870			RESULT_DECL, NULL_TREE, void_type_node);
871  DECL_ARTIFICIAL (resdecl) = 1;
872  DECL_RESULT (decl) = resdecl;
873  DECL_CONTEXT (resdecl) = decl;
874
875  allocate_struct_function (decl, false);
876
877  TREE_STATIC (decl) = 1;
878  TREE_USED (decl) = 1;
879  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) = optimization;
880  DECL_FUNCTION_SPECIFIC_TARGET (decl) = target;
881  DECL_ARTIFICIAL (decl) = 1;
882  DECL_IGNORED_P (decl) = 1;
883  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
884  DECL_SAVED_TREE (decl) = body;
885  if (!targetm.have_ctors_dtors && final)
886    {
887      TREE_PUBLIC (decl) = 1;
888      DECL_PRESERVE_P (decl) = 1;
889    }
890  DECL_UNINLINABLE (decl) = 1;
891
892  DECL_INITIAL (decl) = make_node (BLOCK);
893  BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
894  TREE_USED (DECL_INITIAL (decl)) = 1;
895
896  DECL_SOURCE_LOCATION (decl) = input_location;
897  cfun->function_end_locus = input_location;
898
899  switch (which)
900    {
901    case 'I':
902      DECL_STATIC_CONSTRUCTOR (decl) = 1;
903      decl_init_priority_insert (decl, priority);
904      break;
905    case 'D':
906      DECL_STATIC_DESTRUCTOR (decl) = 1;
907      decl_fini_priority_insert (decl, priority);
908      break;
909    default:
910      gcc_unreachable ();
911    }
912
913  gimplify_function_tree (decl);
914
915  cgraph_node::add_new_function (decl, false);
916
917  set_cfun (NULL);
918  current_function_decl = NULL;
919  return decl;
920}
921
922/* Generate and emit a static constructor or destructor.  WHICH must
923   be one of 'I' (for a constructor) or 'D' (for a destructor).
924   BODY is a STATEMENT_LIST containing GENERIC
925   statements.  PRIORITY is the initialization priority for this
926   constructor or destructor.  */
927
928void
929cgraph_build_static_cdtor (char which, tree body, int priority)
930{
931  /* FIXME: We should be able to
932     gcc_assert (!in_lto_p);
933     because at LTO time the global options are not safe to use.
934     Unfortunately ASAN finish_file will produce constructors late and they
935     may lead to surprises.  */
936  cgraph_build_static_cdtor_1 (which, body, priority, false,
937			       optimization_default_node,
938			       target_option_default_node);
939}
940
941/* When target does not have ctors and dtors, we call all constructor
942   and destructor by special initialization/destruction function
943   recognized by collect2.
944
945   When we are going to build this function, collect all constructors and
946   destructors and turn them into normal functions.  */
947
948static void
949record_cdtor_fn (struct cgraph_node *node, vec<tree> *ctors, vec<tree> *dtors)
950{
951  if (DECL_STATIC_CONSTRUCTOR (node->decl))
952    ctors->safe_push (node->decl);
953  if (DECL_STATIC_DESTRUCTOR (node->decl))
954    dtors->safe_push (node->decl);
955  node = cgraph_node::get (node->decl);
956  DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
957}
958
959/* Define global constructors/destructor functions for the CDTORS, of
960   which they are LEN.  The CDTORS are sorted by initialization
961   priority.  If CTOR_P is true, these are constructors; otherwise,
962   they are destructors.  */
963
964static void
965build_cdtor (bool ctor_p, const vec<tree> &cdtors)
966{
967  size_t i,j;
968  size_t len = cdtors.length ();
969
970  i = 0;
971  while (i < len)
972    {
973      tree body;
974      tree fn;
975      priority_type priority;
976
977      priority = 0;
978      body = NULL_TREE;
979      j = i;
980      do
981	{
982	  priority_type p;
983	  fn = cdtors[j];
984	  p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
985	  if (j == i)
986	    priority = p;
987	  else if (p != priority)
988	    break;
989	  j++;
990	}
991      while (j < len);
992
993      /* When there is only one cdtor and target supports them, do nothing.  */
994      if (j == i + 1
995	  && targetm.have_ctors_dtors)
996	{
997	  i++;
998	  continue;
999	}
1000      /* Find the next batch of constructors/destructors with the same
1001	 initialization priority.  */
1002      for (;i < j; i++)
1003	{
1004	  tree call;
1005	  fn = cdtors[i];
1006	  call = build_call_expr (fn, 0);
1007	  if (ctor_p)
1008	    DECL_STATIC_CONSTRUCTOR (fn) = 0;
1009	  else
1010	    DECL_STATIC_DESTRUCTOR (fn) = 0;
1011	  /* We do not want to optimize away pure/const calls here.
1012	     When optimizing, these should be already removed, when not
1013	     optimizing, we want user to be able to breakpoint in them.  */
1014	  TREE_SIDE_EFFECTS (call) = 1;
1015	  append_to_statement_list (call, &body);
1016	}
1017      gcc_assert (body != NULL_TREE);
1018      /* Generate a function to call all the function of like
1019	 priority.  */
1020      cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true,
1021				   DECL_FUNCTION_SPECIFIC_OPTIMIZATION (cdtors[0]),
1022				   DECL_FUNCTION_SPECIFIC_TARGET (cdtors[0]));
1023    }
1024}
1025
1026/* Helper functions for build_cxa_dtor_registrations ().
1027   Build a decl for __cxa_atexit ().  */
1028
1029static tree
1030build_cxa_atexit_decl ()
1031{
1032  /* The parameter to "__cxa_atexit" is "void (*)(void *)".  */
1033  tree fn_type = build_function_type_list (void_type_node,
1034					   ptr_type_node, NULL_TREE);
1035  tree fn_ptr_type = build_pointer_type (fn_type);
1036  /* The declaration for `__cxa_atexit' is:
1037     int __cxa_atexit (void (*)(void *), void *, void *).  */
1038  const char *name = "__cxa_atexit";
1039  tree cxa_name = get_identifier (name);
1040  fn_type = build_function_type_list (integer_type_node, fn_ptr_type,
1041				      ptr_type_node, ptr_type_node, NULL_TREE);
1042  tree atexit_fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1043				   cxa_name, fn_type);
1044  SET_DECL_ASSEMBLER_NAME (atexit_fndecl, cxa_name);
1045  DECL_VISIBILITY (atexit_fndecl) = VISIBILITY_DEFAULT;
1046  DECL_VISIBILITY_SPECIFIED (atexit_fndecl) = true;
1047  set_call_expr_flags (atexit_fndecl, ECF_LEAF | ECF_NOTHROW);
1048  TREE_PUBLIC (atexit_fndecl) = true;
1049  DECL_EXTERNAL (atexit_fndecl) = true;
1050  DECL_ARTIFICIAL (atexit_fndecl) = true;
1051  return atexit_fndecl;
1052}
1053
1054/* Build a decl for __dso_handle.  */
1055
1056static tree
1057build_dso_handle_decl ()
1058{
1059  /* Declare the __dso_handle variable.  */
1060  tree dso_handle_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1061				     get_identifier ("__dso_handle"),
1062				     ptr_type_node);
1063  TREE_PUBLIC (dso_handle_decl) = true;
1064  DECL_EXTERNAL (dso_handle_decl) = true;
1065  DECL_ARTIFICIAL (dso_handle_decl) = true;
1066#ifdef HAVE_GAS_HIDDEN
1067  if (dso_handle_decl != error_mark_node)
1068    {
1069      DECL_VISIBILITY (dso_handle_decl) = VISIBILITY_HIDDEN;
1070      DECL_VISIBILITY_SPECIFIED (dso_handle_decl) = true;
1071    }
1072#endif
1073  return dso_handle_decl;
1074}
1075
1076/*  This builds one or more constructor functions that register DTORs with
1077    __cxa_atexit ().  Within a priority level, DTORs are registered in TU
1078    order - which means that they will run in reverse TU order from cxa_atexit.
1079    This is the same behavior as using a .fini / .mod_term_funcs section.
1080    As the functions are built, they are appended to the CTORs vector.  */
1081
1082static void
1083build_cxa_dtor_registrations (const vec<tree> &dtors, vec<tree> *ctors)
1084{
1085  size_t i,j;
1086  size_t len = dtors.length ();
1087
1088  location_t sav_loc = input_location;
1089  input_location = UNKNOWN_LOCATION;
1090
1091  tree atexit_fndecl = build_cxa_atexit_decl ();
1092  tree dso_handle_decl = build_dso_handle_decl ();
1093
1094  /* We want &__dso_handle.  */
1095  tree dso_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1096			     ptr_type_node, dso_handle_decl);
1097
1098  i = 0;
1099  while (i < len)
1100    {
1101      priority_type priority = 0;
1102      tree body = NULL_TREE;
1103      j = i;
1104      do
1105	{
1106	  priority_type p;
1107	  tree fn = dtors[j];
1108	  p = DECL_FINI_PRIORITY (fn);
1109	  if (j == i)
1110	    priority = p;
1111	  else if (p != priority)
1112	    break;
1113	  j++;
1114	}
1115      while (j < len);
1116
1117      /* Find the next batch of destructors with the same initialization
1118	 priority.  */
1119      for (;i < j; i++)
1120	{
1121	  tree fn = dtors[i];
1122	  DECL_STATIC_DESTRUCTOR (fn) = 0;
1123	  tree dtor_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1124				      ptr_type_node, fn);
1125	  tree call_cxa_atexit
1126	    = build_call_expr_loc (UNKNOWN_LOCATION, atexit_fndecl, 3,
1127				   dtor_ptr, null_pointer_node, dso_ptr);
1128	  TREE_SIDE_EFFECTS (call_cxa_atexit) = 1;
1129	  append_to_statement_list (call_cxa_atexit, &body);
1130	}
1131
1132      gcc_assert (body != NULL_TREE);
1133      /* Generate a function to register the DTORs at this priority.  */
1134      tree new_ctor
1135	= cgraph_build_static_cdtor_1 ('I', body, priority, true,
1136				       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (dtors[0]),
1137				       DECL_FUNCTION_SPECIFIC_TARGET (dtors[0]));
1138      /* Add this to the list of ctors.  */
1139      ctors->safe_push (new_ctor);
1140    }
1141  input_location = sav_loc;
1142}
1143
1144/* Comparison function for qsort.  P1 and P2 are actually of type
1145   "tree *" and point to static constructors.  DECL_INIT_PRIORITY is
1146   used to determine the sort order.  */
1147
1148static int
1149compare_ctor (const void *p1, const void *p2)
1150{
1151  tree f1;
1152  tree f2;
1153  int priority1;
1154  int priority2;
1155
1156  f1 = *(const tree *)p1;
1157  f2 = *(const tree *)p2;
1158  priority1 = DECL_INIT_PRIORITY (f1);
1159  priority2 = DECL_INIT_PRIORITY (f2);
1160
1161  if (priority1 < priority2)
1162    return -1;
1163  else if (priority1 > priority2)
1164    return 1;
1165  else
1166    /* Ensure a stable sort.  Constructors are executed in backwarding
1167       order to make LTO initialize braries first.  */
1168    return DECL_UID (f2) - DECL_UID (f1);
1169}
1170
1171/* Comparison function for qsort.  P1 and P2 are actually of type
1172   "tree *" and point to static destructors.  DECL_FINI_PRIORITY is
1173   used to determine the sort order.  */
1174
1175static int
1176compare_dtor (const void *p1, const void *p2)
1177{
1178  tree f1;
1179  tree f2;
1180  int priority1;
1181  int priority2;
1182
1183  f1 = *(const tree *)p1;
1184  f2 = *(const tree *)p2;
1185  priority1 = DECL_FINI_PRIORITY (f1);
1186  priority2 = DECL_FINI_PRIORITY (f2);
1187
1188  if (priority1 < priority2)
1189    return -1;
1190  else if (priority1 > priority2)
1191    return 1;
1192  else
1193    /* Ensure a stable sort - into TU order.  */
1194    return DECL_UID (f1) - DECL_UID (f2);
1195}
1196
1197/* Comparison function for qsort.  P1 and P2 are of type "tree *" and point to
1198   a pair of static constructors or destructors.  We first sort on the basis of
1199   priority and then into TU order (on the strict assumption that DECL_UIDs are
1200   ordered in the same way as the original functions).  ???: this seems quite
1201   fragile. */
1202
1203static int
1204compare_cdtor_tu_order (const void *p1, const void *p2)
1205{
1206  tree f1;
1207  tree f2;
1208  int priority1;
1209  int priority2;
1210
1211  f1 = *(const tree *)p1;
1212  f2 = *(const tree *)p2;
1213  /* We process the DTORs first, and then remove their flag, so this order
1214     allows for functions that are declared as both CTOR and DTOR.  */
1215  if (DECL_STATIC_DESTRUCTOR (f1))
1216    {
1217      gcc_checking_assert (DECL_STATIC_DESTRUCTOR (f2));
1218      priority1 = DECL_FINI_PRIORITY (f1);
1219      priority2 = DECL_FINI_PRIORITY (f2);
1220    }
1221  else
1222    {
1223      priority1 = DECL_INIT_PRIORITY (f1);
1224      priority2 = DECL_INIT_PRIORITY (f2);
1225    }
1226
1227  if (priority1 < priority2)
1228    return -1;
1229  else if (priority1 > priority2)
1230    return 1;
1231  else
1232    /* For equal priority, sort into the order of definition in the TU.  */
1233    return DECL_UID (f1) - DECL_UID (f2);
1234}
1235
1236/* Generate functions to call static constructors and destructors
1237   for targets that do not support .ctors/.dtors sections.  These
1238   functions have magic names which are detected by collect2.  */
1239
1240static void
1241build_cdtor_fns (vec<tree> *ctors, vec<tree> *dtors)
1242{
1243  if (!ctors->is_empty ())
1244    {
1245      gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1246      ctors->qsort (compare_ctor);
1247      build_cdtor (/*ctor_p=*/true, *ctors);
1248    }
1249
1250  if (!dtors->is_empty ())
1251    {
1252      gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1253      dtors->qsort (compare_dtor);
1254      build_cdtor (/*ctor_p=*/false, *dtors);
1255    }
1256}
1257
1258/* Generate new CTORs to register static destructors with __cxa_atexit and add
1259   them to the existing list of CTORs; we then process the revised CTORs list.
1260
1261   We sort the DTORs into priority and then TU order, this means that they are
1262   registered in that order with __cxa_atexit () and therefore will be run in
1263   the reverse order.
1264
1265   Likewise, CTORs are sorted into priority and then TU order, which means that
1266   they will run in that order.
1267
1268   This matches the behavior of using init/fini or mod_init_func/mod_term_func
1269   sections.  */
1270
1271static void
1272build_cxa_atexit_fns (vec<tree> *ctors, vec<tree> *dtors)
1273{
1274  if (!dtors->is_empty ())
1275    {
1276      gcc_assert (targetm.dtors_from_cxa_atexit);
1277      dtors->qsort (compare_cdtor_tu_order);
1278      build_cxa_dtor_registrations (*dtors, ctors);
1279    }
1280
1281  if (!ctors->is_empty ())
1282    {
1283      gcc_assert (targetm.dtors_from_cxa_atexit);
1284      ctors->qsort (compare_cdtor_tu_order);
1285      build_cdtor (/*ctor_p=*/true, *ctors);
1286    }
1287}
1288
1289/* Look for constructors and destructors and produce function calling them.
1290   This is needed for targets not supporting ctors or dtors, but we perform the
1291   transformation also at linktime to merge possibly numerous
1292   constructors/destructors into single function to improve code locality and
1293   reduce size.  */
1294
1295static unsigned int
1296ipa_cdtor_merge (void)
1297{
1298  /* A vector of FUNCTION_DECLs declared as static constructors.  */
1299  auto_vec<tree, 20> ctors;
1300  /* A vector of FUNCTION_DECLs declared as static destructors.  */
1301  auto_vec<tree, 20> dtors;
1302  struct cgraph_node *node;
1303  FOR_EACH_DEFINED_FUNCTION (node)
1304    if (DECL_STATIC_CONSTRUCTOR (node->decl)
1305	|| DECL_STATIC_DESTRUCTOR (node->decl))
1306       record_cdtor_fn (node, &ctors, &dtors);
1307  if (targetm.dtors_from_cxa_atexit)
1308    build_cxa_atexit_fns (&ctors, &dtors);
1309  else
1310    build_cdtor_fns (&ctors, &dtors);
1311  return 0;
1312}
1313
1314namespace {
1315
1316const pass_data pass_data_ipa_cdtor_merge =
1317{
1318  IPA_PASS, /* type */
1319  "cdtor", /* name */
1320  OPTGROUP_NONE, /* optinfo_flags */
1321  TV_CGRAPHOPT, /* tv_id */
1322  0, /* properties_required */
1323  0, /* properties_provided */
1324  0, /* properties_destroyed */
1325  0, /* todo_flags_start */
1326  0, /* todo_flags_finish */
1327};
1328
1329class pass_ipa_cdtor_merge : public ipa_opt_pass_d
1330{
1331public:
1332  pass_ipa_cdtor_merge (gcc::context *ctxt)
1333    : ipa_opt_pass_d (pass_data_ipa_cdtor_merge, ctxt,
1334		      NULL, /* generate_summary */
1335		      NULL, /* write_summary */
1336		      NULL, /* read_summary */
1337		      NULL, /* write_optimization_summary */
1338		      NULL, /* read_optimization_summary */
1339		      NULL, /* stmt_fixup */
1340		      0, /* function_transform_todo_flags_start */
1341		      NULL, /* function_transform */
1342		      NULL) /* variable_transform */
1343  {}
1344
1345  /* opt_pass methods: */
1346  virtual bool gate (function *);
1347  virtual unsigned int execute (function *) { return ipa_cdtor_merge (); }
1348
1349}; // class pass_ipa_cdtor_merge
1350
1351bool
1352pass_ipa_cdtor_merge::gate (function *)
1353{
1354  /* Perform the pass when we have no ctors/dtors support
1355     or at LTO time to merge multiple constructors into single
1356     function.  */
1357  return !targetm.have_ctors_dtors || in_lto_p || targetm.dtors_from_cxa_atexit;
1358}
1359
1360} // anon namespace
1361
1362ipa_opt_pass_d *
1363make_pass_ipa_cdtor_merge (gcc::context *ctxt)
1364{
1365  return new pass_ipa_cdtor_merge (ctxt);
1366}
1367
1368/* Invalid pointer representing BOTTOM for single user dataflow.  */
1369#define BOTTOM ((cgraph_node *)(size_t) 2)
1370
1371/* Meet operation for single user dataflow.
1372   Here we want to associate variables with sigle function that may access it.
1373
1374   FUNCTION is current single user of a variable, VAR is variable that uses it.
1375   Latttice is stored in SINGLE_USER_MAP.
1376
1377   We represent:
1378    - TOP by no entry in SIGNLE_USER_MAP
1379    - BOTTOM by BOTTOM in AUX pointer (to save lookups)
1380    - known single user by cgraph pointer in SINGLE_USER_MAP.  */
1381
1382cgraph_node *
1383meet (cgraph_node *function, varpool_node *var,
1384       hash_map<varpool_node *, cgraph_node *> &single_user_map)
1385{
1386  struct cgraph_node *user, **f;
1387
1388  if (var->aux == BOTTOM)
1389    return BOTTOM;
1390
1391  f = single_user_map.get (var);
1392  if (!f)
1393    return function;
1394  user = *f;
1395  if (!function)
1396    return user;
1397  else if (function != user)
1398    return BOTTOM;
1399  else
1400    return function;
1401}
1402
1403/* Propagation step of single-use dataflow.
1404
1405   Check all uses of VNODE and see if they are used by single function FUNCTION.
1406   SINGLE_USER_MAP represents the dataflow lattice.  */
1407
1408cgraph_node *
1409propagate_single_user (varpool_node *vnode, cgraph_node *function,
1410		       hash_map<varpool_node *, cgraph_node *> &single_user_map)
1411{
1412  int i;
1413  struct ipa_ref *ref;
1414
1415  gcc_assert (!vnode->externally_visible);
1416
1417  /* If node is an alias, first meet with its target.  */
1418  if (vnode->alias)
1419    function = meet (function, vnode->get_alias_target (), single_user_map);
1420
1421  /* Check all users and see if they correspond to a single function.  */
1422  for (i = 0; vnode->iterate_referring (i, ref) && function != BOTTOM; i++)
1423    {
1424      struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring);
1425      if (cnode)
1426	{
1427	  if (cnode->inlined_to)
1428	    cnode = cnode->inlined_to;
1429	  if (!function)
1430	    function = cnode;
1431	  else if (function != cnode)
1432	    function = BOTTOM;
1433	}
1434      else
1435	function = meet (function, dyn_cast <varpool_node *> (ref->referring),
1436			 single_user_map);
1437    }
1438  return function;
1439}
1440
1441/* Pass setting used_by_single_function flag.
1442   This flag is set on variable when there is only one function that may
1443   possibly referr to it.  */
1444
1445static unsigned int
1446ipa_single_use (void)
1447{
1448  varpool_node *first = (varpool_node *) (void *) 1;
1449  varpool_node *var;
1450  hash_map<varpool_node *, cgraph_node *> single_user_map;
1451
1452  FOR_EACH_DEFINED_VARIABLE (var)
1453    if (!var->all_refs_explicit_p ())
1454      var->aux = BOTTOM;
1455    else
1456      {
1457	/* Enqueue symbol for dataflow.  */
1458        var->aux = first;
1459	first = var;
1460      }
1461
1462  /* The actual dataflow.  */
1463
1464  while (first != (void *) 1)
1465    {
1466      cgraph_node *user, *orig_user, **f;
1467
1468      var = first;
1469      first = (varpool_node *)first->aux;
1470
1471      f = single_user_map.get (var);
1472      if (f)
1473	orig_user = *f;
1474      else
1475	orig_user = NULL;
1476      user = propagate_single_user (var, orig_user, single_user_map);
1477
1478      gcc_checking_assert (var->aux != BOTTOM);
1479
1480      /* If user differs, enqueue all references.  */
1481      if (user != orig_user)
1482	{
1483	  unsigned int i;
1484	  ipa_ref *ref;
1485
1486	  single_user_map.put (var, user);
1487
1488	  /* Enqueue all aliases for re-processing.  */
1489	  for (i = 0; var->iterate_direct_aliases (i, ref); i++)
1490	    if (!ref->referring->aux)
1491	      {
1492		ref->referring->aux = first;
1493		first = dyn_cast <varpool_node *> (ref->referring);
1494	      }
1495	  /* Enqueue all users for re-processing.  */
1496	  for (i = 0; var->iterate_reference (i, ref); i++)
1497	    if (!ref->referred->aux
1498	        && ref->referred->definition
1499		&& is_a <varpool_node *> (ref->referred))
1500	      {
1501		ref->referred->aux = first;
1502		first = dyn_cast <varpool_node *> (ref->referred);
1503	      }
1504
1505	  /* If user is BOTTOM, just punt on this var.  */
1506	  if (user == BOTTOM)
1507	    var->aux = BOTTOM;
1508	  else
1509	    var->aux = NULL;
1510	}
1511      else
1512	var->aux = NULL;
1513    }
1514
1515  FOR_EACH_DEFINED_VARIABLE (var)
1516    {
1517      if (var->aux != BOTTOM)
1518	{
1519	  /* Not having the single user known means that the VAR is
1520	     unreachable.  Either someone forgot to remove unreachable
1521	     variables or the reachability here is wrong.  */
1522
1523	  gcc_checking_assert (single_user_map.get (var));
1524
1525	  if (dump_file)
1526	    {
1527	      fprintf (dump_file, "Variable %s is used by single function\n",
1528		       var->dump_name ());
1529	    }
1530	  var->used_by_single_function = true;
1531	}
1532      var->aux = NULL;
1533    }
1534  return 0;
1535}
1536
1537namespace {
1538
1539const pass_data pass_data_ipa_single_use =
1540{
1541  IPA_PASS, /* type */
1542  "single-use", /* name */
1543  OPTGROUP_NONE, /* optinfo_flags */
1544  TV_CGRAPHOPT, /* tv_id */
1545  0, /* properties_required */
1546  0, /* properties_provided */
1547  0, /* properties_destroyed */
1548  0, /* todo_flags_start */
1549  0, /* todo_flags_finish */
1550};
1551
1552class pass_ipa_single_use : public ipa_opt_pass_d
1553{
1554public:
1555  pass_ipa_single_use (gcc::context *ctxt)
1556    : ipa_opt_pass_d (pass_data_ipa_single_use, ctxt,
1557		      NULL, /* generate_summary */
1558		      NULL, /* write_summary */
1559		      NULL, /* read_summary */
1560		      NULL, /* write_optimization_summary */
1561		      NULL, /* read_optimization_summary */
1562		      NULL, /* stmt_fixup */
1563		      0, /* function_transform_todo_flags_start */
1564		      NULL, /* function_transform */
1565		      NULL) /* variable_transform */
1566  {}
1567
1568  /* opt_pass methods: */
1569  virtual unsigned int execute (function *) { return ipa_single_use (); }
1570
1571}; // class pass_ipa_single_use
1572
1573} // anon namespace
1574
1575ipa_opt_pass_d *
1576make_pass_ipa_single_use (gcc::context *ctxt)
1577{
1578  return new pass_ipa_single_use (ctxt);
1579}
1580
1581