Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-reference.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
57 #include "flags.h" | 57 #include "flags.h" |
58 #include "timevar.h" | 58 #include "timevar.h" |
59 #include "diagnostic.h" | 59 #include "diagnostic.h" |
60 #include "langhooks.h" | 60 #include "langhooks.h" |
61 #include "lto-streamer.h" | 61 #include "lto-streamer.h" |
62 #include "toplev.h" | |
63 | 62 |
64 static void remove_node_data (struct cgraph_node *node, | 63 static void remove_node_data (struct cgraph_node *node, |
65 void *data ATTRIBUTE_UNUSED); | 64 void *data ATTRIBUTE_UNUSED); |
66 static void duplicate_node_data (struct cgraph_node *src, | 65 static void duplicate_node_data (struct cgraph_node *src, |
67 struct cgraph_node *dst, | 66 struct cgraph_node *dst, |
72 | 71 |
73 struct ipa_reference_local_vars_info_d | 72 struct ipa_reference_local_vars_info_d |
74 { | 73 { |
75 bitmap statics_read; | 74 bitmap statics_read; |
76 bitmap statics_written; | 75 bitmap statics_written; |
77 | |
78 /* Set when this function calls another function external to the | |
79 compilation unit or if the function has a asm clobber of memory. | |
80 In general, such calls are modeled as reading and writing all | |
81 variables (both bits on) but sometime there are attributes on the | |
82 called function so we can do better. */ | |
83 bool calls_read_all; | |
84 bool calls_write_all; | |
85 }; | 76 }; |
86 | 77 |
87 /* Statics that are read and written by some set of functions. The | 78 /* Statics that are read and written by some set of functions. The |
88 local ones are based on the loads and stores local to the function. | 79 local ones are based on the loads and stores local to the function. |
89 The global ones are based on the local info as well as the | 80 The global ones are based on the local info as well as the |
93 { | 84 { |
94 bitmap statics_read; | 85 bitmap statics_read; |
95 bitmap statics_written; | 86 bitmap statics_written; |
96 }; | 87 }; |
97 | 88 |
98 /* Information we save about every function after ipa-reference is completted. */ | 89 /* Information we save about every function after ipa-reference is completed. */ |
99 | 90 |
100 struct ipa_reference_optimization_summary_d | 91 struct ipa_reference_optimization_summary_d |
101 { | 92 { |
102 bitmap statics_not_read; | 93 bitmap statics_not_read; |
103 bitmap statics_not_written; | 94 bitmap statics_not_written; |
158 static inline ipa_reference_optimization_summary_t | 149 static inline ipa_reference_optimization_summary_t |
159 get_reference_optimization_summary (struct cgraph_node *node) | 150 get_reference_optimization_summary (struct cgraph_node *node) |
160 { | 151 { |
161 if (!ipa_reference_opt_sum_vector | 152 if (!ipa_reference_opt_sum_vector |
162 || (VEC_length (ipa_reference_optimization_summary_t, | 153 || (VEC_length (ipa_reference_optimization_summary_t, |
163 ipa_reference_opt_sum_vector) | 154 ipa_reference_opt_sum_vector) |
164 <= (unsigned int) node->uid)) | 155 <= (unsigned int) node->uid)) |
165 return NULL; | 156 return NULL; |
166 return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector, | 157 return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector, |
167 node->uid); | 158 node->uid); |
168 } | 159 } |
206 ipa_reference_optimization_summary_t info; | 197 ipa_reference_optimization_summary_t info; |
207 | 198 |
208 info = get_reference_optimization_summary (fn); | 199 info = get_reference_optimization_summary (fn); |
209 if (info) | 200 if (info) |
210 return info->statics_not_read; | 201 return info->statics_not_read; |
202 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) | |
203 return all_module_statics; | |
211 else | 204 else |
212 return NULL; | 205 return NULL; |
213 } | 206 } |
214 | 207 |
215 /* Return a bitmap indexed by DECL_UID uid for the static variables | 208 /* Return a bitmap indexed by DECL_UID uid for the static variables |
223 ipa_reference_optimization_summary_t info; | 216 ipa_reference_optimization_summary_t info; |
224 | 217 |
225 info = get_reference_optimization_summary (fn); | 218 info = get_reference_optimization_summary (fn); |
226 if (info) | 219 if (info) |
227 return info->statics_not_written; | 220 return info->statics_not_written; |
221 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) | |
222 return all_module_statics; | |
228 else | 223 else |
229 return NULL; | 224 return NULL; |
230 } | 225 } |
231 | 226 |
232 | 227 |
237 static inline void | 232 static inline void |
238 add_static_var (tree var) | 233 add_static_var (tree var) |
239 { | 234 { |
240 int uid = DECL_UID (var); | 235 int uid = DECL_UID (var); |
241 gcc_assert (TREE_CODE (var) == VAR_DECL); | 236 gcc_assert (TREE_CODE (var) == VAR_DECL); |
242 if (!bitmap_bit_p (all_module_statics, uid)) | 237 if (dump_file) |
243 { | 238 splay_tree_insert (reference_vars_to_consider, |
244 if (dump_file) | 239 uid, (splay_tree_value)var); |
245 splay_tree_insert (reference_vars_to_consider, | 240 bitmap_set_bit (all_module_statics, uid); |
246 uid, (splay_tree_value)var); | |
247 bitmap_set_bit (all_module_statics, uid); | |
248 } | |
249 } | 241 } |
250 | 242 |
251 /* Return true if the variable T is the right kind of static variable to | 243 /* Return true if the variable T is the right kind of static variable to |
252 perform compilation unit scope escape analysis. */ | 244 perform compilation unit scope escape analysis. */ |
253 | 245 |
255 is_proper_for_analysis (tree t) | 247 is_proper_for_analysis (tree t) |
256 { | 248 { |
257 /* We handle only variables whose address is never taken. */ | 249 /* We handle only variables whose address is never taken. */ |
258 if (TREE_ADDRESSABLE (t)) | 250 if (TREE_ADDRESSABLE (t)) |
259 return false; | 251 return false; |
252 | |
260 /* If the variable has the "used" attribute, treat it as if it had a | 253 /* If the variable has the "used" attribute, treat it as if it had a |
261 been touched by the devil. */ | 254 been touched by the devil. */ |
262 if (DECL_PRESERVE_P (t)) | 255 if (DECL_PRESERVE_P (t)) |
263 return false; | 256 return false; |
264 | 257 |
265 /* Do not want to do anything with volatile except mark any | 258 /* Do not want to do anything with volatile except mark any |
266 function that uses one to be not const or pure. */ | 259 function that uses one to be not const or pure. */ |
267 if (TREE_THIS_VOLATILE (t)) | 260 if (TREE_THIS_VOLATILE (t)) |
261 return false; | |
262 | |
263 /* We do not need to analyze readonly vars, we already know they do not | |
264 alias. */ | |
265 if (TREE_READONLY (t)) | |
268 return false; | 266 return false; |
269 | 267 |
270 /* We cannot touch decls where the type needs constructing. */ | 268 /* We cannot touch decls where the type needs constructing. */ |
271 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) | 269 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) |
272 return false; | 270 return false; |
302 { | 300 { |
303 struct cgraph_edge *e; | 301 struct cgraph_edge *e; |
304 for (e = x->callees; e; e = e->next_callee) | 302 for (e = x->callees; e; e = e->next_callee) |
305 { | 303 { |
306 struct cgraph_node *y = e->callee; | 304 struct cgraph_node *y = e->callee; |
307 | 305 enum availability avail; |
306 | |
307 avail = cgraph_function_body_availability (e->callee); | |
308 /* Only look into nodes we can propagate something. */ | 308 /* Only look into nodes we can propagate something. */ |
309 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE) | 309 if (avail > AVAIL_OVERWRITABLE |
310 || (avail == AVAIL_OVERWRITABLE | |
311 && (flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))) | |
310 { | 312 { |
313 int flags = flags_from_decl_or_type (e->callee->decl); | |
311 if (get_reference_vars_info (y)) | 314 if (get_reference_vars_info (y)) |
312 { | 315 { |
313 ipa_reference_vars_info_t y_info | 316 ipa_reference_vars_info_t y_info |
314 = get_reference_vars_info (y); | 317 = get_reference_vars_info (y); |
315 ipa_reference_global_vars_info_t y_global = &y_info->global; | 318 ipa_reference_global_vars_info_t y_global = &y_info->global; |
316 | 319 |
317 /* Calls in current cycle do not have global computed yet. */ | 320 /* Calls in current cycle do not have global computed yet. */ |
318 if (!y_global->statics_read) | 321 if (!y_global->statics_read) |
322 continue; | |
323 | |
324 /* If function is declared const, it reads no memory even if it | |
325 seems so to local analysis. */ | |
326 if (flags & ECF_CONST) | |
319 continue; | 327 continue; |
320 | 328 |
321 if (x_global->statics_read | 329 if (x_global->statics_read |
322 != all_module_statics) | 330 != all_module_statics) |
323 { | 331 { |
333 else if (x_global->statics_read | 341 else if (x_global->statics_read |
334 != y_global->statics_read) | 342 != y_global->statics_read) |
335 bitmap_ior_into (x_global->statics_read, | 343 bitmap_ior_into (x_global->statics_read, |
336 y_global->statics_read); | 344 y_global->statics_read); |
337 } | 345 } |
346 | |
347 /* If function is declared pure, it has no stores even if it | |
348 seems so to local analysis; If we can not return from here, | |
349 we can safely ignore the call. */ | |
350 if ((flags & ECF_PURE) | |
351 || cgraph_edge_cannot_lead_to_return (e)) | |
352 continue; | |
338 | 353 |
339 if (x_global->statics_written | 354 if (x_global->statics_written |
340 != all_module_statics) | 355 != all_module_statics) |
341 { | 356 { |
342 if (y_global->statics_written | 357 if (y_global->statics_written |
375 if (dump_file) | 390 if (dump_file) |
376 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); | 391 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); |
377 | 392 |
378 bitmap_obstack_initialize (&local_info_obstack); | 393 bitmap_obstack_initialize (&local_info_obstack); |
379 bitmap_obstack_initialize (&optimization_summary_obstack); | 394 bitmap_obstack_initialize (&optimization_summary_obstack); |
380 all_module_statics = BITMAP_ALLOC (&local_info_obstack); | 395 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); |
381 | 396 |
382 node_removal_hook_holder = | 397 node_removal_hook_holder = |
383 cgraph_add_node_removal_hook (&remove_node_data, NULL); | 398 cgraph_add_node_removal_hook (&remove_node_data, NULL); |
384 node_duplication_hook_holder = | 399 node_duplication_hook_holder = |
385 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | 400 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); |
412 { | 427 { |
413 ipa_reference_local_vars_info_t local; | 428 ipa_reference_local_vars_info_t local; |
414 struct ipa_ref *ref; | 429 struct ipa_ref *ref; |
415 int i; | 430 int i; |
416 tree var; | 431 tree var; |
417 struct cgraph_edge *ie; | |
418 | 432 |
419 local = init_function_info (fn); | 433 local = init_function_info (fn); |
420 /* Process indirect calls. All direct calles are handled at propagation | |
421 time. */ | |
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++) | 434 for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++) |
432 { | 435 { |
433 if (ref->refered_type != IPA_REF_VARPOOL) | 436 if (ref->refered_type != IPA_REF_VARPOOL) |
434 continue; | 437 continue; |
435 var = ipa_ref_varpool_node (ref)->decl; | 438 var = ipa_ref_varpool_node (ref)->decl; |
441 { | 444 { |
442 case IPA_REF_LOAD: | 445 case IPA_REF_LOAD: |
443 bitmap_set_bit (local->statics_read, DECL_UID (var)); | 446 bitmap_set_bit (local->statics_read, DECL_UID (var)); |
444 break; | 447 break; |
445 case IPA_REF_STORE: | 448 case IPA_REF_STORE: |
449 if (ipa_ref_cannot_lead_to_return (ref)) | |
450 break; | |
446 bitmap_set_bit (local->statics_written, DECL_UID (var)); | 451 bitmap_set_bit (local->statics_written, DECL_UID (var)); |
447 break; | 452 break; |
448 case IPA_REF_ADDR: | 453 case IPA_REF_ADDR: |
454 gcc_unreachable (); | |
449 break; | 455 break; |
450 } | 456 } |
451 } | 457 } |
452 | 458 |
453 if ((flags_from_decl_or_type (fn->decl) & (ECF_NOTHROW | ECF_NORETURN)) | 459 if (cgraph_node_cannot_return (fn)) |
454 == (ECF_NOTHROW | ECF_NORETURN)) | 460 bitmap_clear (local->statics_written); |
455 { | |
456 local->calls_write_all = false; | |
457 bitmap_clear (local->statics_written); | |
458 } | |
459 | |
460 /* Free bitmaps of direct references if we can not use them anyway. */ | |
461 if (local->calls_write_all) | |
462 BITMAP_FREE (local->statics_written); | |
463 if (local->calls_read_all) | |
464 BITMAP_FREE (local->statics_read); | |
465 } | 461 } |
466 | 462 |
467 static bitmap | 463 static bitmap |
468 copy_global_bitmap (bitmap src) | 464 copy_global_bitmap (bitmap src) |
469 { | 465 { |
470 bitmap dst; | 466 bitmap dst; |
471 if (!src) | 467 if (!src) |
472 return NULL; | 468 return NULL; |
469 if (src == all_module_statics) | |
470 return all_module_statics; | |
473 dst = BITMAP_ALLOC (&optimization_summary_obstack); | 471 dst = BITMAP_ALLOC (&optimization_summary_obstack); |
474 bitmap_copy (dst, src); | 472 bitmap_copy (dst, src); |
475 return dst; | 473 return dst; |
476 } | 474 } |
477 | 475 |
569 0, index, bi) | 567 0, index, bi) |
570 { | 568 { |
571 fprintf(dump_file, "%s ", | 569 fprintf(dump_file, "%s ", |
572 get_static_name (index)); | 570 get_static_name (index)); |
573 } | 571 } |
574 if (l->calls_read_all) | |
575 fprintf (dump_file, "\n calls read all: "); | |
576 if (l->calls_write_all) | |
577 fprintf (dump_file, "\n calls read all: "); | |
578 } | 572 } |
579 } | 573 } |
580 | 574 |
581 /* Set READ_ALL/WRITE_ALL based on DECL flags. */ | 575 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */ |
582 | 576 |
583 static void | 577 static void |
584 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all) | 578 read_write_all_from_decl (struct cgraph_node *node, bool * read_all, |
585 { | 579 bool * write_all) |
580 { | |
581 tree decl = node->decl; | |
586 int flags = flags_from_decl_or_type (decl); | 582 int flags = flags_from_decl_or_type (decl); |
587 if (flags & ECF_CONST) | 583 if ((flags & ECF_LEAF) |
584 && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | |
588 ; | 585 ; |
589 else if (flags & ECF_PURE) | 586 else if (flags & ECF_CONST) |
590 *read_all = true; | 587 ; |
588 else if ((flags & ECF_PURE) | |
589 || cgraph_node_cannot_return (node)) | |
590 { | |
591 *read_all = true; | |
592 if (dump_file && (dump_flags & TDF_DETAILS)) | |
593 fprintf (dump_file, " %s/%i -> read all\n", | |
594 cgraph_node_name (node), node->uid); | |
595 } | |
591 else | 596 else |
592 { | 597 { |
593 /* TODO: To be able to produce sane results, we should also handle | 598 /* TODO: To be able to produce sane results, we should also handle |
594 common builtins, in particular throw. */ | 599 common builtins, in particular throw. */ |
595 *read_all = true; | 600 *read_all = true; |
596 /* When function does not return, it is safe to ignore anythign it writes | 601 *write_all = true; |
597 to, because the effect will never happen. */ | 602 if (dump_file && (dump_flags & TDF_DETAILS)) |
598 if ((flags & (ECF_NOTHROW | ECF_NORETURN)) | 603 fprintf (dump_file, " %s/%i -> read all, write all\n", |
599 != (ECF_NOTHROW | ECF_NORETURN)) | 604 cgraph_node_name (node), node->uid); |
600 *write_all = true; | |
601 } | 605 } |
602 } | 606 } |
603 | 607 |
604 /* Produce the global information by preforming a transitive closure | 608 /* Produce the global information by preforming a transitive closure |
605 on the local information that was produced by ipa_analyze_function */ | 609 on the local information that was produced by ipa_analyze_function */ |
631 for (i = 0; i < order_pos; i++ ) | 635 for (i = 0; i < order_pos; i++ ) |
632 { | 636 { |
633 ipa_reference_vars_info_t node_info; | 637 ipa_reference_vars_info_t node_info; |
634 ipa_reference_global_vars_info_t node_g; | 638 ipa_reference_global_vars_info_t node_g; |
635 ipa_reference_local_vars_info_t node_l; | 639 ipa_reference_local_vars_info_t node_l; |
636 struct cgraph_edge *e; | 640 struct cgraph_edge *e, *ie; |
637 | 641 |
638 bool read_all; | 642 bool read_all; |
639 bool write_all; | 643 bool write_all; |
640 struct ipa_dfs_info * w_info; | 644 struct ipa_dfs_info * w_info; |
641 | 645 |
642 node = order[i]; | 646 node = order[i]; |
643 node_info = get_reference_vars_info (node); | 647 node_info = get_reference_vars_info (node); |
644 if (!node_info) | 648 gcc_assert (node_info); |
645 { | 649 |
646 dump_cgraph_node (stderr, node); | 650 |
647 dump_cgraph (stderr); | 651 if (dump_file && (dump_flags & TDF_DETAILS)) |
648 gcc_unreachable (); | 652 fprintf (dump_file, "Starting cycle with %s/%i\n", |
649 } | 653 cgraph_node_name (node), node->uid); |
650 | 654 |
651 node_l = &node_info->local; | 655 node_l = &node_info->local; |
652 node_g = &node_info->global; | 656 node_g = &node_info->global; |
653 | 657 |
654 read_all = node_l->calls_read_all; | 658 read_all = false; |
655 write_all = node_l->calls_write_all; | 659 write_all = false; |
656 | 660 |
657 /* When function is overwrittable, we can not assume anything. */ | 661 /* When function is overwritable, we can not assume anything. */ |
658 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | 662 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) |
659 read_write_all_from_decl (node->decl, &read_all, &write_all); | 663 read_write_all_from_decl (node, &read_all, &write_all); |
660 | 664 |
661 for (e = node->callees; e; e = e->next_callee) | 665 for (e = node->callees; e; e = e->next_callee) |
662 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) | 666 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) |
663 read_write_all_from_decl (e->callee->decl, &read_all, &write_all); | 667 read_write_all_from_decl (e->callee, &read_all, &write_all); |
664 | 668 |
665 | 669 for (ie = node->indirect_calls; ie; ie = ie->next_callee) |
666 /* If any node in a cycle is calls_read_all or calls_write_all | 670 if (!(ie->indirect_info->ecf_flags & ECF_CONST)) |
671 { | |
672 read_all = true; | |
673 if (dump_file && (dump_flags & TDF_DETAILS)) | |
674 fprintf (dump_file, " indirect call -> read all\n"); | |
675 if (!cgraph_edge_cannot_lead_to_return (ie) | |
676 && !(ie->indirect_info->ecf_flags & ECF_PURE)) | |
677 { | |
678 if (dump_file && (dump_flags & TDF_DETAILS)) | |
679 fprintf (dump_file, " indirect call -> write all\n"); | |
680 write_all = true; | |
681 } | |
682 } | |
683 | |
684 | |
685 /* If any node in a cycle is read_all or write_all | |
667 they all are. */ | 686 they all are. */ |
668 w_info = (struct ipa_dfs_info *) node->aux; | 687 w_info = (struct ipa_dfs_info *) node->aux; |
669 w = w_info->next_cycle; | 688 w = w_info->next_cycle; |
670 while (w) | 689 while (w && (!read_all || !write_all)) |
671 { | 690 { |
672 ipa_reference_local_vars_info_t w_l = | 691 if (dump_file && (dump_flags & TDF_DETAILS)) |
673 &get_reference_vars_info (w)->local; | 692 fprintf (dump_file, " Visiting %s/%i\n", |
674 | 693 cgraph_node_name (w), w->uid); |
675 /* When function is overwrittable, we can not assume anything. */ | 694 /* When function is overwritable, we can not assume anything. */ |
676 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) | 695 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) |
677 read_write_all_from_decl (w->decl, &read_all, &write_all); | 696 read_write_all_from_decl (w, &read_all, &write_all); |
678 | 697 |
679 for (e = w->callees; e; e = e->next_callee) | 698 for (e = w->callees; e; e = e->next_callee) |
680 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) | 699 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) |
681 read_write_all_from_decl (e->callee->decl, &read_all, &write_all); | 700 read_write_all_from_decl (e->callee, &read_all, &write_all); |
682 | 701 |
683 read_all |= w_l->calls_read_all; | 702 for (ie = w->indirect_calls; ie; ie = ie->next_callee) |
684 write_all |= w_l->calls_write_all; | 703 if (!(ie->indirect_info->ecf_flags & ECF_CONST)) |
704 { | |
705 read_all = true; | |
706 if (dump_file && (dump_flags & TDF_DETAILS)) | |
707 fprintf (dump_file, " indirect call -> read all\n"); | |
708 if (!cgraph_edge_cannot_lead_to_return (ie) | |
709 && !(ie->indirect_info->ecf_flags & ECF_PURE)) | |
710 { | |
711 write_all = true; | |
712 if (dump_file && (dump_flags & TDF_DETAILS)) | |
713 fprintf (dump_file, " indirect call -> write all\n"); | |
714 } | |
715 } | |
685 | 716 |
686 w_info = (struct ipa_dfs_info *) w->aux; | 717 w_info = (struct ipa_dfs_info *) w->aux; |
687 w = w_info->next_cycle; | 718 w = w_info->next_cycle; |
688 } | 719 } |
689 | 720 |
707 } | 738 } |
708 | 739 |
709 propagate_bits (node_g, node); | 740 propagate_bits (node_g, node); |
710 w_info = (struct ipa_dfs_info *) node->aux; | 741 w_info = (struct ipa_dfs_info *) node->aux; |
711 w = w_info->next_cycle; | 742 w = w_info->next_cycle; |
712 while (w) | 743 while (w && (!read_all || !write_all)) |
713 { | 744 { |
714 ipa_reference_vars_info_t w_ri = | 745 ipa_reference_vars_info_t w_ri = |
715 get_reference_vars_info (w); | 746 get_reference_vars_info (w); |
716 ipa_reference_local_vars_info_t w_l = &w_ri->local; | 747 ipa_reference_local_vars_info_t w_l = &w_ri->local; |
748 int flags = flags_from_decl_or_type (w->decl); | |
717 | 749 |
718 /* These global bitmaps are initialized from the local info | 750 /* These global bitmaps are initialized from the local info |
719 of all of the nodes in the region. However there is no | 751 of all of the nodes in the region. However there is no |
720 need to do any work if the bitmaps were set to | 752 need to do any work if the bitmaps were set to |
721 all_module_statics. */ | 753 all_module_statics. */ |
722 if (!read_all) | 754 if (!read_all && !(flags & ECF_CONST)) |
723 bitmap_ior_into (node_g->statics_read, | 755 bitmap_ior_into (node_g->statics_read, |
724 w_l->statics_read); | 756 w_l->statics_read); |
725 if (!write_all) | 757 if (!write_all |
758 && !(flags & ECF_PURE) | |
759 && !cgraph_node_cannot_return (w)) | |
726 bitmap_ior_into (node_g->statics_written, | 760 bitmap_ior_into (node_g->statics_written, |
727 w_l->statics_written); | 761 w_l->statics_written); |
728 propagate_bits (node_g, w); | 762 propagate_bits (node_g, w); |
729 w_info = (struct ipa_dfs_info *) w->aux; | 763 w_info = (struct ipa_dfs_info *) w->aux; |
730 w = w_info->next_cycle; | 764 w = w_info->next_cycle; |
843 | 877 |
844 if (!node->analyzed) | 878 if (!node->analyzed) |
845 continue; | 879 continue; |
846 | 880 |
847 node_info = get_reference_vars_info (node); | 881 node_info = get_reference_vars_info (node); |
848 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE) | 882 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE |
883 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)) | |
849 { | 884 { |
850 node_g = &node_info->global; | 885 node_g = &node_info->global; |
851 | 886 |
852 opt = XCNEW (struct ipa_reference_optimization_summary_d); | 887 opt = XCNEW (struct ipa_reference_optimization_summary_d); |
853 set_reference_optimization_summary (node, opt); | 888 set_reference_optimization_summary (node, opt); |
854 | 889 |
855 /* Create the complimentary sets. */ | 890 /* Create the complimentary sets. */ |
856 opt->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack); | 891 |
857 opt->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack); | 892 if (bitmap_empty_p (node_g->statics_read)) |
858 | 893 opt->statics_not_read = all_module_statics; |
859 if (node_g->statics_read != all_module_statics) | 894 else |
860 bitmap_and_compl (opt->statics_not_read, | 895 { |
861 all_module_statics, | 896 opt->statics_not_read |
862 node_g->statics_read); | 897 = BITMAP_ALLOC (&optimization_summary_obstack); |
863 | 898 if (node_g->statics_read != all_module_statics) |
864 if (node_g->statics_written | 899 bitmap_and_compl (opt->statics_not_read, |
865 != all_module_statics) | 900 all_module_statics, |
866 bitmap_and_compl (opt->statics_not_written, | 901 node_g->statics_read); |
867 all_module_statics, | 902 } |
868 node_g->statics_written); | 903 |
904 if (bitmap_empty_p (node_g->statics_written)) | |
905 opt->statics_not_written = all_module_statics; | |
906 else | |
907 { | |
908 opt->statics_not_written | |
909 = BITMAP_ALLOC (&optimization_summary_obstack); | |
910 if (node_g->statics_written != all_module_statics) | |
911 bitmap_and_compl (opt->statics_not_written, | |
912 all_module_statics, | |
913 node_g->statics_written); | |
914 } | |
869 } | 915 } |
870 if (node_info) | 916 if (node_info) |
871 free (node_info); | 917 free (node_info); |
872 if (node->aux) | 918 if (node->aux) |
873 { | 919 { |
882 VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector); | 928 VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector); |
883 ipa_reference_vars_vector = NULL; | 929 ipa_reference_vars_vector = NULL; |
884 if (dump_file) | 930 if (dump_file) |
885 splay_tree_delete (reference_vars_to_consider); | 931 splay_tree_delete (reference_vars_to_consider); |
886 reference_vars_to_consider = NULL; | 932 reference_vars_to_consider = NULL; |
887 all_module_statics = NULL; | |
888 return 0; | 933 return 0; |
889 } | 934 } |
890 | 935 |
891 /* Return true if we need to write summary of NODE. */ | 936 /* Return true if we need to write summary of NODE. */ |
892 | 937 |
921 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics)) | 966 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics)) |
922 return false; | 967 return false; |
923 return true; | 968 return true; |
924 } | 969 } |
925 | 970 |
926 /* Stream out BITS<RANS_STATICS as list of decls to OB. */ | 971 /* Stream out BITS<RANS_STATICS as list of decls to OB. |
972 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS | |
973 or -1. When it is positive, just output -1 when | |
974 BITS<RANS_STATICS == BITS<RANS_STATICS. */ | |
927 | 975 |
928 static void | 976 static void |
929 stream_out_bitmap (struct lto_simple_output_block *ob, | 977 stream_out_bitmap (struct lto_simple_output_block *ob, |
930 bitmap bits, bitmap ltrans_statics) | 978 bitmap bits, bitmap ltrans_statics, |
931 { | 979 int ltrans_statics_bitcount) |
932 unsigned int count = 0; | 980 { |
981 int count = 0; | |
933 unsigned int index; | 982 unsigned int index; |
934 bitmap_iterator bi; | 983 bitmap_iterator bi; |
984 if (bits == all_module_statics) | |
985 { | |
986 lto_output_sleb128_stream (ob->main_stream, -1); | |
987 return; | |
988 } | |
935 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) | 989 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) |
936 count ++; | 990 count ++; |
937 lto_output_uleb128_stream (ob->main_stream, count); | 991 if (count == ltrans_statics_bitcount) |
992 { | |
993 lto_output_sleb128_stream (ob->main_stream, -1); | |
994 return; | |
995 } | |
996 lto_output_sleb128_stream (ob->main_stream, count); | |
938 if (!count) | 997 if (!count) |
939 return; | 998 return; |
940 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) | 999 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) |
941 { | 1000 { |
942 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value; | 1001 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value; |
949 static void | 1008 static void |
950 ipa_reference_write_optimization_summary (cgraph_node_set set, | 1009 ipa_reference_write_optimization_summary (cgraph_node_set set, |
951 varpool_node_set vset) | 1010 varpool_node_set vset) |
952 { | 1011 { |
953 struct cgraph_node *node; | 1012 struct cgraph_node *node; |
954 struct varpool_node *vnode; | |
955 struct lto_simple_output_block *ob | 1013 struct lto_simple_output_block *ob |
956 = lto_create_simple_output_block (LTO_section_ipa_reference); | 1014 = lto_create_simple_output_block (LTO_section_ipa_reference); |
957 unsigned int count = 0; | 1015 unsigned int count = 0; |
1016 int ltrans_statics_bitcount = 0; | |
958 lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; | 1017 lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; |
1018 lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; | |
959 bitmap ltrans_statics = BITMAP_ALLOC (NULL); | 1019 bitmap ltrans_statics = BITMAP_ALLOC (NULL); |
1020 int i; | |
960 | 1021 |
961 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); | 1022 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); |
962 | 1023 |
963 /* See what variables we are interested in. */ | 1024 /* See what variables we are interested in. */ |
964 for (vnode = varpool_nodes; vnode; vnode = vnode->next) | 1025 for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) |
965 if (referenced_from_this_partition_p (&vnode->ref_list, set, vset)) | 1026 { |
1027 struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i); | |
1028 if (!vnode->externally_visible | |
1029 && vnode->analyzed | |
1030 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl)) | |
1031 && referenced_from_this_partition_p (&vnode->ref_list, set, vset)) | |
1032 { | |
1033 tree decl = vnode->decl; | |
1034 bitmap_set_bit (ltrans_statics, DECL_UID (decl)); | |
1035 splay_tree_insert (reference_vars_to_consider, | |
1036 DECL_UID (decl), (splay_tree_value)decl); | |
1037 ltrans_statics_bitcount ++; | |
1038 } | |
1039 } | |
1040 | |
1041 | |
1042 if (ltrans_statics_bitcount) | |
1043 for (i = 0; i < lto_cgraph_encoder_size (encoder); i++) | |
1044 if (write_node_summary_p (lto_cgraph_encoder_deref (encoder, i), | |
1045 set, vset, ltrans_statics)) | |
1046 count++; | |
1047 | |
1048 lto_output_uleb128_stream (ob->main_stream, count); | |
1049 if (count) | |
1050 stream_out_bitmap (ob, ltrans_statics, ltrans_statics, | |
1051 -1); | |
1052 | |
1053 /* Process all of the functions. */ | |
1054 if (ltrans_statics_bitcount) | |
1055 for (i = 0; i < lto_cgraph_encoder_size (encoder); i++) | |
966 { | 1056 { |
967 tree decl = vnode->decl; | 1057 node = lto_cgraph_encoder_deref (encoder, i); |
968 if (is_proper_for_analysis (decl)) | 1058 if (write_node_summary_p (node, set, vset, ltrans_statics)) |
969 { | 1059 { |
970 bitmap_set_bit (ltrans_statics, DECL_UID (decl)); | 1060 ipa_reference_optimization_summary_t info; |
971 splay_tree_insert (reference_vars_to_consider, | 1061 int node_ref; |
972 DECL_UID (decl), (splay_tree_value)decl); | 1062 |
1063 info = get_reference_optimization_summary (node); | |
1064 node_ref = lto_cgraph_encoder_encode (encoder, node); | |
1065 lto_output_uleb128_stream (ob->main_stream, node_ref); | |
1066 | |
1067 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics, | |
1068 ltrans_statics_bitcount); | |
1069 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics, | |
1070 ltrans_statics_bitcount); | |
973 } | 1071 } |
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 } | 1072 } |
996 BITMAP_FREE (ltrans_statics); | 1073 BITMAP_FREE (ltrans_statics); |
997 lto_destroy_simple_output_block (ob); | 1074 lto_destroy_simple_output_block (ob); |
998 splay_tree_delete (reference_vars_to_consider); | 1075 splay_tree_delete (reference_vars_to_consider); |
999 } | 1076 } |
1011 | 1088 |
1012 node_removal_hook_holder = | 1089 node_removal_hook_holder = |
1013 cgraph_add_node_removal_hook (&remove_node_data, NULL); | 1090 cgraph_add_node_removal_hook (&remove_node_data, NULL); |
1014 node_duplication_hook_holder = | 1091 node_duplication_hook_holder = |
1015 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | 1092 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); |
1093 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); | |
1016 | 1094 |
1017 while ((file_data = file_data_vec[j++])) | 1095 while ((file_data = file_data_vec[j++])) |
1018 { | 1096 { |
1019 const char *data; | 1097 const char *data; |
1020 size_t len; | 1098 size_t len; |
1024 &data, &len); | 1102 &data, &len); |
1025 if (ib) | 1103 if (ib) |
1026 { | 1104 { |
1027 unsigned int i; | 1105 unsigned int i; |
1028 unsigned int f_count = lto_input_uleb128 (ib); | 1106 unsigned int f_count = lto_input_uleb128 (ib); |
1107 int b_count; | |
1108 if (!f_count) | |
1109 continue; | |
1110 b_count = lto_input_sleb128 (ib); | |
1111 if (dump_file) | |
1112 fprintf (dump_file, "all module statics:"); | |
1113 for (i = 0; i < (unsigned int)b_count; i++) | |
1114 { | |
1115 unsigned int var_index = lto_input_uleb128 (ib); | |
1116 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1117 var_index); | |
1118 bitmap_set_bit (all_module_statics, DECL_UID (v_decl)); | |
1119 if (dump_file) | |
1120 fprintf (dump_file, " %s", | |
1121 lang_hooks.decl_printable_name (v_decl, 2)); | |
1122 } | |
1029 | 1123 |
1030 for (i = 0; i < f_count; i++) | 1124 for (i = 0; i < f_count; i++) |
1031 { | 1125 { |
1032 unsigned int j, index; | 1126 unsigned int j, index; |
1033 struct cgraph_node *node; | 1127 struct cgraph_node *node; |
1046 fprintf (dump_file, | 1140 fprintf (dump_file, |
1047 "\nFunction name:%s/%i:\n static not read:", | 1141 "\nFunction name:%s/%i:\n static not read:", |
1048 cgraph_node_name (node), node->uid); | 1142 cgraph_node_name (node), node->uid); |
1049 | 1143 |
1050 /* Set the statics not read. */ | 1144 /* Set the statics not read. */ |
1051 v_count = lto_input_uleb128 (ib); | 1145 v_count = lto_input_sleb128 (ib); |
1052 for (j = 0; j < (unsigned int)v_count; j++) | 1146 if (v_count == -1) |
1053 { | 1147 { |
1054 unsigned int var_index = lto_input_uleb128 (ib); | 1148 info->statics_not_read = all_module_statics; |
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) | 1149 if (dump_file) |
1059 fprintf (dump_file, " %s", | 1150 fprintf (dump_file, " all module statics"); |
1060 lang_hooks.decl_printable_name (v_decl, 2)); | |
1061 } | 1151 } |
1152 else | |
1153 for (j = 0; j < (unsigned int)v_count; j++) | |
1154 { | |
1155 unsigned int var_index = lto_input_uleb128 (ib); | |
1156 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1157 var_index); | |
1158 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl)); | |
1159 if (dump_file) | |
1160 fprintf (dump_file, " %s", | |
1161 lang_hooks.decl_printable_name (v_decl, 2)); | |
1162 } | |
1062 | 1163 |
1063 if (dump_file) | 1164 if (dump_file) |
1064 fprintf (dump_file, | 1165 fprintf (dump_file, |
1065 "\n static not written:"); | 1166 "\n static not written:"); |
1066 /* Set the statics not written. */ | 1167 /* Set the statics not written. */ |
1067 v_count = lto_input_uleb128 (ib); | 1168 v_count = lto_input_sleb128 (ib); |
1068 for (j = 0; j < (unsigned int)v_count; j++) | 1169 if (v_count == -1) |
1069 { | 1170 { |
1070 unsigned int var_index = lto_input_uleb128 (ib); | 1171 info->statics_not_written = all_module_statics; |
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) | 1172 if (dump_file) |
1075 fprintf (dump_file, " %s", | 1173 fprintf (dump_file, " all module statics"); |
1076 lang_hooks.decl_printable_name (v_decl, 2)); | |
1077 } | 1174 } |
1175 else | |
1176 for (j = 0; j < (unsigned int)v_count; j++) | |
1177 { | |
1178 unsigned int var_index = lto_input_uleb128 (ib); | |
1179 tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1180 var_index); | |
1181 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl)); | |
1182 if (dump_file) | |
1183 fprintf (dump_file, " %s", | |
1184 lang_hooks.decl_printable_name (v_decl, 2)); | |
1185 } | |
1078 if (dump_file) | 1186 if (dump_file) |
1079 fprintf (dump_file, "\n"); | 1187 fprintf (dump_file, "\n"); |
1080 } | 1188 } |
1081 | 1189 |
1082 lto_destroy_simple_input_block (file_data, | 1190 lto_destroy_simple_input_block (file_data, |
1094 static bool | 1202 static bool |
1095 gate_reference (void) | 1203 gate_reference (void) |
1096 { | 1204 { |
1097 return (flag_ipa_reference | 1205 return (flag_ipa_reference |
1098 /* Don't bother doing anything if the program has errors. */ | 1206 /* Don't bother doing anything if the program has errors. */ |
1099 && !(errorcount || sorrycount)); | 1207 && !seen_error ()); |
1100 } | 1208 } |
1101 | 1209 |
1102 struct ipa_opt_pass_d pass_ipa_reference = | 1210 struct ipa_opt_pass_d pass_ipa_reference = |
1103 { | 1211 { |
1104 { | 1212 { |