Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-reference.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Callgraph based analysis of static variables. | 1 /* Callgraph based analysis of static variables. |
2 Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. | 2 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. |
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> | 3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
17 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
18 along with GCC; see the file COPYING3. If not see | 18 along with GCC; see the file COPYING3. If not see |
19 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
20 | 20 |
21 /* This file gathers information about how variables whose scope is | 21 /* This file gathers information about how variables whose scope is |
22 confined to the compilation unit are used. | 22 confined to the compilation unit are used. |
23 | 23 |
24 There are two categories of information produced by this pass: | 24 There are two categories of information produced by this pass: |
25 | 25 |
26 1) The addressable (TREE_ADDRESSABLE) bit and readonly | 26 1) The addressable (TREE_ADDRESSABLE) bit and readonly |
27 (TREE_READONLY) bit associated with these variables is properly set | 27 (TREE_READONLY) bit associated with these variables is properly set |
39 performed over the call graph to determine the worst case set of | 39 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 | 40 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 | 41 local and global sets are examined to make the call clobbering less |
42 traumatic, promote some statics to registers, and improve aliasing | 42 traumatic, promote some statics to registers, and improve aliasing |
43 information. | 43 information. |
44 | 44 |
45 Currently must be run after inlining decisions have been made since | 45 Currently must be run after inlining decisions have been made since |
46 otherwise, the local sets will not contain information that is | 46 otherwise, the local sets will not contain information that is |
47 consistent with post inlined state. The global sets are not prone | 47 consistent with post inlined state. The global sets are not prone |
48 to this problem since they are by definition transitive. */ | 48 to this problem since they are by definition transitive. */ |
49 | 49 |
55 #include "tree-flow.h" | 55 #include "tree-flow.h" |
56 #include "tree-inline.h" | 56 #include "tree-inline.h" |
57 #include "tree-pass.h" | 57 #include "tree-pass.h" |
58 #include "langhooks.h" | 58 #include "langhooks.h" |
59 #include "pointer-set.h" | 59 #include "pointer-set.h" |
60 #include "splay-tree.h" | |
60 #include "ggc.h" | 61 #include "ggc.h" |
61 #include "ipa-utils.h" | 62 #include "ipa-utils.h" |
62 #include "ipa-reference.h" | 63 #include "ipa-reference.h" |
63 #include "c-common.h" | |
64 #include "gimple.h" | 64 #include "gimple.h" |
65 #include "cgraph.h" | 65 #include "cgraph.h" |
66 #include "output.h" | 66 #include "output.h" |
67 #include "flags.h" | 67 #include "flags.h" |
68 #include "timevar.h" | 68 #include "timevar.h" |
69 #include "diagnostic.h" | 69 #include "diagnostic.h" |
70 #include "langhooks.h" | 70 #include "langhooks.h" |
71 #include "lto-streamer.h" | |
72 | |
73 static void add_new_function (struct cgraph_node *node, | |
74 void *data ATTRIBUTE_UNUSED); | |
75 static void remove_node_data (struct cgraph_node *node, | |
76 void *data ATTRIBUTE_UNUSED); | |
77 static void duplicate_node_data (struct cgraph_node *src, | |
78 struct cgraph_node *dst, | |
79 void *data ATTRIBUTE_UNUSED); | |
71 | 80 |
72 /* The static variables defined within the compilation unit that are | 81 /* The static variables defined within the compilation unit that are |
73 loaded or stored directly by function that owns this structure. */ | 82 loaded or stored directly by function that owns this structure. */ |
74 | 83 |
75 struct ipa_reference_local_vars_info_d | 84 struct ipa_reference_local_vars_info_d |
76 { | 85 { |
77 bitmap statics_read; | 86 bitmap statics_read; |
78 bitmap statics_written; | 87 bitmap statics_written; |
79 | 88 |
80 /* Set when this function calls another function external to the | 89 /* Set when this function calls another function external to the |
93 structures are separated to allow the global structures to be | 102 structures are separated to allow the global structures to be |
94 shared between several functions since every function within a | 103 shared between several functions since every function within a |
95 strongly connected component will have the same information. This | 104 strongly connected component will have the same information. This |
96 sharing saves both time and space in the computation of the vectors | 105 sharing saves both time and space in the computation of the vectors |
97 as well as their translation from decl_uid form to ann_uid | 106 as well as their translation from decl_uid form to ann_uid |
98 form. */ | 107 form. */ |
99 | 108 |
100 struct ipa_reference_global_vars_info_d | 109 struct ipa_reference_global_vars_info_d |
101 { | 110 { |
102 bitmap statics_read; | 111 bitmap statics_read; |
103 bitmap statics_written; | 112 bitmap statics_written; |
105 bitmap statics_not_written; | 114 bitmap statics_not_written; |
106 }; | 115 }; |
107 | 116 |
108 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; | 117 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; |
109 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; | 118 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; |
110 struct ipa_reference_vars_info_d | 119 struct ipa_reference_vars_info_d |
111 { | 120 { |
112 ipa_reference_local_vars_info_t local; | 121 ipa_reference_local_vars_info_t local; |
113 ipa_reference_global_vars_info_t global; | 122 ipa_reference_global_vars_info_t global; |
114 }; | 123 }; |
115 | 124 |
185 } | 194 } |
186 | 195 |
187 /* Get a bitmap that contains all of the locally referenced static | 196 /* Get a bitmap that contains all of the locally referenced static |
188 variables for function FN. */ | 197 variables for function FN. */ |
189 static ipa_reference_local_vars_info_t | 198 static ipa_reference_local_vars_info_t |
190 get_local_reference_vars_info (struct cgraph_node *fn) | 199 get_local_reference_vars_info (struct cgraph_node *fn) |
191 { | 200 { |
192 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | 201 ipa_reference_vars_info_t info = get_reference_vars_info (fn); |
193 | 202 |
194 if (info) | 203 if (info) |
195 return info->local; | 204 return info->local; |
196 else | 205 else |
197 /* This phase was not run. */ | 206 /* This phase was not run. */ |
198 return NULL; | 207 return NULL; |
199 } | 208 } |
200 | 209 |
201 /* Get a bitmap that contains all of the globally referenced static | 210 /* Get a bitmap that contains all of the globally referenced static |
202 variables for function FN. */ | 211 variables for function FN. */ |
203 | 212 |
204 static ipa_reference_global_vars_info_t | 213 static ipa_reference_global_vars_info_t |
205 get_global_reference_vars_info (struct cgraph_node *fn) | 214 get_global_reference_vars_info (struct cgraph_node *fn) |
206 { | 215 { |
207 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | 216 ipa_reference_vars_info_t info = get_reference_vars_info (fn); |
208 | 217 |
209 if (info) | 218 if (info) |
210 return info->global; | 219 return info->global; |
211 else | 220 else |
212 /* This phase was not run. */ | 221 /* This phase was not run. */ |
213 return NULL; | 222 return NULL; |
214 } | 223 } |
215 | 224 |
216 /* Return a bitmap indexed by VAR_DECL uid for the static variables | 225 /* Return a bitmap indexed by VAR_DECL uid for the static variables |
217 that are read during the execution of the function FN. Returns | 226 that are read during the execution of the function FN. Returns |
218 NULL if no data is available. */ | 227 NULL if no data is available. */ |
219 | 228 |
220 bitmap | 229 bitmap |
221 ipa_reference_get_read_global (struct cgraph_node *fn) | 230 ipa_reference_get_read_global (struct cgraph_node *fn) |
222 { | 231 { |
223 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 232 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); |
224 if (g) | 233 if (g) |
225 return g->statics_read; | 234 return g->statics_read; |
226 else | 235 else |
227 return NULL; | 236 return NULL; |
228 } | 237 } |
229 | 238 |
230 /* Return a bitmap indexed by VAR_DECL uid for the static variables | 239 /* Return a bitmap indexed by VAR_DECL uid for the static variables |
231 that are written during the execution of the function FN. Note | 240 that are written during the execution of the function FN. Note |
232 that variables written may or may not be read during the function | 241 that variables written may or may not be read during the function |
233 call. Returns NULL if no data is available. */ | 242 call. Returns NULL if no data is available. */ |
234 | 243 |
235 bitmap | 244 bitmap |
236 ipa_reference_get_written_global (struct cgraph_node *fn) | 245 ipa_reference_get_written_global (struct cgraph_node *fn) |
237 { | 246 { |
238 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 247 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); |
239 if (g) | 248 if (g) |
240 return g->statics_written; | 249 return g->statics_written; |
241 else | 250 else |
242 return NULL; | 251 return NULL; |
243 } | 252 } |
244 | 253 |
245 /* Return a bitmap indexed by_DECL_UID uid for the static variables | 254 /* Return a bitmap indexed by_DECL_UID uid for the static variables |
246 that are not read during the execution of the function FN. Returns | 255 that are not read during the execution of the function FN. Returns |
247 NULL if no data is available. */ | 256 NULL if no data is available. */ |
248 | 257 |
249 bitmap | 258 bitmap |
250 ipa_reference_get_not_read_global (struct cgraph_node *fn) | 259 ipa_reference_get_not_read_global (struct cgraph_node *fn) |
251 { | 260 { |
252 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 261 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); |
253 if (g) | 262 if (g) |
254 return g->statics_not_read; | 263 return g->statics_not_read; |
255 else | 264 else |
256 return NULL; | 265 return NULL; |
257 } | 266 } |
258 | 267 |
259 /* Return a bitmap indexed by DECL_UID uid for the static variables | 268 /* Return a bitmap indexed by DECL_UID uid for the static variables |
260 that are not written during the execution of the function FN. Note | 269 that are not written during the execution of the function FN. Note |
261 that variables written may or may not be read during the function | 270 that variables written may or may not be read during the function |
262 call. Returns NULL if no data is available. */ | 271 call. Returns NULL if no data is available. */ |
263 | 272 |
264 bitmap | 273 bitmap |
265 ipa_reference_get_not_written_global (struct cgraph_node *fn) | 274 ipa_reference_get_not_written_global (struct cgraph_node *fn) |
266 { | 275 { |
267 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); | 276 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); |
268 if (g) | 277 if (g) |
269 return g->statics_not_written; | 278 return g->statics_not_written; |
270 else | 279 else |
271 return NULL; | 280 return NULL; |
272 } | 281 } |
273 | 282 |
274 | 283 |
275 | 284 |
276 /* Add VAR to all_module_statics and the two | 285 /* Add VAR to all_module_statics and the two |
277 reference_vars_to_consider* sets. */ | 286 reference_vars_to_consider* sets. */ |
278 | 287 |
279 static inline void | 288 static inline void |
280 add_static_var (tree var) | 289 add_static_var (tree var) |
281 { | 290 { |
282 int uid = DECL_UID (var); | 291 int uid = DECL_UID (var); |
283 gcc_assert (TREE_CODE (var) == VAR_DECL); | 292 gcc_assert (TREE_CODE (var) == VAR_DECL); |
284 if (!bitmap_bit_p (all_module_statics, uid)) | 293 if (!bitmap_bit_p (all_module_statics, uid)) |
285 { | 294 { |
290 } | 299 } |
291 | 300 |
292 /* Return true if the variable T is the right kind of static variable to | 301 /* Return true if the variable T is the right kind of static variable to |
293 perform compilation unit scope escape analysis. */ | 302 perform compilation unit scope escape analysis. */ |
294 | 303 |
295 static inline bool | 304 static inline bool |
296 has_proper_scope_for_analysis (tree t) | 305 has_proper_scope_for_analysis (tree t) |
297 { | 306 { |
298 /* If the variable has the "used" attribute, treat it as if it had a | 307 /* If the variable has the "used" attribute, treat it as if it had a |
299 been touched by the devil. */ | 308 been touched by the devil. */ |
300 if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) | 309 if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) |
301 return false; | 310 return false; |
302 | 311 |
303 /* Do not want to do anything with volatile except mark any | 312 /* Do not want to do anything with volatile except mark any |
304 function that uses one to be not const or pure. */ | 313 function that uses one to be not const or pure. */ |
305 if (TREE_THIS_VOLATILE (t)) | 314 if (TREE_THIS_VOLATILE (t)) |
306 return false; | 315 return false; |
307 | 316 |
308 /* Do not care about a local automatic that is not static. */ | 317 /* Do not care about a local automatic that is not static. */ |
309 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) | 318 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) |
310 return false; | 319 return false; |
311 | 320 |
321 /* FIXME: for LTO we should include PUBLIC vars too. This is bit difficult | |
322 as summarie would need unsharing. */ | |
312 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) | 323 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) |
313 return false; | 324 return false; |
314 | 325 |
315 /* We cannot touch decls where the type needs constructing. */ | 326 /* We cannot touch decls where the type needs constructing. */ |
316 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) | 327 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) |
332 if (TREE_CODE (x) == VAR_DECL | 343 if (TREE_CODE (x) == VAR_DECL |
333 && module_statics_escape && has_proper_scope_for_analysis (x)) | 344 && module_statics_escape && has_proper_scope_for_analysis (x)) |
334 bitmap_set_bit (module_statics_escape, DECL_UID (x)); | 345 bitmap_set_bit (module_statics_escape, DECL_UID (x)); |
335 } | 346 } |
336 | 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 | |
337 /* Mark load of T. */ | 360 /* Mark load of T. */ |
338 | 361 |
339 static void | 362 static bool |
340 mark_load (ipa_reference_local_vars_info_t local, | 363 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) |
341 tree t) | 364 { |
342 { | 365 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data; |
343 if (TREE_CODE (t) == VAR_DECL | 366 if (TREE_CODE (t) == VAR_DECL |
344 && has_proper_scope_for_analysis (t)) | 367 && has_proper_scope_for_analysis (t)) |
345 bitmap_set_bit (local->statics_read, DECL_UID (t)); | 368 bitmap_set_bit (local->statics_read, DECL_UID (t)); |
369 return false; | |
346 } | 370 } |
347 | 371 |
348 /* Mark store of T. */ | 372 /* Mark store of T. */ |
349 | 373 |
350 static void | 374 static bool |
351 mark_store (ipa_reference_local_vars_info_t local, | 375 mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data) |
352 tree t) | 376 { |
353 { | 377 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data; |
354 if (TREE_CODE (t) == VAR_DECL | 378 if (TREE_CODE (t) == VAR_DECL |
355 && has_proper_scope_for_analysis (t)) | 379 && has_proper_scope_for_analysis (t)) |
356 { | 380 { |
357 if (local) | 381 if (local) |
358 bitmap_set_bit (local->statics_written, DECL_UID (t)); | 382 bitmap_set_bit (local->statics_written, DECL_UID (t)); |
359 /* Mark the write so we can tell which statics are | 383 /* Mark the write so we can tell which statics are |
360 readonly. */ | 384 readonly. */ |
361 if (module_statics_written) | 385 if (module_statics_written) |
362 bitmap_set_bit (module_statics_written, DECL_UID (t)); | 386 bitmap_set_bit (module_statics_written, DECL_UID (t)); |
363 } | 387 } |
388 return false; | |
364 } | 389 } |
365 | 390 |
366 /* Look for memory clobber and set read_all/write_all if present. */ | 391 /* Look for memory clobber and set read_all/write_all if present. */ |
367 | 392 |
368 static void | 393 static void |
369 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt) | 394 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt) |
370 { | 395 { |
371 size_t i; | 396 size_t i; |
372 tree op; | 397 tree op; |
373 | 398 |
374 for (i = 0; i < gimple_asm_nclobbers (stmt); i++) | 399 for (i = 0; i < gimple_asm_nclobbers (stmt); i++) |
375 { | 400 { |
376 op = gimple_asm_clobber_op (stmt, i); | 401 op = gimple_asm_clobber_op (stmt, i); |
377 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1) | 402 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1) |
378 { | 403 { |
379 /* Abandon all hope, ye who enter here. */ | 404 /* Abandon all hope, ye who enter here. */ |
380 local->calls_read_all = true; | 405 local->calls_read_all = true; |
381 local->calls_write_all = true; | 406 local->calls_write_all = true; |
382 } | 407 } |
383 } | 408 } |
384 } | 409 } |
385 | 410 |
386 /* Look for external calls and set read_all/write_all correspondingly. */ | 411 /* Look for external calls and set read_all/write_all correspondingly. */ |
387 | 412 |
388 static void | 413 static void |
389 check_call (ipa_reference_local_vars_info_t local, gimple stmt) | 414 check_call (ipa_reference_local_vars_info_t local, gimple stmt) |
390 { | 415 { |
391 int flags = gimple_call_flags (stmt); | 416 int flags = gimple_call_flags (stmt); |
392 tree callee_t = gimple_call_fndecl (stmt); | 417 tree callee_t = gimple_call_fndecl (stmt); |
393 enum availability avail = AVAIL_NOT_AVAILABLE; | 418 |
394 | 419 /* Process indirect calls. All direct calles are handled at propagation |
395 if (callee_t) | 420 time. */ |
396 { | 421 if (!callee_t) |
397 struct cgraph_node* callee = cgraph_node(callee_t); | 422 { |
398 avail = cgraph_function_body_availability (callee); | 423 if (flags & ECF_CONST) |
399 } | 424 ; |
400 | 425 else if (flags & ECF_PURE) |
401 if (avail <= AVAIL_OVERWRITABLE) | 426 local->calls_read_all = true; |
402 if (local) | 427 else |
403 { | 428 { |
404 if (flags & ECF_CONST) | |
405 ; | |
406 else if (flags & ECF_PURE) | |
407 local->calls_read_all = true; | 429 local->calls_read_all = true; |
408 else | 430 /* When function does not reutrn, it is safe to ignore anythign it writes |
409 { | 431 to, because the effect will never happen. */ |
410 local->calls_read_all = true; | 432 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) |
433 != (ECF_NOTHROW | ECF_NORETURN)) | |
411 local->calls_write_all = true; | 434 local->calls_write_all = true; |
412 } | 435 } |
413 } | 436 } |
414 /* TODO: To be able to produce sane results, we should also handle | |
415 common builtins, in particular throw. | |
416 Indirect calls hsould be only counted and as inliner is replacing them | |
417 by direct calls, we can conclude if any indirect calls are left in body */ | |
418 } | 437 } |
419 | 438 |
420 /* TP is the part of the tree currently under the microscope. | 439 /* TP is the part of the tree currently under the microscope. |
421 WALK_SUBTREES is part of the walk_tree api but is unused here. | 440 WALK_SUBTREES is part of the walk_tree api but is unused here. |
422 DATA is cgraph_node of the function being walked. */ | 441 DATA is cgraph_node of the function being walked. */ |
425 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip, | 444 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip, |
426 struct cgraph_node *fn) | 445 struct cgraph_node *fn) |
427 { | 446 { |
428 gimple stmt = gsi_stmt (*gsip); | 447 gimple stmt = gsi_stmt (*gsip); |
429 ipa_reference_local_vars_info_t local = NULL; | 448 ipa_reference_local_vars_info_t local = NULL; |
430 unsigned int i; | 449 |
431 bitmap_iterator bi; | 450 if (is_gimple_debug (stmt)) |
451 return NULL; | |
432 | 452 |
433 if (fn) | 453 if (fn) |
434 local = get_reference_vars_info (fn)->local; | 454 local = get_reference_vars_info (fn)->local; |
435 | 455 |
436 if (gimple_loaded_syms (stmt)) | 456 /* Look for direct loads and stores. */ |
437 EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi) | 457 walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store, |
438 mark_load (local, referenced_var_lookup (i)); | 458 mark_address); |
439 if (gimple_stored_syms (stmt)) | 459 |
440 EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi) | 460 if (is_gimple_call (stmt)) |
441 mark_store (local, referenced_var_lookup (i)); | 461 check_call (local, stmt); |
442 if (gimple_addresses_taken (stmt)) | 462 else if (gimple_code (stmt) == GIMPLE_ASM) |
443 EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt), 0, i, bi) | 463 check_asm_memory_clobber (local, stmt); |
444 mark_address_taken (referenced_var_lookup (i)); | 464 |
445 | |
446 switch (gimple_code (stmt)) | |
447 { | |
448 case GIMPLE_CALL: | |
449 check_call (local, stmt); | |
450 break; | |
451 | |
452 case GIMPLE_ASM: | |
453 check_asm_memory_clobber (local, stmt); | |
454 break; | |
455 | |
456 /* We used to check nonlocal labels here and set them as potentially modifying | |
457 everything. This is not needed, since we can get to nonlocal label only | |
458 from callee and thus we will get info propagated. */ | |
459 | |
460 default: | |
461 break; | |
462 } | |
463 | |
464 return NULL; | 465 return NULL; |
465 } | 466 } |
466 | 467 |
467 /* Call-back to scan variable initializers for static references. | 468 /* Call-back to scan variable initializers for static references. |
468 Called using walk_tree. */ | 469 Called using walk_tree. */ |
469 | 470 |
470 static tree | 471 static tree |
471 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees, | 472 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees, |
472 void *data ATTRIBUTE_UNUSED) | 473 void *data ATTRIBUTE_UNUSED) |
480 } | 481 } |
481 /* Save some cycles by not walking types and declaration as we | 482 /* Save some cycles by not walking types and declaration as we |
482 won't find anything useful there anyway. */ | 483 won't find anything useful there anyway. */ |
483 else if (IS_TYPE_OR_DECL_P (*tp)) | 484 else if (IS_TYPE_OR_DECL_P (*tp)) |
484 *walk_subtrees = 0; | 485 *walk_subtrees = 0; |
485 | 486 |
486 return NULL; | 487 return NULL; |
487 } | 488 } |
488 | 489 |
489 /* Lookup the tree node for the static variable that has UID. */ | 490 /* Lookup the tree node for the static variable that has UID. */ |
490 static tree | 491 static tree |
491 get_static_decl (int index) | 492 get_static_decl (int index) |
492 { | 493 { |
493 splay_tree_node stn = | 494 splay_tree_node stn = |
494 splay_tree_lookup (reference_vars_to_consider, index); | 495 splay_tree_lookup (reference_vars_to_consider, index); |
495 if (stn) | 496 if (stn) |
496 return (tree)stn->value; | 497 return (tree)stn->value; |
497 return NULL; | 498 return NULL; |
498 } | 499 } |
501 convert the name to a string for debugging. */ | 502 convert the name to a string for debugging. */ |
502 | 503 |
503 static const char * | 504 static const char * |
504 get_static_name (int index) | 505 get_static_name (int index) |
505 { | 506 { |
506 splay_tree_node stn = | 507 splay_tree_node stn = |
507 splay_tree_lookup (reference_vars_to_consider, index); | 508 splay_tree_lookup (reference_vars_to_consider, index); |
508 if (stn) | 509 if (stn) |
509 return lang_hooks.decl_printable_name ((tree)(stn->value), 2); | 510 return lang_hooks.decl_printable_name ((tree)(stn->value), 2); |
510 return NULL; | 511 return NULL; |
511 } | 512 } |
516 | 517 |
517 static void | 518 static void |
518 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x) | 519 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x) |
519 { | 520 { |
520 struct cgraph_edge *e; | 521 struct cgraph_edge *e; |
521 for (e = x->callees; e; e = e->next_callee) | 522 for (e = x->callees; e; e = e->next_callee) |
522 { | 523 { |
523 struct cgraph_node *y = e->callee; | 524 struct cgraph_node *y = e->callee; |
524 | 525 |
525 /* Only look at the master nodes and skip external nodes. */ | 526 /* Only look into nodes we can propagate something. */ |
526 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE) | 527 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE) |
527 { | 528 { |
528 if (get_reference_vars_info (y)) | 529 if (get_reference_vars_info (y)) |
529 { | 530 { |
530 ipa_reference_vars_info_t y_info | 531 ipa_reference_vars_info_t y_info |
531 = get_reference_vars_info (y); | 532 = get_reference_vars_info (y); |
532 ipa_reference_global_vars_info_t y_global = y_info->global; | 533 ipa_reference_global_vars_info_t y_global = y_info->global; |
533 | 534 |
534 /* Calls in current cycle do not have global computed yet. */ | 535 /* Calls in current cycle do not have global computed yet. */ |
535 if (!y_info->global) | 536 if (!y_info->global) |
536 continue; | 537 continue; |
537 | 538 |
538 if (x_global->statics_read | 539 if (x_global->statics_read |
539 != all_module_statics) | 540 != all_module_statics) |
540 { | 541 { |
541 if (y_global->statics_read | 542 if (y_global->statics_read |
542 == all_module_statics) | 543 == all_module_statics) |
543 { | 544 { |
544 BITMAP_FREE (x_global->statics_read); | 545 BITMAP_FREE (x_global->statics_read); |
545 x_global->statics_read | 546 x_global->statics_read |
546 = all_module_statics; | 547 = all_module_statics; |
547 } | 548 } |
548 /* Skip bitmaps that are pointer equal to node's bitmap | 549 /* Skip bitmaps that are pointer equal to node's bitmap |
549 (no reason to spin within the cycle). */ | 550 (no reason to spin within the cycle). */ |
550 else if (x_global->statics_read | 551 else if (x_global->statics_read |
551 != y_global->statics_read) | 552 != y_global->statics_read) |
552 bitmap_ior_into (x_global->statics_read, | 553 bitmap_ior_into (x_global->statics_read, |
553 y_global->statics_read); | 554 y_global->statics_read); |
554 } | 555 } |
555 | 556 |
556 if (x_global->statics_written | 557 if (x_global->statics_written |
557 != all_module_statics) | 558 != all_module_statics) |
558 { | 559 { |
559 if (y_global->statics_written | 560 if (y_global->statics_written |
560 == all_module_statics) | 561 == all_module_statics) |
561 { | 562 { |
562 BITMAP_FREE (x_global->statics_written); | 563 BITMAP_FREE (x_global->statics_written); |
563 x_global->statics_written | 564 x_global->statics_written |
564 = all_module_statics; | 565 = all_module_statics; |
565 } | 566 } |
566 /* Skip bitmaps that are pointer equal to node's bitmap | 567 /* Skip bitmaps that are pointer equal to node's bitmap |
567 (no reason to spin within the cycle). */ | 568 (no reason to spin within the cycle). */ |
568 else if (x_global->statics_written | 569 else if (x_global->statics_written |
569 != y_global->statics_written) | 570 != y_global->statics_written) |
570 bitmap_ior_into (x_global->statics_written, | 571 bitmap_ior_into (x_global->statics_written, |
571 y_global->statics_written); | 572 y_global->statics_written); |
572 } | 573 } |
573 } | 574 } |
574 else | 575 else |
575 gcc_unreachable (); | 576 gcc_unreachable (); |
576 } | 577 } |
577 } | 578 } |
578 } | 579 } |
579 | 580 |
580 /* The init routine for analyzing global static variable usage. See | 581 /* The init routine for analyzing global static variable usage. See |
581 comments at top for description. */ | 582 comments at top for description. */ |
582 static void | 583 static void |
583 ipa_init (void) | 584 ipa_init (void) |
584 { | 585 { |
586 static bool init_p = false; | |
587 | |
588 if (init_p) | |
589 return; | |
590 | |
591 init_p = true; | |
592 | |
585 memory_identifier_string = build_string(7, "memory"); | 593 memory_identifier_string = build_string(7, "memory"); |
586 | 594 |
587 reference_vars_to_consider = | 595 reference_vars_to_consider = |
588 splay_tree_new_ggc (splay_tree_compare_ints); | 596 splay_tree_new_ggc (splay_tree_compare_ints); |
589 | 597 |
596 /* There are some shared nodes, in particular the initializers on | 604 /* There are some shared nodes, in particular the initializers on |
597 static declarations. We do not need to scan them more than once | 605 static declarations. We do not need to scan them more than once |
598 since all we would be interested in are the addressof | 606 since all we would be interested in are the addressof |
599 operations. */ | 607 operations. */ |
600 visited_nodes = pointer_set_create (); | 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 = | |
613 cgraph_add_node_removal_hook (&remove_node_data, NULL); | |
614 node_duplication_hook_holder = | |
615 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | |
601 } | 616 } |
602 | 617 |
603 /* Check out the rhs of a static or global initialization VNODE to see | 618 /* Check out the rhs of a static or global initialization VNODE to see |
604 if any of them contain addressof operations. Note that some of | 619 if any of them contain addressof operations. Note that some of |
605 these variables may not even be referenced in the code in this | 620 these variables may not even be referenced in the code in this |
606 compilation unit but their right hand sides may contain references | 621 compilation unit but their right hand sides may contain references |
607 to variables defined within this unit. */ | 622 to variables defined within this unit. */ |
608 | 623 |
609 static void | 624 static void |
610 analyze_variable (struct varpool_node *vnode) | 625 analyze_variable (struct varpool_node *vnode) |
611 { | 626 { |
612 struct walk_stmt_info wi; | 627 struct walk_stmt_info wi; |
613 tree global = vnode->decl; | 628 tree global = vnode->decl; |
614 | 629 |
616 wi.pset = visited_nodes; | 631 wi.pset = visited_nodes; |
617 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs, | 632 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs, |
618 &wi, wi.pset); | 633 &wi, wi.pset); |
619 } | 634 } |
620 | 635 |
636 | |
621 /* Set up the persistent info for FN. */ | 637 /* Set up the persistent info for FN. */ |
622 | 638 |
623 static ipa_reference_local_vars_info_t | 639 static ipa_reference_local_vars_info_t |
624 init_function_info (struct cgraph_node *fn) | 640 init_function_info (struct cgraph_node *fn) |
625 { | 641 { |
626 ipa_reference_vars_info_t info | 642 ipa_reference_vars_info_t info |
627 = XCNEW (struct ipa_reference_vars_info_d); | 643 = XCNEW (struct ipa_reference_vars_info_d); |
628 ipa_reference_local_vars_info_t l | 644 ipa_reference_local_vars_info_t l |
629 = XCNEW (struct ipa_reference_local_vars_info_d); | 645 = XCNEW (struct ipa_reference_local_vars_info_d); |
630 | 646 |
631 /* Add the info to the tree's annotation. */ | 647 /* Add the info to the tree's annotation. */ |
636 l->statics_written = BITMAP_ALLOC (&local_info_obstack); | 652 l->statics_written = BITMAP_ALLOC (&local_info_obstack); |
637 | 653 |
638 return l; | 654 return l; |
639 } | 655 } |
640 | 656 |
657 | |
641 /* This is the main routine for finding the reference patterns for | 658 /* This is the main routine for finding the reference patterns for |
642 global variables within a function FN. */ | 659 global variables within a function FN. */ |
643 | 660 |
644 static void | 661 static void |
645 analyze_function (struct cgraph_node *fn) | 662 analyze_function (struct cgraph_node *fn) |
646 { | 663 { |
647 tree decl = fn->decl; | 664 tree decl = fn->decl; |
648 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl); | 665 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl); |
649 basic_block this_block; | 666 basic_block this_block; |
650 #ifdef ENABLE_CHECKING | 667 #ifdef ENABLE_CHECKING |
651 tree step; | 668 tree step; |
652 #endif | 669 #endif |
670 ipa_reference_local_vars_info_t local; | |
653 | 671 |
654 if (dump_file) | 672 if (dump_file) |
655 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn)); | 673 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn)); |
656 | 674 |
657 push_cfun (DECL_STRUCT_FUNCTION (decl)); | 675 push_cfun (DECL_STRUCT_FUNCTION (decl)); |
658 current_function_decl = decl; | 676 current_function_decl = decl; |
659 | 677 |
660 init_function_info (fn); | 678 init_function_info (fn); |
661 FOR_EACH_BB_FN (this_block, this_cfun) | 679 FOR_EACH_BB_FN (this_block, this_cfun) |
662 { | 680 { |
663 gimple_stmt_iterator gsi; | 681 gimple_stmt_iterator gsi; |
664 gimple phi; | 682 gimple phi; |
682 | 700 |
683 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi)) | 701 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi)) |
684 scan_stmt_for_static_refs (&gsi, fn); | 702 scan_stmt_for_static_refs (&gsi, fn); |
685 } | 703 } |
686 | 704 |
705 local = get_reference_vars_info (fn)->local; | |
706 if ((flags_from_decl_or_type (decl) & (ECF_NOTHROW | ECF_NORETURN)) | |
707 == (ECF_NOTHROW | ECF_NORETURN)) | |
708 { | |
709 local->calls_write_all = false; | |
710 bitmap_clear (local->statics_written); | |
711 } | |
712 | |
713 /* Free bitmaps of direct references if we can not use them anyway. */ | |
714 if (local->calls_write_all) | |
715 BITMAP_FREE (local->statics_written); | |
716 if (local->calls_read_all) | |
717 BITMAP_FREE (local->statics_read); | |
718 | |
719 | |
687 #ifdef ENABLE_CHECKING | 720 #ifdef ENABLE_CHECKING |
688 /* Verify that all local initializers was expanded by gimplifier. */ | 721 /* Verify that all local initializers was expanded by gimplifier. */ |
689 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls; | 722 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls; |
690 step; | 723 step; |
691 step = TREE_CHAIN (step)) | 724 step = TREE_CHAIN (step)) |
692 { | 725 { |
693 tree var = TREE_VALUE (step); | 726 tree var = TREE_VALUE (step); |
694 if (TREE_CODE (var) == VAR_DECL | 727 if (TREE_CODE (var) == VAR_DECL |
695 && DECL_INITIAL (var) | 728 && DECL_INITIAL (var) |
696 && !TREE_STATIC (var)) | 729 && !TREE_STATIC (var)) |
697 gcc_unreachable (); | 730 gcc_unreachable (); |
698 } | 731 } |
699 #endif | 732 #endif |
725 static void | 758 static void |
726 clean_function (struct cgraph_node *fn) | 759 clean_function (struct cgraph_node *fn) |
727 { | 760 { |
728 ipa_reference_vars_info_t info = get_reference_vars_info (fn); | 761 ipa_reference_vars_info_t info = get_reference_vars_info (fn); |
729 ipa_reference_global_vars_info_t g = info->global; | 762 ipa_reference_global_vars_info_t g = info->global; |
730 | 763 |
731 clean_function_local_data (fn); | 764 clean_function_local_data (fn); |
732 if (g) | 765 if (g) |
733 { | 766 { |
734 if (g->statics_read | 767 if (g->statics_read |
735 && g->statics_read != all_module_statics) | 768 && g->statics_read != all_module_statics) |
736 BITMAP_FREE (g->statics_read); | 769 BITMAP_FREE (g->statics_read); |
737 | 770 |
738 if (g->statics_written | 771 if (g->statics_written |
739 && g->statics_written != all_module_statics) | 772 && g->statics_written != all_module_statics) |
740 BITMAP_FREE (g->statics_written); | 773 BITMAP_FREE (g->statics_written); |
741 | 774 |
742 if (g->statics_not_read | 775 if (g->statics_not_read |
743 && g->statics_not_read != all_module_statics) | 776 && g->statics_not_read != all_module_statics) |
744 BITMAP_FREE (g->statics_not_read); | 777 BITMAP_FREE (g->statics_not_read); |
745 | 778 |
746 if (g->statics_not_written | 779 if (g->statics_not_written |
747 && g->statics_not_written != all_module_statics) | 780 && g->statics_not_written != all_module_statics) |
748 BITMAP_FREE (g->statics_not_written); | 781 BITMAP_FREE (g->statics_not_written); |
749 free (g); | 782 free (g); |
750 info->global = NULL; | 783 info->global = NULL; |
751 } | 784 } |
752 | 785 |
753 free (get_reference_vars_info (fn)); | 786 free (get_reference_vars_info (fn)); |
754 set_reference_vars_info (fn, NULL); | 787 set_reference_vars_info (fn, NULL); |
755 } | 788 } |
756 | 789 |
757 /* Called when new function is inserted to callgraph late. */ | 790 /* Called when new function is inserted to callgraph late. */ |
837 } | 870 } |
838 | 871 |
839 /* Analyze each function in the cgraph to see which global or statics | 872 /* Analyze each function in the cgraph to see which global or statics |
840 are read or written. */ | 873 are read or written. */ |
841 | 874 |
842 static void | 875 static void |
843 generate_summary (void) | 876 generate_summary (void) |
844 { | 877 { |
845 struct cgraph_node *node; | 878 struct cgraph_node *node; |
846 struct varpool_node *vnode; | 879 struct varpool_node *vnode; |
847 unsigned int index; | 880 unsigned int index; |
848 bitmap_iterator bi; | 881 bitmap_iterator bi; |
849 bitmap module_statics_readonly; | 882 bitmap module_statics_readonly; |
850 bitmap bm_temp; | 883 bitmap bm_temp; |
851 | 884 |
852 function_insertion_hook_holder = | |
853 cgraph_add_function_insertion_hook (&add_new_function, NULL); | |
854 node_removal_hook_holder = | |
855 cgraph_add_node_removal_hook (&remove_node_data, NULL); | |
856 node_duplication_hook_holder = | |
857 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | |
858 ipa_init (); | 885 ipa_init (); |
859 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack); | 886 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack); |
860 bm_temp = BITMAP_ALLOC (&local_info_obstack); | 887 bm_temp = BITMAP_ALLOC (&local_info_obstack); |
861 | 888 |
862 /* Process all of the variables first. */ | 889 /* Process all of the variables first. */ |
863 FOR_EACH_STATIC_INITIALIZER (vnode) | 890 FOR_EACH_STATIC_INITIALIZER (vnode) |
864 analyze_variable (vnode); | 891 analyze_variable (vnode); |
865 | 892 |
866 /* Process all of the functions next. | 893 /* Process all of the functions next. |
867 | 894 |
868 We do not want to process any of the clones so we check that this | 895 We do not want to process any of the clones so we check that this |
869 is a master clone. However, we do need to process any | 896 is a master clone. However, we do need to process any |
870 AVAIL_OVERWRITABLE functions (these are never clones) because | 897 AVAIL_OVERWRITABLE functions (these are never clones) because |
871 they may cause a static variable to escape. The code that can | 898 they may cause a static variable to escape. The code that can |
872 overwrite such a function cannot access the statics because it | 899 overwrite such a function cannot access the statics because it |
873 would not be in the same compilation unit. When the analysis is | 900 would not be in the same compilation unit. When the analysis is |
874 finished, the computed information of these AVAIL_OVERWRITABLE is | 901 finished, the computed information of these AVAIL_OVERWRITABLE is |
875 replaced with worst case info. | 902 replaced with worst case info. |
876 */ | 903 */ |
877 for (node = cgraph_nodes; node; node = node->next) | 904 for (node = cgraph_nodes; node; node = node->next) |
878 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 905 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
879 analyze_function (node); | 906 analyze_function (node); |
880 | 907 |
885 (i.e. have their address taken). */ | 912 (i.e. have their address taken). */ |
886 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi) | 913 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi) |
887 { | 914 { |
888 splay_tree_remove (reference_vars_to_consider, index); | 915 splay_tree_remove (reference_vars_to_consider, index); |
889 } | 916 } |
890 | 917 |
891 bitmap_and_compl_into (all_module_statics, | 918 bitmap_and_compl_into (all_module_statics, |
892 module_statics_escape); | 919 module_statics_escape); |
893 | 920 |
894 bitmap_and_compl (module_statics_readonly, all_module_statics, | 921 bitmap_and_compl (module_statics_readonly, all_module_statics, |
895 module_statics_written); | 922 module_statics_written); |
896 | 923 |
897 /* If the address is not taken, we can unset the addressable bit | 924 /* If the address is not taken, we can unset the addressable bit |
898 on this variable. */ | 925 on this variable. */ |
899 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) | 926 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) |
900 { | 927 { |
901 tree var = get_static_decl (index); | 928 tree var = get_static_decl (index); |
902 TREE_ADDRESSABLE (var) = 0; | 929 TREE_ADDRESSABLE (var) = 0; |
903 if (dump_file) | 930 if (dump_file) |
904 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n", | 931 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n", |
905 get_static_name (index)); | 932 get_static_name (index)); |
906 } | 933 } |
907 | 934 |
908 /* If the variable is never written, we can set the TREE_READONLY | 935 /* If the variable is never written, we can set the TREE_READONLY |
909 flag. Additionally if it has a DECL_INITIAL that is made up of | 936 flag. Additionally if it has a DECL_INITIAL that is made up of |
910 constants we can treat the entire global as a constant. */ | 937 constants we can treat the entire global as a constant. */ |
911 | 938 |
912 bitmap_and_compl (module_statics_readonly, all_module_statics, | 939 bitmap_and_compl (module_statics_readonly, all_module_statics, |
913 module_statics_written); | 940 module_statics_written); |
914 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi) | 941 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi) |
915 { | 942 { |
916 tree var = get_static_decl (index); | 943 tree var = get_static_decl (index); |
917 | 944 |
918 /* Ignore variables in named sections - changing TREE_READONLY | 945 /* Ignore variables in named sections - changing TREE_READONLY |
919 changes the section flags, potentially causing conflicts with | 946 changes the section flags, potentially causing conflicts with |
920 other variables in the same named section. */ | 947 other variables in the same named section. */ |
921 if (DECL_SECTION_NAME (var) == NULL_TREE) | 948 if (DECL_SECTION_NAME (var) == NULL_TREE) |
922 { | 949 { |
923 TREE_READONLY (var) = 1; | 950 TREE_READONLY (var) = 1; |
924 if (dump_file) | 951 if (dump_file) |
925 fprintf (dump_file, "read-only var %s\n", | 952 fprintf (dump_file, "read-only var %s\n", |
926 get_static_name (index)); | 953 get_static_name (index)); |
927 } | 954 } |
928 } | 955 } |
929 | 956 |
930 BITMAP_FREE(module_statics_escape); | 957 BITMAP_FREE(module_statics_escape); |
931 BITMAP_FREE(module_statics_written); | 958 BITMAP_FREE(module_statics_written); |
932 module_statics_escape = NULL; | 959 module_statics_escape = NULL; |
933 module_statics_written = NULL; | 960 module_statics_written = NULL; |
934 | 961 |
935 if (dump_file) | 962 if (dump_file) |
936 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) | 963 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) |
937 { | 964 { |
938 fprintf (dump_file, "\nPromotable global:%s", | 965 fprintf (dump_file, "\nPromotable global:%s", |
939 get_static_name (index)); | 966 get_static_name (index)); |
940 } | 967 } |
941 | 968 |
942 for (node = cgraph_nodes; node; node = node->next) | 969 for (node = cgraph_nodes; node; node = node->next) |
943 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 970 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
944 { | 971 { |
945 ipa_reference_local_vars_info_t l; | 972 ipa_reference_local_vars_info_t l; |
946 l = get_reference_vars_info (node)->local; | 973 l = get_reference_vars_info (node)->local; |
947 | 974 |
948 /* Any variables that are not in all_module_statics are | 975 /* Any variables that are not in all_module_statics are |
949 removed from the local maps. This will include all of the | 976 removed from the local maps. This will include all of the |
950 variables that were found to escape in the function | 977 variables that were found to escape in the function |
951 scanning. */ | 978 scanning. */ |
952 bitmap_and_into (l->statics_read, | 979 if (l->statics_read) |
953 all_module_statics); | 980 bitmap_and_into (l->statics_read, |
954 bitmap_and_into (l->statics_written, | 981 all_module_statics); |
955 all_module_statics); | 982 if (l->statics_written) |
983 bitmap_and_into (l->statics_written, | |
984 all_module_statics); | |
956 } | 985 } |
957 | 986 |
958 BITMAP_FREE(module_statics_readonly); | 987 BITMAP_FREE(module_statics_readonly); |
959 BITMAP_FREE(bm_temp); | 988 BITMAP_FREE(bm_temp); |
960 | 989 |
961 if (dump_file) | 990 if (dump_file) |
962 for (node = cgraph_nodes; node; node = node->next) | 991 for (node = cgraph_nodes; node; node = node->next) |
963 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) | 992 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
964 { | 993 { |
965 ipa_reference_local_vars_info_t l; | 994 ipa_reference_local_vars_info_t l; |
966 unsigned int index; | 995 unsigned int index; |
967 bitmap_iterator bi; | 996 bitmap_iterator bi; |
968 | 997 |
969 l = get_reference_vars_info (node)->local; | 998 l = get_reference_vars_info (node)->local; |
970 fprintf (dump_file, | 999 fprintf (dump_file, |
971 "\nFunction name:%s/%i:", | 1000 "\nFunction name:%s/%i:", |
972 cgraph_node_name (node), node->uid); | 1001 cgraph_node_name (node), node->uid); |
973 fprintf (dump_file, "\n locals read: "); | 1002 fprintf (dump_file, "\n locals read: "); |
974 EXECUTE_IF_SET_IN_BITMAP (l->statics_read, | 1003 if (l->statics_read) |
975 0, index, bi) | 1004 EXECUTE_IF_SET_IN_BITMAP (l->statics_read, |
976 { | 1005 0, index, bi) |
977 fprintf (dump_file, "%s ", | 1006 { |
978 get_static_name (index)); | 1007 fprintf (dump_file, "%s ", |
979 } | 1008 get_static_name (index)); |
1009 } | |
980 fprintf (dump_file, "\n locals written: "); | 1010 fprintf (dump_file, "\n locals written: "); |
981 EXECUTE_IF_SET_IN_BITMAP (l->statics_written, | 1011 if (l->statics_written) |
982 0, index, bi) | 1012 EXECUTE_IF_SET_IN_BITMAP (l->statics_written, |
983 { | 1013 0, index, bi) |
984 fprintf(dump_file, "%s ", | 1014 { |
985 get_static_name (index)); | 1015 fprintf(dump_file, "%s ", |
986 } | 1016 get_static_name (index)); |
1017 } | |
987 if (l->calls_read_all) | 1018 if (l->calls_read_all) |
988 fprintf (dump_file, "\n calls read all: "); | 1019 fprintf (dump_file, "\n calls read all: "); |
989 if (l->calls_write_all) | 1020 if (l->calls_write_all) |
990 fprintf (dump_file, "\n calls read all: "); | 1021 fprintf (dump_file, "\n calls read all: "); |
991 } | 1022 } |
992 } | 1023 } |
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 | |
993 | 1175 |
1176 /* Set READ_ALL/WRITE_ALL based on DECL flags. */ | |
1177 static void | |
1178 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all) | |
1179 { | |
1180 int flags = flags_from_decl_or_type (decl); | |
1181 if (flags & ECF_CONST) | |
1182 ; | |
1183 else if (flags & ECF_PURE) | |
1184 *read_all = true; | |
1185 else | |
1186 { | |
1187 /* TODO: To be able to produce sane results, we should also handle | |
1188 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; | |
1192 /* When function does not reutrn, it is safe to ignore anythign it writes | |
1193 to, because the effect will never happen. */ | |
1194 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) | |
1195 != (ECF_NOTHROW | ECF_NORETURN)) | |
1196 *write_all = true; | |
1197 } | |
1198 } | |
1199 | |
994 /* Produce the global information by preforming a transitive closure | 1200 /* Produce the global information by preforming a transitive closure |
995 on the local information that was produced by ipa_analyze_function | 1201 on the local information that was produced by ipa_analyze_function |
996 and ipa_analyze_variable. */ | 1202 and ipa_analyze_variable. */ |
997 | 1203 |
998 static unsigned int | 1204 static unsigned int |
1000 { | 1206 { |
1001 struct cgraph_node *node; | 1207 struct cgraph_node *node; |
1002 struct cgraph_node *w; | 1208 struct cgraph_node *w; |
1003 struct cgraph_node **order = | 1209 struct cgraph_node **order = |
1004 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | 1210 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); |
1005 int order_pos = ipa_utils_reduced_inorder (order, false, true); | 1211 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL); |
1006 int i; | 1212 int i; |
1007 | 1213 |
1008 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); | 1214 cgraph_remove_function_insertion_hook (function_insertion_hook_holder); |
1009 if (dump_file) | 1215 if (dump_file) |
1010 dump_cgraph (dump_file); | 1216 dump_cgraph (dump_file); |
1011 | 1217 |
1012 /* Propagate the local information thru the call graph to produce | 1218 /* Propagate the local information thru the call graph to produce |
1013 the global information. All the nodes within a cycle will have | 1219 the global information. All the nodes within a cycle will have |
1014 the same info so we collapse cycles first. Then we can do the | 1220 the same info so we collapse cycles first. Then we can do the |
1015 propagation in one pass from the leaves to the roots. */ | 1221 propagation in one pass from the leaves to the roots. */ |
1016 order_pos = ipa_utils_reduced_inorder (order, true, true); | 1222 order_pos = ipa_utils_reduced_inorder (order, true, true, NULL); |
1017 if (dump_file) | 1223 if (dump_file) |
1018 ipa_utils_print_order(dump_file, "reduced", order, order_pos); | 1224 ipa_utils_print_order(dump_file, "reduced", order, order_pos); |
1019 | 1225 |
1020 for (i = 0; i < order_pos; i++ ) | 1226 for (i = 0; i < order_pos; i++ ) |
1021 { | 1227 { |
1022 ipa_reference_vars_info_t node_info; | 1228 ipa_reference_vars_info_t node_info; |
1023 ipa_reference_global_vars_info_t node_g = | 1229 ipa_reference_global_vars_info_t node_g = |
1024 XCNEW (struct ipa_reference_global_vars_info_d); | 1230 XCNEW (struct ipa_reference_global_vars_info_d); |
1025 ipa_reference_local_vars_info_t node_l; | 1231 ipa_reference_local_vars_info_t node_l; |
1026 | 1232 struct cgraph_edge *e; |
1233 | |
1027 bool read_all; | 1234 bool read_all; |
1028 bool write_all; | 1235 bool write_all; |
1029 struct ipa_dfs_info * w_info; | 1236 struct ipa_dfs_info * w_info; |
1030 | 1237 |
1031 node = order[i]; | 1238 node = order[i]; |
1032 node_info = get_reference_vars_info (node); | 1239 node_info = get_reference_vars_info (node); |
1033 if (!node_info) | 1240 if (!node_info) |
1034 { | 1241 { |
1035 dump_cgraph_node (stderr, node); | 1242 dump_cgraph_node (stderr, node); |
1036 dump_cgraph (stderr); | 1243 dump_cgraph (stderr); |
1037 gcc_unreachable (); | 1244 gcc_unreachable (); |
1038 } | 1245 } |
1040 gcc_assert (!node_info->global); | 1247 gcc_assert (!node_info->global); |
1041 node_l = node_info->local; | 1248 node_l = node_info->local; |
1042 | 1249 |
1043 read_all = node_l->calls_read_all; | 1250 read_all = node_l->calls_read_all; |
1044 write_all = node_l->calls_write_all; | 1251 write_all = node_l->calls_write_all; |
1252 | |
1253 /* When function is overwrittable, we can not assume anything. */ | |
1254 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | |
1255 read_write_all_from_decl (node->decl, &read_all, &write_all); | |
1256 | |
1257 for (e = node->callees; e; e = e->next_callee) | |
1258 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) | |
1259 read_write_all_from_decl (e->callee->decl, &read_all, &write_all); | |
1260 | |
1045 | 1261 |
1046 /* If any node in a cycle is calls_read_all or calls_write_all | 1262 /* If any node in a cycle is calls_read_all or calls_write_all |
1047 they all are. */ | 1263 they all are. */ |
1048 w_info = (struct ipa_dfs_info *) node->aux; | 1264 w_info = (struct ipa_dfs_info *) node->aux; |
1049 w = w_info->next_cycle; | 1265 w = w_info->next_cycle; |
1050 while (w) | 1266 while (w) |
1051 { | 1267 { |
1052 ipa_reference_local_vars_info_t w_l = | 1268 ipa_reference_local_vars_info_t w_l = |
1053 get_reference_vars_info (w)->local; | 1269 get_reference_vars_info (w)->local; |
1270 | |
1271 /* When function is overwrittable, we can not assume anything. */ | |
1272 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) | |
1273 read_write_all_from_decl (w->decl, &read_all, &write_all); | |
1274 | |
1275 for (e = w->callees; e; e = e->next_callee) | |
1276 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) | |
1277 read_write_all_from_decl (e->callee->decl, &read_all, &write_all); | |
1278 | |
1054 read_all |= w_l->calls_read_all; | 1279 read_all |= w_l->calls_read_all; |
1055 write_all |= w_l->calls_write_all; | 1280 write_all |= w_l->calls_write_all; |
1056 | 1281 |
1057 w_info = (struct ipa_dfs_info *) w->aux; | 1282 w_info = (struct ipa_dfs_info *) w->aux; |
1058 w = w_info->next_cycle; | 1283 w = w_info->next_cycle; |
1059 } | 1284 } |
1060 | 1285 |
1286 | |
1061 /* Initialized the bitmaps for the reduced nodes */ | 1287 /* Initialized the bitmaps for the reduced nodes */ |
1062 if (read_all) | 1288 if (read_all) |
1063 node_g->statics_read = all_module_statics; | 1289 node_g->statics_read = all_module_statics; |
1064 else | 1290 else |
1065 { | 1291 { |
1066 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack); | 1292 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack); |
1067 bitmap_copy (node_g->statics_read, | 1293 bitmap_copy (node_g->statics_read, |
1068 node_l->statics_read); | 1294 node_l->statics_read); |
1069 } | 1295 } |
1070 | 1296 if (write_all) |
1071 if (write_all) | |
1072 node_g->statics_written = all_module_statics; | 1297 node_g->statics_written = all_module_statics; |
1073 else | 1298 else |
1074 { | 1299 { |
1075 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack); | 1300 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack); |
1076 bitmap_copy (node_g->statics_written, | 1301 bitmap_copy (node_g->statics_written, |
1077 node_l->statics_written); | 1302 node_l->statics_written); |
1078 } | 1303 } |
1079 | 1304 |
1080 propagate_bits (node_g, node); | 1305 propagate_bits (node_g, node); |
1081 w_info = (struct ipa_dfs_info *) node->aux; | 1306 w_info = (struct ipa_dfs_info *) node->aux; |
1082 w = w_info->next_cycle; | 1307 w = w_info->next_cycle; |
1083 while (w) | 1308 while (w) |
1084 { | 1309 { |
1085 ipa_reference_vars_info_t w_ri = | 1310 ipa_reference_vars_info_t w_ri = |
1086 get_reference_vars_info (w); | 1311 get_reference_vars_info (w); |
1087 ipa_reference_local_vars_info_t w_l = w_ri->local; | 1312 ipa_reference_local_vars_info_t w_l = w_ri->local; |
1088 | 1313 |
1089 /* These global bitmaps are initialized from the local info | 1314 /* These global bitmaps are initialized from the local info |
1090 of all of the nodes in the region. However there is no | 1315 of all of the nodes in the region. However there is no |
1091 need to do any work if the bitmaps were set to | 1316 need to do any work if the bitmaps were set to |
1092 all_module_statics. */ | 1317 all_module_statics. */ |
1093 if (!read_all) | 1318 if (!read_all) |
1105 node_info->global = node_g; | 1330 node_info->global = node_g; |
1106 w_info = (struct ipa_dfs_info *) node->aux; | 1331 w_info = (struct ipa_dfs_info *) node->aux; |
1107 w = w_info->next_cycle; | 1332 w = w_info->next_cycle; |
1108 while (w) | 1333 while (w) |
1109 { | 1334 { |
1110 ipa_reference_vars_info_t w_ri = | 1335 ipa_reference_vars_info_t w_ri = |
1111 get_reference_vars_info (w); | 1336 get_reference_vars_info (w); |
1112 | 1337 |
1113 gcc_assert (!w_ri->global); | 1338 gcc_assert (!w_ri->global); |
1114 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d); | 1339 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d); |
1115 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read); | 1340 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read); |
1133 | 1358 |
1134 node = order[i]; | 1359 node = order[i]; |
1135 node_info = get_reference_vars_info (node); | 1360 node_info = get_reference_vars_info (node); |
1136 node_g = node_info->global; | 1361 node_g = node_info->global; |
1137 node_l = node_info->local; | 1362 node_l = node_info->local; |
1138 fprintf (dump_file, | 1363 fprintf (dump_file, |
1139 "\nFunction name:%s/%i:", | 1364 "\nFunction name:%s/%i:", |
1140 cgraph_node_name (node), node->uid); | 1365 cgraph_node_name (node), node->uid); |
1141 fprintf (dump_file, "\n locals read: "); | 1366 fprintf (dump_file, "\n locals read: "); |
1142 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read, | 1367 if (node_l->statics_read) |
1143 0, index, bi) | 1368 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read, |
1144 { | 1369 0, index, bi) |
1145 fprintf (dump_file, "%s ", | 1370 { |
1146 get_static_name (index)); | 1371 fprintf (dump_file, "%s ", |
1147 } | 1372 get_static_name (index)); |
1373 } | |
1148 fprintf (dump_file, "\n locals written: "); | 1374 fprintf (dump_file, "\n locals written: "); |
1149 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written, | 1375 if (node_l->statics_written) |
1150 0, index, bi) | 1376 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written, |
1151 { | 1377 0, index, bi) |
1152 fprintf(dump_file, "%s ", | 1378 { |
1153 get_static_name (index)); | 1379 fprintf(dump_file, "%s ", |
1154 } | 1380 get_static_name (index)); |
1381 } | |
1155 | 1382 |
1156 w_info = (struct ipa_dfs_info *) node->aux; | 1383 w_info = (struct ipa_dfs_info *) node->aux; |
1157 w = w_info->next_cycle; | 1384 w = w_info->next_cycle; |
1158 while (w) | 1385 while (w) |
1159 { | 1386 { |
1160 ipa_reference_vars_info_t w_ri = | 1387 ipa_reference_vars_info_t w_ri = |
1161 get_reference_vars_info (w); | 1388 get_reference_vars_info (w); |
1162 ipa_reference_local_vars_info_t w_l = w_ri->local; | 1389 ipa_reference_local_vars_info_t w_l = w_ri->local; |
1163 fprintf (dump_file, "\n next cycle: %s/%i ", | 1390 fprintf (dump_file, "\n next cycle: %s/%i ", |
1164 cgraph_node_name (w), w->uid); | 1391 cgraph_node_name (w), w->uid); |
1165 fprintf (dump_file, "\n locals read: "); | 1392 fprintf (dump_file, "\n locals read: "); |
1166 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, | 1393 if (w_l->statics_read) |
1167 0, index, bi) | 1394 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, |
1168 { | 1395 0, index, bi) |
1169 fprintf (dump_file, "%s ", | 1396 { |
1170 get_static_name (index)); | 1397 fprintf (dump_file, "%s ", |
1171 } | 1398 get_static_name (index)); |
1399 } | |
1172 | 1400 |
1173 fprintf (dump_file, "\n locals written: "); | 1401 fprintf (dump_file, "\n locals written: "); |
1174 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written, | 1402 if (w_l->statics_written) |
1175 0, index, bi) | 1403 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written, |
1176 { | 1404 0, index, bi) |
1177 fprintf(dump_file, "%s ", | 1405 { |
1178 get_static_name (index)); | 1406 fprintf (dump_file, "%s ", |
1179 } | 1407 get_static_name (index)); |
1180 | 1408 } |
1181 | 1409 |
1182 w_info = (struct ipa_dfs_info *) w->aux; | 1410 w_info = (struct ipa_dfs_info *) w->aux; |
1183 w = w_info->next_cycle; | 1411 w = w_info->next_cycle; |
1184 } | 1412 } |
1185 fprintf (dump_file, "\n globals read: "); | 1413 fprintf (dump_file, "\n globals read: "); |
1186 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read, | 1414 if (node_g->statics_read == all_module_statics) |
1187 0, index, bi) | 1415 fprintf (dump_file, "ALL"); |
1188 { | 1416 else |
1189 fprintf (dump_file, "%s ", | 1417 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read, |
1190 get_static_name (index)); | 1418 0, index, bi) |
1191 } | 1419 { |
1420 fprintf (dump_file, "%s ", | |
1421 get_static_name (index)); | |
1422 } | |
1192 fprintf (dump_file, "\n globals written: "); | 1423 fprintf (dump_file, "\n globals written: "); |
1193 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written, | 1424 if (node_g->statics_written == all_module_statics) |
1194 0, index, bi) | 1425 fprintf (dump_file, "ALL"); |
1195 { | 1426 else |
1196 fprintf (dump_file, "%s ", | 1427 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written, |
1197 get_static_name (index)); | 1428 0, index, bi) |
1198 } | 1429 { |
1430 fprintf (dump_file, "%s ", | |
1431 get_static_name (index)); | |
1432 } | |
1199 } | 1433 } |
1200 } | 1434 } |
1201 | 1435 |
1202 /* Cleanup. */ | 1436 /* Cleanup. */ |
1203 for (i = 0; i < order_pos; i++ ) | 1437 for (i = 0; i < order_pos; i++ ) |
1205 ipa_reference_vars_info_t node_info; | 1439 ipa_reference_vars_info_t node_info; |
1206 ipa_reference_global_vars_info_t node_g; | 1440 ipa_reference_global_vars_info_t node_g; |
1207 node = order[i]; | 1441 node = order[i]; |
1208 node_info = get_reference_vars_info (node); | 1442 node_info = get_reference_vars_info (node); |
1209 node_g = node_info->global; | 1443 node_g = node_info->global; |
1210 | 1444 |
1211 /* Create the complimentary sets. These are more useful for | 1445 /* Create the complimentary sets. These are more useful for |
1212 certain apis. */ | 1446 certain apis. */ |
1213 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack); | 1447 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack); |
1214 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack); | 1448 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack); |
1215 | 1449 |
1216 if (node_g->statics_read != all_module_statics) | 1450 if (node_g->statics_read != all_module_statics) |
1217 bitmap_and_compl (node_g->statics_not_read, | 1451 bitmap_and_compl (node_g->statics_not_read, |
1218 all_module_statics, | 1452 all_module_statics, |
1219 node_g->statics_read); | 1453 node_g->statics_read); |
1220 | 1454 |
1221 if (node_g->statics_written | 1455 if (node_g->statics_written |
1222 != all_module_statics) | 1456 != all_module_statics) |
1223 bitmap_and_compl (node_g->statics_not_written, | 1457 bitmap_and_compl (node_g->statics_not_written, |
1224 all_module_statics, | 1458 all_module_statics, |
1225 node_g->statics_written); | 1459 node_g->statics_written); |
1226 } | 1460 } |
1227 | 1461 |
1228 free (order); | 1462 free (order); |
1230 for (node = cgraph_nodes; node; node = node->next) | 1464 for (node = cgraph_nodes; node; node = node->next) |
1231 { | 1465 { |
1232 ipa_reference_vars_info_t node_info; | 1466 ipa_reference_vars_info_t node_info; |
1233 node_info = get_reference_vars_info (node); | 1467 node_info = get_reference_vars_info (node); |
1234 /* Get rid of the aux information. */ | 1468 /* Get rid of the aux information. */ |
1235 | 1469 |
1236 if (node->aux) | 1470 if (node->aux) |
1237 { | 1471 { |
1238 free (node->aux); | 1472 free (node->aux); |
1239 node->aux = NULL; | 1473 node->aux = NULL; |
1240 } | 1474 } |
1241 | 1475 |
1242 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE) | 1476 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE) |
1243 clean_function (node); | 1477 clean_function (node); |
1244 else if (node_info) | 1478 else if (node_info) |
1245 clean_function_local_data (node); | 1479 clean_function_local_data (node); |
1246 } | 1480 } |
1255 return (flag_ipa_reference | 1489 return (flag_ipa_reference |
1256 /* Don't bother doing anything if the program has errors. */ | 1490 /* Don't bother doing anything if the program has errors. */ |
1257 && !(errorcount || sorrycount)); | 1491 && !(errorcount || sorrycount)); |
1258 } | 1492 } |
1259 | 1493 |
1260 struct ipa_opt_pass pass_ipa_reference = | 1494 struct ipa_opt_pass_d pass_ipa_reference = |
1261 { | 1495 { |
1262 { | 1496 { |
1263 IPA_PASS, | 1497 IPA_PASS, |
1264 "static-var", /* name */ | 1498 "static-var", /* name */ |
1265 gate_reference, /* gate */ | 1499 gate_reference, /* gate */ |
1273 0, /* properties_destroyed */ | 1507 0, /* properties_destroyed */ |
1274 0, /* todo_flags_start */ | 1508 0, /* todo_flags_start */ |
1275 0 /* todo_flags_finish */ | 1509 0 /* todo_flags_finish */ |
1276 }, | 1510 }, |
1277 generate_summary, /* generate_summary */ | 1511 generate_summary, /* generate_summary */ |
1278 NULL, /* write_summary */ | 1512 ipa_reference_write_summary, /* write_summary */ |
1279 NULL, /* read_summary */ | 1513 ipa_reference_read_summary, /* read_summary */ |
1280 NULL, /* function_read_summary */ | 1514 NULL, /* function_read_summary */ |
1515 NULL, /* stmt_fixup */ | |
1281 0, /* TODOs */ | 1516 0, /* TODOs */ |
1282 NULL, /* function_transform */ | 1517 NULL, /* function_transform */ |
1283 NULL /* variable_transform */ | 1518 NULL /* variable_transform */ |
1284 }; | 1519 }; |
1285 | 1520 |