1169689Skan/* Callgraph based analysis of static variables.
2169689Skan   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3169689Skan   Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.
21169689Skan*/
22169689Skan
23169689Skan/* This file gathers information about how variables whose scope is
24169689Skan   confined to the compilation unit are used.
25169689Skan
26169689Skan   There are two categories of information produced by this pass:
27169689Skan
28169689Skan   1) The addressable (TREE_ADDRESSABLE) bit and readonly
29169689Skan   (TREE_READONLY) bit associated with these variables is properly set
30169689Skan   based on scanning all of the code withing the compilation unit.
31169689Skan
32169689Skan   2) The transitive call site specific clobber effects are computed
33169689Skan   for the variables whose scope is contained within this compilation
34169689Skan   unit.
35169689Skan
36169689Skan   First each function and static variable initialization is analyzed
37169689Skan   to determine which local static variables are either read, written,
38169689Skan   or have their address taken.  Any local static that has its address
39169689Skan   taken is removed from consideration.  Once the local read and
40169689Skan   writes are determined, a transitive closure of this information is
41169689Skan   performed over the call graph to determine the worst case set of
42169689Skan   side effects of each call.  In later parts of the compiler, these
43169689Skan   local and global sets are examined to make the call clobbering less
44169689Skan   traumatic, promote some statics to registers, and improve aliasing
45169689Skan   information.
46169689Skan
47169689Skan   Currently must be run after inlining decisions have been made since
48169689Skan   otherwise, the local sets will not contain information that is
49169689Skan   consistent with post inlined state.  The global sets are not prone
50169689Skan   to this problem since they are by definition transitive.
51169689Skan*/
52169689Skan
53169689Skan#include "config.h"
54169689Skan#include "system.h"
55169689Skan#include "coretypes.h"
56169689Skan#include "tm.h"
57169689Skan#include "tree.h"
58169689Skan#include "tree-flow.h"
59169689Skan#include "tree-inline.h"
60169689Skan#include "tree-pass.h"
61169689Skan#include "langhooks.h"
62169689Skan#include "pointer-set.h"
63169689Skan#include "ggc.h"
64169689Skan#include "ipa-utils.h"
65169689Skan#include "ipa-reference.h"
66169689Skan#include "c-common.h"
67169689Skan#include "tree-gimple.h"
68169689Skan#include "cgraph.h"
69169689Skan#include "output.h"
70169689Skan#include "flags.h"
71169689Skan#include "timevar.h"
72169689Skan#include "diagnostic.h"
73169689Skan#include "langhooks.h"
74169689Skan
75169689Skan/* This splay tree contains all of the static variables that are
76169689Skan   being considered by the compilation level alias analysis.  For
77169689Skan   module_at_a_time compilation, this is the set of static but not
78169689Skan   public variables.  Any variables that either have their address
79169689Skan   taken or participate in otherwise unsavory operations are deleted
80169689Skan   from this list.  */
81169689Skanstatic GTY((param1_is(int), param2_is(tree)))
82169689Skan     splay_tree reference_vars_to_consider;
83169689Skan
84169689Skan/* This bitmap is used to knock out the module static variables whose
85169689Skan   addresses have been taken and passed around.  */
86169689Skanstatic bitmap module_statics_escape;
87169689Skan
88169689Skan/* This bitmap is used to knock out the module static variables that
89169689Skan   are not readonly.  */
90169689Skanstatic bitmap module_statics_written;
91169689Skan
92169689Skan/* A bit is set for every module static we are considering.  This is
93169689Skan   ored into the local info when asm code is found that clobbers all
94169689Skan   memory. */
95169689Skanstatic bitmap all_module_statics;
96169689Skan
97169689Skanstatic struct pointer_set_t *visited_nodes;
98169689Skan
99169689Skanstatic bitmap_obstack ipa_obstack;
100169689Skan
101169689Skanenum initialization_status_t
102169689Skan{
103169689Skan  UNINITIALIZED,
104169689Skan  RUNNING,
105169689Skan  FINISHED
106169689Skan};
107169689Skan
108169689Skantree memory_identifier_string;
109169689Skan
110169689Skan/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
111169689Skanstatic inline ipa_reference_vars_info_t
112169689Skanget_reference_vars_info_from_cgraph (struct cgraph_node * node)
113169689Skan{
114169689Skan  return get_function_ann (node->decl)->reference_vars_info;
115169689Skan}
116169689Skan
117169689Skan/* Get a bitmap that contains all of the locally referenced static
118169689Skan   variables for function FN.  */
119169689Skanstatic ipa_reference_local_vars_info_t
120169689Skanget_local_reference_vars_info (tree fn)
121169689Skan{
122169689Skan  ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
123169689Skan
124169689Skan  if (info)
125169689Skan    return info->local;
126169689Skan  else
127169689Skan    /* This phase was not run.  */
128169689Skan    return NULL;
129169689Skan}
130169689Skan
131169689Skan/* Get a bitmap that contains all of the globally referenced static
132169689Skan   variables for function FN.  */
133169689Skan
134169689Skanstatic ipa_reference_global_vars_info_t
135169689Skanget_global_reference_vars_info (tree fn)
136169689Skan{
137169689Skan  ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
138169689Skan
139169689Skan  if (info)
140169689Skan    return info->global;
141169689Skan  else
142169689Skan    /* This phase was not run.  */
143169689Skan    return NULL;
144169689Skan}
145169689Skan
146169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables
147169689Skan   that may be read locally by the execution of the function fn.
148169689Skan   Returns NULL if no data is available.  */
149169689Skan
150169689Skanbitmap
151169689Skanipa_reference_get_read_local (tree fn)
152169689Skan{
153169689Skan  ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
154169689Skan  if (l)
155169689Skan    return l->statics_read;
156169689Skan  else
157169689Skan    return NULL;
158169689Skan}
159169689Skan
160169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables
161169689Skan   that may be written locally by the execution of the function fn.
162169689Skan   Returns NULL if no data is available.  */
163169689Skan
164169689Skanbitmap
165169689Skanipa_reference_get_written_local (tree fn)
166169689Skan{
167169689Skan  ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
168169689Skan  if (l)
169169689Skan    return l->statics_written;
170169689Skan  else
171169689Skan    return NULL;
172169689Skan}
173169689Skan
174169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables
175169689Skan   that are read during the execution of the function FN.  Returns
176169689Skan   NULL if no data is available.  */
177169689Skan
178169689Skanbitmap
179169689Skanipa_reference_get_read_global (tree fn)
180169689Skan{
181169689Skan  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
182169689Skan  if (g)
183169689Skan    return g->statics_read;
184169689Skan  else
185169689Skan    return NULL;
186169689Skan}
187169689Skan
188169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables
189169689Skan   that are written during the execution of the function FN.  Note
190169689Skan   that variables written may or may not be read during the function
191169689Skan   call.  Returns NULL if no data is available.  */
192169689Skan
193169689Skanbitmap
194169689Skanipa_reference_get_written_global (tree fn)
195169689Skan{
196169689Skan  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
197169689Skan  if (g)
198169689Skan    return g->statics_written;
199169689Skan  else
200169689Skan    return NULL;
201169689Skan}
202169689Skan
203169689Skan/* Return a bitmap indexed by_DECL_UID uid for the static variables
204169689Skan   that are not read during the execution of the function FN.  Returns
205169689Skan   NULL if no data is available.  */
206169689Skan
207169689Skanbitmap
208169689Skanipa_reference_get_not_read_global (tree fn)
209169689Skan{
210169689Skan  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
211169689Skan  if (g)
212169689Skan    return g->statics_not_read;
213169689Skan  else
214169689Skan    return NULL;
215169689Skan}
216169689Skan
217169689Skan/* Return a bitmap indexed by DECL_UID uid for the static variables
218169689Skan   that are not written during the execution of the function FN.  Note
219169689Skan   that variables written may or may not be read during the function
220169689Skan   call.  Returns NULL if no data is available.  */
221169689Skan
222169689Skanbitmap
223169689Skanipa_reference_get_not_written_global (tree fn)
224169689Skan{
225169689Skan  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
226169689Skan  if (g)
227169689Skan    return g->statics_not_written;
228169689Skan  else
229169689Skan    return NULL;
230169689Skan}
231169689Skan
232169689Skan
233169689Skan
234169689Skan/* Add VAR to all_module_statics and the two
235169689Skan   reference_vars_to_consider* sets.  */
236169689Skan
237169689Skanstatic inline void
238169689Skanadd_static_var (tree var)
239169689Skan{
240169689Skan  int uid = DECL_UID (var);
241169689Skan  if (!bitmap_bit_p (all_module_statics, uid))
242169689Skan    {
243169689Skan      splay_tree_insert (reference_vars_to_consider,
244169689Skan			 uid, (splay_tree_value)var);
245169689Skan      bitmap_set_bit (all_module_statics, uid);
246169689Skan    }
247169689Skan}
248169689Skan
249169689Skan/* Return true if the variable T is the right kind of static variable to
250169689Skan   perform compilation unit scope escape analysis.  */
251169689Skan
252169689Skanstatic inline bool
253169689Skanhas_proper_scope_for_analysis (tree t)
254169689Skan{
255169689Skan  /* If the variable has the "used" attribute, treat it as if it had a
256169689Skan     been touched by the devil.  */
257169689Skan  if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
258169689Skan    return false;
259169689Skan
260169689Skan  /* Do not want to do anything with volatile except mark any
261169689Skan     function that uses one to be not const or pure.  */
262169689Skan  if (TREE_THIS_VOLATILE (t))
263169689Skan    return false;
264169689Skan
265169689Skan  /* Do not care about a local automatic that is not static.  */
266169689Skan  if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
267169689Skan    return false;
268169689Skan
269169689Skan  if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
270169689Skan    return false;
271169689Skan
272169689Skan  /* This is a variable we care about.  Check if we have seen it
273169689Skan     before, and if not add it the set of variables we care about.  */
274169689Skan  if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
275169689Skan    add_static_var (t);
276169689Skan
277169689Skan  return true;
278169689Skan}
279169689Skan
280169689Skan/* If T is a VAR_DECL for a static that we are interested in, add the
281169689Skan   uid to the bitmap.  */
282169689Skan
283169689Skanstatic void
284169689Skancheck_operand (ipa_reference_local_vars_info_t local,
285169689Skan	       tree t, bool checking_write)
286169689Skan{
287169689Skan  if (!t) return;
288169689Skan
289169689Skan  if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
290169689Skan      && (has_proper_scope_for_analysis (t)))
291169689Skan    {
292169689Skan      if (checking_write)
293169689Skan	{
294169689Skan	  if (local)
295169689Skan	    bitmap_set_bit (local->statics_written, DECL_UID (t));
296169689Skan	  /* Mark the write so we can tell which statics are
297169689Skan	     readonly.  */
298169689Skan	  bitmap_set_bit (module_statics_written, DECL_UID (t));
299169689Skan	}
300169689Skan      else if (local)
301169689Skan	bitmap_set_bit (local->statics_read, DECL_UID (t));
302169689Skan    }
303169689Skan}
304169689Skan
305169689Skan/* Examine tree T for references to static variables. All internal
306169689Skan   references like array references or indirect references are added
307169689Skan   to the READ_BM. Direct references are added to either READ_BM or
308169689Skan   WRITE_BM depending on the value of CHECKING_WRITE.   */
309169689Skan
310169689Skanstatic void
311169689Skancheck_tree (ipa_reference_local_vars_info_t local, tree t, bool checking_write)
312169689Skan{
313169689Skan  if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
314169689Skan    return;
315169689Skan
316169689Skan  while (TREE_CODE (t) == REALPART_EXPR
317169689Skan	 || TREE_CODE (t) == IMAGPART_EXPR
318169689Skan	 || handled_component_p (t))
319169689Skan    {
320169689Skan      if (TREE_CODE (t) == ARRAY_REF)
321169689Skan	check_operand (local, TREE_OPERAND (t, 1), false);
322169689Skan      t = TREE_OPERAND (t, 0);
323169689Skan    }
324169689Skan
325169689Skan  /* The bottom of an indirect reference can only be read, not
326169689Skan     written.  So just recurse and whatever we find, check it against
327169689Skan     the read bitmaps.  */
328169689Skan
329169689Skan  /*  if (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF) */
330169689Skan  /* FIXME when we have array_ref's of pointers.  */
331169689Skan  if (INDIRECT_REF_P (t))
332169689Skan    check_tree (local, TREE_OPERAND (t, 0), false);
333169689Skan
334169689Skan  if (SSA_VAR_P (t))
335169689Skan    check_operand (local, t, checking_write);
336169689Skan}
337169689Skan
338169689Skan/* Scan tree T to see if there are any addresses taken in within T.  */
339169689Skan
340169689Skanstatic void
341169689Skanlook_for_address_of (tree t)
342169689Skan{
343169689Skan  if (TREE_CODE (t) == ADDR_EXPR)
344169689Skan    {
345169689Skan      tree x = get_base_var (t);
346169689Skan      if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL)
347169689Skan	if (has_proper_scope_for_analysis (x))
348169689Skan	  bitmap_set_bit (module_statics_escape, DECL_UID (x));
349169689Skan    }
350169689Skan}
351169689Skan
352169689Skan/* Check to see if T is a read or address of operation on a static var
353169689Skan   we are interested in analyzing.  LOCAL is passed in to get access
354169689Skan   to its bit vectors.  Local is NULL if this is called from a static
355169689Skan   initializer.  */
356169689Skan
357169689Skanstatic void
358169689Skancheck_rhs_var (ipa_reference_local_vars_info_t local, tree t)
359169689Skan{
360169689Skan  look_for_address_of (t);
361169689Skan
362169689Skan  if (local == NULL)
363169689Skan    return;
364169689Skan
365169689Skan  check_tree(local, t, false);
366169689Skan}
367169689Skan
368169689Skan/* Check to see if T is an assignment to a static var we are
369169689Skan   interested in analyzing.  LOCAL is passed in to get access to its bit
370169689Skan   vectors.  */
371169689Skan
372169689Skanstatic void
373169689Skancheck_lhs_var (ipa_reference_local_vars_info_t local, tree t)
374169689Skan{
375169689Skan  if (local == NULL)
376169689Skan    return;
377169689Skan
378169689Skan  check_tree(local, t, true);
379169689Skan}
380169689Skan
381169689Skan/* This is a scaled down version of get_asm_expr_operands from
382169689Skan   tree_ssa_operands.c.  The version there runs much later and assumes
383169689Skan   that aliasing information is already available. Here we are just
384169689Skan   trying to find if the set of inputs and outputs contain references
385169689Skan   or address of operations to local static variables.  FN is the
386169689Skan   function being analyzed and STMT is the actual asm statement.  */
387169689Skan
388169689Skanstatic void
389169689Skanget_asm_expr_operands (ipa_reference_local_vars_info_t local, tree stmt)
390169689Skan{
391169689Skan  int noutputs = list_length (ASM_OUTPUTS (stmt));
392169689Skan  const char **oconstraints
393169689Skan    = (const char **) alloca ((noutputs) * sizeof (const char *));
394169689Skan  int i;
395169689Skan  tree link;
396169689Skan  const char *constraint;
397169689Skan  bool allows_mem, allows_reg, is_inout;
398169689Skan
399169689Skan  for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
400169689Skan    {
401169689Skan      oconstraints[i] = constraint
402169689Skan	= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
403169689Skan      parse_output_constraint (&constraint, i, 0, 0,
404169689Skan			       &allows_mem, &allows_reg, &is_inout);
405169689Skan
406169689Skan      check_lhs_var (local, TREE_VALUE (link));
407169689Skan    }
408169689Skan
409169689Skan  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
410169689Skan    {
411169689Skan      constraint
412169689Skan	= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
413169689Skan      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
414169689Skan			      oconstraints, &allows_mem, &allows_reg);
415169689Skan
416169689Skan      check_rhs_var (local, TREE_VALUE (link));
417169689Skan    }
418169689Skan
419169689Skan  for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
420169689Skan    if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1)
421169689Skan      {
422169689Skan	/* Abandon all hope, ye who enter here. */
423169689Skan	local->calls_read_all = true;
424169689Skan	local->calls_write_all = true;
425169689Skan      }
426169689Skan}
427169689Skan
428169689Skan/* Check the parameters of a function call from CALLER to CALL_EXPR to
429169689Skan   see if any of them are static vars.  Also check to see if this is
430169689Skan   either an indirect call, a call outside the compilation unit, or
431169689Skan   has special attributes that effect the clobbers.  The caller
432169689Skan   parameter is the tree node for the caller and the second operand is
433169689Skan   the tree node for the entire call expression.  */
434169689Skan
435169689Skanstatic void
436169689Skancheck_call (ipa_reference_local_vars_info_t local, tree call_expr)
437169689Skan{
438169689Skan  int flags = call_expr_flags (call_expr);
439169689Skan  tree operand_list = TREE_OPERAND (call_expr, 1);
440169689Skan  tree operand;
441169689Skan  tree callee_t = get_callee_fndecl (call_expr);
442169689Skan  enum availability avail = AVAIL_NOT_AVAILABLE;
443169689Skan
444169689Skan  for (operand = operand_list;
445169689Skan       operand != NULL_TREE;
446169689Skan       operand = TREE_CHAIN (operand))
447169689Skan    {
448169689Skan      tree argument = TREE_VALUE (operand);
449169689Skan      check_rhs_var (local, argument);
450169689Skan    }
451169689Skan
452169689Skan  if (callee_t)
453169689Skan    {
454169689Skan      struct cgraph_node* callee = cgraph_node(callee_t);
455169689Skan      avail = cgraph_function_body_availability (callee);
456169689Skan    }
457169689Skan
458169689Skan  if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
459169689Skan    if (local)
460169689Skan      {
461169689Skan	if (flags & ECF_PURE)
462169689Skan	  local->calls_read_all = true;
463169689Skan	else
464169689Skan	  {
465169689Skan	    local->calls_read_all = true;
466169689Skan	    local->calls_write_all = true;
467169689Skan	  }
468169689Skan      }
469169689Skan}
470169689Skan
471169689Skan/* TP is the part of the tree currently under the microscope.
472169689Skan   WALK_SUBTREES is part of the walk_tree api but is unused here.
473169689Skan   DATA is cgraph_node of the function being walked.  */
474169689Skan
475169689Skan/* FIXME: When this is converted to run over SSA form, this code
476169689Skan   should be converted to use the operand scanner.  */
477169689Skan
478169689Skanstatic tree
479169689Skanscan_for_static_refs (tree *tp,
480169689Skan		      int *walk_subtrees,
481169689Skan		      void *data)
482169689Skan{
483169689Skan  struct cgraph_node *fn = data;
484169689Skan  tree t = *tp;
485169689Skan  ipa_reference_local_vars_info_t local = NULL;
486169689Skan  if (fn)
487169689Skan    local = get_reference_vars_info_from_cgraph (fn)->local;
488169689Skan
489169689Skan  switch (TREE_CODE (t))
490169689Skan    {
491169689Skan    case VAR_DECL:
492169689Skan      if (DECL_INITIAL (t))
493169689Skan	walk_tree (&DECL_INITIAL (t), scan_for_static_refs, fn, visited_nodes);
494169689Skan      *walk_subtrees = 0;
495169689Skan      break;
496169689Skan
497169689Skan    case MODIFY_EXPR:
498169689Skan      {
499169689Skan	/* First look on the lhs and see what variable is stored to */
500169689Skan	tree lhs = TREE_OPERAND (t, 0);
501169689Skan	tree rhs = TREE_OPERAND (t, 1);
502169689Skan	check_lhs_var (local, lhs);
503169689Skan
504169689Skan	/* For the purposes of figuring out what the cast affects */
505169689Skan
506169689Skan	/* Next check the operands on the rhs to see if they are ok. */
507169689Skan	switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
508169689Skan	  {
509169689Skan	  case tcc_binary:
510169689Skan	  case tcc_comparison:
511169689Skan 	    {
512169689Skan 	      tree op0 = TREE_OPERAND (rhs, 0);
513169689Skan 	      tree op1 = TREE_OPERAND (rhs, 1);
514169689Skan 	      check_rhs_var (local, op0);
515169689Skan 	      check_rhs_var (local, op1);
516169689Skan	    }
517169689Skan	    break;
518169689Skan	  case tcc_unary:
519169689Skan 	    {
520169689Skan 	      tree op0 = TREE_OPERAND (rhs, 0);
521169689Skan 	      check_rhs_var (local, op0);
522169689Skan 	    }
523169689Skan
524169689Skan	    break;
525169689Skan	  case tcc_reference:
526169689Skan	    check_rhs_var (local, rhs);
527169689Skan	    break;
528169689Skan	  case tcc_declaration:
529169689Skan	    check_rhs_var (local, rhs);
530169689Skan	    break;
531169689Skan	  case tcc_expression:
532169689Skan	    switch (TREE_CODE (rhs))
533169689Skan	      {
534169689Skan	      case ADDR_EXPR:
535169689Skan		check_rhs_var (local, rhs);
536169689Skan		break;
537169689Skan	      case CALL_EXPR:
538169689Skan		check_call (local, rhs);
539169689Skan		break;
540169689Skan	      default:
541169689Skan		break;
542169689Skan	      }
543169689Skan	    break;
544169689Skan	  default:
545169689Skan	    break;
546169689Skan	  }
547169689Skan	*walk_subtrees = 0;
548169689Skan      }
549169689Skan      break;
550169689Skan
551169689Skan    case ADDR_EXPR:
552169689Skan      /* This case is here to find addresses on rhs of constructors in
553169689Skan	 decl_initial of static variables. */
554169689Skan      check_rhs_var (local, t);
555169689Skan      *walk_subtrees = 0;
556169689Skan      break;
557169689Skan
558169689Skan    case LABEL_EXPR:
559169689Skan      if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
560169689Skan	{
561169689Skan	  /* Target of long jump. */
562169689Skan	  local->calls_read_all = true;
563169689Skan	  local->calls_write_all = true;
564169689Skan	}
565169689Skan      break;
566169689Skan
567169689Skan    case CALL_EXPR:
568169689Skan      check_call (local, t);
569169689Skan      *walk_subtrees = 0;
570169689Skan      break;
571169689Skan
572169689Skan    case ASM_EXPR:
573169689Skan      get_asm_expr_operands (local, t);
574169689Skan      *walk_subtrees = 0;
575169689Skan      break;
576169689Skan
577169689Skan    default:
578169689Skan      break;
579169689Skan    }
580169689Skan  return NULL;
581169689Skan}
582169689Skan
583169689Skan
584169689Skan/* Lookup the tree node for the static variable that has UID.  */
585169689Skanstatic tree
586169689Skanget_static_decl (int index)
587169689Skan{
588169689Skan  splay_tree_node stn =
589169689Skan    splay_tree_lookup (reference_vars_to_consider, index);
590169689Skan  if (stn)
591169689Skan    return (tree)stn->value;
592169689Skan  return NULL;
593169689Skan}
594169689Skan
595169689Skan/* Lookup the tree node for the static variable that has UID and
596169689Skan   convert the name to a string for debugging.  */
597169689Skan
598169689Skanstatic const char *
599169689Skanget_static_name (int index)
600169689Skan{
601169689Skan  splay_tree_node stn =
602169689Skan    splay_tree_lookup (reference_vars_to_consider, index);
603169689Skan  if (stn)
604169689Skan    return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
605169689Skan  return NULL;
606169689Skan}
607169689Skan
608169689Skan/* Or in all of the bits from every callee into X, the caller's, bit
609169689Skan   vector.  There are several cases to check to avoid the sparse
610169689Skan   bitmap oring.  */
611169689Skan
612169689Skanstatic void
613169689Skanpropagate_bits (struct cgraph_node *x)
614169689Skan{
615169689Skan  ipa_reference_vars_info_t x_info = get_reference_vars_info_from_cgraph (x);
616169689Skan  ipa_reference_global_vars_info_t x_global = x_info->global;
617169689Skan
618169689Skan  struct cgraph_edge *e;
619169689Skan  for (e = x->callees; e; e = e->next_callee)
620169689Skan    {
621169689Skan      struct cgraph_node *y = e->callee;
622169689Skan
623169689Skan      /* Only look at the master nodes and skip external nodes.  */
624169689Skan      y = cgraph_master_clone (y);
625169689Skan      if (y)
626169689Skan	{
627169689Skan	  if (get_reference_vars_info_from_cgraph (y))
628169689Skan	    {
629169689Skan	      ipa_reference_vars_info_t y_info = get_reference_vars_info_from_cgraph (y);
630169689Skan	      ipa_reference_global_vars_info_t y_global = y_info->global;
631169689Skan
632169689Skan	      if (x_global->statics_read
633169689Skan		  != all_module_statics)
634169689Skan		{
635169689Skan		  if (y_global->statics_read
636169689Skan		      == all_module_statics)
637169689Skan		    {
638169689Skan		      BITMAP_FREE (x_global->statics_read);
639169689Skan		      x_global->statics_read
640169689Skan			= all_module_statics;
641169689Skan		    }
642169689Skan		  /* Skip bitmaps that are pointer equal to node's bitmap
643169689Skan		     (no reason to spin within the cycle).  */
644169689Skan		  else if (x_global->statics_read
645169689Skan			   != y_global->statics_read)
646169689Skan		    bitmap_ior_into (x_global->statics_read,
647169689Skan				     y_global->statics_read);
648169689Skan		}
649169689Skan
650169689Skan	      if (x_global->statics_written
651169689Skan		  != all_module_statics)
652169689Skan		{
653169689Skan		  if (y_global->statics_written
654169689Skan		      == all_module_statics)
655169689Skan		    {
656169689Skan		      BITMAP_FREE (x_global->statics_written);
657169689Skan		      x_global->statics_written
658169689Skan			= all_module_statics;
659169689Skan		    }
660169689Skan		  /* Skip bitmaps that are pointer equal to node's bitmap
661169689Skan		     (no reason to spin within the cycle).  */
662169689Skan		  else if (x_global->statics_written
663169689Skan			   != y_global->statics_written)
664169689Skan		    bitmap_ior_into (x_global->statics_written,
665169689Skan				     y_global->statics_written);
666169689Skan		}
667169689Skan	    }
668169689Skan	  else
669169689Skan	    {
670169689Skan	      gcc_unreachable ();
671169689Skan	    }
672169689Skan	}
673169689Skan    }
674169689Skan}
675169689Skan
676169689Skan/* Look at all of the callees of X to see which ones represent inlined
677169689Skan   calls.  For each of these callees, merge their local info into
678169689Skan   TARGET and check their children recursively.
679169689Skan
680169689Skan   This function goes away when Jan changes the inliner and IPA
681169689Skan   analysis so that this is not run between the time when inlining
682169689Skan   decisions are made and when the inlining actually occurs.  */
683169689Skan
684169689Skanstatic void
685169689Skanmerge_callee_local_info (struct cgraph_node *target,
686169689Skan			 struct cgraph_node *x)
687169689Skan{
688169689Skan  struct cgraph_edge *e;
689169689Skan  ipa_reference_local_vars_info_t x_l =
690169689Skan    get_reference_vars_info_from_cgraph (target)->local;
691169689Skan
692169689Skan  /* Make the world safe for tail recursion.  */
693169689Skan  struct ipa_dfs_info *node_info = x->aux;
694169689Skan
695169689Skan  if (node_info->aux)
696169689Skan    return;
697169689Skan
698169689Skan  node_info->aux = x;
699169689Skan
700169689Skan  for (e = x->callees; e; e = e->next_callee)
701169689Skan    {
702169689Skan      struct cgraph_node *y = e->callee;
703169689Skan      if (y->global.inlined_to)
704169689Skan	{
705169689Skan	  ipa_reference_vars_info_t y_info;
706169689Skan	  ipa_reference_local_vars_info_t y_l;
707169689Skan	  struct cgraph_node* orig_y = y;
708169689Skan
709169689Skan	  y = cgraph_master_clone (y);
710169689Skan	  if (y)
711169689Skan	    {
712169689Skan	      y_info = get_reference_vars_info_from_cgraph (y);
713169689Skan	      y_l = y_info->local;
714169689Skan	      if (x_l != y_l)
715169689Skan		{
716169689Skan		  bitmap_ior_into (x_l->statics_read,
717169689Skan				   y_l->statics_read);
718169689Skan		  bitmap_ior_into (x_l->statics_written,
719169689Skan				   y_l->statics_written);
720169689Skan		}
721169689Skan	      x_l->calls_read_all |= y_l->calls_read_all;
722169689Skan	      x_l->calls_write_all |= y_l->calls_write_all;
723169689Skan	      merge_callee_local_info (target, y);
724169689Skan	    }
725169689Skan	  else
726169689Skan	    {
727169689Skan	      fprintf(stderr, "suspect inlining of ");
728169689Skan	      dump_cgraph_node (stderr, orig_y);
729169689Skan	      fprintf(stderr, "\ninto ");
730169689Skan	      dump_cgraph_node (stderr, target);
731169689Skan	      dump_cgraph (stderr);
732169689Skan	      gcc_assert(false);
733169689Skan	    }
734169689Skan	}
735169689Skan    }
736169689Skan
737169689Skan  node_info->aux = NULL;
738169689Skan}
739169689Skan
740169689Skan/* The init routine for analyzing global static variable usage.  See
741169689Skan   comments at top for description.  */
742169689Skanstatic void
743169689Skanipa_init (void)
744169689Skan{
745169689Skan  struct cgraph_node *node;
746169689Skan  memory_identifier_string = build_string(7, "memory");
747169689Skan
748169689Skan  reference_vars_to_consider =
749169689Skan    splay_tree_new_ggc (splay_tree_compare_ints);
750169689Skan
751169689Skan  bitmap_obstack_initialize (&ipa_obstack);
752169689Skan  module_statics_escape = BITMAP_ALLOC (&ipa_obstack);
753169689Skan  module_statics_written = BITMAP_ALLOC (&ipa_obstack);
754169689Skan  all_module_statics = BITMAP_ALLOC (&ipa_obstack);
755169689Skan
756169689Skan  /* This will add NODE->DECL to the splay trees.  */
757169689Skan  for (node = cgraph_nodes; node; node = node->next)
758169689Skan    has_proper_scope_for_analysis (node->decl);
759169689Skan
760169689Skan  /* There are some shared nodes, in particular the initializers on
761169689Skan     static declarations.  We do not need to scan them more than once
762169689Skan     since all we would be interested in are the addressof
763169689Skan     operations.  */
764169689Skan  visited_nodes = pointer_set_create ();
765169689Skan}
766169689Skan
767169689Skan/* Check out the rhs of a static or global initialization VNODE to see
768169689Skan   if any of them contain addressof operations.  Note that some of
769169689Skan   these variables may  not even be referenced in the code in this
770169689Skan   compilation unit but their right hand sides may contain references
771169689Skan   to variables defined within this unit.  */
772169689Skan
773169689Skanstatic void
774169689Skananalyze_variable (struct cgraph_varpool_node *vnode)
775169689Skan{
776169689Skan  tree global = vnode->decl;
777169689Skan  if (TREE_CODE (global) == VAR_DECL)
778169689Skan    {
779169689Skan      if (DECL_INITIAL (global))
780169689Skan	walk_tree (&DECL_INITIAL (global), scan_for_static_refs,
781169689Skan		   NULL, visited_nodes);
782169689Skan    }
783169689Skan  else gcc_unreachable ();
784169689Skan}
785169689Skan
786169689Skan/* This is the main routine for finding the reference patterns for
787169689Skan   global variables within a function FN.  */
788169689Skan
789169689Skanstatic void
790169689Skananalyze_function (struct cgraph_node *fn)
791169689Skan{
792169689Skan  ipa_reference_vars_info_t info
793169689Skan    = xcalloc (1, sizeof (struct ipa_reference_vars_info_d));
794169689Skan  ipa_reference_local_vars_info_t l
795169689Skan    = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d));
796169689Skan  tree decl = fn->decl;
797169689Skan
798169689Skan  /* Add the info to the tree's annotation.  */
799169689Skan  get_function_ann (fn->decl)->reference_vars_info = info;
800169689Skan
801169689Skan  info->local = l;
802169689Skan  l->statics_read = BITMAP_ALLOC (&ipa_obstack);
803169689Skan  l->statics_written = BITMAP_ALLOC (&ipa_obstack);
804169689Skan
805169689Skan  if (dump_file)
806169689Skan    fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
807169689Skan
808169689Skan  {
809169689Skan    struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
810169689Skan    basic_block this_block;
811169689Skan
812169689Skan    FOR_EACH_BB_FN (this_block, this_cfun)
813169689Skan      {
814169689Skan	block_stmt_iterator bsi;
815169689Skan	for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
816169689Skan	  walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs,
817169689Skan		     fn, visited_nodes);
818169689Skan      }
819169689Skan  }
820169689Skan
821169689Skan  /* There may be const decls with interesting right hand sides.  */
822169689Skan  if (DECL_STRUCT_FUNCTION (decl))
823169689Skan    {
824169689Skan      tree step;
825169689Skan      for (step = DECL_STRUCT_FUNCTION (decl)->unexpanded_var_list;
826169689Skan	   step;
827169689Skan	   step = TREE_CHAIN (step))
828169689Skan	{
829169689Skan	  tree var = TREE_VALUE (step);
830169689Skan	  if (TREE_CODE (var) == VAR_DECL
831169689Skan	      && DECL_INITIAL (var)
832169689Skan	      && !TREE_STATIC (var))
833169689Skan	    walk_tree (&DECL_INITIAL (var), scan_for_static_refs,
834169689Skan		       fn, visited_nodes);
835169689Skan	}
836169689Skan    }
837169689Skan}
838169689Skan
839169689Skan/* If FN is avail == AVAIL_OVERWRITABLE, replace the effects bit
840169689Skan   vectors with worst case bit vectors.  We had to analyze it above to
841169689Skan   find out if it took the address of any statics. However, now that
842169689Skan   we know that, we can get rid of all of the other side effects.  */
843169689Skan
844169689Skanstatic void
845169689Skanclean_function (struct cgraph_node *fn)
846169689Skan{
847169689Skan  ipa_reference_vars_info_t info = get_reference_vars_info_from_cgraph (fn);
848169689Skan  ipa_reference_local_vars_info_t l = info->local;
849169689Skan  ipa_reference_global_vars_info_t g = info->global;
850169689Skan
851169689Skan  if (l)
852169689Skan    {
853169689Skan      if (l->statics_read
854169689Skan	  && l->statics_read != all_module_statics)
855169689Skan	BITMAP_FREE (l->statics_read);
856169689Skan      if (l->statics_written
857169689Skan	  &&l->statics_written != all_module_statics)
858169689Skan	BITMAP_FREE (l->statics_written);
859169689Skan      free (l);
860169689Skan    }
861169689Skan
862169689Skan  if (g)
863169689Skan    {
864169689Skan      if (g->statics_read
865169689Skan	  && g->statics_read != all_module_statics)
866169689Skan	BITMAP_FREE (g->statics_read);
867169689Skan
868169689Skan      if (g->statics_written
869169689Skan	  && g->statics_written != all_module_statics)
870169689Skan	BITMAP_FREE (g->statics_written);
871169689Skan
872169689Skan      if (g->statics_not_read
873169689Skan	  && g->statics_not_read != all_module_statics)
874169689Skan	BITMAP_FREE (g->statics_not_read);
875169689Skan
876169689Skan      if (g->statics_not_written
877169689Skan	  && g->statics_not_written != all_module_statics)
878169689Skan	BITMAP_FREE (g->statics_not_written);
879169689Skan      free (g);
880169689Skan    }
881169689Skan
882169689Skan
883169689Skan  free (get_function_ann (fn->decl)->reference_vars_info);
884169689Skan  get_function_ann (fn->decl)->reference_vars_info = NULL;
885169689Skan}
886169689Skan
887169689Skan
888169689Skan/* Produce the global information by preforming a transitive closure
889169689Skan   on the local information that was produced by ipa_analyze_function
890169689Skan   and ipa_analyze_variable.  */
891169689Skan
892169689Skanstatic unsigned int
893169689Skanstatic_execute (void)
894169689Skan{
895169689Skan  struct cgraph_node *node;
896169689Skan  struct cgraph_varpool_node *vnode;
897169689Skan  struct cgraph_node *w;
898169689Skan  struct cgraph_node **order =
899169689Skan    xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
900169689Skan  int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true);
901169689Skan  int i;
902169689Skan
903169689Skan  ipa_init ();
904169689Skan
905169689Skan  /* Process all of the variables first.  */
906169689Skan  for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
907169689Skan    analyze_variable (vnode);
908169689Skan
909169689Skan  /* Process all of the functions next.
910169689Skan
911169689Skan     We do not want to process any of the clones so we check that this
912169689Skan     is a master clone.  However, we do need to process any
913169689Skan     AVAIL_OVERWRITABLE functions (these are never clones) because
914169689Skan     they may cause a static variable to escape.  The code that can
915169689Skan     overwrite such a function cannot access the statics because it
916169689Skan     would not be in the same compilation unit.  When the analysis is
917169689Skan     finished, the computed information of these AVAIL_OVERWRITABLE is
918169689Skan     replaced with worst case info.
919169689Skan  */
920169689Skan  for (node = cgraph_nodes; node; node = node->next)
921169689Skan    if (node->analyzed
922169689Skan	&& (cgraph_is_master_clone (node)
923169689Skan	    || (cgraph_function_body_availability (node)
924169689Skan		== AVAIL_OVERWRITABLE)))
925169689Skan      analyze_function (node);
926169689Skan
927169689Skan  pointer_set_destroy (visited_nodes);
928169689Skan  visited_nodes = NULL;
929169689Skan  if (dump_file)
930169689Skan    dump_cgraph (dump_file);
931169689Skan
932169689Skan  /* Prune out the variables that were found to behave badly
933169689Skan     (i.e. have their address taken).  */
934169689Skan  {
935169689Skan    unsigned int index;
936169689Skan    bitmap_iterator bi;
937169689Skan    bitmap module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
938169689Skan    bitmap module_statics_const = BITMAP_ALLOC (&ipa_obstack);
939169689Skan    bitmap bm_temp = BITMAP_ALLOC (&ipa_obstack);
940169689Skan
941169689Skan    EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
942169689Skan      {
943169689Skan	splay_tree_remove (reference_vars_to_consider, index);
944169689Skan      }
945169689Skan
946169689Skan    bitmap_and_compl_into (all_module_statics,
947169689Skan			   module_statics_escape);
948169689Skan
949169689Skan    bitmap_and_compl (module_statics_readonly, all_module_statics,
950169689Skan		      module_statics_written);
951169689Skan
952169689Skan    /* If the address is not taken, we can unset the addressable bit
953169689Skan       on this variable.  */
954169689Skan    EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
955169689Skan      {
956169689Skan	tree var = get_static_decl (index);
957169689Skan 	TREE_ADDRESSABLE (var) = 0;
958169689Skan	if (dump_file)
959169689Skan	  fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
960169689Skan		   get_static_name (index));
961169689Skan      }
962169689Skan
963169689Skan    /* If the variable is never written, we can set the TREE_READONLY
964169689Skan       flag.  Additionally if it has a DECL_INITIAL that is made up of
965169689Skan       constants we can treat the entire global as a constant.  */
966169689Skan
967169689Skan    bitmap_and_compl (module_statics_readonly, all_module_statics,
968169689Skan		      module_statics_written);
969169689Skan    EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
970169689Skan      {
971169689Skan	tree var = get_static_decl (index);
972169689Skan
973169689Skan	/* Readonly on a function decl is very different from the
974169689Skan	   variable.  */
975169689Skan	if (TREE_CODE (var) == FUNCTION_DECL)
976169689Skan	  continue;
977169689Skan
978169689Skan	/* Ignore variables in named sections - changing TREE_READONLY
979169689Skan	   changes the section flags, potentially causing conflicts with
980169689Skan	   other variables in the same named section.  */
981169689Skan	if (DECL_SECTION_NAME (var) == NULL_TREE)
982169689Skan	  {
983169689Skan	    TREE_READONLY (var) = 1;
984169689Skan	    if (dump_file)
985169689Skan	      fprintf (dump_file, "read-only var %s\n",
986169689Skan		       get_static_name (index));
987169689Skan	  }
988169689Skan	if (DECL_INITIAL (var)
989169689Skan	    && is_gimple_min_invariant (DECL_INITIAL (var)))
990169689Skan	  {
991169689Skan 	    bitmap_set_bit (module_statics_const, index);
992169689Skan	    if (dump_file)
993169689Skan	      fprintf (dump_file, "read-only constant %s\n",
994169689Skan		       get_static_name (index));
995169689Skan	  }
996169689Skan      }
997169689Skan
998169689Skan    BITMAP_FREE(module_statics_escape);
999169689Skan    BITMAP_FREE(module_statics_written);
1000169689Skan
1001169689Skan    if (dump_file)
1002169689Skan      EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
1003169689Skan	{
1004169689Skan	  fprintf (dump_file, "\nPromotable global:%s",
1005169689Skan		   get_static_name (index));
1006169689Skan	}
1007169689Skan
1008169689Skan    for (i = 0; i < order_pos; i++ )
1009169689Skan      {
1010169689Skan	ipa_reference_local_vars_info_t l;
1011169689Skan	node = order[i];
1012169689Skan	l = get_reference_vars_info_from_cgraph (node)->local;
1013169689Skan
1014169689Skan	/* Any variables that are not in all_module_statics are
1015169689Skan	   removed from the local maps.  This will include all of the
1016169689Skan	   variables that were found to escape in the function
1017169689Skan	   scanning.  */
1018169689Skan	bitmap_and_into (l->statics_read,
1019169689Skan		         all_module_statics);
1020169689Skan	bitmap_and_into (l->statics_written,
1021169689Skan		         all_module_statics);
1022169689Skan      }
1023169689Skan
1024169689Skan    BITMAP_FREE(module_statics_readonly);
1025169689Skan    BITMAP_FREE(module_statics_const);
1026169689Skan    BITMAP_FREE(bm_temp);
1027169689Skan  }
1028169689Skan
1029169689Skan  if (dump_file)
1030169689Skan    {
1031169689Skan      for (i = 0; i < order_pos; i++ )
1032169689Skan	{
1033169689Skan	  unsigned int index;
1034169689Skan	  ipa_reference_local_vars_info_t l;
1035169689Skan	  bitmap_iterator bi;
1036169689Skan
1037169689Skan	  node = order[i];
1038169689Skan	  l = get_reference_vars_info_from_cgraph (node)->local;
1039169689Skan	  fprintf (dump_file,
1040169689Skan		   "\nFunction name:%s/%i:",
1041169689Skan		   cgraph_node_name (node), node->uid);
1042169689Skan	  fprintf (dump_file, "\n  locals read: ");
1043169689Skan	  EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
1044169689Skan				    0, index, bi)
1045169689Skan	    {
1046169689Skan	      fprintf (dump_file, "%s ",
1047169689Skan		       get_static_name (index));
1048169689Skan	    }
1049169689Skan	  fprintf (dump_file, "\n  locals written: ");
1050169689Skan	  EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
1051169689Skan				    0, index, bi)
1052169689Skan	    {
1053169689Skan	      fprintf(dump_file, "%s ",
1054169689Skan		      get_static_name (index));
1055169689Skan	    }
1056169689Skan	}
1057169689Skan    }
1058169689Skan
1059169689Skan  /* Propagate the local information thru the call graph to produce
1060169689Skan     the global information.  All the nodes within a cycle will have
1061169689Skan     the same info so we collapse cycles first.  Then we can do the
1062169689Skan     propagation in one pass from the leaves to the roots.  */
1063169689Skan  order_pos = ipa_utils_reduced_inorder (order, true, true);
1064169689Skan  if (dump_file)
1065169689Skan    ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1066169689Skan
1067169689Skan  for (i = 0; i < order_pos; i++ )
1068169689Skan    {
1069169689Skan      ipa_reference_vars_info_t node_info;
1070169689Skan      ipa_reference_global_vars_info_t node_g =
1071169689Skan	xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d));
1072169689Skan      ipa_reference_local_vars_info_t node_l;
1073169689Skan
1074169689Skan      bool read_all;
1075169689Skan      bool write_all;
1076169689Skan      struct ipa_dfs_info * w_info;
1077169689Skan
1078169689Skan      node = order[i];
1079169689Skan      node_info = get_reference_vars_info_from_cgraph (node);
1080169689Skan      if (!node_info)
1081169689Skan	{
1082169689Skan	  dump_cgraph_node (stderr, node);
1083169689Skan	  dump_cgraph (stderr);
1084169689Skan	  gcc_unreachable ();
1085169689Skan	}
1086169689Skan
1087169689Skan      node_info->global = node_g;
1088169689Skan      node_l = node_info->local;
1089169689Skan
1090169689Skan      read_all = node_l->calls_read_all;
1091169689Skan      write_all = node_l->calls_write_all;
1092169689Skan
1093169689Skan      /* If any node in a cycle is calls_read_all or calls_write_all
1094169689Skan	 they all are. */
1095169689Skan      w_info = node->aux;
1096169689Skan      w = w_info->next_cycle;
1097169689Skan      while (w)
1098169689Skan	{
1099169689Skan	  ipa_reference_local_vars_info_t w_l =
1100169689Skan	    get_reference_vars_info_from_cgraph (w)->local;
1101169689Skan	  read_all |= w_l->calls_read_all;
1102169689Skan	  write_all |= w_l->calls_write_all;
1103169689Skan
1104169689Skan	  w_info = w->aux;
1105169689Skan	  w = w_info->next_cycle;
1106169689Skan	}
1107169689Skan
1108169689Skan      /* Initialized the bitmaps for the reduced nodes */
1109169689Skan      if (read_all)
1110169689Skan	node_g->statics_read = all_module_statics;
1111169689Skan      else
1112169689Skan	{
1113169689Skan	  node_g->statics_read = BITMAP_ALLOC (&ipa_obstack);
1114169689Skan	  bitmap_copy (node_g->statics_read,
1115169689Skan		       node_l->statics_read);
1116169689Skan	}
1117169689Skan
1118169689Skan      if (write_all)
1119169689Skan	node_g->statics_written = all_module_statics;
1120169689Skan      else
1121169689Skan	{
1122169689Skan	  node_g->statics_written = BITMAP_ALLOC (&ipa_obstack);
1123169689Skan	  bitmap_copy (node_g->statics_written,
1124169689Skan		       node_l->statics_written);
1125169689Skan	}
1126169689Skan
1127169689Skan      w_info = node->aux;
1128169689Skan      w = w_info->next_cycle;
1129169689Skan      while (w)
1130169689Skan	{
1131169689Skan	  ipa_reference_vars_info_t w_ri =
1132169689Skan	    get_reference_vars_info_from_cgraph (w);
1133169689Skan	  ipa_reference_local_vars_info_t w_l = w_ri->local;
1134169689Skan
1135169689Skan	  /* All nodes within a cycle share the same global info bitmaps.  */
1136169689Skan	  w_ri->global = node_g;
1137169689Skan
1138169689Skan	  /* These global bitmaps are initialized from the local info
1139169689Skan	     of all of the nodes in the region.  However there is no
1140169689Skan	     need to do any work if the bitmaps were set to
1141169689Skan	     all_module_statics.  */
1142169689Skan	  if (!read_all)
1143169689Skan	    bitmap_ior_into (node_g->statics_read,
1144169689Skan			     w_l->statics_read);
1145169689Skan	  if (!write_all)
1146169689Skan	    bitmap_ior_into (node_g->statics_written,
1147169689Skan			     w_l->statics_written);
1148169689Skan	  w_info = w->aux;
1149169689Skan	  w = w_info->next_cycle;
1150169689Skan	}
1151169689Skan
1152169689Skan      w = node;
1153169689Skan      while (w)
1154169689Skan	{
1155169689Skan	  propagate_bits (w);
1156169689Skan	  w_info = w->aux;
1157169689Skan	  w = w_info->next_cycle;
1158169689Skan	}
1159169689Skan    }
1160169689Skan
1161169689Skan  /* Need to fix up the local information sets.  The information that
1162169689Skan     has been gathered so far is preinlining.  However, the
1163169689Skan     compilation will progress post inlining so the local sets for the
1164169689Skan     inlined calls need to be merged into the callers.  Note that the
1165169689Skan     local sets are not shared between all of the nodes in a cycle so
1166169689Skan     those nodes in the cycle must be processed explicitly.  */
1167169689Skan  for (i = 0; i < order_pos; i++ )
1168169689Skan    {
1169169689Skan      struct ipa_dfs_info * w_info;
1170169689Skan      node = order[i];
1171169689Skan      merge_callee_local_info (node, node);
1172169689Skan
1173169689Skan      w_info = node->aux;
1174169689Skan      w = w_info->next_cycle;
1175169689Skan      while (w)
1176169689Skan	{
1177169689Skan	  merge_callee_local_info (w, w);
1178169689Skan	  w_info = w->aux;
1179169689Skan	  w = w_info->next_cycle;
1180169689Skan	}
1181169689Skan    }
1182169689Skan
1183169689Skan  if (dump_file)
1184169689Skan    {
1185169689Skan      for (i = 0; i < order_pos; i++ )
1186169689Skan	{
1187169689Skan	  ipa_reference_vars_info_t node_info;
1188169689Skan	  ipa_reference_global_vars_info_t node_g;
1189169689Skan	  ipa_reference_local_vars_info_t node_l;
1190169689Skan	  unsigned int index;
1191169689Skan	  bitmap_iterator bi;
1192169689Skan	  struct ipa_dfs_info * w_info;
1193169689Skan
1194169689Skan	  node = order[i];
1195169689Skan	  node_info = get_reference_vars_info_from_cgraph (node);
1196169689Skan	  node_g = node_info->global;
1197169689Skan	  node_l = node_info->local;
1198169689Skan	  fprintf (dump_file,
1199169689Skan		   "\nFunction name:%s/%i:",
1200169689Skan		   cgraph_node_name (node), node->uid);
1201169689Skan	  fprintf (dump_file, "\n  locals read: ");
1202169689Skan	  EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1203169689Skan				    0, index, bi)
1204169689Skan	    {
1205169689Skan	      fprintf (dump_file, "%s ",
1206169689Skan		       get_static_name (index));
1207169689Skan	    }
1208169689Skan	  fprintf (dump_file, "\n  locals written: ");
1209169689Skan	  EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1210169689Skan				    0, index, bi)
1211169689Skan	    {
1212169689Skan	      fprintf(dump_file, "%s ",
1213169689Skan		      get_static_name (index));
1214169689Skan	    }
1215169689Skan
1216169689Skan	  w_info = node->aux;
1217169689Skan	  w = w_info->next_cycle;
1218169689Skan	  while (w)
1219169689Skan	    {
1220169689Skan	      ipa_reference_vars_info_t w_ri =
1221169689Skan		get_reference_vars_info_from_cgraph (w);
1222169689Skan	      ipa_reference_local_vars_info_t w_l = w_ri->local;
1223169689Skan	      fprintf (dump_file, "\n  next cycle: %s/%i ",
1224169689Skan		       cgraph_node_name (w), w->uid);
1225169689Skan 	      fprintf (dump_file, "\n    locals read: ");
1226169689Skan	      EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1227169689Skan					0, index, bi)
1228169689Skan		{
1229169689Skan		  fprintf (dump_file, "%s ",
1230169689Skan			   get_static_name (index));
1231169689Skan		}
1232169689Skan
1233169689Skan	      fprintf (dump_file, "\n    locals written: ");
1234169689Skan	      EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1235169689Skan					0, index, bi)
1236169689Skan		{
1237169689Skan		  fprintf(dump_file, "%s ",
1238169689Skan			  get_static_name (index));
1239169689Skan		}
1240169689Skan
1241169689Skan
1242169689Skan	      w_info = w->aux;
1243169689Skan	      w = w_info->next_cycle;
1244169689Skan	    }
1245169689Skan	  fprintf (dump_file, "\n  globals read: ");
1246169689Skan	  EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1247169689Skan				    0, index, bi)
1248169689Skan	    {
1249169689Skan	      fprintf (dump_file, "%s ",
1250169689Skan		       get_static_name (index));
1251169689Skan	    }
1252169689Skan	  fprintf (dump_file, "\n  globals written: ");
1253169689Skan	  EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1254169689Skan				    0, index, bi)
1255169689Skan	    {
1256169689Skan	      fprintf (dump_file, "%s ",
1257169689Skan		       get_static_name (index));
1258169689Skan	    }
1259169689Skan	}
1260169689Skan    }
1261169689Skan
1262169689Skan  /* Cleanup. */
1263169689Skan  for (i = 0; i < order_pos; i++ )
1264169689Skan    {
1265169689Skan      ipa_reference_vars_info_t node_info;
1266169689Skan      ipa_reference_global_vars_info_t node_g;
1267169689Skan      node = order[i];
1268169689Skan      node_info = get_reference_vars_info_from_cgraph (node);
1269169689Skan      node_g = node_info->global;
1270169689Skan
1271169689Skan      /* Create the complimentary sets.  These are more useful for
1272169689Skan	 certain apis.  */
1273169689Skan      node_g->statics_not_read = BITMAP_ALLOC (&ipa_obstack);
1274169689Skan      node_g->statics_not_written = BITMAP_ALLOC (&ipa_obstack);
1275169689Skan
1276169689Skan      if (node_g->statics_read != all_module_statics)
1277169689Skan	{
1278169689Skan	  bitmap_and_compl (node_g->statics_not_read,
1279169689Skan			    all_module_statics,
1280169689Skan			    node_g->statics_read);
1281169689Skan	}
1282169689Skan
1283169689Skan      if (node_g->statics_written
1284169689Skan	  != all_module_statics)
1285169689Skan	bitmap_and_compl (node_g->statics_not_written,
1286169689Skan			  all_module_statics,
1287169689Skan			  node_g->statics_written);
1288169689Skan   }
1289169689Skan
1290169689Skan  free (order);
1291169689Skan
1292169689Skan  for (node = cgraph_nodes; node; node = node->next)
1293169689Skan    {
1294169689Skan      /* Get rid of the aux information.  */
1295169689Skan
1296169689Skan      if (node->aux)
1297169689Skan	{
1298169689Skan	  free (node->aux);
1299169689Skan	  node->aux = NULL;
1300169689Skan	}
1301169689Skan
1302169689Skan      if (node->analyzed
1303169689Skan	  && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
1304169689Skan	clean_function (node);
1305169689Skan    }
1306169689Skan  return 0;
1307169689Skan}
1308169689Skan
1309169689Skan
1310169689Skanstatic bool
1311169689Skangate_reference (void)
1312169689Skan{
1313169689Skan  return (flag_unit_at_a_time != 0  && flag_ipa_reference
1314169689Skan	  /* Don't bother doing anything if the program has errors.  */
1315169689Skan	  && !(errorcount || sorrycount));
1316169689Skan}
1317169689Skan
1318169689Skanstruct tree_opt_pass pass_ipa_reference =
1319169689Skan{
1320169689Skan  "static-var",				/* name */
1321169689Skan  gate_reference,			/* gate */
1322169689Skan  static_execute,			/* execute */
1323169689Skan  NULL,					/* sub */
1324169689Skan  NULL,					/* next */
1325169689Skan  0,					/* static_pass_number */
1326169689Skan  TV_IPA_REFERENCE,		        /* tv_id */
1327169689Skan  0,	                                /* properties_required */
1328169689Skan  0,					/* properties_provided */
1329169689Skan  0,					/* properties_destroyed */
1330169689Skan  0,					/* todo_flags_start */
1331169689Skan  0,                                    /* todo_flags_finish */
1332169689Skan  0					/* letter */
1333169689Skan};
1334169689Skan
1335169689Skan#include "gt-ipa-reference.h"
1336169689Skan
1337