xref: /dflybsd-src/contrib/gcc-4.7/gcc/ipa-reference.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Callgraph based analysis of static variables.
2*e4b17023SJohn Marino    Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino /* This file gathers information about how variables whose scope is
23*e4b17023SJohn Marino    confined to the compilation unit are used.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino    The transitive call site specific clobber effects are computed
26*e4b17023SJohn Marino    for the variables whose scope is contained within this compilation
27*e4b17023SJohn Marino    unit.
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino    First each function and static variable initialization is analyzed
30*e4b17023SJohn Marino    to determine which local static variables are either read, written,
31*e4b17023SJohn Marino    or have their address taken.  Any local static that has its address
32*e4b17023SJohn Marino    taken is removed from consideration.  Once the local read and
33*e4b17023SJohn Marino    writes are determined, a transitive closure of this information is
34*e4b17023SJohn Marino    performed over the call graph to determine the worst case set of
35*e4b17023SJohn Marino    side effects of each call.  In later parts of the compiler, these
36*e4b17023SJohn Marino    local and global sets are examined to make the call clobbering less
37*e4b17023SJohn Marino    traumatic, promote some statics to registers, and improve aliasing
38*e4b17023SJohn Marino    information.  */
39*e4b17023SJohn Marino 
40*e4b17023SJohn Marino #include "config.h"
41*e4b17023SJohn Marino #include "system.h"
42*e4b17023SJohn Marino #include "coretypes.h"
43*e4b17023SJohn Marino #include "tm.h"
44*e4b17023SJohn Marino #include "tree.h"
45*e4b17023SJohn Marino #include "tree-flow.h"
46*e4b17023SJohn Marino #include "tree-inline.h"
47*e4b17023SJohn Marino #include "tree-pass.h"
48*e4b17023SJohn Marino #include "langhooks.h"
49*e4b17023SJohn Marino #include "pointer-set.h"
50*e4b17023SJohn Marino #include "splay-tree.h"
51*e4b17023SJohn Marino #include "ggc.h"
52*e4b17023SJohn Marino #include "ipa-utils.h"
53*e4b17023SJohn Marino #include "ipa-reference.h"
54*e4b17023SJohn Marino #include "gimple.h"
55*e4b17023SJohn Marino #include "cgraph.h"
56*e4b17023SJohn Marino #include "output.h"
57*e4b17023SJohn Marino #include "flags.h"
58*e4b17023SJohn Marino #include "timevar.h"
59*e4b17023SJohn Marino #include "diagnostic.h"
60*e4b17023SJohn Marino #include "langhooks.h"
61*e4b17023SJohn Marino #include "data-streamer.h"
62*e4b17023SJohn Marino #include "lto-streamer.h"
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino static void remove_node_data (struct cgraph_node *node,
65*e4b17023SJohn Marino 			      void *data ATTRIBUTE_UNUSED);
66*e4b17023SJohn Marino static void duplicate_node_data (struct cgraph_node *src,
67*e4b17023SJohn Marino 				 struct cgraph_node *dst,
68*e4b17023SJohn Marino 				 void *data ATTRIBUTE_UNUSED);
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino /* The static variables defined within the compilation unit that are
71*e4b17023SJohn Marino    loaded or stored directly by function that owns this structure.  */
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino struct ipa_reference_local_vars_info_d
74*e4b17023SJohn Marino {
75*e4b17023SJohn Marino   bitmap statics_read;
76*e4b17023SJohn Marino   bitmap statics_written;
77*e4b17023SJohn Marino };
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino /* Statics that are read and written by some set of functions. The
80*e4b17023SJohn Marino    local ones are based on the loads and stores local to the function.
81*e4b17023SJohn Marino    The global ones are based on the local info as well as the
82*e4b17023SJohn Marino    transitive closure of the functions that are called. */
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino struct ipa_reference_global_vars_info_d
85*e4b17023SJohn Marino {
86*e4b17023SJohn Marino   bitmap statics_read;
87*e4b17023SJohn Marino   bitmap statics_written;
88*e4b17023SJohn Marino };
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino /* Information we save about every function after ipa-reference is completed.  */
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino struct ipa_reference_optimization_summary_d
93*e4b17023SJohn Marino {
94*e4b17023SJohn Marino   bitmap statics_not_read;
95*e4b17023SJohn Marino   bitmap statics_not_written;
96*e4b17023SJohn Marino };
97*e4b17023SJohn Marino 
98*e4b17023SJohn Marino typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
99*e4b17023SJohn Marino typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
100*e4b17023SJohn Marino typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino struct ipa_reference_vars_info_d
103*e4b17023SJohn Marino {
104*e4b17023SJohn Marino   struct ipa_reference_local_vars_info_d local;
105*e4b17023SJohn Marino   struct ipa_reference_global_vars_info_d global;
106*e4b17023SJohn Marino };
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino /* This splay tree contains all of the static variables that are
111*e4b17023SJohn Marino    being considered by the compilation level alias analysis.  */
112*e4b17023SJohn Marino static splay_tree reference_vars_to_consider;
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino /* A bit is set for every module static we are considering.  This is
115*e4b17023SJohn Marino    ored into the local info when asm code is found that clobbers all
116*e4b17023SJohn Marino    memory. */
117*e4b17023SJohn Marino static bitmap all_module_statics;
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino /* Obstack holding bitmaps of local analysis (live from analysis to
120*e4b17023SJohn Marino    propagation)  */
121*e4b17023SJohn Marino static bitmap_obstack local_info_obstack;
122*e4b17023SJohn Marino /* Obstack holding global analysis live forever.  */
123*e4b17023SJohn Marino static bitmap_obstack optimization_summary_obstack;
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino /* Holders of ipa cgraph hooks: */
126*e4b17023SJohn Marino static struct cgraph_2node_hook_list *node_duplication_hook_holder;
127*e4b17023SJohn Marino static struct cgraph_node_hook_list *node_removal_hook_holder;
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino /* Vector where the reference var infos are actually stored. */
130*e4b17023SJohn Marino DEF_VEC_P (ipa_reference_vars_info_t);
131*e4b17023SJohn Marino DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
132*e4b17023SJohn Marino static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
133*e4b17023SJohn Marino DEF_VEC_P (ipa_reference_optimization_summary_t);
134*e4b17023SJohn Marino DEF_VEC_ALLOC_P (ipa_reference_optimization_summary_t, heap);
VEC(ipa_reference_optimization_summary_t,heap)135*e4b17023SJohn Marino static VEC (ipa_reference_optimization_summary_t, heap) *ipa_reference_opt_sum_vector;
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
138*e4b17023SJohn Marino static inline ipa_reference_vars_info_t
139*e4b17023SJohn Marino get_reference_vars_info (struct cgraph_node *node)
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino   if (!ipa_reference_vars_vector
142*e4b17023SJohn Marino       || VEC_length (ipa_reference_vars_info_t,
143*e4b17023SJohn Marino 		     ipa_reference_vars_vector) <= (unsigned int) node->uid)
144*e4b17023SJohn Marino     return NULL;
145*e4b17023SJohn Marino   return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector,
146*e4b17023SJohn Marino 		    node->uid);
147*e4b17023SJohn Marino }
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
150*e4b17023SJohn Marino static inline ipa_reference_optimization_summary_t
get_reference_optimization_summary(struct cgraph_node * node)151*e4b17023SJohn Marino get_reference_optimization_summary (struct cgraph_node *node)
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino   if (!ipa_reference_opt_sum_vector
154*e4b17023SJohn Marino       || (VEC_length (ipa_reference_optimization_summary_t,
155*e4b17023SJohn Marino 		      ipa_reference_opt_sum_vector)
156*e4b17023SJohn Marino 	  <= (unsigned int) node->uid))
157*e4b17023SJohn Marino     return NULL;
158*e4b17023SJohn Marino   return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector,
159*e4b17023SJohn Marino 		    node->uid);
160*e4b17023SJohn Marino }
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
163*e4b17023SJohn Marino static inline void
set_reference_vars_info(struct cgraph_node * node,ipa_reference_vars_info_t info)164*e4b17023SJohn Marino set_reference_vars_info (struct cgraph_node *node,
165*e4b17023SJohn Marino 			 ipa_reference_vars_info_t info)
166*e4b17023SJohn Marino {
167*e4b17023SJohn Marino   if (!ipa_reference_vars_vector
168*e4b17023SJohn Marino       || VEC_length (ipa_reference_vars_info_t,
169*e4b17023SJohn Marino 		     ipa_reference_vars_vector) <= (unsigned int) node->uid)
170*e4b17023SJohn Marino     VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap,
171*e4b17023SJohn Marino 			   ipa_reference_vars_vector, node->uid + 1);
172*e4b17023SJohn Marino   VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector,
173*e4b17023SJohn Marino 	       node->uid, info);
174*e4b17023SJohn Marino }
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
177*e4b17023SJohn Marino static inline void
set_reference_optimization_summary(struct cgraph_node * node,ipa_reference_optimization_summary_t info)178*e4b17023SJohn Marino set_reference_optimization_summary (struct cgraph_node *node,
179*e4b17023SJohn Marino 				    ipa_reference_optimization_summary_t info)
180*e4b17023SJohn Marino {
181*e4b17023SJohn Marino   if (!ipa_reference_opt_sum_vector
182*e4b17023SJohn Marino       || (VEC_length (ipa_reference_optimization_summary_t,
183*e4b17023SJohn Marino 		      ipa_reference_opt_sum_vector)
184*e4b17023SJohn Marino 	  <= (unsigned int) node->uid))
185*e4b17023SJohn Marino     VEC_safe_grow_cleared (ipa_reference_optimization_summary_t,
186*e4b17023SJohn Marino 			   heap, ipa_reference_opt_sum_vector, node->uid + 1);
187*e4b17023SJohn Marino   VEC_replace (ipa_reference_optimization_summary_t,
188*e4b17023SJohn Marino 	       ipa_reference_opt_sum_vector, node->uid, info);
189*e4b17023SJohn Marino }
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino /* Return a bitmap indexed by_DECL_UID uid for the static variables
192*e4b17023SJohn Marino    that are not read during the execution of the function FN.  Returns
193*e4b17023SJohn Marino    NULL if no data is available.  */
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino bitmap
ipa_reference_get_not_read_global(struct cgraph_node * fn)196*e4b17023SJohn Marino ipa_reference_get_not_read_global (struct cgraph_node *fn)
197*e4b17023SJohn Marino {
198*e4b17023SJohn Marino   ipa_reference_optimization_summary_t info;
199*e4b17023SJohn Marino 
200*e4b17023SJohn Marino   info = get_reference_optimization_summary (cgraph_function_node (fn, NULL));
201*e4b17023SJohn Marino   if (info)
202*e4b17023SJohn Marino     return info->statics_not_read;
203*e4b17023SJohn Marino   else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
204*e4b17023SJohn Marino     return all_module_statics;
205*e4b17023SJohn Marino   else
206*e4b17023SJohn Marino     return NULL;
207*e4b17023SJohn Marino }
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino /* Return a bitmap indexed by DECL_UID uid for the static variables
210*e4b17023SJohn Marino    that are not written during the execution of the function FN.  Note
211*e4b17023SJohn Marino    that variables written may or may not be read during the function
212*e4b17023SJohn Marino    call.  Returns NULL if no data is available.  */
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino bitmap
ipa_reference_get_not_written_global(struct cgraph_node * fn)215*e4b17023SJohn Marino ipa_reference_get_not_written_global (struct cgraph_node *fn)
216*e4b17023SJohn Marino {
217*e4b17023SJohn Marino   ipa_reference_optimization_summary_t info;
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   info = get_reference_optimization_summary (fn);
220*e4b17023SJohn Marino   if (info)
221*e4b17023SJohn Marino     return info->statics_not_written;
222*e4b17023SJohn Marino   else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
223*e4b17023SJohn Marino     return all_module_statics;
224*e4b17023SJohn Marino   else
225*e4b17023SJohn Marino     return NULL;
226*e4b17023SJohn Marino }
227*e4b17023SJohn Marino 
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino /* Add VAR to all_module_statics and the two
231*e4b17023SJohn Marino    reference_vars_to_consider* sets.  */
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino static inline void
add_static_var(tree var)234*e4b17023SJohn Marino add_static_var (tree var)
235*e4b17023SJohn Marino {
236*e4b17023SJohn Marino   int uid = DECL_UID (var);
237*e4b17023SJohn Marino   gcc_assert (TREE_CODE (var) == VAR_DECL);
238*e4b17023SJohn Marino   if (dump_file)
239*e4b17023SJohn Marino     splay_tree_insert (reference_vars_to_consider,
240*e4b17023SJohn Marino 		       uid, (splay_tree_value)var);
241*e4b17023SJohn Marino   bitmap_set_bit (all_module_statics, uid);
242*e4b17023SJohn Marino }
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino /* Return true if the variable T is the right kind of static variable to
245*e4b17023SJohn Marino    perform compilation unit scope escape analysis.  */
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino static inline bool
is_proper_for_analysis(tree t)248*e4b17023SJohn Marino is_proper_for_analysis (tree t)
249*e4b17023SJohn Marino {
250*e4b17023SJohn Marino   /* We handle only variables whose address is never taken.  */
251*e4b17023SJohn Marino   if (TREE_ADDRESSABLE (t))
252*e4b17023SJohn Marino     return false;
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino   /* If the variable has the "used" attribute, treat it as if it had a
255*e4b17023SJohn Marino      been touched by the devil.  */
256*e4b17023SJohn Marino   if (DECL_PRESERVE_P (t))
257*e4b17023SJohn Marino     return false;
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   /* Do not want to do anything with volatile except mark any
260*e4b17023SJohn Marino      function that uses one to be not const or pure.  */
261*e4b17023SJohn Marino   if (TREE_THIS_VOLATILE (t))
262*e4b17023SJohn Marino     return false;
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino   /* We do not need to analyze readonly vars, we already know they do not
265*e4b17023SJohn Marino      alias.  */
266*e4b17023SJohn Marino   if (TREE_READONLY (t))
267*e4b17023SJohn Marino     return false;
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino   /* We cannot touch decls where the type needs constructing.  */
270*e4b17023SJohn Marino   if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
271*e4b17023SJohn Marino     return false;
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino   /* This is a variable we care about.  Check if we have seen it
274*e4b17023SJohn Marino      before, and if not add it the set of variables we care about.  */
275*e4b17023SJohn Marino   if (all_module_statics
276*e4b17023SJohn Marino       && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
277*e4b17023SJohn Marino     add_static_var (t);
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino   return true;
280*e4b17023SJohn Marino }
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino /* Lookup the tree node for the static variable that has UID and
283*e4b17023SJohn Marino    convert the name to a string for debugging.  */
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino static const char *
get_static_name(int index)286*e4b17023SJohn Marino get_static_name (int index)
287*e4b17023SJohn Marino {
288*e4b17023SJohn Marino   splay_tree_node stn =
289*e4b17023SJohn Marino     splay_tree_lookup (reference_vars_to_consider, index);
290*e4b17023SJohn Marino   if (stn)
291*e4b17023SJohn Marino     return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
292*e4b17023SJohn Marino   return NULL;
293*e4b17023SJohn Marino }
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
296*e4b17023SJohn Marino    bit vector.  There are several cases to check to avoid the sparse
297*e4b17023SJohn Marino    bitmap oring.  */
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino static void
propagate_bits(ipa_reference_global_vars_info_t x_global,struct cgraph_node * x)300*e4b17023SJohn Marino propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
301*e4b17023SJohn Marino {
302*e4b17023SJohn Marino   struct cgraph_edge *e;
303*e4b17023SJohn Marino   for (e = x->callees; e; e = e->next_callee)
304*e4b17023SJohn Marino     {
305*e4b17023SJohn Marino       enum availability avail;
306*e4b17023SJohn Marino       struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino       if (!y)
309*e4b17023SJohn Marino 	continue;
310*e4b17023SJohn Marino       /* Only look into nodes we can propagate something.  */
311*e4b17023SJohn Marino       if (avail > AVAIL_OVERWRITABLE
312*e4b17023SJohn Marino 	  || (avail == AVAIL_OVERWRITABLE
313*e4b17023SJohn Marino 	      && (flags_from_decl_or_type (y->decl) & ECF_LEAF)))
314*e4b17023SJohn Marino 	{
315*e4b17023SJohn Marino 	  int flags = flags_from_decl_or_type (y->decl);
316*e4b17023SJohn Marino 	  if (get_reference_vars_info (y))
317*e4b17023SJohn Marino 	    {
318*e4b17023SJohn Marino 	      ipa_reference_vars_info_t y_info
319*e4b17023SJohn Marino 		= get_reference_vars_info (y);
320*e4b17023SJohn Marino 	      ipa_reference_global_vars_info_t y_global = &y_info->global;
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino 	      /* Calls in current cycle do not have global computed yet.  */
323*e4b17023SJohn Marino 	      if (!y_global->statics_read)
324*e4b17023SJohn Marino 		continue;
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino 	      /* If function is declared const, it reads no memory even if it
327*e4b17023SJohn Marino 		 seems so to local analysis.  */
328*e4b17023SJohn Marino 	      if (flags & ECF_CONST)
329*e4b17023SJohn Marino 		continue;
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino 	      if (x_global->statics_read
332*e4b17023SJohn Marino 		  != all_module_statics)
333*e4b17023SJohn Marino 		{
334*e4b17023SJohn Marino 		  if (y_global->statics_read
335*e4b17023SJohn Marino 		      == all_module_statics)
336*e4b17023SJohn Marino 		    {
337*e4b17023SJohn Marino 		      BITMAP_FREE (x_global->statics_read);
338*e4b17023SJohn Marino 		      x_global->statics_read
339*e4b17023SJohn Marino 			= all_module_statics;
340*e4b17023SJohn Marino 		    }
341*e4b17023SJohn Marino 		  /* Skip bitmaps that are pointer equal to node's bitmap
342*e4b17023SJohn Marino 		     (no reason to spin within the cycle).  */
343*e4b17023SJohn Marino 		  else if (x_global->statics_read
344*e4b17023SJohn Marino 			   != y_global->statics_read)
345*e4b17023SJohn Marino 		    bitmap_ior_into (x_global->statics_read,
346*e4b17023SJohn Marino 				     y_global->statics_read);
347*e4b17023SJohn Marino 		}
348*e4b17023SJohn Marino 
349*e4b17023SJohn Marino 	      /* If function is declared pure, it has no stores even if it
350*e4b17023SJohn Marino 		 seems so to local analysis; If we can not return from here,
351*e4b17023SJohn Marino 		 we can safely ignore the call.  */
352*e4b17023SJohn Marino 	      if ((flags & ECF_PURE)
353*e4b17023SJohn Marino 		  || cgraph_edge_cannot_lead_to_return (e))
354*e4b17023SJohn Marino 		continue;
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino 	      if (x_global->statics_written
357*e4b17023SJohn Marino 		  != all_module_statics)
358*e4b17023SJohn Marino 		{
359*e4b17023SJohn Marino 		  if (y_global->statics_written
360*e4b17023SJohn Marino 		      == all_module_statics)
361*e4b17023SJohn Marino 		    {
362*e4b17023SJohn Marino 		      BITMAP_FREE (x_global->statics_written);
363*e4b17023SJohn Marino 		      x_global->statics_written
364*e4b17023SJohn Marino 			= all_module_statics;
365*e4b17023SJohn Marino 		    }
366*e4b17023SJohn Marino 		  /* Skip bitmaps that are pointer equal to node's bitmap
367*e4b17023SJohn Marino 		     (no reason to spin within the cycle).  */
368*e4b17023SJohn Marino 		  else if (x_global->statics_written
369*e4b17023SJohn Marino 			   != y_global->statics_written)
370*e4b17023SJohn Marino 		    bitmap_ior_into (x_global->statics_written,
371*e4b17023SJohn Marino 				     y_global->statics_written);
372*e4b17023SJohn Marino 		}
373*e4b17023SJohn Marino 	    }
374*e4b17023SJohn Marino 	  else
375*e4b17023SJohn Marino 	    gcc_unreachable ();
376*e4b17023SJohn Marino 	}
377*e4b17023SJohn Marino     }
378*e4b17023SJohn Marino }
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino /* The init routine for analyzing global static variable usage.  See
381*e4b17023SJohn Marino    comments at top for description.  */
382*e4b17023SJohn Marino static void
ipa_init(void)383*e4b17023SJohn Marino ipa_init (void)
384*e4b17023SJohn Marino {
385*e4b17023SJohn Marino   static bool init_p = false;
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino   if (init_p)
388*e4b17023SJohn Marino     return;
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino   init_p = true;
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino   if (dump_file)
393*e4b17023SJohn Marino     reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino   bitmap_obstack_initialize (&local_info_obstack);
396*e4b17023SJohn Marino   bitmap_obstack_initialize (&optimization_summary_obstack);
397*e4b17023SJohn Marino   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino   node_removal_hook_holder =
400*e4b17023SJohn Marino       cgraph_add_node_removal_hook (&remove_node_data, NULL);
401*e4b17023SJohn Marino   node_duplication_hook_holder =
402*e4b17023SJohn Marino       cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
403*e4b17023SJohn Marino }
404*e4b17023SJohn Marino 
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino /* Set up the persistent info for FN.  */
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino static ipa_reference_local_vars_info_t
init_function_info(struct cgraph_node * fn)409*e4b17023SJohn Marino init_function_info (struct cgraph_node *fn)
410*e4b17023SJohn Marino {
411*e4b17023SJohn Marino   ipa_reference_vars_info_t info
412*e4b17023SJohn Marino     = XCNEW (struct ipa_reference_vars_info_d);
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino   /* Add the info to the tree's annotation.  */
415*e4b17023SJohn Marino   set_reference_vars_info (fn, info);
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino   info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
418*e4b17023SJohn Marino   info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
419*e4b17023SJohn Marino 
420*e4b17023SJohn Marino   return &info->local;
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino /* This is the main routine for finding the reference patterns for
425*e4b17023SJohn Marino    global variables within a function FN.  */
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino static void
analyze_function(struct cgraph_node * fn)428*e4b17023SJohn Marino analyze_function (struct cgraph_node *fn)
429*e4b17023SJohn Marino {
430*e4b17023SJohn Marino   ipa_reference_local_vars_info_t local;
431*e4b17023SJohn Marino   struct ipa_ref *ref;
432*e4b17023SJohn Marino   int i;
433*e4b17023SJohn Marino   tree var;
434*e4b17023SJohn Marino 
435*e4b17023SJohn Marino   local = init_function_info (fn);
436*e4b17023SJohn Marino   for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
437*e4b17023SJohn Marino     {
438*e4b17023SJohn Marino       if (ref->refered_type != IPA_REF_VARPOOL)
439*e4b17023SJohn Marino 	continue;
440*e4b17023SJohn Marino       var = ipa_ref_varpool_node (ref)->decl;
441*e4b17023SJohn Marino       if (ipa_ref_varpool_node (ref)->externally_visible
442*e4b17023SJohn Marino 	  || !ipa_ref_varpool_node (ref)->analyzed
443*e4b17023SJohn Marino 	  || !is_proper_for_analysis (var))
444*e4b17023SJohn Marino 	continue;
445*e4b17023SJohn Marino       switch (ref->use)
446*e4b17023SJohn Marino 	{
447*e4b17023SJohn Marino 	case IPA_REF_LOAD:
448*e4b17023SJohn Marino           bitmap_set_bit (local->statics_read, DECL_UID (var));
449*e4b17023SJohn Marino 	  break;
450*e4b17023SJohn Marino 	case IPA_REF_STORE:
451*e4b17023SJohn Marino 	  if (ipa_ref_cannot_lead_to_return (ref))
452*e4b17023SJohn Marino 	    break;
453*e4b17023SJohn Marino           bitmap_set_bit (local->statics_written, DECL_UID (var));
454*e4b17023SJohn Marino 	  break;
455*e4b17023SJohn Marino 	case IPA_REF_ADDR:
456*e4b17023SJohn Marino 	  gcc_unreachable ();
457*e4b17023SJohn Marino 	  break;
458*e4b17023SJohn Marino 	}
459*e4b17023SJohn Marino     }
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino   if (cgraph_node_cannot_return (fn))
462*e4b17023SJohn Marino     bitmap_clear (local->statics_written);
463*e4b17023SJohn Marino }
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino static bitmap
copy_global_bitmap(bitmap src)466*e4b17023SJohn Marino copy_global_bitmap (bitmap src)
467*e4b17023SJohn Marino {
468*e4b17023SJohn Marino   bitmap dst;
469*e4b17023SJohn Marino   if (!src)
470*e4b17023SJohn Marino     return NULL;
471*e4b17023SJohn Marino   if (src == all_module_statics)
472*e4b17023SJohn Marino     return all_module_statics;
473*e4b17023SJohn Marino   dst = BITMAP_ALLOC (&optimization_summary_obstack);
474*e4b17023SJohn Marino   bitmap_copy (dst, src);
475*e4b17023SJohn Marino   return dst;
476*e4b17023SJohn Marino }
477*e4b17023SJohn Marino 
478*e4b17023SJohn Marino 
479*e4b17023SJohn Marino /* Called when new clone is inserted to callgraph late.  */
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino static void
duplicate_node_data(struct cgraph_node * src,struct cgraph_node * dst,void * data ATTRIBUTE_UNUSED)482*e4b17023SJohn Marino duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
483*e4b17023SJohn Marino 	 	     void *data ATTRIBUTE_UNUSED)
484*e4b17023SJohn Marino {
485*e4b17023SJohn Marino   ipa_reference_optimization_summary_t ginfo;
486*e4b17023SJohn Marino   ipa_reference_optimization_summary_t dst_ginfo;
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino   ginfo = get_reference_optimization_summary (src);
489*e4b17023SJohn Marino   if (!ginfo)
490*e4b17023SJohn Marino     return;
491*e4b17023SJohn Marino   dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
492*e4b17023SJohn Marino   set_reference_optimization_summary (dst, dst_ginfo);
493*e4b17023SJohn Marino   dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
494*e4b17023SJohn Marino   dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
495*e4b17023SJohn Marino }
496*e4b17023SJohn Marino 
497*e4b17023SJohn Marino /* Called when node is removed.  */
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino static void
remove_node_data(struct cgraph_node * node,void * data ATTRIBUTE_UNUSED)500*e4b17023SJohn Marino remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
501*e4b17023SJohn Marino {
502*e4b17023SJohn Marino   ipa_reference_optimization_summary_t ginfo;
503*e4b17023SJohn Marino   ginfo = get_reference_optimization_summary (node);
504*e4b17023SJohn Marino   if (ginfo)
505*e4b17023SJohn Marino     {
506*e4b17023SJohn Marino       if (ginfo->statics_not_read
507*e4b17023SJohn Marino 	  && ginfo->statics_not_read != all_module_statics)
508*e4b17023SJohn Marino 	BITMAP_FREE (ginfo->statics_not_read);
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino       if (ginfo->statics_not_written
511*e4b17023SJohn Marino 	  && ginfo->statics_not_written != all_module_statics)
512*e4b17023SJohn Marino 	BITMAP_FREE (ginfo->statics_not_written);
513*e4b17023SJohn Marino       free (ginfo);
514*e4b17023SJohn Marino       set_reference_optimization_summary (node, NULL);
515*e4b17023SJohn Marino     }
516*e4b17023SJohn Marino }
517*e4b17023SJohn Marino 
518*e4b17023SJohn Marino /* Analyze each function in the cgraph to see which global or statics
519*e4b17023SJohn Marino    are read or written.  */
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino static void
generate_summary(void)522*e4b17023SJohn Marino generate_summary (void)
523*e4b17023SJohn Marino {
524*e4b17023SJohn Marino   struct cgraph_node *node;
525*e4b17023SJohn Marino   unsigned int index;
526*e4b17023SJohn Marino   bitmap_iterator bi;
527*e4b17023SJohn Marino   bitmap bm_temp;
528*e4b17023SJohn Marino 
529*e4b17023SJohn Marino   ipa_init ();
530*e4b17023SJohn Marino   bm_temp = BITMAP_ALLOC (&local_info_obstack);
531*e4b17023SJohn Marino 
532*e4b17023SJohn Marino   /* Process all of the functions next.  */
533*e4b17023SJohn Marino   for (node = cgraph_nodes; node; node = node->next)
534*e4b17023SJohn Marino     if (node->analyzed)
535*e4b17023SJohn Marino       analyze_function (node);
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino   if (dump_file)
538*e4b17023SJohn Marino     EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
539*e4b17023SJohn Marino       {
540*e4b17023SJohn Marino 	fprintf (dump_file, "\nPromotable global:%s",
541*e4b17023SJohn Marino 		 get_static_name (index));
542*e4b17023SJohn Marino       }
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino   BITMAP_FREE(bm_temp);
545*e4b17023SJohn Marino 
546*e4b17023SJohn Marino   if (dump_file)
547*e4b17023SJohn Marino     for (node = cgraph_nodes; node; node = node->next)
548*e4b17023SJohn Marino       if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
549*e4b17023SJohn Marino 	{
550*e4b17023SJohn Marino 	  ipa_reference_local_vars_info_t l;
551*e4b17023SJohn Marino 	  unsigned int index;
552*e4b17023SJohn Marino 	  bitmap_iterator bi;
553*e4b17023SJohn Marino 
554*e4b17023SJohn Marino 	  l = &get_reference_vars_info (node)->local;
555*e4b17023SJohn Marino 	  fprintf (dump_file,
556*e4b17023SJohn Marino 		   "\nFunction name:%s/%i:",
557*e4b17023SJohn Marino 		   cgraph_node_name (node), node->uid);
558*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  locals read: ");
559*e4b17023SJohn Marino 	  if (l->statics_read)
560*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
561*e4b17023SJohn Marino 				      0, index, bi)
562*e4b17023SJohn Marino 	      {
563*e4b17023SJohn Marino 	        fprintf (dump_file, "%s ",
564*e4b17023SJohn Marino 		         get_static_name (index));
565*e4b17023SJohn Marino 	      }
566*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  locals written: ");
567*e4b17023SJohn Marino 	  if (l->statics_written)
568*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
569*e4b17023SJohn Marino 				      0, index, bi)
570*e4b17023SJohn Marino 	      {
571*e4b17023SJohn Marino 	        fprintf(dump_file, "%s ",
572*e4b17023SJohn Marino 		        get_static_name (index));
573*e4b17023SJohn Marino 	      }
574*e4b17023SJohn Marino 	}
575*e4b17023SJohn Marino }
576*e4b17023SJohn Marino 
577*e4b17023SJohn Marino /* Set READ_ALL/WRITE_ALL based on decl flags of NODE.  */
578*e4b17023SJohn Marino 
579*e4b17023SJohn Marino static void
read_write_all_from_decl(struct cgraph_node * node,bool * read_all,bool * write_all)580*e4b17023SJohn Marino read_write_all_from_decl (struct cgraph_node *node, bool * read_all,
581*e4b17023SJohn Marino 			  bool * write_all)
582*e4b17023SJohn Marino {
583*e4b17023SJohn Marino   tree decl = node->decl;
584*e4b17023SJohn Marino   int flags = flags_from_decl_or_type (decl);
585*e4b17023SJohn Marino   if ((flags & ECF_LEAF)
586*e4b17023SJohn Marino       && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
587*e4b17023SJohn Marino     ;
588*e4b17023SJohn Marino   else if (flags & ECF_CONST)
589*e4b17023SJohn Marino     ;
590*e4b17023SJohn Marino   else if ((flags & ECF_PURE)
591*e4b17023SJohn Marino 	   || cgraph_node_cannot_return (node))
592*e4b17023SJohn Marino     {
593*e4b17023SJohn Marino       *read_all = true;
594*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
595*e4b17023SJohn Marino          fprintf (dump_file, "   %s/%i -> read all\n",
596*e4b17023SJohn Marino 		  cgraph_node_name (node), node->uid);
597*e4b17023SJohn Marino     }
598*e4b17023SJohn Marino   else
599*e4b17023SJohn Marino     {
600*e4b17023SJohn Marino        /* TODO: To be able to produce sane results, we should also handle
601*e4b17023SJohn Marino 	  common builtins, in particular throw.  */
602*e4b17023SJohn Marino       *read_all = true;
603*e4b17023SJohn Marino       *write_all = true;
604*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
605*e4b17023SJohn Marino          fprintf (dump_file, "   %s/%i -> read all, write all\n",
606*e4b17023SJohn Marino 		  cgraph_node_name (node), node->uid);
607*e4b17023SJohn Marino     }
608*e4b17023SJohn Marino }
609*e4b17023SJohn Marino 
610*e4b17023SJohn Marino /* Produce the global information by preforming a transitive closure
611*e4b17023SJohn Marino    on the local information that was produced by ipa_analyze_function */
612*e4b17023SJohn Marino 
613*e4b17023SJohn Marino static unsigned int
propagate(void)614*e4b17023SJohn Marino propagate (void)
615*e4b17023SJohn Marino {
616*e4b17023SJohn Marino   struct cgraph_node *node;
617*e4b17023SJohn Marino   struct cgraph_node *w;
618*e4b17023SJohn Marino   struct cgraph_node **order =
619*e4b17023SJohn Marino     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
620*e4b17023SJohn Marino   int order_pos;
621*e4b17023SJohn Marino   int i;
622*e4b17023SJohn Marino 
623*e4b17023SJohn Marino   if (dump_file)
624*e4b17023SJohn Marino     dump_cgraph (dump_file);
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino   ipa_discover_readonly_nonaddressable_vars ();
627*e4b17023SJohn Marino   generate_summary ();
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino   /* Propagate the local information thru the call graph to produce
630*e4b17023SJohn Marino      the global information.  All the nodes within a cycle will have
631*e4b17023SJohn Marino      the same info so we collapse cycles first.  Then we can do the
632*e4b17023SJohn Marino      propagation in one pass from the leaves to the roots.  */
633*e4b17023SJohn Marino   order_pos = ipa_reduced_postorder (order, true, true, NULL);
634*e4b17023SJohn Marino   if (dump_file)
635*e4b17023SJohn Marino     ipa_print_order (dump_file, "reduced", order, order_pos);
636*e4b17023SJohn Marino 
637*e4b17023SJohn Marino   for (i = 0; i < order_pos; i++ )
638*e4b17023SJohn Marino     {
639*e4b17023SJohn Marino       ipa_reference_vars_info_t node_info;
640*e4b17023SJohn Marino       ipa_reference_global_vars_info_t node_g;
641*e4b17023SJohn Marino       ipa_reference_local_vars_info_t node_l;
642*e4b17023SJohn Marino       struct cgraph_edge *e, *ie;
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino       bool read_all;
645*e4b17023SJohn Marino       bool write_all;
646*e4b17023SJohn Marino       struct ipa_dfs_info * w_info;
647*e4b17023SJohn Marino 
648*e4b17023SJohn Marino       node = order[i];
649*e4b17023SJohn Marino       if (node->alias)
650*e4b17023SJohn Marino 	continue;
651*e4b17023SJohn Marino       node_info = get_reference_vars_info (node);
652*e4b17023SJohn Marino       gcc_assert (node_info);
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino 
655*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
656*e4b17023SJohn Marino 	fprintf (dump_file, "Starting cycle with %s/%i\n",
657*e4b17023SJohn Marino 		  cgraph_node_name (node), node->uid);
658*e4b17023SJohn Marino 
659*e4b17023SJohn Marino       node_l = &node_info->local;
660*e4b17023SJohn Marino       node_g = &node_info->global;
661*e4b17023SJohn Marino 
662*e4b17023SJohn Marino       read_all = false;
663*e4b17023SJohn Marino       write_all = false;
664*e4b17023SJohn Marino 
665*e4b17023SJohn Marino       /* When function is overwritable, we can not assume anything.  */
666*e4b17023SJohn Marino       if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
667*e4b17023SJohn Marino         read_write_all_from_decl (node, &read_all, &write_all);
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino       for (e = node->callees; e; e = e->next_callee)
670*e4b17023SJohn Marino 	{
671*e4b17023SJohn Marino 	  enum availability avail;
672*e4b17023SJohn Marino 	  struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
673*e4b17023SJohn Marino           if (!callee || avail <= AVAIL_OVERWRITABLE)
674*e4b17023SJohn Marino             read_write_all_from_decl (callee, &read_all, &write_all);
675*e4b17023SJohn Marino 	}
676*e4b17023SJohn Marino 
677*e4b17023SJohn Marino       for (ie = node->indirect_calls; ie; ie = ie->next_callee)
678*e4b17023SJohn Marino 	if (!(ie->indirect_info->ecf_flags & ECF_CONST))
679*e4b17023SJohn Marino 	  {
680*e4b17023SJohn Marino 	    read_all = true;
681*e4b17023SJohn Marino 	    if (dump_file && (dump_flags & TDF_DETAILS))
682*e4b17023SJohn Marino 	       fprintf (dump_file, "   indirect call -> read all\n");
683*e4b17023SJohn Marino 	    if (!cgraph_edge_cannot_lead_to_return (ie)
684*e4b17023SJohn Marino 		&& !(ie->indirect_info->ecf_flags & ECF_PURE))
685*e4b17023SJohn Marino 	      {
686*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
687*e4b17023SJohn Marino 		   fprintf (dump_file, "   indirect call -> write all\n");
688*e4b17023SJohn Marino 	        write_all = true;
689*e4b17023SJohn Marino 	      }
690*e4b17023SJohn Marino 	  }
691*e4b17023SJohn Marino 
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino       /* If any node in a cycle is read_all or write_all
694*e4b17023SJohn Marino 	 they all are. */
695*e4b17023SJohn Marino       w_info = (struct ipa_dfs_info *) node->aux;
696*e4b17023SJohn Marino       w = w_info->next_cycle;
697*e4b17023SJohn Marino       while (w && (!read_all || !write_all))
698*e4b17023SJohn Marino 	{
699*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
700*e4b17023SJohn Marino 	    fprintf (dump_file, "  Visiting %s/%i\n",
701*e4b17023SJohn Marino 		      cgraph_node_name (w), w->uid);
702*e4b17023SJohn Marino 	  /* When function is overwritable, we can not assume anything.  */
703*e4b17023SJohn Marino 	  if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
704*e4b17023SJohn Marino 	    read_write_all_from_decl (w, &read_all, &write_all);
705*e4b17023SJohn Marino 
706*e4b17023SJohn Marino 	  for (e = w->callees; e; e = e->next_callee)
707*e4b17023SJohn Marino 	    {
708*e4b17023SJohn Marino 	      enum availability avail;
709*e4b17023SJohn Marino 	      struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino 	      if (avail <= AVAIL_OVERWRITABLE)
712*e4b17023SJohn Marino 		read_write_all_from_decl (callee, &read_all, &write_all);
713*e4b17023SJohn Marino 	    }
714*e4b17023SJohn Marino 
715*e4b17023SJohn Marino 	  for (ie = w->indirect_calls; ie; ie = ie->next_callee)
716*e4b17023SJohn Marino 	    if (!(ie->indirect_info->ecf_flags & ECF_CONST))
717*e4b17023SJohn Marino 	      {
718*e4b17023SJohn Marino 		read_all = true;
719*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
720*e4b17023SJohn Marino 		   fprintf (dump_file, "   indirect call -> read all\n");
721*e4b17023SJohn Marino 		if (!cgraph_edge_cannot_lead_to_return (ie)
722*e4b17023SJohn Marino 		    && !(ie->indirect_info->ecf_flags & ECF_PURE))
723*e4b17023SJohn Marino 		  {
724*e4b17023SJohn Marino 		    write_all = true;
725*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
726*e4b17023SJohn Marino 		       fprintf (dump_file, "   indirect call -> write all\n");
727*e4b17023SJohn Marino 		  }
728*e4b17023SJohn Marino 	      }
729*e4b17023SJohn Marino 
730*e4b17023SJohn Marino 	  w_info = (struct ipa_dfs_info *) w->aux;
731*e4b17023SJohn Marino 	  w = w_info->next_cycle;
732*e4b17023SJohn Marino 	}
733*e4b17023SJohn Marino 
734*e4b17023SJohn Marino 
735*e4b17023SJohn Marino       /* Initialized the bitmaps for the reduced nodes */
736*e4b17023SJohn Marino       if (read_all)
737*e4b17023SJohn Marino 	node_g->statics_read = all_module_statics;
738*e4b17023SJohn Marino       else
739*e4b17023SJohn Marino 	{
740*e4b17023SJohn Marino 	  node_g->statics_read = BITMAP_ALLOC (&local_info_obstack);
741*e4b17023SJohn Marino 	  bitmap_copy (node_g->statics_read,
742*e4b17023SJohn Marino 		       node_l->statics_read);
743*e4b17023SJohn Marino 	}
744*e4b17023SJohn Marino       if (write_all)
745*e4b17023SJohn Marino 	node_g->statics_written = all_module_statics;
746*e4b17023SJohn Marino       else
747*e4b17023SJohn Marino 	{
748*e4b17023SJohn Marino 	  node_g->statics_written = BITMAP_ALLOC (&local_info_obstack);
749*e4b17023SJohn Marino 	  bitmap_copy (node_g->statics_written,
750*e4b17023SJohn Marino 		       node_l->statics_written);
751*e4b17023SJohn Marino 	}
752*e4b17023SJohn Marino 
753*e4b17023SJohn Marino       propagate_bits (node_g, node);
754*e4b17023SJohn Marino       w_info = (struct ipa_dfs_info *) node->aux;
755*e4b17023SJohn Marino       w = w_info->next_cycle;
756*e4b17023SJohn Marino       while (w && (!read_all || !write_all))
757*e4b17023SJohn Marino 	{
758*e4b17023SJohn Marino 	  ipa_reference_vars_info_t w_ri =
759*e4b17023SJohn Marino 	    get_reference_vars_info (w);
760*e4b17023SJohn Marino 	  ipa_reference_local_vars_info_t w_l = &w_ri->local;
761*e4b17023SJohn Marino 	  int flags = flags_from_decl_or_type (w->decl);
762*e4b17023SJohn Marino 
763*e4b17023SJohn Marino 	  /* These global bitmaps are initialized from the local info
764*e4b17023SJohn Marino 	     of all of the nodes in the region.  However there is no
765*e4b17023SJohn Marino 	     need to do any work if the bitmaps were set to
766*e4b17023SJohn Marino 	     all_module_statics.  */
767*e4b17023SJohn Marino 	  if (!read_all && !(flags & ECF_CONST))
768*e4b17023SJohn Marino 	    bitmap_ior_into (node_g->statics_read,
769*e4b17023SJohn Marino 			     w_l->statics_read);
770*e4b17023SJohn Marino 	  if (!write_all
771*e4b17023SJohn Marino 	      && !(flags & ECF_PURE)
772*e4b17023SJohn Marino 	      && !cgraph_node_cannot_return (w))
773*e4b17023SJohn Marino 	    bitmap_ior_into (node_g->statics_written,
774*e4b17023SJohn Marino 			     w_l->statics_written);
775*e4b17023SJohn Marino 	  propagate_bits (node_g, w);
776*e4b17023SJohn Marino 	  w_info = (struct ipa_dfs_info *) w->aux;
777*e4b17023SJohn Marino 	  w = w_info->next_cycle;
778*e4b17023SJohn Marino 	}
779*e4b17023SJohn Marino 
780*e4b17023SJohn Marino       /* All nodes within a cycle have the same global info bitmaps.  */
781*e4b17023SJohn Marino       node_info->global = *node_g;
782*e4b17023SJohn Marino       w_info = (struct ipa_dfs_info *) node->aux;
783*e4b17023SJohn Marino       w = w_info->next_cycle;
784*e4b17023SJohn Marino       while (w)
785*e4b17023SJohn Marino 	{
786*e4b17023SJohn Marino 	  ipa_reference_vars_info_t w_ri =
787*e4b17023SJohn Marino 	    get_reference_vars_info (w);
788*e4b17023SJohn Marino 
789*e4b17023SJohn Marino           w_ri->global = *node_g;
790*e4b17023SJohn Marino 
791*e4b17023SJohn Marino 	  w_info = (struct ipa_dfs_info *) w->aux;
792*e4b17023SJohn Marino 	  w = w_info->next_cycle;
793*e4b17023SJohn Marino 	}
794*e4b17023SJohn Marino     }
795*e4b17023SJohn Marino 
796*e4b17023SJohn Marino   if (dump_file)
797*e4b17023SJohn Marino     {
798*e4b17023SJohn Marino       for (i = 0; i < order_pos; i++ )
799*e4b17023SJohn Marino 	{
800*e4b17023SJohn Marino 	  ipa_reference_vars_info_t node_info;
801*e4b17023SJohn Marino 	  ipa_reference_global_vars_info_t node_g;
802*e4b17023SJohn Marino 	  ipa_reference_local_vars_info_t node_l;
803*e4b17023SJohn Marino 	  unsigned int index;
804*e4b17023SJohn Marino 	  bitmap_iterator bi;
805*e4b17023SJohn Marino 	  struct ipa_dfs_info * w_info;
806*e4b17023SJohn Marino 
807*e4b17023SJohn Marino 	  node = order[i];
808*e4b17023SJohn Marino 	  if (node->alias)
809*e4b17023SJohn Marino 	    continue;
810*e4b17023SJohn Marino 	  node_info = get_reference_vars_info (node);
811*e4b17023SJohn Marino 	  node_g = &node_info->global;
812*e4b17023SJohn Marino 	  node_l = &node_info->local;
813*e4b17023SJohn Marino 	  fprintf (dump_file,
814*e4b17023SJohn Marino 		   "\nFunction name:%s/%i:",
815*e4b17023SJohn Marino 		   cgraph_node_name (node), node->uid);
816*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  locals read: ");
817*e4b17023SJohn Marino 	  if (node_l->statics_read)
818*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
819*e4b17023SJohn Marino 				      0, index, bi)
820*e4b17023SJohn Marino 	      {
821*e4b17023SJohn Marino 		fprintf (dump_file, "%s ",
822*e4b17023SJohn Marino 			 get_static_name (index));
823*e4b17023SJohn Marino 	      }
824*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  locals written: ");
825*e4b17023SJohn Marino 	  if (node_l->statics_written)
826*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
827*e4b17023SJohn Marino 				      0, index, bi)
828*e4b17023SJohn Marino 	      {
829*e4b17023SJohn Marino 		fprintf(dump_file, "%s ",
830*e4b17023SJohn Marino 			get_static_name (index));
831*e4b17023SJohn Marino 	      }
832*e4b17023SJohn Marino 
833*e4b17023SJohn Marino 	  w_info = (struct ipa_dfs_info *) node->aux;
834*e4b17023SJohn Marino 	  w = w_info->next_cycle;
835*e4b17023SJohn Marino 	  while (w)
836*e4b17023SJohn Marino 	    {
837*e4b17023SJohn Marino 	      ipa_reference_vars_info_t w_ri =
838*e4b17023SJohn Marino 		get_reference_vars_info (w);
839*e4b17023SJohn Marino 	      ipa_reference_local_vars_info_t w_l = &w_ri->local;
840*e4b17023SJohn Marino 	      fprintf (dump_file, "\n  next cycle: %s/%i ",
841*e4b17023SJohn Marino 		       cgraph_node_name (w), w->uid);
842*e4b17023SJohn Marino 	      fprintf (dump_file, "\n    locals read: ");
843*e4b17023SJohn Marino 	      if (w_l->statics_read)
844*e4b17023SJohn Marino 		EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
845*e4b17023SJohn Marino 					  0, index, bi)
846*e4b17023SJohn Marino 		  {
847*e4b17023SJohn Marino 		    fprintf (dump_file, "%s ",
848*e4b17023SJohn Marino 			     get_static_name (index));
849*e4b17023SJohn Marino 		  }
850*e4b17023SJohn Marino 
851*e4b17023SJohn Marino 	      fprintf (dump_file, "\n    locals written: ");
852*e4b17023SJohn Marino 	      if (w_l->statics_written)
853*e4b17023SJohn Marino 		EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
854*e4b17023SJohn Marino 					  0, index, bi)
855*e4b17023SJohn Marino 		  {
856*e4b17023SJohn Marino 		    fprintf (dump_file, "%s ",
857*e4b17023SJohn Marino 			     get_static_name (index));
858*e4b17023SJohn Marino 		  }
859*e4b17023SJohn Marino 
860*e4b17023SJohn Marino 	      w_info = (struct ipa_dfs_info *) w->aux;
861*e4b17023SJohn Marino 	      w = w_info->next_cycle;
862*e4b17023SJohn Marino 	    }
863*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  globals read: ");
864*e4b17023SJohn Marino 	  if (node_g->statics_read == all_module_statics)
865*e4b17023SJohn Marino 	    fprintf (dump_file, "ALL");
866*e4b17023SJohn Marino 	  else
867*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
868*e4b17023SJohn Marino 				      0, index, bi)
869*e4b17023SJohn Marino 	      {
870*e4b17023SJohn Marino 	        fprintf (dump_file, "%s ",
871*e4b17023SJohn Marino 		         get_static_name (index));
872*e4b17023SJohn Marino 	      }
873*e4b17023SJohn Marino 	  fprintf (dump_file, "\n  globals written: ");
874*e4b17023SJohn Marino 	  if (node_g->statics_written == all_module_statics)
875*e4b17023SJohn Marino 	    fprintf (dump_file, "ALL");
876*e4b17023SJohn Marino 	  else
877*e4b17023SJohn Marino 	    EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
878*e4b17023SJohn Marino 				      0, index, bi)
879*e4b17023SJohn Marino 	      {
880*e4b17023SJohn Marino 		fprintf (dump_file, "%s ",
881*e4b17023SJohn Marino 			 get_static_name (index));
882*e4b17023SJohn Marino 	      }
883*e4b17023SJohn Marino 	}
884*e4b17023SJohn Marino     }
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino   /* Cleanup. */
887*e4b17023SJohn Marino   for (node = cgraph_nodes; node; node = node->next)
888*e4b17023SJohn Marino     {
889*e4b17023SJohn Marino       ipa_reference_vars_info_t node_info;
890*e4b17023SJohn Marino       ipa_reference_global_vars_info_t node_g;
891*e4b17023SJohn Marino       ipa_reference_optimization_summary_t opt;
892*e4b17023SJohn Marino 
893*e4b17023SJohn Marino       if (!node->analyzed || node->alias)
894*e4b17023SJohn Marino         continue;
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino       node_info = get_reference_vars_info (node);
897*e4b17023SJohn Marino       if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
898*e4b17023SJohn Marino 	  || (flags_from_decl_or_type (node->decl) & ECF_LEAF))
899*e4b17023SJohn Marino 	{
900*e4b17023SJohn Marino 	  node_g = &node_info->global;
901*e4b17023SJohn Marino 
902*e4b17023SJohn Marino 	  opt = XCNEW (struct ipa_reference_optimization_summary_d);
903*e4b17023SJohn Marino 	  set_reference_optimization_summary (node, opt);
904*e4b17023SJohn Marino 
905*e4b17023SJohn Marino 	  /* Create the complimentary sets.  */
906*e4b17023SJohn Marino 
907*e4b17023SJohn Marino 	  if (bitmap_empty_p (node_g->statics_read))
908*e4b17023SJohn Marino 	    opt->statics_not_read = all_module_statics;
909*e4b17023SJohn Marino 	  else
910*e4b17023SJohn Marino 	    {
911*e4b17023SJohn Marino 	      opt->statics_not_read
912*e4b17023SJohn Marino 		 = BITMAP_ALLOC (&optimization_summary_obstack);
913*e4b17023SJohn Marino 	      if (node_g->statics_read != all_module_statics)
914*e4b17023SJohn Marino 		bitmap_and_compl (opt->statics_not_read,
915*e4b17023SJohn Marino 				  all_module_statics,
916*e4b17023SJohn Marino 				  node_g->statics_read);
917*e4b17023SJohn Marino 	    }
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino 	  if (bitmap_empty_p (node_g->statics_written))
920*e4b17023SJohn Marino 	    opt->statics_not_written = all_module_statics;
921*e4b17023SJohn Marino 	  else
922*e4b17023SJohn Marino 	    {
923*e4b17023SJohn Marino 	      opt->statics_not_written
924*e4b17023SJohn Marino 	        = BITMAP_ALLOC (&optimization_summary_obstack);
925*e4b17023SJohn Marino 	      if (node_g->statics_written != all_module_statics)
926*e4b17023SJohn Marino 		bitmap_and_compl (opt->statics_not_written,
927*e4b17023SJohn Marino 				  all_module_statics,
928*e4b17023SJohn Marino 				  node_g->statics_written);
929*e4b17023SJohn Marino 	    }
930*e4b17023SJohn Marino 	}
931*e4b17023SJohn Marino       free (node_info);
932*e4b17023SJohn Marino    }
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino   ipa_free_postorder_info ();
935*e4b17023SJohn Marino   free (order);
936*e4b17023SJohn Marino 
937*e4b17023SJohn Marino   bitmap_obstack_release (&local_info_obstack);
938*e4b17023SJohn Marino   VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector);
939*e4b17023SJohn Marino   ipa_reference_vars_vector = NULL;
940*e4b17023SJohn Marino   if (dump_file)
941*e4b17023SJohn Marino     splay_tree_delete (reference_vars_to_consider);
942*e4b17023SJohn Marino   reference_vars_to_consider = NULL;
943*e4b17023SJohn Marino   return 0;
944*e4b17023SJohn Marino }
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino /* Return true if we need to write summary of NODE. */
947*e4b17023SJohn Marino 
948*e4b17023SJohn Marino static bool
write_node_summary_p(struct cgraph_node * node,cgraph_node_set set,varpool_node_set vset,bitmap ltrans_statics)949*e4b17023SJohn Marino write_node_summary_p (struct cgraph_node *node,
950*e4b17023SJohn Marino 		      cgraph_node_set set,
951*e4b17023SJohn Marino 		      varpool_node_set vset,
952*e4b17023SJohn Marino 		      bitmap ltrans_statics)
953*e4b17023SJohn Marino {
954*e4b17023SJohn Marino   ipa_reference_optimization_summary_t info;
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino   /* See if we have (non-empty) info.  */
957*e4b17023SJohn Marino   if (!node->analyzed || node->global.inlined_to)
958*e4b17023SJohn Marino     return false;
959*e4b17023SJohn Marino   info = get_reference_optimization_summary (node);
960*e4b17023SJohn Marino   if (!info || (bitmap_empty_p (info->statics_not_read)
961*e4b17023SJohn Marino 		&& bitmap_empty_p (info->statics_not_written)))
962*e4b17023SJohn Marino     return false;
963*e4b17023SJohn Marino 
964*e4b17023SJohn Marino   /* See if we want to encode it.
965*e4b17023SJohn Marino      Encode also referenced functions since constant folding might turn it into
966*e4b17023SJohn Marino      a direct call.
967*e4b17023SJohn Marino 
968*e4b17023SJohn Marino      In future we might also want to include summaries of functions references
969*e4b17023SJohn Marino      by initializers of constant variables references in current unit.  */
970*e4b17023SJohn Marino   if (!reachable_from_this_partition_p (node, set)
971*e4b17023SJohn Marino       && !referenced_from_this_partition_p (&node->ref_list, set, vset))
972*e4b17023SJohn Marino     return false;
973*e4b17023SJohn Marino 
974*e4b17023SJohn Marino   /* See if the info has non-empty intersections with vars we want to encode.  */
975*e4b17023SJohn Marino   if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
976*e4b17023SJohn Marino       && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
977*e4b17023SJohn Marino     return false;
978*e4b17023SJohn Marino   return true;
979*e4b17023SJohn Marino }
980*e4b17023SJohn Marino 
981*e4b17023SJohn Marino /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
982*e4b17023SJohn Marino    LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
983*e4b17023SJohn Marino    or -1.  When it is positive, just output -1 when
984*e4b17023SJohn Marino    BITS&LTRANS_STATICS == BITS&LTRANS_STATICS.  */
985*e4b17023SJohn Marino 
986*e4b17023SJohn Marino static void
stream_out_bitmap(struct lto_simple_output_block * ob,bitmap bits,bitmap ltrans_statics,int ltrans_statics_bitcount)987*e4b17023SJohn Marino stream_out_bitmap (struct lto_simple_output_block *ob,
988*e4b17023SJohn Marino 		   bitmap bits, bitmap ltrans_statics,
989*e4b17023SJohn Marino 		   int ltrans_statics_bitcount)
990*e4b17023SJohn Marino {
991*e4b17023SJohn Marino   int count = 0;
992*e4b17023SJohn Marino   unsigned int index;
993*e4b17023SJohn Marino   bitmap_iterator bi;
994*e4b17023SJohn Marino   if (bits == all_module_statics)
995*e4b17023SJohn Marino     {
996*e4b17023SJohn Marino       streamer_write_hwi_stream (ob->main_stream, -1);
997*e4b17023SJohn Marino       return;
998*e4b17023SJohn Marino     }
999*e4b17023SJohn Marino   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
1000*e4b17023SJohn Marino     count ++;
1001*e4b17023SJohn Marino   if (count == ltrans_statics_bitcount)
1002*e4b17023SJohn Marino     {
1003*e4b17023SJohn Marino       streamer_write_hwi_stream (ob->main_stream, -1);
1004*e4b17023SJohn Marino       return;
1005*e4b17023SJohn Marino     }
1006*e4b17023SJohn Marino   streamer_write_hwi_stream (ob->main_stream, count);
1007*e4b17023SJohn Marino   if (!count)
1008*e4b17023SJohn Marino     return;
1009*e4b17023SJohn Marino   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
1010*e4b17023SJohn Marino     {
1011*e4b17023SJohn Marino       tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
1012*e4b17023SJohn Marino       lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
1013*e4b17023SJohn Marino     }
1014*e4b17023SJohn Marino }
1015*e4b17023SJohn Marino 
1016*e4b17023SJohn Marino /* Serialize the ipa info for lto.  */
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino static void
ipa_reference_write_optimization_summary(cgraph_node_set set,varpool_node_set vset)1019*e4b17023SJohn Marino ipa_reference_write_optimization_summary (cgraph_node_set set,
1020*e4b17023SJohn Marino 					  varpool_node_set vset)
1021*e4b17023SJohn Marino {
1022*e4b17023SJohn Marino   struct cgraph_node *node;
1023*e4b17023SJohn Marino   struct lto_simple_output_block *ob
1024*e4b17023SJohn Marino     = lto_create_simple_output_block (LTO_section_ipa_reference);
1025*e4b17023SJohn Marino   unsigned int count = 0;
1026*e4b17023SJohn Marino   int ltrans_statics_bitcount = 0;
1027*e4b17023SJohn Marino   lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
1028*e4b17023SJohn Marino   lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
1029*e4b17023SJohn Marino   bitmap ltrans_statics = BITMAP_ALLOC (NULL);
1030*e4b17023SJohn Marino   int i;
1031*e4b17023SJohn Marino 
1032*e4b17023SJohn Marino   reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
1033*e4b17023SJohn Marino 
1034*e4b17023SJohn Marino   /* See what variables we are interested in.  */
1035*e4b17023SJohn Marino   for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
1036*e4b17023SJohn Marino     {
1037*e4b17023SJohn Marino       struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i);
1038*e4b17023SJohn Marino       if (!vnode->externally_visible
1039*e4b17023SJohn Marino 	  && vnode->analyzed
1040*e4b17023SJohn Marino 	  && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
1041*e4b17023SJohn Marino 	  && referenced_from_this_partition_p (&vnode->ref_list, set, vset))
1042*e4b17023SJohn Marino 	{
1043*e4b17023SJohn Marino 	  tree decl = vnode->decl;
1044*e4b17023SJohn Marino 	  bitmap_set_bit (ltrans_statics, DECL_UID (decl));
1045*e4b17023SJohn Marino 	  splay_tree_insert (reference_vars_to_consider,
1046*e4b17023SJohn Marino 			     DECL_UID (decl), (splay_tree_value)decl);
1047*e4b17023SJohn Marino 	  ltrans_statics_bitcount ++;
1048*e4b17023SJohn Marino 	}
1049*e4b17023SJohn Marino     }
1050*e4b17023SJohn Marino 
1051*e4b17023SJohn Marino 
1052*e4b17023SJohn Marino   if (ltrans_statics_bitcount)
1053*e4b17023SJohn Marino     for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1054*e4b17023SJohn Marino       if (write_node_summary_p (lto_cgraph_encoder_deref (encoder, i),
1055*e4b17023SJohn Marino 				set, vset, ltrans_statics))
1056*e4b17023SJohn Marino 	  count++;
1057*e4b17023SJohn Marino 
1058*e4b17023SJohn Marino   streamer_write_uhwi_stream (ob->main_stream, count);
1059*e4b17023SJohn Marino   if (count)
1060*e4b17023SJohn Marino     stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1061*e4b17023SJohn Marino 		       -1);
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino   /* Process all of the functions.  */
1064*e4b17023SJohn Marino   if (ltrans_statics_bitcount)
1065*e4b17023SJohn Marino     for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1066*e4b17023SJohn Marino       {
1067*e4b17023SJohn Marino 	node = lto_cgraph_encoder_deref (encoder, i);
1068*e4b17023SJohn Marino 	if (write_node_summary_p (node, set, vset, ltrans_statics))
1069*e4b17023SJohn Marino 	  {
1070*e4b17023SJohn Marino 	    ipa_reference_optimization_summary_t info;
1071*e4b17023SJohn Marino 	    int node_ref;
1072*e4b17023SJohn Marino 
1073*e4b17023SJohn Marino 	    info = get_reference_optimization_summary (node);
1074*e4b17023SJohn Marino 	    node_ref = lto_cgraph_encoder_encode (encoder, node);
1075*e4b17023SJohn Marino 	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
1076*e4b17023SJohn Marino 
1077*e4b17023SJohn Marino 	    stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1078*e4b17023SJohn Marino 			       ltrans_statics_bitcount);
1079*e4b17023SJohn Marino 	    stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1080*e4b17023SJohn Marino 			       ltrans_statics_bitcount);
1081*e4b17023SJohn Marino 	  }
1082*e4b17023SJohn Marino       }
1083*e4b17023SJohn Marino   BITMAP_FREE (ltrans_statics);
1084*e4b17023SJohn Marino   lto_destroy_simple_output_block (ob);
1085*e4b17023SJohn Marino   splay_tree_delete (reference_vars_to_consider);
1086*e4b17023SJohn Marino }
1087*e4b17023SJohn Marino 
1088*e4b17023SJohn Marino /* Deserialize the ipa info for lto.  */
1089*e4b17023SJohn Marino 
1090*e4b17023SJohn Marino static void
ipa_reference_read_optimization_summary(void)1091*e4b17023SJohn Marino ipa_reference_read_optimization_summary (void)
1092*e4b17023SJohn Marino {
1093*e4b17023SJohn Marino   struct lto_file_decl_data ** file_data_vec
1094*e4b17023SJohn Marino     = lto_get_file_decl_data ();
1095*e4b17023SJohn Marino   struct lto_file_decl_data * file_data;
1096*e4b17023SJohn Marino   unsigned int j = 0;
1097*e4b17023SJohn Marino   bitmap_obstack_initialize (&optimization_summary_obstack);
1098*e4b17023SJohn Marino 
1099*e4b17023SJohn Marino   node_removal_hook_holder =
1100*e4b17023SJohn Marino       cgraph_add_node_removal_hook (&remove_node_data, NULL);
1101*e4b17023SJohn Marino   node_duplication_hook_holder =
1102*e4b17023SJohn Marino       cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1103*e4b17023SJohn Marino   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1104*e4b17023SJohn Marino 
1105*e4b17023SJohn Marino   while ((file_data = file_data_vec[j++]))
1106*e4b17023SJohn Marino     {
1107*e4b17023SJohn Marino       const char *data;
1108*e4b17023SJohn Marino       size_t len;
1109*e4b17023SJohn Marino       struct lto_input_block *ib
1110*e4b17023SJohn Marino 	= lto_create_simple_input_block (file_data,
1111*e4b17023SJohn Marino 					 LTO_section_ipa_reference,
1112*e4b17023SJohn Marino 					 &data, &len);
1113*e4b17023SJohn Marino       if (ib)
1114*e4b17023SJohn Marino 	{
1115*e4b17023SJohn Marino 	  unsigned int i;
1116*e4b17023SJohn Marino 	  unsigned int f_count = streamer_read_uhwi (ib);
1117*e4b17023SJohn Marino 	  int b_count;
1118*e4b17023SJohn Marino 	  if (!f_count)
1119*e4b17023SJohn Marino 	    continue;
1120*e4b17023SJohn Marino 	  b_count = streamer_read_hwi (ib);
1121*e4b17023SJohn Marino 	  if (dump_file)
1122*e4b17023SJohn Marino 	    fprintf (dump_file, "all module statics:");
1123*e4b17023SJohn Marino 	  for (i = 0; i < (unsigned int)b_count; i++)
1124*e4b17023SJohn Marino 	    {
1125*e4b17023SJohn Marino 	      unsigned int var_index = streamer_read_uhwi (ib);
1126*e4b17023SJohn Marino 	      tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1127*e4b17023SJohn Marino 							     var_index);
1128*e4b17023SJohn Marino 	      bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1129*e4b17023SJohn Marino 	      if (dump_file)
1130*e4b17023SJohn Marino 		fprintf (dump_file, " %s",
1131*e4b17023SJohn Marino 			 lang_hooks.decl_printable_name (v_decl, 2));
1132*e4b17023SJohn Marino 	    }
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino 	  for (i = 0; i < f_count; i++)
1135*e4b17023SJohn Marino 	    {
1136*e4b17023SJohn Marino 	      unsigned int j, index;
1137*e4b17023SJohn Marino 	      struct cgraph_node *node;
1138*e4b17023SJohn Marino 	      ipa_reference_optimization_summary_t info;
1139*e4b17023SJohn Marino 	      int v_count;
1140*e4b17023SJohn Marino 	      lto_cgraph_encoder_t encoder;
1141*e4b17023SJohn Marino 
1142*e4b17023SJohn Marino 	      index = streamer_read_uhwi (ib);
1143*e4b17023SJohn Marino 	      encoder = file_data->cgraph_node_encoder;
1144*e4b17023SJohn Marino 	      node = lto_cgraph_encoder_deref (encoder, index);
1145*e4b17023SJohn Marino 	      info = XCNEW (struct ipa_reference_optimization_summary_d);
1146*e4b17023SJohn Marino 	      set_reference_optimization_summary (node, info);
1147*e4b17023SJohn Marino 	      info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1148*e4b17023SJohn Marino 	      info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1149*e4b17023SJohn Marino 	      if (dump_file)
1150*e4b17023SJohn Marino 		fprintf (dump_file,
1151*e4b17023SJohn Marino 			 "\nFunction name:%s/%i:\n  static not read:",
1152*e4b17023SJohn Marino 			 cgraph_node_name (node), node->uid);
1153*e4b17023SJohn Marino 
1154*e4b17023SJohn Marino 	      /* Set the statics not read.  */
1155*e4b17023SJohn Marino 	      v_count = streamer_read_hwi (ib);
1156*e4b17023SJohn Marino 	      if (v_count == -1)
1157*e4b17023SJohn Marino 		{
1158*e4b17023SJohn Marino 		  info->statics_not_read = all_module_statics;
1159*e4b17023SJohn Marino 		  if (dump_file)
1160*e4b17023SJohn Marino 		    fprintf (dump_file, " all module statics");
1161*e4b17023SJohn Marino 		}
1162*e4b17023SJohn Marino 	      else
1163*e4b17023SJohn Marino 		for (j = 0; j < (unsigned int)v_count; j++)
1164*e4b17023SJohn Marino 		  {
1165*e4b17023SJohn Marino 		    unsigned int var_index = streamer_read_uhwi (ib);
1166*e4b17023SJohn Marino 		    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1167*e4b17023SJohn Marino 								   var_index);
1168*e4b17023SJohn Marino 		    bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1169*e4b17023SJohn Marino 		    if (dump_file)
1170*e4b17023SJohn Marino 		      fprintf (dump_file, " %s",
1171*e4b17023SJohn Marino 			       lang_hooks.decl_printable_name (v_decl, 2));
1172*e4b17023SJohn Marino 		  }
1173*e4b17023SJohn Marino 
1174*e4b17023SJohn Marino 	      if (dump_file)
1175*e4b17023SJohn Marino 		fprintf (dump_file,
1176*e4b17023SJohn Marino 			 "\n  static not written:");
1177*e4b17023SJohn Marino 	      /* Set the statics not written.  */
1178*e4b17023SJohn Marino 	      v_count = streamer_read_hwi (ib);
1179*e4b17023SJohn Marino 	      if (v_count == -1)
1180*e4b17023SJohn Marino 		{
1181*e4b17023SJohn Marino 		  info->statics_not_written = all_module_statics;
1182*e4b17023SJohn Marino 		  if (dump_file)
1183*e4b17023SJohn Marino 		    fprintf (dump_file, " all module statics");
1184*e4b17023SJohn Marino 		}
1185*e4b17023SJohn Marino 	      else
1186*e4b17023SJohn Marino 		for (j = 0; j < (unsigned int)v_count; j++)
1187*e4b17023SJohn Marino 		  {
1188*e4b17023SJohn Marino 		    unsigned int var_index = streamer_read_uhwi (ib);
1189*e4b17023SJohn Marino 		    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1190*e4b17023SJohn Marino 								   var_index);
1191*e4b17023SJohn Marino 		    bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1192*e4b17023SJohn Marino 		    if (dump_file)
1193*e4b17023SJohn Marino 		      fprintf (dump_file, " %s",
1194*e4b17023SJohn Marino 			       lang_hooks.decl_printable_name (v_decl, 2));
1195*e4b17023SJohn Marino 		  }
1196*e4b17023SJohn Marino 	      if (dump_file)
1197*e4b17023SJohn Marino 		fprintf (dump_file, "\n");
1198*e4b17023SJohn Marino 	    }
1199*e4b17023SJohn Marino 
1200*e4b17023SJohn Marino 	  lto_destroy_simple_input_block (file_data,
1201*e4b17023SJohn Marino 					  LTO_section_ipa_reference,
1202*e4b17023SJohn Marino 					  ib, data, len);
1203*e4b17023SJohn Marino 	}
1204*e4b17023SJohn Marino       else
1205*e4b17023SJohn Marino 	/* Fatal error here.  We do not want to support compiling ltrans units with
1206*e4b17023SJohn Marino 	   different version of compiler or different flags than the WPA unit, so
1207*e4b17023SJohn Marino 	   this should never happen.  */
1208*e4b17023SJohn Marino 	fatal_error ("ipa reference summary is missing in ltrans unit");
1209*e4b17023SJohn Marino     }
1210*e4b17023SJohn Marino }
1211*e4b17023SJohn Marino 
1212*e4b17023SJohn Marino static bool
gate_reference(void)1213*e4b17023SJohn Marino gate_reference (void)
1214*e4b17023SJohn Marino {
1215*e4b17023SJohn Marino   return (flag_ipa_reference
1216*e4b17023SJohn Marino 	  /* Don't bother doing anything if the program has errors.  */
1217*e4b17023SJohn Marino 	  && !seen_error ());
1218*e4b17023SJohn Marino }
1219*e4b17023SJohn Marino 
1220*e4b17023SJohn Marino struct ipa_opt_pass_d pass_ipa_reference =
1221*e4b17023SJohn Marino {
1222*e4b17023SJohn Marino  {
1223*e4b17023SJohn Marino   IPA_PASS,
1224*e4b17023SJohn Marino   "static-var",				/* name */
1225*e4b17023SJohn Marino   gate_reference,			/* gate */
1226*e4b17023SJohn Marino   propagate,			        /* execute */
1227*e4b17023SJohn Marino   NULL,					/* sub */
1228*e4b17023SJohn Marino   NULL,					/* next */
1229*e4b17023SJohn Marino   0,					/* static_pass_number */
1230*e4b17023SJohn Marino   TV_IPA_REFERENCE,		        /* tv_id */
1231*e4b17023SJohn Marino   0,	                                /* properties_required */
1232*e4b17023SJohn Marino   0,					/* properties_provided */
1233*e4b17023SJohn Marino   0,					/* properties_destroyed */
1234*e4b17023SJohn Marino   0,					/* todo_flags_start */
1235*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
1236*e4b17023SJohn Marino  },
1237*e4b17023SJohn Marino  NULL,				        /* generate_summary */
1238*e4b17023SJohn Marino  NULL,					/* write_summary */
1239*e4b17023SJohn Marino  NULL,				 	/* read_summary */
1240*e4b17023SJohn Marino  ipa_reference_write_optimization_summary,/* write_optimization_summary */
1241*e4b17023SJohn Marino  ipa_reference_read_optimization_summary,/* read_optimization_summary */
1242*e4b17023SJohn Marino  NULL,					/* stmt_fixup */
1243*e4b17023SJohn Marino  0,					/* TODOs */
1244*e4b17023SJohn Marino  NULL,			                /* function_transform */
1245*e4b17023SJohn Marino  NULL					/* variable_transform */
1246*e4b17023SJohn Marino };
1247