00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "config.h"
00054 #include "system.h"
00055 #include "coretypes.h"
00056 #include "tm.h"
00057 #include "tree.h"
00058 #include "tree-flow.h"
00059 #include "tree-inline.h"
00060 #include "tree-pass.h"
00061 #include "langhooks.h"
00062 #include "pointer-set.h"
00063 #include "ggc.h"
00064 #include "ipa-utils.h"
00065 #include "ipa-reference.h"
00066 #include "c-common.h"
00067 #include "tree-gimple.h"
00068 #include "cgraph.h"
00069 #include "output.h"
00070 #include "flags.h"
00071 #include "timevar.h"
00072 #include "diagnostic.h"
00073 #include "langhooks.h"
00074
00075
00076
00077
00078
00079
00080
00081 static GTY((param1_is(int), param2_is(tree)))
00082 splay_tree reference_vars_to_consider;
00083
00084
00085
00086 static bitmap module_statics_escape;
00087
00088
00089
00090 static bitmap module_statics_written;
00091
00092
00093
00094
00095 static bitmap all_module_statics;
00096
00097 static struct pointer_set_t *visited_nodes;
00098
00099 static bitmap_obstack ipa_obstack;
00100
00101 enum initialization_status_t
00102 {
00103 UNINITIALIZED,
00104 RUNNING,
00105 FINISHED
00106 };
00107
00108 tree memory_identifier_string;
00109
00110
00111 static inline ipa_reference_vars_info_t
00112 get_reference_vars_info_from_cgraph (struct cgraph_node * node)
00113 {
00114 return get_function_ann (node->decl)->reference_vars_info;
00115 }
00116
00117
00118
00119 static ipa_reference_local_vars_info_t
00120 get_local_reference_vars_info (tree fn)
00121 {
00122 ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
00123
00124 if (info)
00125 return info->local;
00126 else
00127
00128 return NULL;
00129 }
00130
00131
00132
00133
00134 static ipa_reference_global_vars_info_t
00135 get_global_reference_vars_info (tree fn)
00136 {
00137 ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
00138
00139 if (info)
00140 return info->global;
00141 else
00142
00143 return NULL;
00144 }
00145
00146
00147
00148
00149
00150 bitmap
00151 ipa_reference_get_read_local (tree fn)
00152 {
00153 ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
00154 if (l)
00155 return l->statics_read;
00156 else
00157 return NULL;
00158 }
00159
00160
00161
00162
00163
00164 bitmap
00165 ipa_reference_get_written_local (tree fn)
00166 {
00167 ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
00168 if (l)
00169 return l->statics_written;
00170 else
00171 return NULL;
00172 }
00173
00174
00175
00176
00177
00178 bitmap
00179 ipa_reference_get_read_global (tree fn)
00180 {
00181 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
00182 if (g)
00183 return g->statics_read;
00184 else
00185 return NULL;
00186 }
00187
00188
00189
00190
00191
00192
00193 bitmap
00194 ipa_reference_get_written_global (tree fn)
00195 {
00196 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
00197 if (g)
00198 return g->statics_written;
00199 else
00200 return NULL;
00201 }
00202
00203
00204
00205
00206
00207 bitmap
00208 ipa_reference_get_not_read_global (tree fn)
00209 {
00210 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
00211 if (g)
00212 return g->statics_not_read;
00213 else
00214 return NULL;
00215 }
00216
00217
00218
00219
00220
00221
00222 bitmap
00223 ipa_reference_get_not_written_global (tree fn)
00224 {
00225 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
00226 if (g)
00227 return g->statics_not_written;
00228 else
00229 return NULL;
00230 }
00231
00232
00233
00234
00235
00236
00237 static inline void
00238 add_static_var (tree var)
00239 {
00240 int uid = DECL_UID (var);
00241 if (!bitmap_bit_p (all_module_statics, uid))
00242 {
00243 splay_tree_insert (reference_vars_to_consider,
00244 uid, (splay_tree_value)var);
00245 bitmap_set_bit (all_module_statics, uid);
00246 }
00247 }
00248
00249
00250
00251
00252 static inline bool
00253 has_proper_scope_for_analysis (tree t)
00254 {
00255
00256
00257 if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
00258 return false;
00259
00260
00261
00262 if (TREE_THIS_VOLATILE (t))
00263 return false;
00264
00265
00266 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
00267 return false;
00268
00269 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
00270 return false;
00271
00272
00273
00274 if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
00275 add_static_var (t);
00276
00277 return true;
00278 }
00279
00280
00281
00282
00283 static void
00284 check_operand (ipa_reference_local_vars_info_t local,
00285 tree t, bool checking_write)
00286 {
00287 if (!t) return;
00288
00289 if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
00290 && (has_proper_scope_for_analysis (t)))
00291 {
00292 if (checking_write)
00293 {
00294 if (local)
00295 bitmap_set_bit (local->statics_written, DECL_UID (t));
00296
00297
00298 bitmap_set_bit (module_statics_written, DECL_UID (t));
00299 }
00300 else if (local)
00301 bitmap_set_bit (local->statics_read, DECL_UID (t));
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310 static void
00311 check_tree (ipa_reference_local_vars_info_t local, tree t, bool checking_write)
00312 {
00313 if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
00314 return;
00315
00316 while (TREE_CODE (t) == REALPART_EXPR
00317 || TREE_CODE (t) == IMAGPART_EXPR
00318 || handled_component_p (t))
00319 {
00320 if (TREE_CODE (t) == ARRAY_REF)
00321 check_operand (local, TREE_OPERAND (t, 1), false);
00322 t = TREE_OPERAND (t, 0);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 if (INDIRECT_REF_P (t))
00332 check_tree (local, TREE_OPERAND (t, 0), false);
00333
00334 if (SSA_VAR_P (t))
00335 check_operand (local, t, checking_write);
00336 }
00337
00338
00339
00340 static void
00341 look_for_address_of (tree t)
00342 {
00343 if (TREE_CODE (t) == ADDR_EXPR)
00344 {
00345 tree x = get_base_var (t);
00346 if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL)
00347 if (has_proper_scope_for_analysis (x))
00348 bitmap_set_bit (module_statics_escape, DECL_UID (x));
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357 static void
00358 check_rhs_var (ipa_reference_local_vars_info_t local, tree t)
00359 {
00360 look_for_address_of (t);
00361
00362 if (local == NULL)
00363 return;
00364
00365 check_tree(local, t, false);
00366 }
00367
00368
00369
00370
00371
00372 static void
00373 check_lhs_var (ipa_reference_local_vars_info_t local, tree t)
00374 {
00375 if (local == NULL)
00376 return;
00377
00378 check_tree(local, t, true);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388 static void
00389 get_asm_expr_operands (ipa_reference_local_vars_info_t local, tree stmt)
00390 {
00391 int noutputs = list_length (ASM_OUTPUTS (stmt));
00392 const char **oconstraints
00393 = (const char **) alloca ((noutputs) * sizeof (const char *));
00394 int i;
00395 tree link;
00396 const char *constraint;
00397 bool allows_mem, allows_reg, is_inout;
00398
00399 for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
00400 {
00401 oconstraints[i] = constraint
00402 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
00403 parse_output_constraint (&constraint, i, 0, 0,
00404 &allows_mem, &allows_reg, &is_inout);
00405
00406 check_lhs_var (local, TREE_VALUE (link));
00407 }
00408
00409 for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
00410 {
00411 constraint
00412 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
00413 parse_input_constraint (&constraint, 0, 0, noutputs, 0,
00414 oconstraints, &allows_mem, &allows_reg);
00415
00416 check_rhs_var (local, TREE_VALUE (link));
00417 }
00418
00419 for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
00420 if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1)
00421 {
00422
00423 local->calls_read_all = true;
00424 local->calls_write_all = true;
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435 static void
00436 check_call (ipa_reference_local_vars_info_t local, tree call_expr)
00437 {
00438 int flags = call_expr_flags (call_expr);
00439 tree operand_list = TREE_OPERAND (call_expr, 1);
00440 tree operand;
00441 tree callee_t = get_callee_fndecl (call_expr);
00442 enum availability avail = AVAIL_NOT_AVAILABLE;
00443
00444 for (operand = operand_list;
00445 operand != NULL_TREE;
00446 operand = TREE_CHAIN (operand))
00447 {
00448 tree argument = TREE_VALUE (operand);
00449 check_rhs_var (local, argument);
00450 }
00451
00452 if (callee_t)
00453 {
00454 struct cgraph_node* callee = cgraph_node(callee_t);
00455 avail = cgraph_function_body_availability (callee);
00456 }
00457
00458 if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
00459 if (local)
00460 {
00461 if (flags & ECF_PURE)
00462 local->calls_read_all = true;
00463 else
00464 {
00465 local->calls_read_all = true;
00466 local->calls_write_all = true;
00467 }
00468 }
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478 static tree
00479 scan_for_static_refs (tree *tp,
00480 int *walk_subtrees,
00481 void *data)
00482 {
00483 struct cgraph_node *fn = data;
00484 tree t = *tp;
00485 ipa_reference_local_vars_info_t local = NULL;
00486 if (fn)
00487 local = get_reference_vars_info_from_cgraph (fn)->local;
00488
00489 switch (TREE_CODE (t))
00490 {
00491 case VAR_DECL:
00492 if (DECL_INITIAL (t))
00493 walk_tree (&DECL_INITIAL (t), scan_for_static_refs, fn, visited_nodes);
00494 *walk_subtrees = 0;
00495 break;
00496
00497 case MODIFY_EXPR:
00498 {
00499
00500 tree lhs = TREE_OPERAND (t, 0);
00501 tree rhs = TREE_OPERAND (t, 1);
00502 check_lhs_var (local, lhs);
00503
00504
00505
00506
00507 switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
00508 {
00509 case tcc_binary:
00510 case tcc_comparison:
00511 {
00512 tree op0 = TREE_OPERAND (rhs, 0);
00513 tree op1 = TREE_OPERAND (rhs, 1);
00514 check_rhs_var (local, op0);
00515 check_rhs_var (local, op1);
00516 }
00517 break;
00518 case tcc_unary:
00519 {
00520 tree op0 = TREE_OPERAND (rhs, 0);
00521 check_rhs_var (local, op0);
00522 }
00523
00524 break;
00525 case tcc_reference:
00526 check_rhs_var (local, rhs);
00527 break;
00528 case tcc_declaration:
00529 check_rhs_var (local, rhs);
00530 break;
00531 case tcc_expression:
00532 switch (TREE_CODE (rhs))
00533 {
00534 case ADDR_EXPR:
00535 check_rhs_var (local, rhs);
00536 break;
00537 case CALL_EXPR:
00538 check_call (local, rhs);
00539 break;
00540 default:
00541 break;
00542 }
00543 break;
00544 default:
00545 break;
00546 }
00547 *walk_subtrees = 0;
00548 }
00549 break;
00550
00551 case ADDR_EXPR:
00552
00553
00554 check_rhs_var (local, t);
00555 *walk_subtrees = 0;
00556 break;
00557
00558 case LABEL_EXPR:
00559 if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
00560 {
00561
00562 local->calls_read_all = true;
00563 local->calls_write_all = true;
00564 }
00565 break;
00566
00567 case CALL_EXPR:
00568 check_call (local, t);
00569 *walk_subtrees = 0;
00570 break;
00571
00572 case ASM_EXPR:
00573 get_asm_expr_operands (local, t);
00574 *walk_subtrees = 0;
00575 break;
00576
00577 default:
00578 break;
00579 }
00580 return NULL;
00581 }
00582
00583
00584
00585 static tree
00586 get_static_decl (int index)
00587 {
00588 splay_tree_node stn =
00589 splay_tree_lookup (reference_vars_to_consider, index);
00590 if (stn)
00591 return (tree)stn->value;
00592 return NULL;
00593 }
00594
00595
00596
00597
00598 static const char *
00599 get_static_name (int index)
00600 {
00601 splay_tree_node stn =
00602 splay_tree_lookup (reference_vars_to_consider, index);
00603 if (stn)
00604 return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
00605 return NULL;
00606 }
00607
00608
00609
00610
00611
00612 static void
00613 propagate_bits (struct cgraph_node *x)
00614 {
00615 ipa_reference_vars_info_t x_info = get_reference_vars_info_from_cgraph (x);
00616 ipa_reference_global_vars_info_t x_global = x_info->global;
00617
00618 struct cgraph_edge *e;
00619 for (e = x->callees; e; e = e->next_callee)
00620 {
00621 struct cgraph_node *y = e->callee;
00622
00623
00624 y = cgraph_master_clone (y);
00625 if (y)
00626 {
00627 if (get_reference_vars_info_from_cgraph (y))
00628 {
00629 ipa_reference_vars_info_t y_info = get_reference_vars_info_from_cgraph (y);
00630 ipa_reference_global_vars_info_t y_global = y_info->global;
00631
00632 if (x_global->statics_read
00633 != all_module_statics)
00634 {
00635 if (y_global->statics_read
00636 == all_module_statics)
00637 {
00638 BITMAP_FREE (x_global->statics_read);
00639 x_global->statics_read
00640 = all_module_statics;
00641 }
00642
00643
00644 else if (x_global->statics_read
00645 != y_global->statics_read)
00646 bitmap_ior_into (x_global->statics_read,
00647 y_global->statics_read);
00648 }
00649
00650 if (x_global->statics_written
00651 != all_module_statics)
00652 {
00653 if (y_global->statics_written
00654 == all_module_statics)
00655 {
00656 BITMAP_FREE (x_global->statics_written);
00657 x_global->statics_written
00658 = all_module_statics;
00659 }
00660
00661
00662 else if (x_global->statics_written
00663 != y_global->statics_written)
00664 bitmap_ior_into (x_global->statics_written,
00665 y_global->statics_written);
00666 }
00667 }
00668 else
00669 {
00670 gcc_unreachable ();
00671 }
00672 }
00673 }
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 static void
00685 merge_callee_local_info (struct cgraph_node *target,
00686 struct cgraph_node *x)
00687 {
00688 struct cgraph_edge *e;
00689 ipa_reference_local_vars_info_t x_l =
00690 get_reference_vars_info_from_cgraph (target)->local;
00691
00692
00693 struct ipa_dfs_info *node_info = x->aux;
00694
00695 if (node_info->aux)
00696 return;
00697
00698 node_info->aux = x;
00699
00700 for (e = x->callees; e; e = e->next_callee)
00701 {
00702 struct cgraph_node *y = e->callee;
00703 if (y->global.inlined_to)
00704 {
00705 ipa_reference_vars_info_t y_info;
00706 ipa_reference_local_vars_info_t y_l;
00707 struct cgraph_node* orig_y = y;
00708
00709 y = cgraph_master_clone (y);
00710 if (y)
00711 {
00712 y_info = get_reference_vars_info_from_cgraph (y);
00713 y_l = y_info->local;
00714 if (x_l != y_l)
00715 {
00716 bitmap_ior_into (x_l->statics_read,
00717 y_l->statics_read);
00718 bitmap_ior_into (x_l->statics_written,
00719 y_l->statics_written);
00720 }
00721 x_l->calls_read_all |= y_l->calls_read_all;
00722 x_l->calls_write_all |= y_l->calls_write_all;
00723 merge_callee_local_info (target, y);
00724 }
00725 else
00726 {
00727 fprintf(stderr, "suspect inlining of ");
00728 dump_cgraph_node (stderr, orig_y);
00729 fprintf(stderr, "\ninto ");
00730 dump_cgraph_node (stderr, target);
00731 dump_cgraph (stderr);
00732 gcc_assert(false);
00733 }
00734 }
00735 }
00736
00737 node_info->aux = NULL;
00738 }
00739
00740
00741
00742 static void
00743 ipa_init (void)
00744 {
00745 struct cgraph_node *node;
00746 memory_identifier_string = build_string(7, "memory");
00747
00748 reference_vars_to_consider =
00749 splay_tree_new_ggc (splay_tree_compare_ints);
00750
00751 bitmap_obstack_initialize (&ipa_obstack);
00752 module_statics_escape = BITMAP_ALLOC (&ipa_obstack);
00753 module_statics_written = BITMAP_ALLOC (&ipa_obstack);
00754 all_module_statics = BITMAP_ALLOC (&ipa_obstack);
00755
00756
00757 for (node = cgraph_nodes; node; node = node->next)
00758 has_proper_scope_for_analysis (node->decl);
00759
00760
00761
00762
00763
00764 visited_nodes = pointer_set_create ();
00765 }
00766
00767
00768
00769
00770
00771
00772
00773 static void
00774 analyze_variable (struct cgraph_varpool_node *vnode)
00775 {
00776 tree global = vnode->decl;
00777 if (TREE_CODE (global) == VAR_DECL)
00778 {
00779 if (DECL_INITIAL (global))
00780 walk_tree (&DECL_INITIAL (global), scan_for_static_refs,
00781 NULL, visited_nodes);
00782 }
00783 else gcc_unreachable ();
00784 }
00785
00786
00787
00788
00789 static void
00790 analyze_function (struct cgraph_node *fn)
00791 {
00792 ipa_reference_vars_info_t info
00793 = xcalloc (1, sizeof (struct ipa_reference_vars_info_d));
00794 ipa_reference_local_vars_info_t l
00795 = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d));
00796 tree decl = fn->decl;
00797
00798
00799 get_function_ann (fn->decl)->reference_vars_info = info;
00800
00801 info->local = l;
00802 l->statics_read = BITMAP_ALLOC (&ipa_obstack);
00803 l->statics_written = BITMAP_ALLOC (&ipa_obstack);
00804
00805 if (dump_file)
00806 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
00807
00808 {
00809 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
00810 basic_block this_block;
00811
00812 FOR_EACH_BB_FN (this_block, this_cfun)
00813 {
00814 block_stmt_iterator bsi;
00815 for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
00816 walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs,
00817 fn, visited_nodes);
00818 }
00819 }
00820
00821
00822 if (DECL_STRUCT_FUNCTION (decl))
00823 {
00824 tree step;
00825 for (step = DECL_STRUCT_FUNCTION (decl)->unexpanded_var_list;
00826 step;
00827 step = TREE_CHAIN (step))
00828 {
00829 tree var = TREE_VALUE (step);
00830 if (TREE_CODE (var) == VAR_DECL
00831 && DECL_INITIAL (var)
00832 && !TREE_STATIC (var))
00833 walk_tree (&DECL_INITIAL (var), scan_for_static_refs,
00834 fn, visited_nodes);
00835 }
00836 }
00837 }
00838
00839
00840
00841
00842
00843
00844 static void
00845 clean_function (struct cgraph_node *fn)
00846 {
00847 ipa_reference_vars_info_t info = get_reference_vars_info_from_cgraph (fn);
00848 ipa_reference_local_vars_info_t l = info->local;
00849 ipa_reference_global_vars_info_t g = info->global;
00850
00851 if (l)
00852 {
00853 if (l->statics_read
00854 && l->statics_read != all_module_statics)
00855 BITMAP_FREE (l->statics_read);
00856 if (l->statics_written
00857 &&l->statics_written != all_module_statics)
00858 BITMAP_FREE (l->statics_written);
00859 free (l);
00860 }
00861
00862 if (g)
00863 {
00864 if (g->statics_read
00865 && g->statics_read != all_module_statics)
00866 BITMAP_FREE (g->statics_read);
00867
00868 if (g->statics_written
00869 && g->statics_written != all_module_statics)
00870 BITMAP_FREE (g->statics_written);
00871
00872 if (g->statics_not_read
00873 && g->statics_not_read != all_module_statics)
00874 BITMAP_FREE (g->statics_not_read);
00875
00876 if (g->statics_not_written
00877 && g->statics_not_written != all_module_statics)
00878 BITMAP_FREE (g->statics_not_written);
00879 free (g);
00880 }
00881
00882
00883 free (get_function_ann (fn->decl)->reference_vars_info);
00884 get_function_ann (fn->decl)->reference_vars_info = NULL;
00885 }
00886
00887
00888
00889
00890
00891
00892 static unsigned int
00893 static_execute (void)
00894 {
00895 struct cgraph_node *node;
00896 struct cgraph_varpool_node *vnode;
00897 struct cgraph_node *w;
00898 struct cgraph_node **order =
00899 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
00900 int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true);
00901 int i;
00902
00903 ipa_init ();
00904
00905
00906 for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
00907 analyze_variable (vnode);
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 for (node = cgraph_nodes; node; node = node->next)
00921 if (node->analyzed
00922 && (cgraph_is_master_clone (node)
00923 || (cgraph_function_body_availability (node)
00924 == AVAIL_OVERWRITABLE)))
00925 analyze_function (node);
00926
00927 pointer_set_destroy (visited_nodes);
00928 visited_nodes = NULL;
00929 if (dump_file)
00930 dump_cgraph (dump_file);
00931
00932
00933
00934 {
00935 unsigned int index;
00936 bitmap_iterator bi;
00937 bitmap module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
00938 bitmap module_statics_const = BITMAP_ALLOC (&ipa_obstack);
00939 bitmap bm_temp = BITMAP_ALLOC (&ipa_obstack);
00940
00941 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
00942 {
00943 splay_tree_remove (reference_vars_to_consider, index);
00944 }
00945
00946 bitmap_and_compl_into (all_module_statics,
00947 module_statics_escape);
00948
00949 bitmap_and_compl (module_statics_readonly, all_module_statics,
00950 module_statics_written);
00951
00952
00953
00954 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
00955 {
00956 tree var = get_static_decl (index);
00957 TREE_ADDRESSABLE (var) = 0;
00958 if (dump_file)
00959 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
00960 get_static_name (index));
00961 }
00962
00963
00964
00965
00966
00967 bitmap_and_compl (module_statics_readonly, all_module_statics,
00968 module_statics_written);
00969 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
00970 {
00971 tree var = get_static_decl (index);
00972
00973
00974
00975 if (TREE_CODE (var) == FUNCTION_DECL)
00976 continue;
00977
00978
00979
00980
00981 if (DECL_SECTION_NAME (var) == NULL_TREE)
00982 {
00983 TREE_READONLY (var) = 1;
00984 if (dump_file)
00985 fprintf (dump_file, "read-only var %s\n",
00986 get_static_name (index));
00987 }
00988 if (DECL_INITIAL (var)
00989 && is_gimple_min_invariant (DECL_INITIAL (var)))
00990 {
00991 bitmap_set_bit (module_statics_const, index);
00992 if (dump_file)
00993 fprintf (dump_file, "read-only constant %s\n",
00994 get_static_name (index));
00995 }
00996 }
00997
00998 BITMAP_FREE(module_statics_escape);
00999 BITMAP_FREE(module_statics_written);
01000
01001 if (dump_file)
01002 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
01003 {
01004 fprintf (dump_file, "\nPromotable global:%s",
01005 get_static_name (index));
01006 }
01007
01008 for (i = 0; i < order_pos; i++ )
01009 {
01010 ipa_reference_local_vars_info_t l;
01011 node = order[i];
01012 l = get_reference_vars_info_from_cgraph (node)->local;
01013
01014
01015
01016
01017
01018 bitmap_and_into (l->statics_read,
01019 all_module_statics);
01020 bitmap_and_into (l->statics_written,
01021 all_module_statics);
01022 }
01023
01024 BITMAP_FREE(module_statics_readonly);
01025 BITMAP_FREE(module_statics_const);
01026 BITMAP_FREE(bm_temp);
01027 }
01028
01029 if (dump_file)
01030 {
01031 for (i = 0; i < order_pos; i++ )
01032 {
01033 unsigned int index;
01034 ipa_reference_local_vars_info_t l;
01035 bitmap_iterator bi;
01036
01037 node = order[i];
01038 l = get_reference_vars_info_from_cgraph (node)->local;
01039 fprintf (dump_file,
01040 "\nFunction name:%s/%i:",
01041 cgraph_node_name (node), node->uid);
01042 fprintf (dump_file, "\n locals read: ");
01043 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
01044 0, index, bi)
01045 {
01046 fprintf (dump_file, "%s ",
01047 get_static_name (index));
01048 }
01049 fprintf (dump_file, "\n locals written: ");
01050 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
01051 0, index, bi)
01052 {
01053 fprintf(dump_file, "%s ",
01054 get_static_name (index));
01055 }
01056 }
01057 }
01058
01059
01060
01061
01062
01063 order_pos = ipa_utils_reduced_inorder (order, true, true);
01064 if (dump_file)
01065 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
01066
01067 for (i = 0; i < order_pos; i++ )
01068 {
01069 ipa_reference_vars_info_t node_info;
01070 ipa_reference_global_vars_info_t node_g =
01071 xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d));
01072 ipa_reference_local_vars_info_t node_l;
01073
01074 bool read_all;
01075 bool write_all;
01076 struct ipa_dfs_info * w_info;
01077
01078 node = order[i];
01079 node_info = get_reference_vars_info_from_cgraph (node);
01080 if (!node_info)
01081 {
01082 dump_cgraph_node (stderr, node);
01083 dump_cgraph (stderr);
01084 gcc_unreachable ();
01085 }
01086
01087 node_info->global = node_g;
01088 node_l = node_info->local;
01089
01090 read_all = node_l->calls_read_all;
01091 write_all = node_l->calls_write_all;
01092
01093
01094
01095 w_info = node->aux;
01096 w = w_info->next_cycle;
01097 while (w)
01098 {
01099 ipa_reference_local_vars_info_t w_l =
01100 get_reference_vars_info_from_cgraph (w)->local;
01101 read_all |= w_l->calls_read_all;
01102 write_all |= w_l->calls_write_all;
01103
01104 w_info = w->aux;
01105 w = w_info->next_cycle;
01106 }
01107
01108
01109 if (read_all)
01110 node_g->statics_read = all_module_statics;
01111 else
01112 {
01113 node_g->statics_read = BITMAP_ALLOC (&ipa_obstack);
01114 bitmap_copy (node_g->statics_read,
01115 node_l->statics_read);
01116 }
01117
01118 if (write_all)
01119 node_g->statics_written = all_module_statics;
01120 else
01121 {
01122 node_g->statics_written = BITMAP_ALLOC (&ipa_obstack);
01123 bitmap_copy (node_g->statics_written,
01124 node_l->statics_written);
01125 }
01126
01127 w_info = node->aux;
01128 w = w_info->next_cycle;
01129 while (w)
01130 {
01131 ipa_reference_vars_info_t w_ri =
01132 get_reference_vars_info_from_cgraph (w);
01133 ipa_reference_local_vars_info_t w_l = w_ri->local;
01134
01135
01136 w_ri->global = node_g;
01137
01138
01139
01140
01141
01142 if (!read_all)
01143 bitmap_ior_into (node_g->statics_read,
01144 w_l->statics_read);
01145 if (!write_all)
01146 bitmap_ior_into (node_g->statics_written,
01147 w_l->statics_written);
01148 w_info = w->aux;
01149 w = w_info->next_cycle;
01150 }
01151
01152 w = node;
01153 while (w)
01154 {
01155 propagate_bits (w);
01156 w_info = w->aux;
01157 w = w_info->next_cycle;
01158 }
01159 }
01160
01161
01162
01163
01164
01165
01166
01167 for (i = 0; i < order_pos; i++ )
01168 {
01169 struct ipa_dfs_info * w_info;
01170 node = order[i];
01171 merge_callee_local_info (node, node);
01172
01173 w_info = node->aux;
01174 w = w_info->next_cycle;
01175 while (w)
01176 {
01177 merge_callee_local_info (w, w);
01178 w_info = w->aux;
01179 w = w_info->next_cycle;
01180 }
01181 }
01182
01183 if (dump_file)
01184 {
01185 for (i = 0; i < order_pos; i++ )
01186 {
01187 ipa_reference_vars_info_t node_info;
01188 ipa_reference_global_vars_info_t node_g;
01189 ipa_reference_local_vars_info_t node_l;
01190 unsigned int index;
01191 bitmap_iterator bi;
01192 struct ipa_dfs_info * w_info;
01193
01194 node = order[i];
01195 node_info = get_reference_vars_info_from_cgraph (node);
01196 node_g = node_info->global;
01197 node_l = node_info->local;
01198 fprintf (dump_file,
01199 "\nFunction name:%s/%i:",
01200 cgraph_node_name (node), node->uid);
01201 fprintf (dump_file, "\n locals read: ");
01202 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
01203 0, index, bi)
01204 {
01205 fprintf (dump_file, "%s ",
01206 get_static_name (index));
01207 }
01208 fprintf (dump_file, "\n locals written: ");
01209 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
01210 0, index, bi)
01211 {
01212 fprintf(dump_file, "%s ",
01213 get_static_name (index));
01214 }
01215
01216 w_info = node->aux;
01217 w = w_info->next_cycle;
01218 while (w)
01219 {
01220 ipa_reference_vars_info_t w_ri =
01221 get_reference_vars_info_from_cgraph (w);
01222 ipa_reference_local_vars_info_t w_l = w_ri->local;
01223 fprintf (dump_file, "\n next cycle: %s/%i ",
01224 cgraph_node_name (w), w->uid);
01225 fprintf (dump_file, "\n locals read: ");
01226 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
01227 0, index, bi)
01228 {
01229 fprintf (dump_file, "%s ",
01230 get_static_name (index));
01231 }
01232
01233 fprintf (dump_file, "\n locals written: ");
01234 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
01235 0, index, bi)
01236 {
01237 fprintf(dump_file, "%s ",
01238 get_static_name (index));
01239 }
01240
01241
01242 w_info = w->aux;
01243 w = w_info->next_cycle;
01244 }
01245 fprintf (dump_file, "\n globals read: ");
01246 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
01247 0, index, bi)
01248 {
01249 fprintf (dump_file, "%s ",
01250 get_static_name (index));
01251 }
01252 fprintf (dump_file, "\n globals written: ");
01253 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
01254 0, index, bi)
01255 {
01256 fprintf (dump_file, "%s ",
01257 get_static_name (index));
01258 }
01259 }
01260 }
01261
01262
01263 for (i = 0; i < order_pos; i++ )
01264 {
01265 ipa_reference_vars_info_t node_info;
01266 ipa_reference_global_vars_info_t node_g;
01267 node = order[i];
01268 node_info = get_reference_vars_info_from_cgraph (node);
01269 node_g = node_info->global;
01270
01271
01272
01273 node_g->statics_not_read = BITMAP_ALLOC (&ipa_obstack);
01274 node_g->statics_not_written = BITMAP_ALLOC (&ipa_obstack);
01275
01276 if (node_g->statics_read != all_module_statics)
01277 {
01278 bitmap_and_compl (node_g->statics_not_read,
01279 all_module_statics,
01280 node_g->statics_read);
01281 }
01282
01283 if (node_g->statics_written
01284 != all_module_statics)
01285 bitmap_and_compl (node_g->statics_not_written,
01286 all_module_statics,
01287 node_g->statics_written);
01288 }
01289
01290 free (order);
01291
01292 for (node = cgraph_nodes; node; node = node->next)
01293 {
01294
01295
01296 if (node->aux)
01297 {
01298 free (node->aux);
01299 node->aux = NULL;
01300 }
01301
01302 if (node->analyzed
01303 && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
01304 clean_function (node);
01305 }
01306 return 0;
01307 }
01308
01309
01310 static bool
01311 gate_reference (void)
01312 {
01313 return (flag_unit_at_a_time != 0 && flag_ipa_reference
01314
01315 && !(errorcount || sorrycount));
01316 }
01317
01318 struct tree_opt_pass pass_ipa_reference =
01319 {
01320 "static-var",
01321 gate_reference,
01322 static_execute,
01323 NULL,
01324 NULL,
01325 0,
01326 TV_IPA_REFERENCE,
01327 0,
01328 0,
01329 0,
01330 0,
01331 0,
01332 0
01333 };
01334
01335 #include "gt-ipa-reference.h"
01336