Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-reference.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Callgraph based analysis of static variables. | 1 /* Callgraph based analysis of static variables. |
2 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. | 2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | |
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> | 4 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
4 | 5 |
5 This file is part of GCC. | 6 This file is part of GCC. |
6 | 7 |
7 GCC is free software; you can redistribute it and/or modify it under | 8 GCC is free software; you can redistribute it and/or modify it under |
19 <http://www.gnu.org/licenses/>. */ | 20 <http://www.gnu.org/licenses/>. */ |
20 | 21 |
21 /* This file gathers information about how variables whose scope is | 22 /* This file gathers information about how variables whose scope is |
22 confined to the compilation unit are used. | 23 confined to the compilation unit are used. |
23 | 24 |
24 There are two categories of information produced by this pass: | 25 The transitive call site specific clobber effects are computed |
25 | |
26 1) The addressable (TREE_ADDRESSABLE) bit and readonly | |
27 (TREE_READONLY) bit associated with these variables is properly set | |
28 based on scanning all of the code withing the compilation unit. | |
29 | |
30 2) The transitive call site specific clobber effects are computed | |
31 for the variables whose scope is contained within this compilation | 26 for the variables whose scope is contained within this compilation |
32 unit. | 27 unit. |
33 | 28 |
34 First each function and static variable initialization is analyzed | 29 First each function and static variable initialization is analyzed |
35 to determine which local static variables are either read, written, | 30 to determine which local static variables are either read, written, |
38 writes are determined, a transitive closure of this information is | 33 writes are determined, a transitive closure of this information is |
39 performed over the call graph to determine the worst case set of | 34 performed over the call graph to determine the worst case set of |
40 side effects of each call. In later parts of the compiler, these | 35 side effects of each call. In later parts of the compiler, these |
41 local and global sets are examined to make the call clobbering less | 36 local and global sets are examined to make the call clobbering less |
42 traumatic, promote some statics to registers, and improve aliasing | 37 traumatic, promote some statics to registers, and improve aliasing |
43 information. | 38 information. */ |
44 | |
45 Currently must be run after inlining decisions have been made since | |
46 otherwise, the local sets will not contain information that is | |
47 consistent with post inlined state. The global sets are not prone | |
48 to this problem since they are by definition transitive. */ | |
49 | 39 |
50 #include "config.h" | 40 #include "config.h" |
51 #include "system.h" | 41 #include "system.h" |
52 #include "coretypes.h" | 42 #include "coretypes.h" |
53 #include "tm.h" | 43 #include "tm.h" |
67 #include "flags.h" | 57 #include "flags.h" |
68 #include "timevar.h" | 58 #include "timevar.h" |
69 #include "diagnostic.h" | 59 #include "diagnostic.h" |
70 #include "langhooks.h" | 60 #include "langhooks.h" |
71 #include "lto-streamer.h" | 61 #include "lto-streamer.h" |
72 | 62 #include "toplev.h" |
73 static void add_new_function (struct cgraph_node *node, | 63 |
74 void *data ATTRIBUTE_UNUSED); | |
75 static void remove_node_data (struct cgraph_node *node, | 64 static void remove_node_data (struct cgraph_node *node, |
76 void *data ATTRIBUTE_UNUSED); | 65 void *data ATTRIBUTE_UNUSED); |
77 static void duplicate_node_data (struct cgraph_node *src, | 66 static void duplicate_node_data (struct cgraph_node *src, |
78 struct cgraph_node *dst, | 67 struct cgraph_node *dst, |
79 void *data ATTRIBUTE_UNUSED); | 68 void *data ATTRIBUTE_UNUSED); |
96 }; | 85 }; |
97 | 86 |
98 /* Statics that are read and written by some set of functions. The | 87 /* Statics that are read and written by some set of functions. The |
99 local ones are based on the loads and stores local to the function. | 88 local ones are based on the loads and stores local to the function. |
100 The global ones are based on the local info as well as the | 89 The global ones are based on the local info as well as the |
101 transitive closure of the functions that are called. The | 90 transitive closure of the functions that are called. */ |
102 structures are separated to allow the global structures to be | |
103 shared between several functions since every function within a | |
104 strongly connected component will have the same information. This | |
105 sharing saves both time and space in the computation of the vectors | |
106 as well as their translation from decl_uid form to ann_uid | |
107 form. */ | |
108 | 91 |
109 struct ipa_reference_global_vars_info_d | 92 struct ipa_reference_global_vars_info_d |
110 { | 93 { |
111 bitmap statics_read; | 94 bitmap statics_read; |
112 bitmap statics_written; | 95 bitmap statics_written; |
96 }; | |
97 | |
98 /* Information we save about every function after ipa-reference is completted. */ | |
99 | |
100 struct ipa_reference_optimization_summary_d | |
101 { | |
113 bitmap statics_not_read; | 102 bitmap statics_not_read; |
114 bitmap statics_not_written; | 103 bitmap statics_not_written; |
115 }; | 104 }; |
116 | 105 |
117 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; | 106 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; |
118 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; | 107 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; |
108 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t; | |
109 | |
119 struct ipa_reference_vars_info_d | 110 struct ipa_reference_vars_info_d |
120 { | 111 { |
121 ipa_reference_local_vars_info_t local; | 112 struct ipa_reference_local_vars_info_d local; |
122 ipa_reference_global_vars_info_t global; | 113 struct ipa_reference_global_vars_info_d global; |
123 }; | 114 }; |
124 | 115 |
125 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t; | 116 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t; |
126 | 117 |
127 /* This splay tree contains all of the static variables that are | 118 /* This splay tree contains all of the static variables that are |
128 being considered by the compilation level alias analysis. For | 119 being considered by the compilation level alias analysis. */ |
129 module_at_a_time compilation, this is the set of static but not | 120 static splay_tree reference_vars_to_consider; |
130 public variables. Any variables that either have their address | |
131 taken or participate in otherwise unsavory operations are deleted | |
132 from this list. */ | |
133 static GTY((param1_is(int), param2_is(tree))) | |
134 splay_tree reference_vars_to_consider; | |
135 | |
136 /* This bitmap is used to knock out the module static variables whose | |
137 addresses have been taken and passed around. */ | |
138 static bitmap module_statics_escape; | |
139 | |
140 /* This bitmap is used to knock out the module static variables that | |
141 are not readonly. */ | |
142 static bitmap module_statics_written; | |
143 | 121 |
144 /* A bit is set for every module static we are considering. This is | 122 /* A bit is set for every module static we are considering. This is |
145 ored into the local info when asm code is found that clobbers all | 123 ored into the local info when asm code is found that clobbers all |
146 memory. */ | 124 memory. */ |
147 static bitmap all_module_statics; | 125 static bitmap all_module_statics; |
148 | 126 |
149 static struct pointer_set_t *visited_nodes; | |
150 | |
151 /* Obstack holding bitmaps of local analysis (live from analysis to | 127 /* Obstack holding bitmaps of local analysis (live from analysis to |
152 propagation) */ | 128 propagation) */ |
153 static bitmap_obstack local_info_obstack; | 129 static bitmap_obstack local_info_obstack; |
154 /* Obstack holding global analysis live forever. */ | 130 /* Obstack holding global analysis live forever. */ |
155 static bitmap_obstack global_info_obstack; | 131 static bitmap_obstack optimization_summary_obstack; |
156 | 132 |
157 /* Holders of ipa cgraph hooks: */ | 133 /* Holders of ipa cgraph hooks: */ |
158 static struct cgraph_node_hook_list *function_insertion_hook_holder; | |
159 static struct cgraph_2node_hook_list *node_duplication_hook_holder; | 134 static struct cgraph_2node_hook_list *node_duplication_hook_holder; |
160 static struct cgraph_node_hook_list *node_removal_hook_holder; | 135 static struct cgraph_node_hook_list *node_removal_hook_holder; |
161 | |
162 enum initialization_status_t | |
163 { | |
164 UNINITIALIZED, | |
165 RUNNING, | |
166 FINISHED | |
167 }; | |
168 | |
169 tree memory_identifier_string; | |
170 | 136 |
171 /* Vector where the reference var infos are actually stored. */ | 137 /* Vector where the reference var infos are actually stored. */ |
172 DEF_VEC_P (ipa_reference_vars_info_t); | 138 DEF_VEC_P (ipa_reference_vars_info_t); |
173 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap); | 139 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap); |
174 static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector; | 140 static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector; |
141 DEF_VEC_P (ipa_reference_optimization_summary_t); | |
142 DEF_VEC_ALLOC_P (ipa_reference_optimization_summary_t, heap); | |
143 static VEC (ipa_reference_optimization_summary_t, heap) *ipa_reference_opt_sum_vector; | |
175 | 144 |
176 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ | 145 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
177 static inline ipa_reference_vars_info_t | 146 static inline ipa_reference_vars_info_t |
178 get_reference_vars_info (struct cgraph_node *node) | 147 get_reference_vars_info (struct cgraph_node *node) |
179 { | 148 { |
180 if (!ipa_reference_vars_vector | 149 if (!ipa_reference_vars_vector |
181 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid) | 150 || VEC_length (ipa_reference_vars_info_t, |
151 ipa_reference_vars_vector) <= (unsigned int) node->uid) | |
182 return NULL; | 152 return NULL; |
183 return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid); | 153 return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, |
154 node->uid); | |
155 } | |
156 | |
157 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ | |
158 static inline ipa_reference_optimization_summary_t | |
159 get_reference_optimization_summary (struct cgraph_node *node) | |
160 { | |
161 if (!ipa_reference_opt_sum_vector | |
162 || (VEC_length (ipa_reference_optimization_summary_t, | |
163 ipa_reference_opt_sum_vector) | |
164 <= (unsigned int) node->uid)) | |
165 return NULL; | |
166 return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector, | |
167 node->uid); | |
184 } | 168 } |
185 | 169 |
186 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ | 170 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
187 static inline void | 171 static inline void |
188 set_reference_vars_info (struct cgraph_node *node, ipa_reference_vars_info_t info) | 172 set_reference_vars_info (struct cgraph_node *node, |
173 ipa_reference_vars_info_t info) | |
189 { | 174 { |
190 if (!ipa_reference_vars_vector | 175 if (!ipa_reference_vars_vector |
191 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid) | 176 || VEC_length (ipa_reference_vars_info_t, |
192 VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector, node->uid + 1); | 177 ipa_reference_vars_vector) <= (unsigned int) node->uid) |
193 VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid, info); | 178 VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, |
194 } | 179 ipa_reference_vars_vector, node->uid + 1); |
195 | 180 VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, |
196 /* Get a bitmap that contains all of the locally referenced static | 181 node->uid, info); |
197 variables for function FN. */ | 182 } |
198 static ipa_reference_local_vars_info_t | 183 |
199 get_local_reference_vars_info (struct cgraph_node *fn) | 184 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
200 { | 185 static inline void |
201 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | 186 set_reference_optimization_summary (struct cgraph_node *node, |
202 | 187 ipa_reference_optimization_summary_t info) |
203 if (info) | 188 { |
204 return info->local; | 189 if (!ipa_reference_opt_sum_vector |
205 else | 190 || (VEC_length (ipa_reference_optimization_summary_t, |
206 /* This phase was not run. */ | 191 ipa_reference_opt_sum_vector) |
207 return NULL; | 192 <= (unsigned int) node->uid)) |
208 } | 193 VEC_safe_grow_cleared (ipa_reference_optimization_summary_t, |
209 | 194 heap, ipa_reference_opt_sum_vector, node->uid + 1); |
210 /* Get a bitmap that contains all of the globally referenced static | 195 VEC_replace (ipa_reference_optimization_summary_t, |
211 variables for function FN. */ | 196 ipa_reference_opt_sum_vector, node->uid, info); |
212 | |
213 static ipa_reference_global_vars_info_t | |
214 get_global_reference_vars_info (struct cgraph_node *fn) | |
215 { | |
216 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | |
217 | |
218 if (info) | |
219 return info->global; | |
220 else | |
221 /* This phase was not run. */ | |
222 return NULL; | |
223 } | |
224 | |
225 /* Return a bitmap indexed by VAR_DECL uid for the static variables | |
226 that are read during the execution of the function FN. Returns | |
227 NULL if no data is available. */ | |
228 | |
229 bitmap | |
230 ipa_reference_get_read_global (struct cgraph_node *fn) | |
231 { | |
232 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | |
233 if (g) | |
234 return g->statics_read; | |
235 else | |
236 return NULL; | |
237 } | |
238 | |
239 /* Return a bitmap indexed by VAR_DECL uid for the static variables | |
240 that are written during the execution of the function FN. Note | |
241 that variables written may or may not be read during the function | |
242 call. Returns NULL if no data is available. */ | |
243 | |
244 bitmap | |
245 ipa_reference_get_written_global (struct cgraph_node *fn) | |
246 { | |
247 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | |
248 if (g) | |
249 return g->statics_written; | |
250 else | |
251 return NULL; | |
252 } | 197 } |
253 | 198 |
254 /* Return a bitmap indexed by_DECL_UID uid for the static variables | 199 /* Return a bitmap indexed by_DECL_UID uid for the static variables |
255 that are not read during the execution of the function FN. Returns | 200 that are not read during the execution of the function FN. Returns |
256 NULL if no data is available. */ | 201 NULL if no data is available. */ |
257 | 202 |
258 bitmap | 203 bitmap |
259 ipa_reference_get_not_read_global (struct cgraph_node *fn) | 204 ipa_reference_get_not_read_global (struct cgraph_node *fn) |
260 { | 205 { |
261 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 206 ipa_reference_optimization_summary_t info; |
262 if (g) | 207 |
263 return g->statics_not_read; | 208 info = get_reference_optimization_summary (fn); |
209 if (info) | |
210 return info->statics_not_read; | |
264 else | 211 else |
265 return NULL; | 212 return NULL; |
266 } | 213 } |
267 | 214 |
268 /* Return a bitmap indexed by DECL_UID uid for the static variables | 215 /* Return a bitmap indexed by DECL_UID uid for the static variables |
271 call. Returns NULL if no data is available. */ | 218 call. Returns NULL if no data is available. */ |
272 | 219 |
273 bitmap | 220 bitmap |
274 ipa_reference_get_not_written_global (struct cgraph_node *fn) | 221 ipa_reference_get_not_written_global (struct cgraph_node *fn) |
275 { | 222 { |
276 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 223 ipa_reference_optimization_summary_t info; |
277 if (g) | 224 |
278 return g->statics_not_written; | 225 info = get_reference_optimization_summary (fn); |
226 if (info) | |
227 return info->statics_not_written; | |
279 else | 228 else |
280 return NULL; | 229 return NULL; |
281 } | 230 } |
282 | 231 |
283 | 232 |
290 { | 239 { |
291 int uid = DECL_UID (var); | 240 int uid = DECL_UID (var); |
292 gcc_assert (TREE_CODE (var) == VAR_DECL); | 241 gcc_assert (TREE_CODE (var) == VAR_DECL); |
293 if (!bitmap_bit_p (all_module_statics, uid)) | 242 if (!bitmap_bit_p (all_module_statics, uid)) |
294 { | 243 { |
295 splay_tree_insert (reference_vars_to_consider, | 244 if (dump_file) |
296 uid, (splay_tree_value)var); | 245 splay_tree_insert (reference_vars_to_consider, |
246 uid, (splay_tree_value)var); | |
297 bitmap_set_bit (all_module_statics, uid); | 247 bitmap_set_bit (all_module_statics, uid); |
298 } | 248 } |
299 } | 249 } |
300 | 250 |
301 /* Return true if the variable T is the right kind of static variable to | 251 /* Return true if the variable T is the right kind of static variable to |
302 perform compilation unit scope escape analysis. */ | 252 perform compilation unit scope escape analysis. */ |
303 | 253 |
304 static inline bool | 254 static inline bool |
305 has_proper_scope_for_analysis (tree t) | 255 is_proper_for_analysis (tree t) |
306 { | 256 { |
257 /* We handle only variables whose address is never taken. */ | |
258 if (TREE_ADDRESSABLE (t)) | |
259 return false; | |
307 /* If the variable has the "used" attribute, treat it as if it had a | 260 /* If the variable has the "used" attribute, treat it as if it had a |
308 been touched by the devil. */ | 261 been touched by the devil. */ |
309 if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) | 262 if (DECL_PRESERVE_P (t)) |
310 return false; | 263 return false; |
311 | 264 |
312 /* Do not want to do anything with volatile except mark any | 265 /* Do not want to do anything with volatile except mark any |
313 function that uses one to be not const or pure. */ | 266 function that uses one to be not const or pure. */ |
314 if (TREE_THIS_VOLATILE (t)) | 267 if (TREE_THIS_VOLATILE (t)) |
315 return false; | 268 return false; |
316 | 269 |
317 /* Do not care about a local automatic that is not static. */ | |
318 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) | |
319 return false; | |
320 | |
321 /* FIXME: for LTO we should include PUBLIC vars too. This is bit difficult | |
322 as summarie would need unsharing. */ | |
323 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) | |
324 return false; | |
325 | |
326 /* We cannot touch decls where the type needs constructing. */ | 270 /* We cannot touch decls where the type needs constructing. */ |
327 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) | 271 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) |
328 return false; | 272 return false; |
329 | 273 |
330 /* This is a variable we care about. Check if we have seen it | 274 /* This is a variable we care about. Check if we have seen it |
331 before, and if not add it the set of variables we care about. */ | 275 before, and if not add it the set of variables we care about. */ |
332 if (!bitmap_bit_p (all_module_statics, DECL_UID (t))) | 276 if (all_module_statics |
277 && !bitmap_bit_p (all_module_statics, DECL_UID (t))) | |
333 add_static_var (t); | 278 add_static_var (t); |
334 | 279 |
335 return true; | 280 return true; |
336 } | |
337 | |
338 /* Mark tree T as having address taken. */ | |
339 | |
340 static void | |
341 mark_address_taken (tree x) | |
342 { | |
343 if (TREE_CODE (x) == VAR_DECL | |
344 && module_statics_escape && has_proper_scope_for_analysis (x)) | |
345 bitmap_set_bit (module_statics_escape, DECL_UID (x)); | |
346 } | |
347 | |
348 /* Wrapper around mark_address_taken for the stmt walker. */ | |
349 | |
350 static bool | |
351 mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr, | |
352 void *data ATTRIBUTE_UNUSED) | |
353 { | |
354 while (handled_component_p (addr)) | |
355 addr = TREE_OPERAND (addr, 0); | |
356 mark_address_taken (addr); | |
357 return false; | |
358 } | |
359 | |
360 /* Mark load of T. */ | |
361 | |
362 static bool | |
363 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) | |
364 { | |
365 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data; | |
366 if (TREE_CODE (t) == VAR_DECL | |
367 && has_proper_scope_for_analysis (t)) | |
368 bitmap_set_bit (local->statics_read, DECL_UID (t)); | |
369 return false; | |
370 } | |
371 | |
372 /* Mark store of T. */ | |
373 | |
374 static bool | |
375 mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) | |
376 { | |
377 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data; | |
378 if (TREE_CODE (t) == VAR_DECL | |
379 && has_proper_scope_for_analysis (t)) | |
380 { | |
381 if (local) | |
382 bitmap_set_bit (local->statics_written, DECL_UID (t)); | |
383 /* Mark the write so we can tell which statics are | |
384 readonly. */ | |
385 if (module_statics_written) | |
386 bitmap_set_bit (module_statics_written, DECL_UID (t)); | |
387 } | |
388 return false; | |
389 } | |
390 | |
391 /* Look for memory clobber and set read_all/write_all if present. */ | |
392 | |
393 static void | |
394 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt) | |
395 { | |
396 size_t i; | |
397 tree op; | |
398 | |
399 for (i = 0; i < gimple_asm_nclobbers (stmt); i++) | |
400 { | |
401 op = gimple_asm_clobber_op (stmt, i); | |
402 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1) | |
403 { | |
404 /* Abandon all hope, ye who enter here. */ | |
405 local->calls_read_all = true; | |
406 local->calls_write_all = true; | |
407 } | |
408 } | |
409 } | |
410 | |
411 /* Look for external calls and set read_all/write_all correspondingly. */ | |
412 | |
413 static void | |
414 check_call (ipa_reference_local_vars_info_t local, gimple stmt) | |
415 { | |
416 int flags = gimple_call_flags (stmt); | |
417 tree callee_t = gimple_call_fndecl (stmt); | |
418 | |
419 /* Process indirect calls. All direct calles are handled at propagation | |
420 time. */ | |
421 if (!callee_t) | |
422 { | |
423 if (flags & ECF_CONST) | |
424 ; | |
425 else if (flags & ECF_PURE) | |
426 local->calls_read_all = true; | |
427 else | |
428 { | |
429 local->calls_read_all = true; | |
430 /* When function does not reutrn, it is safe to ignore anythign it writes | |
431 to, because the effect will never happen. */ | |
432 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) | |
433 != (ECF_NOTHROW | ECF_NORETURN)) | |
434 local->calls_write_all = true; | |
435 } | |
436 } | |
437 } | |
438 | |
439 /* TP is the part of the tree currently under the microscope. | |
440 WALK_SUBTREES is part of the walk_tree api but is unused here. | |
441 DATA is cgraph_node of the function being walked. */ | |
442 | |
443 static tree | |
444 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip, | |
445 struct cgraph_node *fn) | |
446 { | |
447 gimple stmt = gsi_stmt (*gsip); | |
448 ipa_reference_local_vars_info_t local = NULL; | |
449 | |
450 if (is_gimple_debug (stmt)) | |
451 return NULL; | |
452 | |
453 if (fn) | |
454 local = get_reference_vars_info (fn)->local; | |
455 | |
456 /* Look for direct loads and stores. */ | |
457 walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store, | |
458 mark_address); | |
459 | |
460 if (is_gimple_call (stmt)) | |
461 check_call (local, stmt); | |
462 else if (gimple_code (stmt) == GIMPLE_ASM) | |
463 check_asm_memory_clobber (local, stmt); | |
464 | |
465 return NULL; | |
466 } | |
467 | |
468 /* Call-back to scan variable initializers for static references. | |
469 Called using walk_tree. */ | |
470 | |
471 static tree | |
472 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees, | |
473 void *data ATTRIBUTE_UNUSED) | |
474 { | |
475 tree t = *tp; | |
476 | |
477 if (TREE_CODE (t) == ADDR_EXPR) | |
478 { | |
479 mark_address_taken (get_base_var (t)); | |
480 *walk_subtrees = 0; | |
481 } | |
482 /* Save some cycles by not walking types and declaration as we | |
483 won't find anything useful there anyway. */ | |
484 else if (IS_TYPE_OR_DECL_P (*tp)) | |
485 *walk_subtrees = 0; | |
486 | |
487 return NULL; | |
488 } | |
489 | |
490 /* Lookup the tree node for the static variable that has UID. */ | |
491 static tree | |
492 get_static_decl (int index) | |
493 { | |
494 splay_tree_node stn = | |
495 splay_tree_lookup (reference_vars_to_consider, index); | |
496 if (stn) | |
497 return (tree)stn->value; | |
498 return NULL; | |
499 } | 281 } |
500 | 282 |
501 /* Lookup the tree node for the static variable that has UID and | 283 /* Lookup the tree node for the static variable that has UID and |
502 convert the name to a string for debugging. */ | 284 convert the name to a string for debugging. */ |
503 | 285 |
528 { | 310 { |
529 if (get_reference_vars_info (y)) | 311 if (get_reference_vars_info (y)) |
530 { | 312 { |
531 ipa_reference_vars_info_t y_info | 313 ipa_reference_vars_info_t y_info |
532 = get_reference_vars_info (y); | 314 = get_reference_vars_info (y); |
533 ipa_reference_global_vars_info_t y_global = y_info->global; | 315 ipa_reference_global_vars_info_t y_global = &y_info->global; |
534 | 316 |
535 /* Calls in current cycle do not have global computed yet. */ | 317 /* Calls in current cycle do not have global computed yet. */ |
536 if (!y_info->global) | 318 if (!y_global->statics_read) |
537 continue; | 319 continue; |
538 | 320 |
539 if (x_global->statics_read | 321 if (x_global->statics_read |
540 != all_module_statics) | 322 != all_module_statics) |
541 { | 323 { |
588 if (init_p) | 370 if (init_p) |
589 return; | 371 return; |
590 | 372 |
591 init_p = true; | 373 init_p = true; |
592 | 374 |
593 memory_identifier_string = build_string(7, "memory"); | 375 if (dump_file) |
594 | 376 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); |
595 reference_vars_to_consider = | |
596 splay_tree_new_ggc (splay_tree_compare_ints); | |
597 | 377 |
598 bitmap_obstack_initialize (&local_info_obstack); | 378 bitmap_obstack_initialize (&local_info_obstack); |
599 bitmap_obstack_initialize (&global_info_obstack); | 379 bitmap_obstack_initialize (&optimization_summary_obstack); |
600 module_statics_escape = BITMAP_ALLOC (&local_info_obstack); | 380 all_module_statics = BITMAP_ALLOC (&local_info_obstack); |
601 module_statics_written = BITMAP_ALLOC (&local_info_obstack); | 381 |
602 all_module_statics = BITMAP_ALLOC (&global_info_obstack); | |
603 | |
604 /* There are some shared nodes, in particular the initializers on | |
605 static declarations. We do not need to scan them more than once | |
606 since all we would be interested in are the addressof | |
607 operations. */ | |
608 visited_nodes = pointer_set_create (); | |
609 | |
610 function_insertion_hook_holder = | |
611 cgraph_add_function_insertion_hook (&add_new_function, NULL); | |
612 node_removal_hook_holder = | 382 node_removal_hook_holder = |
613 cgraph_add_node_removal_hook (&remove_node_data, NULL); | 383 cgraph_add_node_removal_hook (&remove_node_data, NULL); |
614 node_duplication_hook_holder = | 384 node_duplication_hook_holder = |
615 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | 385 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); |
616 } | 386 } |
617 | 387 |
618 /* Check out the rhs of a static or global initialization VNODE to see | |
619 if any of them contain addressof operations. Note that some of | |
620 these variables may not even be referenced in the code in this | |
621 compilation unit but their right hand sides may contain references | |
622 to variables defined within this unit. */ | |
623 | |
624 static void | |
625 analyze_variable (struct varpool_node *vnode) | |
626 { | |
627 struct walk_stmt_info wi; | |
628 tree global = vnode->decl; | |
629 | |
630 memset (&wi, 0, sizeof (wi)); | |
631 wi.pset = visited_nodes; | |
632 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs, | |
633 &wi, wi.pset); | |
634 } | |
635 | |
636 | 388 |
637 /* Set up the persistent info for FN. */ | 389 /* Set up the persistent info for FN. */ |
638 | 390 |
639 static ipa_reference_local_vars_info_t | 391 static ipa_reference_local_vars_info_t |
640 init_function_info (struct cgraph_node *fn) | 392 init_function_info (struct cgraph_node *fn) |
641 { | 393 { |
642 ipa_reference_vars_info_t info | 394 ipa_reference_vars_info_t info |
643 = XCNEW (struct ipa_reference_vars_info_d); | 395 = XCNEW (struct ipa_reference_vars_info_d); |
644 ipa_reference_local_vars_info_t l | |
645 = XCNEW (struct ipa_reference_local_vars_info_d); | |
646 | 396 |
647 /* Add the info to the tree's annotation. */ | 397 /* Add the info to the tree's annotation. */ |
648 set_reference_vars_info (fn, info); | 398 set_reference_vars_info (fn, info); |
649 | 399 |
650 info->local = l; | 400 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack); |
651 l->statics_read = BITMAP_ALLOC (&local_info_obstack); | 401 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack); |
652 l->statics_written = BITMAP_ALLOC (&local_info_obstack); | 402 |
653 | 403 return &info->local; |
654 return l; | |
655 } | 404 } |
656 | 405 |
657 | 406 |
658 /* This is the main routine for finding the reference patterns for | 407 /* This is the main routine for finding the reference patterns for |
659 global variables within a function FN. */ | 408 global variables within a function FN. */ |
660 | 409 |
661 static void | 410 static void |
662 analyze_function (struct cgraph_node *fn) | 411 analyze_function (struct cgraph_node *fn) |
663 { | 412 { |
664 tree decl = fn->decl; | |
665 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl); | |
666 basic_block this_block; | |
667 #ifdef ENABLE_CHECKING | |
668 tree step; | |
669 #endif | |
670 ipa_reference_local_vars_info_t local; | 413 ipa_reference_local_vars_info_t local; |
671 | 414 struct ipa_ref *ref; |
672 if (dump_file) | 415 int i; |
673 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn)); | 416 tree var; |
674 | 417 struct cgraph_edge *ie; |
675 push_cfun (DECL_STRUCT_FUNCTION (decl)); | 418 |
676 current_function_decl = decl; | 419 local = init_function_info (fn); |
677 | 420 /* Process indirect calls. All direct calles are handled at propagation |
678 init_function_info (fn); | 421 time. */ |
679 FOR_EACH_BB_FN (this_block, this_cfun) | 422 for (ie = fn->indirect_calls; ie; ie = ie->next_callee) |
423 if (!(ie->indirect_info->ecf_flags & ECF_CONST)) | |
424 { | |
425 local->calls_read_all = true; | |
426 if (!(ie->indirect_info->ecf_flags & ECF_PURE) | |
427 && ((ie->indirect_info->ecf_flags & (ECF_NOTHROW | ECF_NORETURN)) | |
428 != (ECF_NOTHROW | ECF_NORETURN))) | |
429 local->calls_write_all = true; | |
430 } | |
431 for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++) | |
680 { | 432 { |
681 gimple_stmt_iterator gsi; | 433 if (ref->refered_type != IPA_REF_VARPOOL) |
682 gimple phi; | 434 continue; |
683 tree op; | 435 var = ipa_ref_varpool_node (ref)->decl; |
684 use_operand_p use; | 436 if (ipa_ref_varpool_node (ref)->externally_visible |
685 ssa_op_iter iter; | 437 || !ipa_ref_varpool_node (ref)->analyzed |
686 | 438 || !is_proper_for_analysis (var)) |
687 /* Find the addresses taken in phi node arguments. */ | 439 continue; |
688 for (gsi = gsi_start_phis (this_block); | 440 switch (ref->use) |
689 !gsi_end_p (gsi); | 441 { |
690 gsi_next (&gsi)) | 442 case IPA_REF_LOAD: |
691 { | 443 bitmap_set_bit (local->statics_read, DECL_UID (var)); |
692 phi = gsi_stmt (gsi); | 444 break; |
693 FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE) | 445 case IPA_REF_STORE: |
694 { | 446 bitmap_set_bit (local->statics_written, DECL_UID (var)); |
695 op = USE_FROM_PTR (use); | 447 break; |
696 if (TREE_CODE (op) == ADDR_EXPR) | 448 case IPA_REF_ADDR: |
697 mark_address_taken (get_base_var (op)); | 449 break; |
698 } | 450 } |
699 } | |
700 | |
701 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi)) | |
702 scan_stmt_for_static_refs (&gsi, fn); | |
703 } | 451 } |
704 | 452 |
705 local = get_reference_vars_info (fn)->local; | 453 if ((flags_from_decl_or_type (fn->decl) & (ECF_NOTHROW | ECF_NORETURN)) |
706 if ((flags_from_decl_or_type (decl) & (ECF_NOTHROW | ECF_NORETURN)) | |
707 == (ECF_NOTHROW | ECF_NORETURN)) | 454 == (ECF_NOTHROW | ECF_NORETURN)) |
708 { | 455 { |
709 local->calls_write_all = false; | 456 local->calls_write_all = false; |
710 bitmap_clear (local->statics_written); | 457 bitmap_clear (local->statics_written); |
711 } | 458 } |
713 /* Free bitmaps of direct references if we can not use them anyway. */ | 460 /* Free bitmaps of direct references if we can not use them anyway. */ |
714 if (local->calls_write_all) | 461 if (local->calls_write_all) |
715 BITMAP_FREE (local->statics_written); | 462 BITMAP_FREE (local->statics_written); |
716 if (local->calls_read_all) | 463 if (local->calls_read_all) |
717 BITMAP_FREE (local->statics_read); | 464 BITMAP_FREE (local->statics_read); |
718 | |
719 | |
720 #ifdef ENABLE_CHECKING | |
721 /* Verify that all local initializers was expanded by gimplifier. */ | |
722 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls; | |
723 step; | |
724 step = TREE_CHAIN (step)) | |
725 { | |
726 tree var = TREE_VALUE (step); | |
727 if (TREE_CODE (var) == VAR_DECL | |
728 && DECL_INITIAL (var) | |
729 && !TREE_STATIC (var)) | |
730 gcc_unreachable (); | |
731 } | |
732 #endif | |
733 pop_cfun (); | |
734 current_function_decl = NULL; | |
735 } | |
736 | |
737 /* Remove local data associated with function FN. */ | |
738 static void | |
739 clean_function_local_data (struct cgraph_node *fn) | |
740 { | |
741 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | |
742 ipa_reference_local_vars_info_t l = info->local; | |
743 if (l) | |
744 { | |
745 if (l->statics_read | |
746 && l->statics_read != all_module_statics) | |
747 BITMAP_FREE (l->statics_read); | |
748 if (l->statics_written | |
749 &&l->statics_written != all_module_statics) | |
750 BITMAP_FREE (l->statics_written); | |
751 free (l); | |
752 info->local = NULL; | |
753 } | |
754 } | |
755 | |
756 /* Remove all data associated with function FN. */ | |
757 | |
758 static void | |
759 clean_function (struct cgraph_node *fn) | |
760 { | |
761 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | |
762 ipa_reference_global_vars_info_t g = info->global; | |
763 | |
764 clean_function_local_data (fn); | |
765 if (g) | |
766 { | |
767 if (g->statics_read | |
768 && g->statics_read != all_module_statics) | |
769 BITMAP_FREE (g->statics_read); | |
770 | |
771 if (g->statics_written | |
772 && g->statics_written != all_module_statics) | |
773 BITMAP_FREE (g->statics_written); | |
774 | |
775 if (g->statics_not_read | |
776 && g->statics_not_read != all_module_statics) | |
777 BITMAP_FREE (g->statics_not_read); | |
778 | |
779 if (g->statics_not_written | |
780 && g->statics_not_written != all_module_statics) | |
781 BITMAP_FREE (g->statics_not_written); | |
782 free (g); | |
783 info->global = NULL; | |
784 } | |
785 | |
786 free (get_reference_vars_info (fn)); | |
787 set_reference_vars_info (fn, NULL); | |
788 } | |
789 | |
790 /* Called when new function is inserted to callgraph late. */ | |
791 static void | |
792 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | |
793 { | |
794 /* There are some shared nodes, in particular the initializers on | |
795 static declarations. We do not need to scan them more than once | |
796 since all we would be interested in are the addressof | |
797 operations. */ | |
798 analyze_function (node); | |
799 visited_nodes = NULL; | |
800 } | 465 } |
801 | 466 |
802 static bitmap | 467 static bitmap |
803 copy_local_bitmap (bitmap src) | 468 copy_global_bitmap (bitmap src) |
804 { | 469 { |
805 bitmap dst; | 470 bitmap dst; |
806 if (!src) | 471 if (!src) |
807 return NULL; | 472 return NULL; |
808 if (src == all_module_statics) | 473 dst = BITMAP_ALLOC (&optimization_summary_obstack); |
809 return all_module_statics; | |
810 dst = BITMAP_ALLOC (&local_info_obstack); | |
811 bitmap_copy (dst, src); | 474 bitmap_copy (dst, src); |
812 return dst; | 475 return dst; |
813 } | 476 } |
814 | 477 |
815 static bitmap | |
816 copy_global_bitmap (bitmap src) | |
817 { | |
818 bitmap dst; | |
819 if (!src) | |
820 return NULL; | |
821 if (src == all_module_statics) | |
822 return all_module_statics; | |
823 dst = BITMAP_ALLOC (&global_info_obstack); | |
824 bitmap_copy (dst, src); | |
825 return dst; | |
826 } | |
827 | 478 |
828 /* Called when new clone is inserted to callgraph late. */ | 479 /* Called when new clone is inserted to callgraph late. */ |
829 | 480 |
830 static void | 481 static void |
831 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, | 482 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, |
832 void *data ATTRIBUTE_UNUSED) | 483 void *data ATTRIBUTE_UNUSED) |
833 { | 484 { |
834 ipa_reference_global_vars_info_t ginfo; | 485 ipa_reference_optimization_summary_t ginfo; |
835 ipa_reference_local_vars_info_t linfo; | 486 ipa_reference_optimization_summary_t dst_ginfo; |
836 ipa_reference_global_vars_info_t dst_ginfo; | 487 |
837 ipa_reference_local_vars_info_t dst_linfo; | 488 ginfo = get_reference_optimization_summary (src); |
838 | 489 if (!ginfo) |
839 ginfo = get_global_reference_vars_info (src); | |
840 linfo = get_local_reference_vars_info (src); | |
841 if (!linfo && !ginfo) | |
842 return; | 490 return; |
843 init_function_info (dst); | 491 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d); |
844 if (linfo) | 492 set_reference_optimization_summary (dst, dst_ginfo); |
845 { | 493 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read); |
846 dst_linfo = get_local_reference_vars_info (dst); | 494 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written); |
847 dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read); | 495 } |
848 dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written); | 496 |
849 dst_linfo->calls_read_all = linfo->calls_read_all; | 497 /* Called when node is removed. */ |
850 dst_linfo->calls_write_all = linfo->calls_write_all; | 498 |
851 } | 499 static void |
500 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | |
501 { | |
502 ipa_reference_optimization_summary_t ginfo; | |
503 ginfo = get_reference_optimization_summary (node); | |
852 if (ginfo) | 504 if (ginfo) |
853 { | 505 { |
854 get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d); | 506 if (ginfo->statics_not_read |
855 dst_ginfo = get_global_reference_vars_info (dst); | 507 && ginfo->statics_not_read != all_module_statics) |
856 dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read); | 508 BITMAP_FREE (ginfo->statics_not_read); |
857 dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written); | 509 |
858 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read); | 510 if (ginfo->statics_not_written |
859 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written); | 511 && ginfo->statics_not_written != all_module_statics) |
512 BITMAP_FREE (ginfo->statics_not_written); | |
513 free (ginfo); | |
514 set_reference_optimization_summary (node, NULL); | |
860 } | 515 } |
861 } | |
862 | |
863 /* Called when node is removed. */ | |
864 | |
865 static void | |
866 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | |
867 { | |
868 if (get_reference_vars_info (node)) | |
869 clean_function (node); | |
870 } | 516 } |
871 | 517 |
872 /* Analyze each function in the cgraph to see which global or statics | 518 /* Analyze each function in the cgraph to see which global or statics |
873 are read or written. */ | 519 are read or written. */ |
874 | 520 |
875 static void | 521 static void |
876 generate_summary (void) | 522 generate_summary (void) |
877 { | 523 { |
878 struct cgraph_node *node; | 524 struct cgraph_node *node; |
879 struct varpool_node *vnode; | |
880 unsigned int index; | 525 unsigned int index; |
881 bitmap_iterator bi; | 526 bitmap_iterator bi; |
882 bitmap module_statics_readonly; | |
883 bitmap bm_temp; | 527 bitmap bm_temp; |
884 | 528 |
885 ipa_init (); | 529 ipa_init (); |
886 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack); | |
887 bm_temp = BITMAP_ALLOC (&local_info_obstack); | 530 bm_temp = BITMAP_ALLOC (&local_info_obstack); |
888 | 531 |
889 /* Process all of the variables first. */ | 532 /* Process all of the functions next. */ |
890 FOR_EACH_STATIC_INITIALIZER (vnode) | |
891 analyze_variable (vnode); | |
892 | |
893 /* Process all of the functions next. | |
894 | |
895 We do not want to process any of the clones so we check that this | |
896 is a master clone. However, we do need to process any | |
897 AVAIL_OVERWRITABLE functions (these are never clones) because | |
898 they may cause a static variable to escape. The code that can | |
899 overwrite such a function cannot access the statics because it | |
900 would not be in the same compilation unit. When the analysis is | |
901 finished, the computed information of these AVAIL_OVERWRITABLE is | |
902 replaced with worst case info. | |
903 */ | |
904 for (node = cgraph_nodes; node; node = node->next) | 533 for (node = cgraph_nodes; node; node = node->next) |
905 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 534 if (node->analyzed) |
906 analyze_function (node); | 535 analyze_function (node); |
907 | |
908 pointer_set_destroy (visited_nodes); | |
909 visited_nodes = NULL; | |
910 | |
911 /* Prune out the variables that were found to behave badly | |
912 (i.e. have their address taken). */ | |
913 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi) | |
914 { | |
915 splay_tree_remove (reference_vars_to_consider, index); | |
916 } | |
917 | |
918 bitmap_and_compl_into (all_module_statics, | |
919 module_statics_escape); | |
920 | |
921 bitmap_and_compl (module_statics_readonly, all_module_statics, | |
922 module_statics_written); | |
923 | |
924 /* If the address is not taken, we can unset the addressable bit | |
925 on this variable. */ | |
926 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) | |
927 { | |
928 tree var = get_static_decl (index); | |
929 TREE_ADDRESSABLE (var) = 0; | |
930 if (dump_file) | |
931 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n", | |
932 get_static_name (index)); | |
933 } | |
934 | |
935 /* If the variable is never written, we can set the TREE_READONLY | |
936 flag. Additionally if it has a DECL_INITIAL that is made up of | |
937 constants we can treat the entire global as a constant. */ | |
938 | |
939 bitmap_and_compl (module_statics_readonly, all_module_statics, | |
940 module_statics_written); | |
941 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi) | |
942 { | |
943 tree var = get_static_decl (index); | |
944 | |
945 /* Ignore variables in named sections - changing TREE_READONLY | |
946 changes the section flags, potentially causing conflicts with | |
947 other variables in the same named section. */ | |
948 if (DECL_SECTION_NAME (var) == NULL_TREE) | |
949 { | |
950 TREE_READONLY (var) = 1; | |
951 if (dump_file) | |
952 fprintf (dump_file, "read-only var %s\n", | |
953 get_static_name (index)); | |
954 } | |
955 } | |
956 | |
957 BITMAP_FREE(module_statics_escape); | |
958 BITMAP_FREE(module_statics_written); | |
959 module_statics_escape = NULL; | |
960 module_statics_written = NULL; | |
961 | 536 |
962 if (dump_file) | 537 if (dump_file) |
963 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) | 538 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) |
964 { | 539 { |
965 fprintf (dump_file, "\nPromotable global:%s", | 540 fprintf (dump_file, "\nPromotable global:%s", |
966 get_static_name (index)); | 541 get_static_name (index)); |
967 } | 542 } |
968 | 543 |
969 for (node = cgraph_nodes; node; node = node->next) | |
970 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | |
971 { | |
972 ipa_reference_local_vars_info_t l; | |
973 l = get_reference_vars_info (node)->local; | |
974 | |
975 /* Any variables that are not in all_module_statics are | |
976 removed from the local maps. This will include all of the | |
977 variables that were found to escape in the function | |
978 scanning. */ | |
979 if (l->statics_read) | |
980 bitmap_and_into (l->statics_read, | |
981 all_module_statics); | |
982 if (l->statics_written) | |
983 bitmap_and_into (l->statics_written, | |
984 all_module_statics); | |
985 } | |
986 | |
987 BITMAP_FREE(module_statics_readonly); | |
988 BITMAP_FREE(bm_temp); | 544 BITMAP_FREE(bm_temp); |
989 | 545 |
990 if (dump_file) | 546 if (dump_file) |
991 for (node = cgraph_nodes; node; node = node->next) | 547 for (node = cgraph_nodes; node; node = node->next) |
992 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 548 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
993 { | 549 { |
994 ipa_reference_local_vars_info_t l; | 550 ipa_reference_local_vars_info_t l; |
995 unsigned int index; | 551 unsigned int index; |
996 bitmap_iterator bi; | 552 bitmap_iterator bi; |
997 | 553 |
998 l = get_reference_vars_info (node)->local; | 554 l = &get_reference_vars_info (node)->local; |
999 fprintf (dump_file, | 555 fprintf (dump_file, |
1000 "\nFunction name:%s/%i:", | 556 "\nFunction name:%s/%i:", |
1001 cgraph_node_name (node), node->uid); | 557 cgraph_node_name (node), node->uid); |
1002 fprintf (dump_file, "\n locals read: "); | 558 fprintf (dump_file, "\n locals read: "); |
1003 if (l->statics_read) | 559 if (l->statics_read) |
1019 fprintf (dump_file, "\n calls read all: "); | 575 fprintf (dump_file, "\n calls read all: "); |
1020 if (l->calls_write_all) | 576 if (l->calls_write_all) |
1021 fprintf (dump_file, "\n calls read all: "); | 577 fprintf (dump_file, "\n calls read all: "); |
1022 } | 578 } |
1023 } | 579 } |
1024 | |
1025 | |
1026 /* Return true if we need to write summary of NODE. */ | |
1027 | |
1028 static bool | |
1029 write_node_summary_p (struct cgraph_node *node) | |
1030 { | |
1031 gcc_assert (node->global.inlined_to == NULL); | |
1032 return (node->analyzed | |
1033 && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE | |
1034 && get_reference_vars_info (node) != NULL); | |
1035 } | |
1036 | |
1037 /* Serialize the ipa info for lto. */ | |
1038 | |
1039 static void | |
1040 ipa_reference_write_summary (cgraph_node_set set) | |
1041 { | |
1042 struct cgraph_node *node; | |
1043 struct lto_simple_output_block *ob | |
1044 = lto_create_simple_output_block (LTO_section_ipa_reference); | |
1045 unsigned int count = 0; | |
1046 cgraph_node_set_iterator csi; | |
1047 | |
1048 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
1049 if (write_node_summary_p (csi_node (csi))) | |
1050 count++; | |
1051 | |
1052 lto_output_uleb128_stream (ob->main_stream, count); | |
1053 | |
1054 /* Process all of the functions. */ | |
1055 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
1056 { | |
1057 node = csi_node (csi); | |
1058 if (write_node_summary_p (node)) | |
1059 { | |
1060 ipa_reference_local_vars_info_t l | |
1061 = get_reference_vars_info (node)->local; | |
1062 unsigned int index; | |
1063 bitmap_iterator bi; | |
1064 lto_cgraph_encoder_t encoder; | |
1065 int node_ref; | |
1066 | |
1067 encoder = ob->decl_state->cgraph_node_encoder; | |
1068 node_ref = lto_cgraph_encoder_encode (encoder, node); | |
1069 lto_output_uleb128_stream (ob->main_stream, node_ref); | |
1070 | |
1071 /* Stream out the statics read. */ | |
1072 if (l->calls_read_all) | |
1073 lto_output_sleb128_stream (ob->main_stream, -1); | |
1074 else | |
1075 { | |
1076 lto_output_sleb128_stream (ob->main_stream, | |
1077 bitmap_count_bits (l->statics_read)); | |
1078 EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 0, index, bi) | |
1079 lto_output_var_decl_index(ob->decl_state, ob->main_stream, | |
1080 get_static_decl (index)); | |
1081 } | |
1082 | |
1083 /* Stream out the statics written. */ | |
1084 if (l->calls_write_all) | |
1085 lto_output_sleb128_stream (ob->main_stream, -1); | |
1086 else | |
1087 { | |
1088 lto_output_sleb128_stream (ob->main_stream, | |
1089 bitmap_count_bits (l->statics_written)); | |
1090 EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 0, index, bi) | |
1091 lto_output_var_decl_index(ob->decl_state, ob->main_stream, | |
1092 get_static_decl (index)); | |
1093 } | |
1094 } | |
1095 } | |
1096 lto_destroy_simple_output_block (ob); | |
1097 } | |
1098 | |
1099 | |
1100 /* Deserialize the ipa info for lto. */ | |
1101 | |
1102 static void | |
1103 ipa_reference_read_summary (void) | |
1104 { | |
1105 struct lto_file_decl_data ** file_data_vec | |
1106 = lto_get_file_decl_data (); | |
1107 struct lto_file_decl_data * file_data; | |
1108 unsigned int j = 0; | |
1109 | |
1110 ipa_init (); | |
1111 | |
1112 while ((file_data = file_data_vec[j++])) | |
1113 { | |
1114 const char *data; | |
1115 size_t len; | |
1116 struct lto_input_block *ib | |
1117 = lto_create_simple_input_block (file_data, | |
1118 LTO_section_ipa_reference, | |
1119 &data, &len); | |
1120 if (ib) | |
1121 { | |
1122 unsigned int i; | |
1123 unsigned int f_count = lto_input_uleb128 (ib); | |
1124 | |
1125 for (i = 0; i < f_count; i++) | |
1126 { | |
1127 unsigned int j, index; | |
1128 struct cgraph_node *node; | |
1129 ipa_reference_local_vars_info_t l; | |
1130 int v_count; | |
1131 lto_cgraph_encoder_t encoder; | |
1132 | |
1133 index = lto_input_uleb128 (ib); | |
1134 encoder = file_data->cgraph_node_encoder; | |
1135 node = lto_cgraph_encoder_deref (encoder, index); | |
1136 l = init_function_info (node); | |
1137 | |
1138 /* Set the statics read. */ | |
1139 v_count = lto_input_sleb128 (ib); | |
1140 if (v_count == -1) | |
1141 l->calls_read_all = true; | |
1142 else | |
1143 for (j = 0; j < (unsigned int)v_count; j++) | |
1144 { | |
1145 unsigned int var_index = lto_input_uleb128 (ib); | |
1146 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1147 var_index); | |
1148 add_static_var (v_decl); | |
1149 bitmap_set_bit (l->statics_read, DECL_UID (v_decl)); | |
1150 } | |
1151 | |
1152 /* Set the statics written. */ | |
1153 v_count = lto_input_sleb128 (ib); | |
1154 if (v_count == -1) | |
1155 l->calls_write_all = true; | |
1156 else | |
1157 for (j = 0; j < (unsigned int)v_count; j++) | |
1158 { | |
1159 unsigned int var_index = lto_input_uleb128 (ib); | |
1160 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1161 var_index); | |
1162 add_static_var (v_decl); | |
1163 bitmap_set_bit (l->statics_written, DECL_UID (v_decl)); | |
1164 } | |
1165 } | |
1166 | |
1167 lto_destroy_simple_input_block (file_data, | |
1168 LTO_section_ipa_reference, | |
1169 ib, data, len); | |
1170 } | |
1171 } | |
1172 } | |
1173 | |
1174 | |
1175 | 580 |
1176 /* Set READ_ALL/WRITE_ALL based on DECL flags. */ | 581 /* Set READ_ALL/WRITE_ALL based on DECL flags. */ |
582 | |
1177 static void | 583 static void |
1178 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all) | 584 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all) |
1179 { | 585 { |
1180 int flags = flags_from_decl_or_type (decl); | 586 int flags = flags_from_decl_or_type (decl); |
1181 if (flags & ECF_CONST) | 587 if (flags & ECF_CONST) |
1183 else if (flags & ECF_PURE) | 589 else if (flags & ECF_PURE) |
1184 *read_all = true; | 590 *read_all = true; |
1185 else | 591 else |
1186 { | 592 { |
1187 /* TODO: To be able to produce sane results, we should also handle | 593 /* TODO: To be able to produce sane results, we should also handle |
1188 common builtins, in particular throw. | 594 common builtins, in particular throw. */ |
1189 Indirect calls hsould be only counted and as inliner is replacing them | |
1190 by direct calls, we can conclude if any indirect calls are left in body */ | |
1191 *read_all = true; | 595 *read_all = true; |
1192 /* When function does not reutrn, it is safe to ignore anythign it writes | 596 /* When function does not return, it is safe to ignore anythign it writes |
1193 to, because the effect will never happen. */ | 597 to, because the effect will never happen. */ |
1194 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) | 598 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) |
1195 != (ECF_NOTHROW | ECF_NORETURN)) | 599 != (ECF_NOTHROW | ECF_NORETURN)) |
1196 *write_all = true; | 600 *write_all = true; |
1197 } | 601 } |
1198 } | 602 } |
1199 | 603 |
1200 /* Produce the global information by preforming a transitive closure | 604 /* Produce the global information by preforming a transitive closure |
1201 on the local information that was produced by ipa_analyze_function | 605 on the local information that was produced by ipa_analyze_function */ |
1202 and ipa_analyze_variable. */ | |
1203 | 606 |
1204 static unsigned int | 607 static unsigned int |
1205 propagate (void) | 608 propagate (void) |
1206 { | 609 { |
1207 struct cgraph_node *node; | 610 struct cgraph_node *node; |
1209 struct cgraph_node **order = | 612 struct cgraph_node **order = |
1210 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | 613 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); |
1211 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL); | 614 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL); |
1212 int i; | 615 int i; |
1213 | 616 |
1214 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); | |
1215 if (dump_file) | 617 if (dump_file) |
1216 dump_cgraph (dump_file); | 618 dump_cgraph (dump_file); |
619 | |
620 ipa_discover_readonly_nonaddressable_vars (); | |
621 generate_summary (); | |
1217 | 622 |
1218 /* Propagate the local information thru the call graph to produce | 623 /* Propagate the local information thru the call graph to produce |
1219 the global information. All the nodes within a cycle will have | 624 the global information. All the nodes within a cycle will have |
1220 the same info so we collapse cycles first. Then we can do the | 625 the same info so we collapse cycles first. Then we can do the |
1221 propagation in one pass from the leaves to the roots. */ | 626 propagation in one pass from the leaves to the roots. */ |
1224 ipa_utils_print_order(dump_file, "reduced", order, order_pos); | 629 ipa_utils_print_order(dump_file, "reduced", order, order_pos); |
1225 | 630 |
1226 for (i = 0; i < order_pos; i++ ) | 631 for (i = 0; i < order_pos; i++ ) |
1227 { | 632 { |
1228 ipa_reference_vars_info_t node_info; | 633 ipa_reference_vars_info_t node_info; |
1229 ipa_reference_global_vars_info_t node_g = | 634 ipa_reference_global_vars_info_t node_g; |
1230 XCNEW (struct ipa_reference_global_vars_info_d); | |
1231 ipa_reference_local_vars_info_t node_l; | 635 ipa_reference_local_vars_info_t node_l; |
1232 struct cgraph_edge *e; | 636 struct cgraph_edge *e; |
1233 | 637 |
1234 bool read_all; | 638 bool read_all; |
1235 bool write_all; | 639 bool write_all; |
1242 dump_cgraph_node (stderr, node); | 646 dump_cgraph_node (stderr, node); |
1243 dump_cgraph (stderr); | 647 dump_cgraph (stderr); |
1244 gcc_unreachable (); | 648 gcc_unreachable (); |
1245 } | 649 } |
1246 | 650 |
1247 gcc_assert (!node_info->global); | 651 node_l = &node_info->local; |
1248 node_l = node_info->local; | 652 node_g = &node_info->global; |
1249 | 653 |
1250 read_all = node_l->calls_read_all; | 654 read_all = node_l->calls_read_all; |
1251 write_all = node_l->calls_write_all; | 655 write_all = node_l->calls_write_all; |
1252 | 656 |
1253 /* When function is overwrittable, we can not assume anything. */ | 657 /* When function is overwrittable, we can not assume anything. */ |
1264 w_info = (struct ipa_dfs_info *) node->aux; | 668 w_info = (struct ipa_dfs_info *) node->aux; |
1265 w = w_info->next_cycle; | 669 w = w_info->next_cycle; |
1266 while (w) | 670 while (w) |
1267 { | 671 { |
1268 ipa_reference_local_vars_info_t w_l = | 672 ipa_reference_local_vars_info_t w_l = |
1269 get_reference_vars_info (w)->local; | 673 &get_reference_vars_info (w)->local; |
1270 | 674 |
1271 /* When function is overwrittable, we can not assume anything. */ | 675 /* When function is overwrittable, we can not assume anything. */ |
1272 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) | 676 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) |
1273 read_write_all_from_decl (w->decl, &read_all, &write_all); | 677 read_write_all_from_decl (w->decl, &read_all, &write_all); |
1274 | 678 |
1287 /* Initialized the bitmaps for the reduced nodes */ | 691 /* Initialized the bitmaps for the reduced nodes */ |
1288 if (read_all) | 692 if (read_all) |
1289 node_g->statics_read = all_module_statics; | 693 node_g->statics_read = all_module_statics; |
1290 else | 694 else |
1291 { | 695 { |
1292 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack); | 696 node_g->statics_read = BITMAP_ALLOC (&local_info_obstack); |
1293 bitmap_copy (node_g->statics_read, | 697 bitmap_copy (node_g->statics_read, |
1294 node_l->statics_read); | 698 node_l->statics_read); |
1295 } | 699 } |
1296 if (write_all) | 700 if (write_all) |
1297 node_g->statics_written = all_module_statics; | 701 node_g->statics_written = all_module_statics; |
1298 else | 702 else |
1299 { | 703 { |
1300 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack); | 704 node_g->statics_written = BITMAP_ALLOC (&local_info_obstack); |
1301 bitmap_copy (node_g->statics_written, | 705 bitmap_copy (node_g->statics_written, |
1302 node_l->statics_written); | 706 node_l->statics_written); |
1303 } | 707 } |
1304 | 708 |
1305 propagate_bits (node_g, node); | 709 propagate_bits (node_g, node); |
1307 w = w_info->next_cycle; | 711 w = w_info->next_cycle; |
1308 while (w) | 712 while (w) |
1309 { | 713 { |
1310 ipa_reference_vars_info_t w_ri = | 714 ipa_reference_vars_info_t w_ri = |
1311 get_reference_vars_info (w); | 715 get_reference_vars_info (w); |
1312 ipa_reference_local_vars_info_t w_l = w_ri->local; | 716 ipa_reference_local_vars_info_t w_l = &w_ri->local; |
1313 | 717 |
1314 /* These global bitmaps are initialized from the local info | 718 /* These global bitmaps are initialized from the local info |
1315 of all of the nodes in the region. However there is no | 719 of all of the nodes in the region. However there is no |
1316 need to do any work if the bitmaps were set to | 720 need to do any work if the bitmaps were set to |
1317 all_module_statics. */ | 721 all_module_statics. */ |
1325 w_info = (struct ipa_dfs_info *) w->aux; | 729 w_info = (struct ipa_dfs_info *) w->aux; |
1326 w = w_info->next_cycle; | 730 w = w_info->next_cycle; |
1327 } | 731 } |
1328 | 732 |
1329 /* All nodes within a cycle have the same global info bitmaps. */ | 733 /* All nodes within a cycle have the same global info bitmaps. */ |
1330 node_info->global = node_g; | 734 node_info->global = *node_g; |
1331 w_info = (struct ipa_dfs_info *) node->aux; | 735 w_info = (struct ipa_dfs_info *) node->aux; |
1332 w = w_info->next_cycle; | 736 w = w_info->next_cycle; |
1333 while (w) | 737 while (w) |
1334 { | 738 { |
1335 ipa_reference_vars_info_t w_ri = | 739 ipa_reference_vars_info_t w_ri = |
1336 get_reference_vars_info (w); | 740 get_reference_vars_info (w); |
1337 | 741 |
1338 gcc_assert (!w_ri->global); | 742 w_ri->global = *node_g; |
1339 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d); | |
1340 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read); | |
1341 w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written); | |
1342 | 743 |
1343 w_info = (struct ipa_dfs_info *) w->aux; | 744 w_info = (struct ipa_dfs_info *) w->aux; |
1344 w = w_info->next_cycle; | 745 w = w_info->next_cycle; |
1345 } | 746 } |
1346 } | 747 } |
1356 bitmap_iterator bi; | 757 bitmap_iterator bi; |
1357 struct ipa_dfs_info * w_info; | 758 struct ipa_dfs_info * w_info; |
1358 | 759 |
1359 node = order[i]; | 760 node = order[i]; |
1360 node_info = get_reference_vars_info (node); | 761 node_info = get_reference_vars_info (node); |
1361 node_g = node_info->global; | 762 node_g = &node_info->global; |
1362 node_l = node_info->local; | 763 node_l = &node_info->local; |
1363 fprintf (dump_file, | 764 fprintf (dump_file, |
1364 "\nFunction name:%s/%i:", | 765 "\nFunction name:%s/%i:", |
1365 cgraph_node_name (node), node->uid); | 766 cgraph_node_name (node), node->uid); |
1366 fprintf (dump_file, "\n locals read: "); | 767 fprintf (dump_file, "\n locals read: "); |
1367 if (node_l->statics_read) | 768 if (node_l->statics_read) |
1384 w = w_info->next_cycle; | 785 w = w_info->next_cycle; |
1385 while (w) | 786 while (w) |
1386 { | 787 { |
1387 ipa_reference_vars_info_t w_ri = | 788 ipa_reference_vars_info_t w_ri = |
1388 get_reference_vars_info (w); | 789 get_reference_vars_info (w); |
1389 ipa_reference_local_vars_info_t w_l = w_ri->local; | 790 ipa_reference_local_vars_info_t w_l = &w_ri->local; |
1390 fprintf (dump_file, "\n next cycle: %s/%i ", | 791 fprintf (dump_file, "\n next cycle: %s/%i ", |
1391 cgraph_node_name (w), w->uid); | 792 cgraph_node_name (w), w->uid); |
1392 fprintf (dump_file, "\n locals read: "); | 793 fprintf (dump_file, "\n locals read: "); |
1393 if (w_l->statics_read) | 794 if (w_l->statics_read) |
1394 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, | 795 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, |
1432 } | 833 } |
1433 } | 834 } |
1434 } | 835 } |
1435 | 836 |
1436 /* Cleanup. */ | 837 /* Cleanup. */ |
1437 for (i = 0; i < order_pos; i++ ) | 838 for (node = cgraph_nodes; node; node = node->next) |
1438 { | 839 { |
1439 ipa_reference_vars_info_t node_info; | 840 ipa_reference_vars_info_t node_info; |
1440 ipa_reference_global_vars_info_t node_g; | 841 ipa_reference_global_vars_info_t node_g; |
1441 node = order[i]; | 842 ipa_reference_optimization_summary_t opt; |
843 | |
844 if (!node->analyzed) | |
845 continue; | |
846 | |
1442 node_info = get_reference_vars_info (node); | 847 node_info = get_reference_vars_info (node); |
1443 node_g = node_info->global; | 848 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE) |
1444 | 849 { |
1445 /* Create the complimentary sets. These are more useful for | 850 node_g = &node_info->global; |
1446 certain apis. */ | 851 |
1447 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack); | 852 opt = XCNEW (struct ipa_reference_optimization_summary_d); |
1448 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack); | 853 set_reference_optimization_summary (node, opt); |
1449 | 854 |
1450 if (node_g->statics_read != all_module_statics) | 855 /* Create the complimentary sets. */ |
1451 bitmap_and_compl (node_g->statics_not_read, | 856 opt->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack); |
1452 all_module_statics, | 857 opt->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack); |
1453 node_g->statics_read); | 858 |
1454 | 859 if (node_g->statics_read != all_module_statics) |
1455 if (node_g->statics_written | 860 bitmap_and_compl (opt->statics_not_read, |
1456 != all_module_statics) | 861 all_module_statics, |
1457 bitmap_and_compl (node_g->statics_not_written, | 862 node_g->statics_read); |
1458 all_module_statics, | 863 |
1459 node_g->statics_written); | 864 if (node_g->statics_written |
1460 } | 865 != all_module_statics) |
1461 | 866 bitmap_and_compl (opt->statics_not_written, |
1462 free (order); | 867 all_module_statics, |
1463 | 868 node_g->statics_written); |
1464 for (node = cgraph_nodes; node; node = node->next) | 869 } |
1465 { | 870 if (node_info) |
1466 ipa_reference_vars_info_t node_info; | 871 free (node_info); |
1467 node_info = get_reference_vars_info (node); | |
1468 /* Get rid of the aux information. */ | |
1469 | |
1470 if (node->aux) | 872 if (node->aux) |
1471 { | 873 { |
1472 free (node->aux); | 874 free (node->aux); |
1473 node->aux = NULL; | 875 node->aux = NULL; |
1474 } | 876 } |
1475 | 877 } |
1476 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE) | 878 |
1477 clean_function (node); | 879 free (order); |
1478 else if (node_info) | 880 |
1479 clean_function_local_data (node); | 881 bitmap_obstack_release (&local_info_obstack); |
882 VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector); | |
883 ipa_reference_vars_vector = NULL; | |
884 if (dump_file) | |
885 splay_tree_delete (reference_vars_to_consider); | |
886 reference_vars_to_consider = NULL; | |
887 all_module_statics = NULL; | |
888 return 0; | |
889 } | |
890 | |
891 /* Return true if we need to write summary of NODE. */ | |
892 | |
893 static bool | |
894 write_node_summary_p (struct cgraph_node *node, | |
895 cgraph_node_set set, | |
896 varpool_node_set vset, | |
897 bitmap ltrans_statics) | |
898 { | |
899 ipa_reference_optimization_summary_t info; | |
900 | |
901 /* See if we have (non-empty) info. */ | |
902 if (!node->analyzed || node->global.inlined_to) | |
903 return false; | |
904 info = get_reference_optimization_summary (node); | |
905 if (!info || (bitmap_empty_p (info->statics_not_read) | |
906 && bitmap_empty_p (info->statics_not_written))) | |
907 return false; | |
908 | |
909 /* See if we want to encode it. | |
910 Encode also referenced functions since constant folding might turn it into | |
911 a direct call. | |
912 | |
913 In future we might also want to include summaries of functions references | |
914 by initializers of constant variables references in current unit. */ | |
915 if (!reachable_from_this_partition_p (node, set) | |
916 && !referenced_from_this_partition_p (&node->ref_list, set, vset)) | |
917 return false; | |
918 | |
919 /* See if the info has non-empty intersections with vars we want to encode. */ | |
920 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics) | |
921 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics)) | |
922 return false; | |
923 return true; | |
924 } | |
925 | |
926 /* Stream out BITS<RANS_STATICS as list of decls to OB. */ | |
927 | |
928 static void | |
929 stream_out_bitmap (struct lto_simple_output_block *ob, | |
930 bitmap bits, bitmap ltrans_statics) | |
931 { | |
932 unsigned int count = 0; | |
933 unsigned int index; | |
934 bitmap_iterator bi; | |
935 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) | |
936 count ++; | |
937 lto_output_uleb128_stream (ob->main_stream, count); | |
938 if (!count) | |
939 return; | |
940 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) | |
941 { | |
942 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value; | |
943 lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl); | |
1480 } | 944 } |
1481 bitmap_obstack_release (&local_info_obstack); | 945 } |
1482 return 0; | 946 |
1483 } | 947 /* Serialize the ipa info for lto. */ |
1484 | 948 |
949 static void | |
950 ipa_reference_write_optimization_summary (cgraph_node_set set, | |
951 varpool_node_set vset) | |
952 { | |
953 struct cgraph_node *node; | |
954 struct varpool_node *vnode; | |
955 struct lto_simple_output_block *ob | |
956 = lto_create_simple_output_block (LTO_section_ipa_reference); | |
957 unsigned int count = 0; | |
958 lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; | |
959 bitmap ltrans_statics = BITMAP_ALLOC (NULL); | |
960 | |
961 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); | |
962 | |
963 /* See what variables we are interested in. */ | |
964 for (vnode = varpool_nodes; vnode; vnode = vnode->next) | |
965 if (referenced_from_this_partition_p (&vnode->ref_list, set, vset)) | |
966 { | |
967 tree decl = vnode->decl; | |
968 if (is_proper_for_analysis (decl)) | |
969 { | |
970 bitmap_set_bit (ltrans_statics, DECL_UID (decl)); | |
971 splay_tree_insert (reference_vars_to_consider, | |
972 DECL_UID (decl), (splay_tree_value)decl); | |
973 } | |
974 } | |
975 | |
976 for (node = cgraph_nodes; node; node = node->next) | |
977 if (write_node_summary_p (node, set, vset, ltrans_statics)) | |
978 count++; | |
979 | |
980 lto_output_uleb128_stream (ob->main_stream, count); | |
981 | |
982 /* Process all of the functions. */ | |
983 for (node = cgraph_nodes; node; node = node->next) | |
984 if (write_node_summary_p (node, set, vset, ltrans_statics)) | |
985 { | |
986 ipa_reference_optimization_summary_t info; | |
987 int node_ref; | |
988 | |
989 info = get_reference_optimization_summary (node); | |
990 node_ref = lto_cgraph_encoder_encode (encoder, node); | |
991 lto_output_uleb128_stream (ob->main_stream, node_ref); | |
992 | |
993 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics); | |
994 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics); | |
995 } | |
996 BITMAP_FREE (ltrans_statics); | |
997 lto_destroy_simple_output_block (ob); | |
998 splay_tree_delete (reference_vars_to_consider); | |
999 } | |
1000 | |
1001 /* Deserialize the ipa info for lto. */ | |
1002 | |
1003 static void | |
1004 ipa_reference_read_optimization_summary (void) | |
1005 { | |
1006 struct lto_file_decl_data ** file_data_vec | |
1007 = lto_get_file_decl_data (); | |
1008 struct lto_file_decl_data * file_data; | |
1009 unsigned int j = 0; | |
1010 bitmap_obstack_initialize (&optimization_summary_obstack); | |
1011 | |
1012 node_removal_hook_holder = | |
1013 cgraph_add_node_removal_hook (&remove_node_data, NULL); | |
1014 node_duplication_hook_holder = | |
1015 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | |
1016 | |
1017 while ((file_data = file_data_vec[j++])) | |
1018 { | |
1019 const char *data; | |
1020 size_t len; | |
1021 struct lto_input_block *ib | |
1022 = lto_create_simple_input_block (file_data, | |
1023 LTO_section_ipa_reference, | |
1024 &data, &len); | |
1025 if (ib) | |
1026 { | |
1027 unsigned int i; | |
1028 unsigned int f_count = lto_input_uleb128 (ib); | |
1029 | |
1030 for (i = 0; i < f_count; i++) | |
1031 { | |
1032 unsigned int j, index; | |
1033 struct cgraph_node *node; | |
1034 ipa_reference_optimization_summary_t info; | |
1035 int v_count; | |
1036 lto_cgraph_encoder_t encoder; | |
1037 | |
1038 index = lto_input_uleb128 (ib); | |
1039 encoder = file_data->cgraph_node_encoder; | |
1040 node = lto_cgraph_encoder_deref (encoder, index); | |
1041 info = XCNEW (struct ipa_reference_optimization_summary_d); | |
1042 set_reference_optimization_summary (node, info); | |
1043 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack); | |
1044 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack); | |
1045 if (dump_file) | |
1046 fprintf (dump_file, | |
1047 "\nFunction name:%s/%i:\n static not read:", | |
1048 cgraph_node_name (node), node->uid); | |
1049 | |
1050 /* Set the statics not read. */ | |
1051 v_count = lto_input_uleb128 (ib); | |
1052 for (j = 0; j < (unsigned int)v_count; j++) | |
1053 { | |
1054 unsigned int var_index = lto_input_uleb128 (ib); | |
1055 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1056 var_index); | |
1057 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl)); | |
1058 if (dump_file) | |
1059 fprintf (dump_file, " %s", | |
1060 lang_hooks.decl_printable_name (v_decl, 2)); | |
1061 } | |
1062 | |
1063 if (dump_file) | |
1064 fprintf (dump_file, | |
1065 "\n static not written:"); | |
1066 /* Set the statics not written. */ | |
1067 v_count = lto_input_uleb128 (ib); | |
1068 for (j = 0; j < (unsigned int)v_count; j++) | |
1069 { | |
1070 unsigned int var_index = lto_input_uleb128 (ib); | |
1071 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1072 var_index); | |
1073 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl)); | |
1074 if (dump_file) | |
1075 fprintf (dump_file, " %s", | |
1076 lang_hooks.decl_printable_name (v_decl, 2)); | |
1077 } | |
1078 if (dump_file) | |
1079 fprintf (dump_file, "\n"); | |
1080 } | |
1081 | |
1082 lto_destroy_simple_input_block (file_data, | |
1083 LTO_section_ipa_reference, | |
1084 ib, data, len); | |
1085 } | |
1086 else | |
1087 /* Fatal error here. We do not want to support compiling ltrans units with | |
1088 different version of compiler or different flags than the WPA unit, so | |
1089 this should never happen. */ | |
1090 fatal_error ("ipa reference summary is missing in ltrans unit"); | |
1091 } | |
1092 } | |
1485 | 1093 |
1486 static bool | 1094 static bool |
1487 gate_reference (void) | 1095 gate_reference (void) |
1488 { | 1096 { |
1489 return (flag_ipa_reference | 1097 return (flag_ipa_reference |
1506 0, /* properties_provided */ | 1114 0, /* properties_provided */ |
1507 0, /* properties_destroyed */ | 1115 0, /* properties_destroyed */ |
1508 0, /* todo_flags_start */ | 1116 0, /* todo_flags_start */ |
1509 0 /* todo_flags_finish */ | 1117 0 /* todo_flags_finish */ |
1510 }, | 1118 }, |
1511 generate_summary, /* generate_summary */ | 1119 NULL, /* generate_summary */ |
1512 ipa_reference_write_summary, /* write_summary */ | 1120 NULL, /* write_summary */ |
1513 ipa_reference_read_summary, /* read_summary */ | 1121 NULL, /* read_summary */ |
1514 NULL, /* function_read_summary */ | 1122 ipa_reference_write_optimization_summary,/* write_optimization_summary */ |
1123 ipa_reference_read_optimization_summary,/* read_optimization_summary */ | |
1515 NULL, /* stmt_fixup */ | 1124 NULL, /* stmt_fixup */ |
1516 0, /* TODOs */ | 1125 0, /* TODOs */ |
1517 NULL, /* function_transform */ | 1126 NULL, /* function_transform */ |
1518 NULL /* variable_transform */ | 1127 NULL /* variable_transform */ |
1519 }; | 1128 }; |
1520 | |
1521 #include "gt-ipa-reference.h" |