00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "hard-reg-set.h"
00030 #include "basic-block.h"
00031 #include "timevar.h"
00032 #include "expr.h"
00033 #include "ggc.h"
00034 #include "langhooks.h"
00035 #include "flags.h"
00036 #include "function.h"
00037 #include "diagnostic.h"
00038 #include "tree-dump.h"
00039 #include "tree-gimple.h"
00040 #include "tree-flow.h"
00041 #include "tree-inline.h"
00042 #include "tree-pass.h"
00043 #include "tree-ssa-structalias.h"
00044 #include "convert.h"
00045 #include "params.h"
00046 #include "ipa-type-escape.h"
00047 #include "vec.h"
00048 #include "bitmap.h"
00049 #include "vecprim.h"
00050 #include "pointer-set.h"
00051
00052
00053
00054 static bitmap_obstack alias_obstack;
00055
00056
00057 bool aliases_computed_p;
00058
00059
00060
00061 struct alias_map_d
00062 {
00063
00064 tree var;
00065 HOST_WIDE_INT set;
00066
00067
00068
00069 long total_alias_vops;
00070
00071
00072
00073 unsigned int grouped_p : 1;
00074
00075
00076
00077
00078 bitmap may_aliases;
00079 };
00080
00081
00082
00083 struct alias_stats_d
00084 {
00085 unsigned int alias_queries;
00086 unsigned int alias_mayalias;
00087 unsigned int alias_noalias;
00088 unsigned int simple_queries;
00089 unsigned int simple_resolved;
00090 unsigned int tbaa_queries;
00091 unsigned int tbaa_resolved;
00092 unsigned int structnoaddress_queries;
00093 unsigned int structnoaddress_resolved;
00094 };
00095
00096
00097
00098 static struct alias_stats_d alias_stats;
00099
00100
00101 static void compute_flow_insensitive_aliasing (struct alias_info *);
00102 static void finalize_ref_all_pointers (struct alias_info *);
00103 static void dump_alias_stats (FILE *);
00104 static bool may_alias_p (tree, HOST_WIDE_INT, tree, HOST_WIDE_INT, bool);
00105 static tree create_memory_tag (tree type, bool is_type_tag);
00106 static tree get_tmt_for (tree, struct alias_info *);
00107 static tree get_nmt_for (tree);
00108 static void add_may_alias (tree, tree);
00109 static void replace_may_alias (tree, size_t, tree);
00110 static struct alias_info *init_alias_info (void);
00111 static void delete_alias_info (struct alias_info *);
00112 static void compute_flow_sensitive_aliasing (struct alias_info *);
00113 static void setup_pointers_and_addressables (struct alias_info *);
00114 static void create_global_var (void);
00115 static void maybe_create_global_var (struct alias_info *ai);
00116 static void group_aliases (struct alias_info *);
00117 static void set_pt_anything (tree ptr);
00118
00119
00120
00121
00122
00123 bitmap call_clobbered_vars;
00124
00125
00126
00127
00128
00129
00130
00131
00132 bitmap addressable_vars;
00133
00134
00135
00136
00137
00138
00139 tree global_var;
00140
00141
00142
00143 static int
00144 sort_tags_by_id (const void *pa, const void *pb)
00145 {
00146 tree a = *(tree *)pa;
00147 tree b = *(tree *)pb;
00148
00149 return DECL_UID (a) - DECL_UID (b);
00150 }
00151
00152
00153
00154
00155
00156 static void
00157 init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
00158 VEC (int, heap) **worklist2)
00159 {
00160 referenced_var_iterator rvi;
00161 tree curr;
00162
00163 FOR_EACH_REFERENCED_VAR (curr, rvi)
00164 {
00165 if (MTAG_P (curr) && is_call_clobbered (curr))
00166 {
00167 VEC_safe_push (tree, heap, *worklist, curr);
00168 VEC_safe_push (int, heap, *worklist2, var_ann (curr)->escape_mask);
00169 }
00170 }
00171 }
00172
00173
00174
00175
00176
00177 static void
00178 add_to_worklist (tree alias, VEC (tree, heap) **worklist,
00179 VEC (int, heap) **worklist2,
00180 int reason)
00181 {
00182 if (MTAG_P (alias) && !is_call_clobbered (alias))
00183 {
00184 VEC_safe_push (tree, heap, *worklist, alias);
00185 VEC_safe_push (int, heap, *worklist2, reason);
00186 }
00187 }
00188
00189
00190
00191
00192 static void
00193 mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
00194 VEC (int, heap) **worklist2)
00195 {
00196 unsigned int i;
00197 VEC (tree, gc) *ma;
00198 tree entry;
00199 var_ann_t ta = var_ann (tag);
00200
00201 if (!MTAG_P (tag))
00202 return;
00203 ma = may_aliases (tag);
00204 if (!ma)
00205 return;
00206
00207 for (i = 0; VEC_iterate (tree, ma, i, entry); i++)
00208 {
00209 if (!unmodifiable_var_p (entry))
00210 {
00211 add_to_worklist (entry, worklist, worklist2, ta->escape_mask);
00212 mark_call_clobbered (entry, ta->escape_mask);
00213 }
00214 }
00215 }
00216
00217
00218
00219
00220
00221 static void
00222 compute_tag_properties (void)
00223 {
00224 referenced_var_iterator rvi;
00225 tree tag;
00226 bool changed = true;
00227 VEC (tree, heap) *taglist = NULL;
00228
00229 FOR_EACH_REFERENCED_VAR (tag, rvi)
00230 {
00231 if (!MTAG_P (tag) || TREE_CODE (tag) == STRUCT_FIELD_TAG)
00232 continue;
00233 VEC_safe_push (tree, heap, taglist, tag);
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 qsort (VEC_address (tree, taglist),
00246 VEC_length (tree, taglist),
00247 sizeof (tree),
00248 sort_tags_by_id);
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 while (changed)
00260 {
00261 unsigned int k;
00262
00263 changed = false;
00264 for (k = 0; VEC_iterate (tree, taglist, k, tag); k++)
00265 {
00266 VEC (tree, gc) *ma;
00267 unsigned int i;
00268 tree entry;
00269 bool tagcc = is_call_clobbered (tag);
00270 bool tagglobal = MTAG_GLOBAL (tag);
00271
00272 if (tagcc && tagglobal)
00273 continue;
00274
00275 ma = may_aliases (tag);
00276 if (!ma)
00277 continue;
00278
00279 for (i = 0; VEC_iterate (tree, ma, i, entry); i++)
00280 {
00281
00282
00283 if (!tagcc && is_call_clobbered (entry))
00284 {
00285 mark_call_clobbered (tag, var_ann (entry)->escape_mask);
00286 tagcc = true;
00287 changed = true;
00288 }
00289
00290
00291 if (!tagglobal && is_global_var (entry))
00292 {
00293 MTAG_GLOBAL (tag) = true;
00294 changed = true;
00295 tagglobal = true;
00296 }
00297
00298
00299
00300 if (tagcc && tagglobal)
00301 break;
00302 }
00303 }
00304 }
00305 VEC_free (tree, heap, taglist);
00306 }
00307
00308
00309
00310
00311
00312
00313 static void
00314 set_initial_properties (struct alias_info *ai)
00315 {
00316 unsigned int i;
00317 referenced_var_iterator rvi;
00318 tree var;
00319 tree ptr;
00320
00321 FOR_EACH_REFERENCED_VAR (var, rvi)
00322 {
00323 if (is_global_var (var)
00324 && (!var_can_have_subvars (var)
00325 || get_subvars_for_var (var) == NULL))
00326 {
00327 if (!unmodifiable_var_p (var))
00328 mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
00329 }
00330 else if (TREE_CODE (var) == PARM_DECL
00331 && default_def (var)
00332 && POINTER_TYPE_P (TREE_TYPE (var)))
00333 {
00334 tree def = default_def (var);
00335 get_ptr_info (def)->value_escapes_p = 1;
00336 get_ptr_info (def)->escape_mask |= ESCAPE_IS_PARM;
00337 }
00338 }
00339
00340 for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
00341 {
00342 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
00343 var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
00344
00345 if (pi->value_escapes_p)
00346 {
00347
00348
00349 if (pi->name_mem_tag)
00350 mark_call_clobbered (pi->name_mem_tag, pi->escape_mask);
00351
00352 if (v_ann->symbol_mem_tag)
00353 mark_call_clobbered (v_ann->symbol_mem_tag, pi->escape_mask);
00354
00355 if (pi->pt_vars)
00356 {
00357 bitmap_iterator bi;
00358 unsigned int j;
00359 EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
00360 if (!unmodifiable_var_p (referenced_var (j)))
00361 mark_call_clobbered (referenced_var (j), pi->escape_mask);
00362 }
00363 }
00364
00365
00366
00367 if (pi->name_mem_tag
00368 && v_ann->symbol_mem_tag
00369 && is_call_clobbered (pi->name_mem_tag))
00370 mark_call_clobbered (v_ann->symbol_mem_tag, pi->escape_mask);
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 if ((pi->pt_global_mem || pi->pt_anything)
00381 && pi->is_dereferenced && pi->name_mem_tag)
00382 {
00383 mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
00384 MTAG_GLOBAL (pi->name_mem_tag) = true;
00385 }
00386
00387 if ((pi->pt_global_mem || pi->pt_anything)
00388 && pi->is_dereferenced
00389 && v_ann->symbol_mem_tag)
00390 {
00391 mark_call_clobbered (v_ann->symbol_mem_tag, ESCAPE_IS_GLOBAL);
00392 MTAG_GLOBAL (v_ann->symbol_mem_tag) = true;
00393 }
00394 }
00395 }
00396
00397
00398
00399
00400
00401 bool updating_used_alone;
00402
00403
00404
00405
00406
00407 static void
00408 compute_call_clobbered (struct alias_info *ai)
00409 {
00410 VEC (tree, heap) *worklist = NULL;
00411 VEC(int,heap) *worklist2 = NULL;
00412
00413 set_initial_properties (ai);
00414 init_transitive_clobber_worklist (&worklist, &worklist2);
00415 while (VEC_length (tree, worklist) != 0)
00416 {
00417 tree curr = VEC_pop (tree, worklist);
00418 int reason = VEC_pop (int, worklist2);
00419
00420 mark_call_clobbered (curr, reason);
00421 mark_aliases_call_clobbered (curr, &worklist, &worklist2);
00422 }
00423 VEC_free (tree, heap, worklist);
00424 VEC_free (int, heap, worklist2);
00425 compute_tag_properties ();
00426 }
00427
00428
00429
00430
00431
00432 static bool
00433 lhs_may_store_to (tree stmt, tree sym ATTRIBUTE_UNUSED)
00434 {
00435 tree lhs = TREE_OPERAND (stmt, 0);
00436
00437 lhs = get_base_address (lhs);
00438
00439 if (!lhs)
00440 return false;
00441
00442 if (TREE_CODE (lhs) == SSA_NAME)
00443 return false;
00444
00445
00446 return true;
00447 }
00448
00449
00450
00451 void
00452 recalculate_used_alone (void)
00453 {
00454 VEC (tree, heap) *calls = NULL;
00455 block_stmt_iterator bsi;
00456 basic_block bb;
00457 tree stmt;
00458 size_t i;
00459 referenced_var_iterator rvi;
00460 tree var;
00461
00462
00463 updating_used_alone = true;
00464 FOR_EACH_REFERENCED_VAR (var, rvi)
00465 if (TREE_CODE (var) == SYMBOL_MEMORY_TAG)
00466 {
00467 SMT_OLD_USED_ALONE (var) = SMT_USED_ALONE (var);
00468 SMT_USED_ALONE (var) = 0;
00469 }
00470
00471
00472
00473
00474
00475
00476 FOR_EACH_BB (bb)
00477 {
00478 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00479 {
00480 bool iscall = false;
00481 ssa_op_iter iter;
00482
00483 stmt = bsi_stmt (bsi);
00484
00485 if (TREE_CODE (stmt) == CALL_EXPR
00486 || (TREE_CODE (stmt) == MODIFY_EXPR
00487 && TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR))
00488 {
00489 iscall = true;
00490 VEC_safe_push (tree, heap, calls, stmt);
00491 }
00492
00493 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter,
00494 SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS)
00495 {
00496 tree svar = var;
00497
00498 if (TREE_CODE (var) == SSA_NAME)
00499 svar = SSA_NAME_VAR (var);
00500
00501 if (TREE_CODE (svar) == SYMBOL_MEMORY_TAG)
00502 {
00503
00504 if (iscall && !lhs_may_store_to (stmt, svar))
00505 continue;
00506
00507 if (!SMT_USED_ALONE (svar))
00508 {
00509 SMT_USED_ALONE (svar) = true;
00510
00511
00512
00513 if (!SMT_OLD_USED_ALONE (svar))
00514 mark_sym_for_renaming (svar);
00515 }
00516 }
00517 }
00518 }
00519 }
00520
00521
00522 if (calls)
00523 {
00524 for (i = 0; VEC_iterate (tree, calls, i, stmt); i++)
00525 update_stmt (stmt);
00526 }
00527
00528
00529
00530
00531 FOR_EACH_REFERENCED_VAR (var, rvi)
00532 if (TREE_CODE (var) == SYMBOL_MEMORY_TAG)
00533 {
00534 if (SMT_OLD_USED_ALONE (var) && !SMT_USED_ALONE (var))
00535 mark_sym_for_renaming (var);
00536 }
00537
00538 VEC_free (tree, heap, calls);
00539 updating_used_alone = false;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 static unsigned int
00652 compute_may_aliases (void)
00653 {
00654 struct alias_info *ai;
00655
00656 memset (&alias_stats, 0, sizeof (alias_stats));
00657
00658
00659 ai = init_alias_info ();
00660
00661
00662
00663
00664
00665
00666 compute_points_to_sets (ai);
00667
00668
00669
00670
00671 setup_pointers_and_addressables (ai);
00672
00673
00674
00675
00676
00677 compute_flow_sensitive_aliasing (ai);
00678
00679
00680
00681 compute_flow_insensitive_aliasing (ai);
00682
00683
00684 compute_call_clobbered (ai);
00685
00686
00687 if (ai->total_alias_vops >= MAX_ALIASED_VOPS)
00688 group_aliases (ai);
00689
00690
00691
00692
00693
00694
00695 maybe_create_global_var (ai);
00696
00697
00698
00699
00700 if (ai->ref_all_symbol_mem_tag)
00701 finalize_ref_all_pointers (ai);
00702
00703
00704 if (dump_file)
00705 {
00706 dump_referenced_vars (dump_file);
00707 if (dump_flags & TDF_STATS)
00708 dump_alias_stats (dump_file);
00709 dump_points_to_info (dump_file);
00710 dump_alias_info (dump_file);
00711 }
00712
00713
00714 delete_alias_info (ai);
00715
00716 updating_used_alone = true;
00717 {
00718 block_stmt_iterator bsi;
00719 basic_block bb;
00720 FOR_EACH_BB (bb)
00721 {
00722 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00723 {
00724 update_stmt_if_modified (bsi_stmt (bsi));
00725 }
00726 }
00727 }
00728 recalculate_used_alone ();
00729 updating_used_alone = false;
00730 return 0;
00731 }
00732
00733
00734 struct tree_opt_pass pass_may_alias =
00735 {
00736 "alias",
00737 NULL,
00738 compute_may_aliases,
00739 NULL,
00740 NULL,
00741 0,
00742 TV_TREE_MAY_ALIAS,
00743 PROP_cfg | PROP_ssa,
00744 PROP_alias,
00745 0,
00746 0,
00747 TODO_dump_func | TODO_update_ssa
00748 | TODO_ggc_collect | TODO_verify_ssa
00749 | TODO_verify_stmts,
00750 0
00751 };
00752
00753
00754
00755
00756 struct count_ptr_d
00757 {
00758 tree ptr;
00759 unsigned count;
00760 };
00761
00762
00763
00764
00765
00766 static tree
00767 count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
00768 {
00769 struct count_ptr_d *count_p = (struct count_ptr_d *) data;
00770
00771
00772
00773
00774 if (TREE_CODE (*tp) == ADDR_EXPR)
00775 {
00776 *walk_subtrees = 0;
00777 return NULL_TREE;
00778 }
00779
00780 if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
00781 count_p->count++;
00782
00783 return NULL_TREE;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792 void
00793 count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p,
00794 unsigned *num_derefs_p, bool *is_store)
00795 {
00796 ssa_op_iter i;
00797 tree use;
00798
00799 *num_uses_p = 0;
00800 *num_derefs_p = 0;
00801 *is_store = false;
00802
00803
00804 FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
00805 if (use == ptr)
00806 (*num_uses_p)++;
00807
00808
00809
00810
00811
00812
00813
00814
00815 if (TREE_CODE (stmt) == MODIFY_EXPR
00816 || (TREE_CODE (stmt) == RETURN_EXPR
00817 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
00818 || TREE_CODE (stmt) == ASM_EXPR
00819 || TREE_CODE (stmt) == CALL_EXPR)
00820 {
00821 tree lhs, rhs;
00822
00823 if (TREE_CODE (stmt) == MODIFY_EXPR)
00824 {
00825 lhs = TREE_OPERAND (stmt, 0);
00826 rhs = TREE_OPERAND (stmt, 1);
00827 }
00828 else if (TREE_CODE (stmt) == RETURN_EXPR)
00829 {
00830 tree e = TREE_OPERAND (stmt, 0);
00831 lhs = TREE_OPERAND (e, 0);
00832 rhs = TREE_OPERAND (e, 1);
00833 }
00834 else if (TREE_CODE (stmt) == ASM_EXPR)
00835 {
00836 lhs = ASM_OUTPUTS (stmt);
00837 rhs = ASM_INPUTS (stmt);
00838 }
00839 else
00840 {
00841 lhs = NULL_TREE;
00842 rhs = stmt;
00843 }
00844
00845 if (lhs && (TREE_CODE (lhs) == TREE_LIST || EXPR_P (lhs)))
00846 {
00847 struct count_ptr_d count;
00848 count.ptr = ptr;
00849 count.count = 0;
00850 walk_tree (&lhs, count_ptr_derefs, &count, NULL);
00851 *is_store = true;
00852 *num_derefs_p = count.count;
00853 }
00854
00855 if (rhs && (TREE_CODE (rhs) == TREE_LIST || EXPR_P (rhs)))
00856 {
00857 struct count_ptr_d count;
00858 count.ptr = ptr;
00859 count.count = 0;
00860 walk_tree (&rhs, count_ptr_derefs, &count, NULL);
00861 *num_derefs_p += count.count;
00862 }
00863 }
00864
00865 gcc_assert (*num_uses_p >= *num_derefs_p);
00866 }
00867
00868
00869
00870 static struct alias_info *
00871 init_alias_info (void)
00872 {
00873 struct alias_info *ai;
00874 referenced_var_iterator rvi;
00875 tree var;
00876
00877 bitmap_obstack_initialize (&alias_obstack);
00878 ai = XCNEW (struct alias_info);
00879 ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
00880 sbitmap_zero (ai->ssa_names_visited);
00881 ai->processed_ptrs = VEC_alloc (tree, heap, 50);
00882 ai->written_vars = BITMAP_ALLOC (&alias_obstack);
00883 ai->dereferenced_ptrs_store = BITMAP_ALLOC (&alias_obstack);
00884 ai->dereferenced_ptrs_load = BITMAP_ALLOC (&alias_obstack);
00885
00886
00887 if (aliases_computed_p)
00888 {
00889 unsigned i;
00890
00891
00892
00893
00894 bitmap_clear (addressable_vars);
00895
00896
00897 FOR_EACH_REFERENCED_VAR (var, rvi)
00898 {
00899 var_ann_t ann = var_ann (var);
00900
00901 ann->is_aliased = 0;
00902 ann->may_aliases = NULL;
00903 NUM_REFERENCES_CLEAR (ann);
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 if (TREE_CODE (var) == NAME_MEMORY_TAG
00916 || TREE_CODE (var) == SYMBOL_MEMORY_TAG
00917 || !is_global_var (var))
00918 clear_call_clobbered (var);
00919 }
00920
00921
00922 for (i = 1; i < num_ssa_names; i++)
00923 {
00924 tree name = ssa_name (i);
00925
00926 if (!name || !POINTER_TYPE_P (TREE_TYPE (name)))
00927 continue;
00928
00929 if (SSA_NAME_PTR_INFO (name))
00930 {
00931 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
00932
00933
00934
00935
00936
00937
00938 pi->pt_anything = 0;
00939 pi->pt_null = 0;
00940 pi->value_escapes_p = 0;
00941 pi->is_dereferenced = 0;
00942 if (pi->pt_vars)
00943 bitmap_clear (pi->pt_vars);
00944 }
00945 }
00946 }
00947
00948
00949 aliases_computed_p = true;
00950
00951 return ai;
00952 }
00953
00954
00955
00956
00957 static void
00958 delete_alias_info (struct alias_info *ai)
00959 {
00960 size_t i;
00961 referenced_var_iterator rvi;
00962 tree var;
00963
00964 sbitmap_free (ai->ssa_names_visited);
00965 VEC_free (tree, heap, ai->processed_ptrs);
00966
00967 for (i = 0; i < ai->num_addressable_vars; i++)
00968 free (ai->addressable_vars[i]);
00969
00970 FOR_EACH_REFERENCED_VAR(var, rvi)
00971 {
00972 var_ann_t ann = var_ann (var);
00973 NUM_REFERENCES_CLEAR (ann);
00974 }
00975
00976 free (ai->addressable_vars);
00977
00978 for (i = 0; i < ai->num_pointers; i++)
00979 free (ai->pointers[i]);
00980 free (ai->pointers);
00981
00982 BITMAP_FREE (ai->written_vars);
00983 BITMAP_FREE (ai->dereferenced_ptrs_store);
00984 BITMAP_FREE (ai->dereferenced_ptrs_load);
00985 bitmap_obstack_release (&alias_obstack);
00986 free (ai);
00987
00988 delete_points_to_sets ();
00989 }
00990
00991
00992
00993 static int
00994 eq_ptr_info (const void *p1, const void *p2)
00995 {
00996 const struct ptr_info_def *n1 = (const struct ptr_info_def *) p1;
00997 const struct ptr_info_def *n2 = (const struct ptr_info_def *) p2;
00998 return bitmap_equal_p (n1->pt_vars, n2->pt_vars);
00999 }
01000
01001 static hashval_t
01002 ptr_info_hash (const void *p)
01003 {
01004 const struct ptr_info_def *n = (const struct ptr_info_def *) p;
01005 return bitmap_hash (n->pt_vars);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 static void
01018 create_name_tags (void)
01019 {
01020 size_t i;
01021 VEC (tree, heap) *with_ptvars = NULL;
01022 tree ptr;
01023 htab_t ptr_hash;
01024
01025
01026 for (i = 1; i < num_ssa_names; i++)
01027 {
01028 tree ptr = ssa_name (i);
01029 struct ptr_info_def *pi;
01030
01031 if (!ptr
01032 || !POINTER_TYPE_P (TREE_TYPE (ptr))
01033 || !SSA_NAME_PTR_INFO (ptr))
01034 continue;
01035
01036 pi = SSA_NAME_PTR_INFO (ptr);
01037
01038 if (pi->pt_anything || !pi->is_dereferenced)
01039 {
01040
01041
01042 pi->name_mem_tag = NULL_TREE;
01043 continue;
01044 }
01045
01046
01047
01048 if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))
01049 VEC_safe_push (tree, heap, with_ptvars, ptr);
01050 else
01051 set_pt_anything (ptr);
01052 }
01053
01054
01055 if (!with_ptvars)
01056 return;
01057
01058 ptr_hash = htab_create (10, ptr_info_hash, eq_ptr_info, NULL);
01059
01060
01061
01062 for (i = 0; VEC_iterate (tree, with_ptvars, i, ptr); i++)
01063 {
01064 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
01065 tree old_name_tag = pi->name_mem_tag;
01066 struct ptr_info_def **slot;
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 slot = (struct ptr_info_def **) htab_find_slot (ptr_hash, pi, INSERT);
01081 if (*slot)
01082 pi->name_mem_tag = (*slot)->name_mem_tag;
01083 else
01084 {
01085 *slot = pi;
01086
01087
01088 if (pi->name_mem_tag == NULL_TREE)
01089 pi->name_mem_tag = get_nmt_for (ptr);
01090 }
01091
01092
01093
01094
01095
01096 if (old_name_tag && old_name_tag != pi->name_mem_tag)
01097 mark_sym_for_renaming (old_name_tag);
01098
01099 TREE_THIS_VOLATILE (pi->name_mem_tag)
01100 |= TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
01101
01102
01103 mark_sym_for_renaming (pi->name_mem_tag);
01104 }
01105 htab_delete (ptr_hash);
01106
01107 VEC_free (tree, heap, with_ptvars);
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 static void
01120 compute_flow_sensitive_aliasing (struct alias_info *ai)
01121 {
01122 size_t i;
01123 tree ptr;
01124
01125 for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
01126 {
01127 if (!find_what_p_points_to (ptr))
01128 set_pt_anything (ptr);
01129 }
01130
01131 create_name_tags ();
01132
01133 for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
01134 {
01135 unsigned j;
01136 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
01137 var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
01138 bitmap_iterator bi;
01139
01140
01141
01142
01143
01144 if (pi->name_mem_tag && pi->pt_vars)
01145 EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
01146 {
01147 add_may_alias (pi->name_mem_tag, referenced_var (j));
01148 add_may_alias (v_ann->symbol_mem_tag, referenced_var (j));
01149 }
01150 }
01151 }
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 static void
01164 compute_flow_insensitive_aliasing (struct alias_info *ai)
01165 {
01166 size_t i;
01167
01168
01169
01170
01171
01172 ai->total_alias_vops = 0;
01173
01174
01175
01176 for (i = 0; i < ai->num_pointers; i++)
01177 {
01178 size_t j;
01179 struct alias_map_d *p_map = ai->pointers[i];
01180 tree tag = var_ann (p_map->var)->symbol_mem_tag;
01181 var_ann_t tag_ann = var_ann (tag);
01182 tree var;
01183
01184
01185 if (PTR_IS_REF_ALL (p_map->var))
01186 continue;
01187
01188 p_map->total_alias_vops = 0;
01189 p_map->may_aliases = BITMAP_ALLOC (&alias_obstack);
01190
01191
01192
01193 for (j = 0; VEC_iterate (tree, tag_ann->may_aliases, j, var); ++j)
01194 bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
01195
01196 for (j = 0; j < ai->num_addressable_vars; j++)
01197 {
01198 struct alias_map_d *v_map;
01199 var_ann_t v_ann;
01200 bool tag_stored_p, var_stored_p;
01201
01202 v_map = ai->addressable_vars[j];
01203 var = v_map->var;
01204 v_ann = var_ann (var);
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 tag_stored_p = is_call_clobbered (tag)
01216 || bitmap_bit_p (ai->written_vars, DECL_UID (tag));
01217 var_stored_p = is_call_clobbered (var)
01218 || bitmap_bit_p (ai->written_vars, DECL_UID (var));
01219 if (!tag_stored_p && !var_stored_p)
01220 continue;
01221
01222 if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
01223 {
01224 size_t num_tag_refs, num_var_refs;
01225
01226 num_tag_refs = NUM_REFERENCES (tag_ann);
01227 num_var_refs = NUM_REFERENCES (v_ann);
01228
01229
01230
01231
01232
01233 gcc_assert (!var_can_have_subvars (var)
01234 || get_subvars_for_var (var) == NULL);
01235
01236 add_may_alias (tag, var);
01237
01238
01239 bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
01240
01241
01242
01243
01244
01245
01246
01247 ai->total_alias_vops += (num_var_refs + num_tag_refs);
01248 p_map->total_alias_vops += (num_var_refs + num_tag_refs);
01249
01250
01251 }
01252 }
01253 }
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275 for (i = 0; i < ai->num_pointers; i++)
01276 {
01277 size_t j;
01278 struct alias_map_d *p_map1 = ai->pointers[i];
01279 tree tag1 = var_ann (p_map1->var)->symbol_mem_tag;
01280 bitmap may_aliases1 = p_map1->may_aliases;
01281
01282 if (PTR_IS_REF_ALL (p_map1->var))
01283 continue;
01284
01285 for (j = i + 1; j < ai->num_pointers; j++)
01286 {
01287 struct alias_map_d *p_map2 = ai->pointers[j];
01288 tree tag2 = var_ann (p_map2->var)->symbol_mem_tag;
01289 bitmap may_aliases2 = p_map2->may_aliases;
01290
01291 if (PTR_IS_REF_ALL (p_map2->var))
01292 continue;
01293
01294
01295 if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set, true))
01296 continue;
01297
01298
01299
01300 if (bitmap_intersect_p (may_aliases1, may_aliases2))
01301 continue;
01302
01303 if (!bitmap_empty_p (may_aliases2))
01304 {
01305 unsigned int k;
01306 bitmap_iterator bi;
01307
01308
01309
01310 EXECUTE_IF_SET_IN_BITMAP (may_aliases2, 0, k, bi)
01311 add_may_alias (tag1, referenced_var (k));
01312 bitmap_ior_into (may_aliases1, may_aliases2);
01313 }
01314 else
01315 {
01316
01317
01318 add_may_alias (tag1, tag2);
01319 bitmap_set_bit (may_aliases1, DECL_UID (tag2));
01320 }
01321 }
01322 }
01323
01324 if (dump_file)
01325 fprintf (dump_file, "\n%s: Total number of aliased vops: %ld\n",
01326 get_name (current_function_decl),
01327 ai->total_alias_vops);
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340 static void
01341 finalize_ref_all_pointers (struct alias_info *ai)
01342 {
01343 size_t i;
01344
01345 if (global_var)
01346 add_may_alias (ai->ref_all_symbol_mem_tag, global_var);
01347 else
01348 {
01349
01350 for (i = 0; i < ai->num_addressable_vars; i++)
01351 {
01352 tree var = ai->addressable_vars[i]->var;
01353 if (is_call_clobbered (var))
01354 add_may_alias (ai->ref_all_symbol_mem_tag, var);
01355 }
01356
01357
01358
01359 for (i = 0; i < ai->num_pointers; i++)
01360 {
01361 tree ptr = ai->pointers[i]->var, tag;
01362 if (PTR_IS_REF_ALL (ptr))
01363 continue;
01364 tag = var_ann (ptr)->symbol_mem_tag;
01365 if (is_call_clobbered (tag))
01366 add_may_alias (ai->ref_all_symbol_mem_tag, tag);
01367 }
01368 }
01369 }
01370
01371
01372
01373
01374 static int
01375 total_alias_vops_cmp (const void *p, const void *q)
01376 {
01377 const struct alias_map_d **p1 = (const struct alias_map_d **)p;
01378 const struct alias_map_d **p2 = (const struct alias_map_d **)q;
01379 long n1 = (*p1)->total_alias_vops;
01380 long n2 = (*p2)->total_alias_vops;
01381
01382
01383 return (n1 > n2 ? -1 : (n1 == n2) ? 0 : 1);
01384 }
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 static void
01401 group_aliases_into (tree tag, bitmap tag_aliases, struct alias_info *ai)
01402 {
01403 unsigned int i;
01404 var_ann_t tag_ann = var_ann (tag);
01405 size_t num_tag_refs = NUM_REFERENCES (tag_ann);
01406 bitmap_iterator bi;
01407
01408 EXECUTE_IF_SET_IN_BITMAP (tag_aliases, 0, i, bi)
01409 {
01410 tree var = referenced_var (i);
01411 var_ann_t ann = var_ann (var);
01412
01413
01414 ann->is_aliased = 0;
01415 ann->may_aliases = NULL;
01416
01417
01418
01419
01420 if (var != tag)
01421 add_may_alias (var, tag);
01422
01423
01424
01425
01426
01427 ai->total_alias_vops -= num_tag_refs;
01428 }
01429
01430
01431
01432
01433
01434 ai->total_alias_vops += num_tag_refs;
01435
01436
01437 tag_ann->may_aliases = NULL;
01438 }
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 static void
01501 group_aliases (struct alias_info *ai)
01502 {
01503 size_t i;
01504 tree ptr;
01505
01506
01507
01508 qsort (ai->pointers, ai->num_pointers, sizeof (struct alias_map_d *),
01509 total_alias_vops_cmp);
01510
01511
01512
01513 for (i = 0; i < ai->num_pointers; i++)
01514 {
01515 size_t j;
01516 tree tag1 = var_ann (ai->pointers[i]->var)->symbol_mem_tag;
01517 bitmap tag1_aliases = ai->pointers[i]->may_aliases;
01518
01519
01520 if (ai->pointers[i]->grouped_p)
01521 continue;
01522
01523
01524
01525
01526 for (j = i + 1; j < ai->num_pointers; j++)
01527 {
01528 bitmap tag2_aliases = ai->pointers[j]->may_aliases;
01529
01530 if (bitmap_intersect_p (tag1_aliases, tag2_aliases))
01531 {
01532 tree tag2 = var_ann (ai->pointers[j]->var)->symbol_mem_tag;
01533
01534 bitmap_ior_into (tag1_aliases, tag2_aliases);
01535
01536
01537 bitmap_clear (tag2_aliases);
01538 var_ann (tag2)->may_aliases = NULL;
01539
01540
01541 add_may_alias (tag2, tag1);
01542
01543 ai->pointers[j]->grouped_p = true;
01544 }
01545 }
01546
01547
01548 group_aliases_into (tag1, tag1_aliases, ai);
01549
01550
01551
01552 if (ai->total_alias_vops < MAX_ALIASED_VOPS)
01553 break;
01554 }
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
01573 {
01574 size_t j;
01575 tree name_tag = SSA_NAME_PTR_INFO (ptr)->name_mem_tag;
01576 VEC(tree,gc) *aliases;
01577 tree alias;
01578
01579 if (name_tag == NULL_TREE)
01580 continue;
01581
01582 aliases = var_ann (name_tag)->may_aliases;
01583 for (j = 0; VEC_iterate (tree, aliases, j, alias); j++)
01584 {
01585 var_ann_t ann = var_ann (alias);
01586
01587 if ((!MTAG_P (alias)
01588 || TREE_CODE (alias) == STRUCT_FIELD_TAG)
01589 && ann->may_aliases)
01590 {
01591 tree new_alias;
01592
01593 gcc_assert (VEC_length (tree, ann->may_aliases) == 1);
01594
01595 new_alias = VEC_index (tree, ann->may_aliases, 0);
01596 replace_may_alias (name_tag, j, new_alias);
01597 }
01598 }
01599 }
01600
01601 if (dump_file)
01602 fprintf (dump_file,
01603 "%s: Total number of aliased vops after grouping: %ld%s\n",
01604 get_name (current_function_decl),
01605 ai->total_alias_vops,
01606 (ai->total_alias_vops < 0) ? " (negative values are OK)" : "");
01607 }
01608
01609
01610
01611
01612 static void
01613 create_alias_map_for (tree var, struct alias_info *ai)
01614 {
01615 struct alias_map_d *alias_map;
01616 alias_map = XCNEW (struct alias_map_d);
01617 alias_map->var = var;
01618 alias_map->set = get_alias_set (var);
01619 ai->addressable_vars[ai->num_addressable_vars++] = alias_map;
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629 static void
01630 setup_pointers_and_addressables (struct alias_info *ai)
01631 {
01632 size_t n_vars, num_addressable_vars, num_pointers;
01633 referenced_var_iterator rvi;
01634 tree var;
01635 VEC (tree, heap) *varvec = NULL;
01636 safe_referenced_var_iterator srvi;
01637
01638
01639 num_addressable_vars = num_pointers = 0;
01640
01641 FOR_EACH_REFERENCED_VAR (var, rvi)
01642 {
01643 if (may_be_aliased (var))
01644 num_addressable_vars++;
01645
01646 if (POINTER_TYPE_P (TREE_TYPE (var)))
01647 {
01648
01649
01650 if (TREE_THIS_VOLATILE (var))
01651 bitmap_set_bit (ai->dereferenced_ptrs_store, DECL_UID (var));
01652
01653 num_pointers++;
01654 }
01655 }
01656
01657
01658
01659
01660
01661
01662 ai->addressable_vars = XCNEWVEC (struct alias_map_d *, num_addressable_vars);
01663 ai->pointers = XCNEWVEC (struct alias_map_d *, num_pointers);
01664 ai->num_addressable_vars = 0;
01665 ai->num_pointers = 0;
01666
01667
01668
01669
01670 n_vars = num_referenced_vars;
01671
01672 FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi)
01673 {
01674 var_ann_t v_ann = var_ann (var);
01675 subvar_t svars;
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG)
01687 continue;
01688
01689
01690
01691
01692
01693
01694 if (TREE_ADDRESSABLE (var))
01695 {
01696 if (!bitmap_bit_p (addressable_vars, DECL_UID (var))
01697 && TREE_CODE (var) != RESULT_DECL
01698 && !is_global_var (var))
01699 {
01700 bool okay_to_mark = true;
01701
01702
01703
01704 mark_sym_for_renaming (var);
01705
01706
01707
01708
01709 if (var_can_have_subvars (var)
01710 && (svars = get_subvars_for_var (var)))
01711 {
01712 subvar_t sv;
01713
01714 for (sv = svars; sv; sv = sv->next)
01715 {
01716 if (bitmap_bit_p (addressable_vars, DECL_UID (sv->var)))
01717 okay_to_mark = false;
01718 mark_sym_for_renaming (sv->var);
01719 }
01720 }
01721
01722
01723
01724
01725 if (okay_to_mark)
01726 mark_non_addressable (var);
01727 }
01728 }
01729
01730
01731
01732 if (may_be_aliased (var)
01733 && (!var_can_have_subvars (var)
01734 || get_subvars_for_var (var) == NULL))
01735 {
01736 create_alias_map_for (var, ai);
01737 mark_sym_for_renaming (var);
01738 }
01739
01740
01741
01742 if (POINTER_TYPE_P (TREE_TYPE (var)))
01743 {
01744 if ((bitmap_bit_p (ai->dereferenced_ptrs_store, DECL_UID (var))
01745 || bitmap_bit_p (ai->dereferenced_ptrs_load, DECL_UID (var))))
01746 {
01747 tree tag;
01748 var_ann_t t_ann;
01749
01750
01751
01752
01753 tag = get_tmt_for (var, ai);
01754 t_ann = var_ann (tag);
01755
01756
01757
01758
01759
01760 mark_sym_for_renaming (tag);
01761
01762
01763
01764
01765 if (v_ann->symbol_mem_tag)
01766 mark_sym_for_renaming (v_ann->symbol_mem_tag);
01767
01768
01769 v_ann->symbol_mem_tag = tag;
01770
01771
01772
01773 if (bitmap_bit_p (ai->dereferenced_ptrs_store, DECL_UID (var)))
01774 bitmap_set_bit (ai->written_vars, DECL_UID (tag));
01775
01776
01777
01778
01779
01780 NUM_REFERENCES_SET (t_ann,
01781 NUM_REFERENCES (t_ann)
01782 + NUM_REFERENCES (v_ann));
01783 }
01784 else
01785 {
01786
01787
01788
01789 var_ann_t ann = var_ann (var);
01790 tree tag = ann->symbol_mem_tag;
01791 if (tag)
01792 {
01793 mark_sym_for_renaming (tag);
01794 ann->symbol_mem_tag = NULL_TREE;
01795 }
01796 }
01797 }
01798 }
01799 VEC_free (tree, heap, varvec);
01800 }
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 static void
01831 maybe_create_global_var (struct alias_info *ai)
01832 {
01833 unsigned i, n_clobbered;
01834 bitmap_iterator bi;
01835
01836
01837 if (global_var == NULL_TREE)
01838 {
01839
01840 n_clobbered = 0;
01841 EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
01842 {
01843 n_clobbered++;
01844 }
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873 if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD
01874 || (n_clobbered == 0
01875 && ai->num_calls_found > 0
01876 && ai->num_pure_const_calls_found > 0
01877 && ai->num_calls_found > ai->num_pure_const_calls_found))
01878 create_global_var ();
01879 }
01880
01881
01882
01883
01884 EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
01885 {
01886 tree var = referenced_var (i);
01887
01888
01889
01890
01891 if (global_var && var != global_var)
01892 {
01893 add_may_alias (var, global_var);
01894 gcc_assert (!get_subvars_for_var (var));
01895 }
01896
01897 mark_sym_for_renaming (var);
01898 }
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 static bool
01912 may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set,
01913 tree var, HOST_WIDE_INT var_alias_set,
01914 bool alias_set_only)
01915 {
01916 tree mem;
01917
01918 alias_stats.alias_queries++;
01919 alias_stats.simple_queries++;
01920
01921
01922 mem = var_ann (ptr)->symbol_mem_tag;
01923 if (mem == var)
01924 {
01925 alias_stats.alias_noalias++;
01926 alias_stats.simple_resolved++;
01927 return false;
01928 }
01929
01930
01931
01932 if (flag_argument_noalias > 2 && TREE_CODE (ptr) == PARM_DECL)
01933 {
01934 alias_stats.alias_noalias++;
01935 alias_stats.simple_resolved++;
01936 return false;
01937 }
01938
01939
01940
01941 if (flag_argument_noalias > 1 && is_global_var (var)
01942 && TREE_CODE (ptr) == PARM_DECL)
01943 {
01944 alias_stats.alias_noalias++;
01945 alias_stats.simple_resolved++;
01946 return false;
01947 }
01948
01949
01950
01951 if ((unmodifiable_var_p (mem) && !unmodifiable_var_p (var))
01952 || (unmodifiable_var_p (var) && !unmodifiable_var_p (mem)))
01953 {
01954 alias_stats.alias_noalias++;
01955 alias_stats.simple_resolved++;
01956 return false;
01957 }
01958
01959 gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG);
01960
01961 alias_stats.tbaa_queries++;
01962
01963
01964 if (!alias_sets_conflict_p (mem_alias_set, var_alias_set))
01965 {
01966 alias_stats.alias_noalias++;
01967 alias_stats.tbaa_resolved++;
01968 return false;
01969 }
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979 if ((mem_alias_set != 0) && (var_alias_set != 0))
01980 {
01981 tree ptr_type = TREE_TYPE (ptr);
01982 tree var_type = TREE_TYPE (var);
01983
01984
01985
01986 if ((!alias_set_only) &&
01987 ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
01988 {
01989 int ptr_star_count = 0;
01990
01991
01992
01993
01994
01995 while (POINTER_TYPE_P (ptr_type))
01996
01997 {
01998 ptr_type = TREE_TYPE (ptr_type);
01999 ptr_star_count++;
02000 }
02001
02002
02003
02004
02005
02006 if (ptr_star_count > 0)
02007 {
02008 alias_stats.structnoaddress_queries++;
02009 if (ipa_type_escape_field_does_not_clobber_p (var_type,
02010 TREE_TYPE (ptr)))
02011 {
02012 alias_stats.structnoaddress_resolved++;
02013 alias_stats.alias_noalias++;
02014 return false;
02015 }
02016 }
02017 else if (ptr_star_count == 0)
02018 {
02019
02020
02021 alias_stats.structnoaddress_queries++;
02022 alias_stats.structnoaddress_resolved++;
02023 alias_stats.alias_noalias++;
02024 return false;
02025 }
02026 }
02027 }
02028
02029 alias_stats.alias_mayalias++;
02030 return true;
02031 }
02032
02033
02034
02035
02036 static void
02037 add_may_alias (tree var, tree alias)
02038 {
02039 size_t i;
02040 var_ann_t v_ann = get_var_ann (var);
02041 var_ann_t a_ann = get_var_ann (alias);
02042 tree al;
02043
02044
02045 gcc_assert (var != alias);
02046
02047
02048 #if 1
02049 TREE_ADDRESSABLE (alias) = 1;
02050 #else
02051 gcc_assert (may_be_aliased (alias));
02052 #endif
02053
02054 if (v_ann->may_aliases == NULL)
02055 v_ann->may_aliases = VEC_alloc (tree, gc, 2);
02056
02057
02058 for (i = 0; VEC_iterate (tree, v_ann->may_aliases, i, al); i++)
02059 if (alias == al)
02060 return;
02061
02062 VEC_safe_push (tree, gc, v_ann->may_aliases, alias);
02063 a_ann->is_aliased = 1;
02064 }
02065
02066
02067
02068
02069 static void
02070 replace_may_alias (tree var, size_t i, tree new_alias)
02071 {
02072 var_ann_t v_ann = var_ann (var);
02073 VEC_replace (tree, v_ann->may_aliases, i, new_alias);
02074 }
02075
02076
02077
02078
02079 static void
02080 set_pt_anything (tree ptr)
02081 {
02082 struct ptr_info_def *pi = get_ptr_info (ptr);
02083
02084 pi->pt_anything = 1;
02085 pi->pt_vars = NULL;
02086
02087
02088
02089
02090 if (pi->name_mem_tag)
02091 {
02092 mark_sym_for_renaming (pi->name_mem_tag);
02093 pi->name_mem_tag = NULL_TREE;
02094 }
02095 }
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 enum escape_type
02111 is_escape_site (tree stmt)
02112 {
02113 tree call = get_call_expr_in (stmt);
02114 if (call != NULL_TREE)
02115 {
02116 if (!TREE_SIDE_EFFECTS (call))
02117 return ESCAPE_TO_PURE_CONST;
02118
02119 return ESCAPE_TO_CALL;
02120 }
02121 else if (TREE_CODE (stmt) == ASM_EXPR)
02122 return ESCAPE_TO_ASM;
02123 else if (TREE_CODE (stmt) == MODIFY_EXPR)
02124 {
02125 tree lhs = TREE_OPERAND (stmt, 0);
02126
02127
02128 if (TREE_CODE (lhs) != SSA_NAME)
02129 lhs = get_base_address (lhs);
02130
02131
02132
02133 if (lhs == NULL_TREE)
02134 return ESCAPE_UNKNOWN;
02135
02136 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == NOP_EXPR
02137 || TREE_CODE (TREE_OPERAND (stmt, 1)) == CONVERT_EXPR
02138 || TREE_CODE (TREE_OPERAND (stmt, 1)) == VIEW_CONVERT_EXPR)
02139 {
02140 tree from = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (stmt, 1), 0));
02141 tree to = TREE_TYPE (TREE_OPERAND (stmt, 1));
02142
02143
02144
02145 if (POINTER_TYPE_P (from) && !POINTER_TYPE_P (to))
02146 return ESCAPE_BAD_CAST;
02147
02148
02149
02150 if (POINTER_TYPE_P (from) && !TYPE_REF_CAN_ALIAS_ALL (from)
02151 && POINTER_TYPE_P (to) && TYPE_REF_CAN_ALIAS_ALL (to))
02152 return ESCAPE_BAD_CAST;
02153 }
02154
02155
02156
02157 if (TREE_CODE (lhs) == SSA_NAME)
02158 return NO_ESCAPE;
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169 return ESCAPE_STORED_IN_GLOBAL;
02170 }
02171 else if (TREE_CODE (stmt) == RETURN_EXPR)
02172 return ESCAPE_TO_RETURN;
02173
02174 return NO_ESCAPE;
02175 }
02176
02177
02178
02179
02180 static tree
02181 create_tag_raw (enum tree_code code, tree type, const char *prefix)
02182 {
02183 tree tmp_var;
02184 tree new_type;
02185
02186
02187 new_type = build_type_variant (type, 0, 0);
02188 TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
02189
02190 tmp_var = build_decl (code, create_tmp_var_name (prefix),
02191 type);
02192
02193 TREE_READONLY (tmp_var) = 0;
02194
02195
02196 MTAG_GLOBAL (tmp_var) = 0;
02197 TREE_STATIC (tmp_var) = 0;
02198 TREE_USED (tmp_var) = 1;
02199
02200 return tmp_var;
02201 }
02202
02203
02204
02205
02206
02207
02208 static tree
02209 create_memory_tag (tree type, bool is_type_tag)
02210 {
02211 var_ann_t ann;
02212 tree tag = create_tag_raw (is_type_tag ? SYMBOL_MEMORY_TAG : NAME_MEMORY_TAG,
02213 type, (is_type_tag) ? "SMT" : "NMT");
02214
02215
02216
02217 DECL_CONTEXT (tag) = current_function_decl;
02218
02219
02220 TREE_ADDRESSABLE (tag) = 1;
02221
02222 ann = get_var_ann (tag);
02223 ann->symbol_mem_tag = NULL_TREE;
02224
02225
02226 add_referenced_var (tag);
02227
02228 return tag;
02229 }
02230
02231
02232
02233
02234
02235
02236
02237 static tree
02238 get_nmt_for (tree ptr)
02239 {
02240 struct ptr_info_def *pi = get_ptr_info (ptr);
02241 tree tag = pi->name_mem_tag;
02242
02243 if (tag == NULL_TREE)
02244 tag = create_memory_tag (TREE_TYPE (TREE_TYPE (ptr)), false);
02245 return tag;
02246 }
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257 static tree
02258 get_tmt_for (tree ptr, struct alias_info *ai)
02259 {
02260 size_t i;
02261 tree tag;
02262 tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
02263 HOST_WIDE_INT tag_set = get_alias_set (tag_type);
02264
02265
02266 if (PTR_IS_REF_ALL (ptr))
02267 {
02268 if (!ai->ref_all_symbol_mem_tag)
02269 ai->ref_all_symbol_mem_tag = create_memory_tag (void_type_node, true);
02270 return ai->ref_all_symbol_mem_tag;
02271 }
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 for (i = 0, tag = NULL_TREE; i < ai->num_pointers; i++)
02282 {
02283 struct alias_map_d *curr = ai->pointers[i];
02284 tree curr_tag = var_ann (curr->var)->symbol_mem_tag;
02285 if (tag_set == curr->set)
02286 {
02287 tag = curr_tag;
02288 break;
02289 }
02290 }
02291
02292
02293
02294 if (tag == NULL_TREE)
02295 {
02296 struct alias_map_d *alias_map;
02297
02298
02299
02300
02301 if (var_ann (ptr)->symbol_mem_tag == NULL_TREE)
02302 tag = create_memory_tag (tag_type, true);
02303 else
02304 tag = var_ann (ptr)->symbol_mem_tag;
02305
02306
02307
02308
02309 alias_map = XCNEW (struct alias_map_d);
02310 alias_map->var = ptr;
02311 alias_map->set = tag_set;
02312 ai->pointers[ai->num_pointers++] = alias_map;
02313 }
02314
02315
02316 TREE_THIS_VOLATILE (tag) |= TREE_THIS_VOLATILE (tag_type);
02317
02318
02319
02320 gcc_assert (tag_set == get_alias_set (tag));
02321
02322 return tag;
02323 }
02324
02325
02326
02327
02328
02329
02330 static void
02331 create_global_var (void)
02332 {
02333 global_var = build_decl (VAR_DECL, get_identifier (".GLOBAL_VAR"),
02334 void_type_node);
02335 DECL_ARTIFICIAL (global_var) = 1;
02336 TREE_READONLY (global_var) = 0;
02337 DECL_EXTERNAL (global_var) = 1;
02338 TREE_STATIC (global_var) = 1;
02339 TREE_USED (global_var) = 1;
02340 DECL_CONTEXT (global_var) = NULL_TREE;
02341 TREE_THIS_VOLATILE (global_var) = 0;
02342 TREE_ADDRESSABLE (global_var) = 0;
02343
02344 create_var_ann (global_var);
02345 mark_call_clobbered (global_var, ESCAPE_UNKNOWN);
02346 add_referenced_var (global_var);
02347 mark_sym_for_renaming (global_var);
02348 }
02349
02350
02351
02352
02353 static void
02354 dump_alias_stats (FILE *file)
02355 {
02356 const char *funcname
02357 = lang_hooks.decl_printable_name (current_function_decl, 2);
02358 fprintf (file, "\nAlias statistics for %s\n\n", funcname);
02359 fprintf (file, "Total alias queries:\t%u\n", alias_stats.alias_queries);
02360 fprintf (file, "Total alias mayalias results:\t%u\n",
02361 alias_stats.alias_mayalias);
02362 fprintf (file, "Total alias noalias results:\t%u\n",
02363 alias_stats.alias_noalias);
02364 fprintf (file, "Total simple queries:\t%u\n",
02365 alias_stats.simple_queries);
02366 fprintf (file, "Total simple resolved:\t%u\n",
02367 alias_stats.simple_resolved);
02368 fprintf (file, "Total TBAA queries:\t%u\n",
02369 alias_stats.tbaa_queries);
02370 fprintf (file, "Total TBAA resolved:\t%u\n",
02371 alias_stats.tbaa_resolved);
02372 fprintf (file, "Total non-addressable structure type queries:\t%u\n",
02373 alias_stats.structnoaddress_queries);
02374 fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
02375 alias_stats.structnoaddress_resolved);
02376 }
02377
02378
02379
02380
02381 void
02382 dump_alias_info (FILE *file)
02383 {
02384 size_t i;
02385 const char *funcname
02386 = lang_hooks.decl_printable_name (current_function_decl, 2);
02387 referenced_var_iterator rvi;
02388 tree var;
02389
02390 fprintf (file, "\nFlow-insensitive alias information for %s\n\n", funcname);
02391
02392 fprintf (file, "Aliased symbols\n\n");
02393
02394 FOR_EACH_REFERENCED_VAR (var, rvi)
02395 {
02396 if (may_be_aliased (var))
02397 dump_variable (file, var);
02398 }
02399
02400 fprintf (file, "\nDereferenced pointers\n\n");
02401
02402 FOR_EACH_REFERENCED_VAR (var, rvi)
02403 {
02404 var_ann_t ann = var_ann (var);
02405 if (ann->symbol_mem_tag)
02406 dump_variable (file, var);
02407 }
02408
02409 fprintf (file, "\nSymbol memory tags\n\n");
02410
02411 FOR_EACH_REFERENCED_VAR (var, rvi)
02412 {
02413 if (TREE_CODE (var) == SYMBOL_MEMORY_TAG)
02414 dump_variable (file, var);
02415 }
02416
02417 fprintf (file, "\n\nFlow-sensitive alias information for %s\n\n", funcname);
02418
02419 fprintf (file, "SSA_NAME pointers\n\n");
02420 for (i = 1; i < num_ssa_names; i++)
02421 {
02422 tree ptr = ssa_name (i);
02423 struct ptr_info_def *pi;
02424
02425 if (ptr == NULL_TREE)
02426 continue;
02427
02428 pi = SSA_NAME_PTR_INFO (ptr);
02429 if (!SSA_NAME_IN_FREE_LIST (ptr)
02430 && pi
02431 && pi->name_mem_tag)
02432 dump_points_to_info_for (file, ptr);
02433 }
02434
02435 fprintf (file, "\nName memory tags\n\n");
02436
02437 FOR_EACH_REFERENCED_VAR (var, rvi)
02438 {
02439 if (TREE_CODE (var) == NAME_MEMORY_TAG)
02440 dump_variable (file, var);
02441 }
02442
02443 fprintf (file, "\n");
02444 }
02445
02446
02447
02448
02449 void
02450 debug_alias_info (void)
02451 {
02452 dump_alias_info (stderr);
02453 }
02454
02455
02456
02457
02458
02459 struct ptr_info_def *
02460 get_ptr_info (tree t)
02461 {
02462 struct ptr_info_def *pi;
02463
02464 gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
02465
02466 pi = SSA_NAME_PTR_INFO (t);
02467 if (pi == NULL)
02468 {
02469 pi = GGC_NEW (struct ptr_info_def);
02470 memset ((void *)pi, 0, sizeof (*pi));
02471 SSA_NAME_PTR_INFO (t) = pi;
02472 }
02473
02474 return pi;
02475 }
02476
02477
02478
02479
02480 void
02481 dump_points_to_info_for (FILE *file, tree ptr)
02482 {
02483 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
02484
02485 print_generic_expr (file, ptr, dump_flags);
02486
02487 if (pi)
02488 {
02489 if (pi->name_mem_tag)
02490 {
02491 fprintf (file, ", name memory tag: ");
02492 print_generic_expr (file, pi->name_mem_tag, dump_flags);
02493 }
02494
02495 if (pi->is_dereferenced)
02496 fprintf (file, ", is dereferenced");
02497
02498 if (pi->value_escapes_p)
02499 fprintf (file, ", its value escapes");
02500
02501 if (pi->pt_anything)
02502 fprintf (file, ", points-to anything");
02503
02504 if (pi->pt_null)
02505 fprintf (file, ", points-to NULL");
02506
02507 if (pi->pt_vars)
02508 {
02509 unsigned ix;
02510 bitmap_iterator bi;
02511
02512 fprintf (file, ", points-to vars: { ");
02513 EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
02514 {
02515 print_generic_expr (file, referenced_var (ix), dump_flags);
02516 fprintf (file, " ");
02517 }
02518 fprintf (file, "}");
02519 }
02520 }
02521
02522 fprintf (file, "\n");
02523 }
02524
02525
02526
02527
02528 void
02529 debug_points_to_info_for (tree var)
02530 {
02531 dump_points_to_info_for (stderr, var);
02532 }
02533
02534
02535
02536
02537
02538 void
02539 dump_points_to_info (FILE *file)
02540 {
02541 basic_block bb;
02542 block_stmt_iterator si;
02543 ssa_op_iter iter;
02544 const char *fname =
02545 lang_hooks.decl_printable_name (current_function_decl, 2);
02546 referenced_var_iterator rvi;
02547 tree var;
02548
02549 fprintf (file, "\n\nPointed-to sets for pointers in %s\n\n", fname);
02550
02551
02552
02553
02554 FOR_EACH_REFERENCED_VAR (var, rvi)
02555 {
02556 if (POINTER_TYPE_P (TREE_TYPE (var)))
02557 {
02558 tree def = default_def (var);
02559 if (def)
02560 dump_points_to_info_for (file, def);
02561 }
02562 }
02563
02564
02565 FOR_EACH_BB (bb)
02566 {
02567 tree phi;
02568
02569 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
02570 {
02571 tree ptr = PHI_RESULT (phi);
02572 if (POINTER_TYPE_P (TREE_TYPE (ptr)))
02573 dump_points_to_info_for (file, ptr);
02574 }
02575
02576 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
02577 {
02578 tree stmt = bsi_stmt (si);
02579 tree def;
02580 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
02581 if (POINTER_TYPE_P (TREE_TYPE (def)))
02582 dump_points_to_info_for (file, def);
02583 }
02584 }
02585
02586 fprintf (file, "\n");
02587 }
02588
02589
02590
02591
02592 void
02593 debug_points_to_info (void)
02594 {
02595 dump_points_to_info (stderr);
02596 }
02597
02598
02599
02600 void
02601 dump_may_aliases_for (FILE *file, tree var)
02602 {
02603 VEC(tree, gc) *aliases;
02604
02605 if (TREE_CODE (var) == SSA_NAME)
02606 var = SSA_NAME_VAR (var);
02607
02608 aliases = var_ann (var)->may_aliases;
02609 if (aliases)
02610 {
02611 size_t i;
02612 tree al;
02613 fprintf (file, "{ ");
02614 for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
02615 {
02616 print_generic_expr (file, al, dump_flags);
02617 fprintf (file, " ");
02618 }
02619 fprintf (file, "}");
02620 }
02621 }
02622
02623
02624
02625
02626 void
02627 debug_may_aliases_for (tree var)
02628 {
02629 dump_may_aliases_for (stderr, var);
02630 }
02631
02632
02633
02634 bool
02635 may_be_aliased (tree var)
02636 {
02637
02638 if (TREE_ADDRESSABLE (var))
02639 return true;
02640
02641
02642
02643
02644 if (MTAG_P (var)
02645 && (MTAG_GLOBAL (var) || TREE_PUBLIC (var)))
02646 return true;
02647 else if (!MTAG_P (var)
02648 && (DECL_EXTERNAL (var) || TREE_PUBLIC (var)))
02649 return true;
02650
02651
02652
02653
02654 if (!TREE_STATIC (var))
02655 return false;
02656
02657
02658
02659
02660
02661 if (flag_unit_at_a_time)
02662 return false;
02663 if (decl_function_context (var) == current_function_decl)
02664 return false;
02665
02666 return true;
02667 }
02668
02669
02670
02671 bool
02672 is_aliased_with (tree tag, tree sym)
02673 {
02674 size_t i;
02675 VEC(tree,gc) *aliases;
02676 tree al;
02677
02678 if (var_ann (sym)->is_aliased)
02679 {
02680 aliases = var_ann (tag)->may_aliases;
02681
02682 if (aliases == NULL)
02683 return false;
02684
02685 for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
02686 if (al == sym)
02687 return true;
02688 }
02689 else
02690 {
02691 aliases = var_ann (sym)->may_aliases;
02692
02693 if (aliases == NULL)
02694 return false;
02695
02696 for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
02697 if (al == tag)
02698 return true;
02699 }
02700
02701 return false;
02702 }
02703
02704
02705
02706
02707 bool
02708 may_aliases_intersect (tree tag1, tree tag2)
02709 {
02710 struct pointer_set_t *set1 = pointer_set_create ();
02711 unsigned i;
02712 VEC(tree,gc) *may_aliases1 = may_aliases (tag1);
02713 VEC(tree,gc) *may_aliases2 = may_aliases (tag2);
02714 tree sym;
02715
02716
02717
02718 for (i = 0; VEC_iterate (tree, may_aliases1, i, sym); i++)
02719 pointer_set_insert (set1, sym);
02720
02721
02722
02723 for (i = 0; VEC_iterate (tree, may_aliases2, i, sym); i++)
02724 if (pointer_set_contains (set1, sym))
02725 {
02726 pointer_set_destroy (set1);
02727 return true;
02728 }
02729
02730 pointer_set_destroy (set1);
02731 return false;
02732 }
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742 static tree
02743 add_may_alias_for_new_tag (tree tag, tree var)
02744 {
02745 var_ann_t v_ann = var_ann (var);
02746 VEC(tree, gc) *aliases = v_ann->may_aliases;
02747
02748
02749 if ((aliases != NULL)
02750 && (VEC_length (tree, aliases) == 1))
02751 {
02752 tree ali = VEC_index (tree, aliases, 0);
02753
02754 if (TREE_CODE (ali) == SYMBOL_MEMORY_TAG)
02755 return ali;
02756 }
02757
02758
02759 if (aliases == NULL)
02760 add_may_alias (tag, var);
02761 else
02762 {
02763
02764 unsigned i;
02765 tree al;
02766
02767 for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
02768 add_may_alias (tag, al);
02769 }
02770
02771 return tag;
02772 }
02773
02774
02775
02776
02777
02778
02779
02780
02781 void
02782 new_type_alias (tree ptr, tree var, tree expr)
02783 {
02784 var_ann_t p_ann = var_ann (ptr);
02785 tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
02786 tree tag;
02787 subvar_t svars;
02788 tree ali = NULL_TREE;
02789 HOST_WIDE_INT offset, size, maxsize;
02790 tree ref;
02791
02792 gcc_assert (p_ann->symbol_mem_tag == NULL_TREE);
02793 gcc_assert (!MTAG_P (var));
02794
02795 ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
02796 gcc_assert (ref);
02797
02798 tag = create_memory_tag (tag_type, true);
02799 p_ann->symbol_mem_tag = tag;
02800
02801
02802
02803 if (var_can_have_subvars (var)
02804 && (svars = get_subvars_for_var (var)))
02805 {
02806 subvar_t sv;
02807 VEC (tree, heap) *overlaps = NULL;
02808 unsigned int len;
02809
02810 for (sv = svars; sv; sv = sv->next)
02811 {
02812 bool exact;
02813
02814 if (overlap_subvar (offset, maxsize, sv->var, &exact))
02815 VEC_safe_push (tree, heap, overlaps, sv->var);
02816 }
02817 len = VEC_length (tree, overlaps);
02818 if (dump_file && (dump_flags & TDF_DETAILS))
02819 fprintf (dump_file, "\nnumber of overlapping subvars = %u\n", len);
02820 gcc_assert (len);
02821
02822 if (len == 1)
02823 ali = add_may_alias_for_new_tag (tag, VEC_index (tree, overlaps, 0));
02824 else if (len > 1)
02825 {
02826 unsigned int k;
02827 tree sv_var;
02828
02829 for (k = 0; VEC_iterate (tree, overlaps, k, sv_var); k++)
02830 {
02831 ali = add_may_alias_for_new_tag (tag, sv_var);
02832
02833 if (ali != tag)
02834 {
02835
02836
02837
02838 add_may_alias (tag, ali);
02839 ali = tag;
02840 }
02841 }
02842 }
02843 }
02844 else
02845 ali = add_may_alias_for_new_tag (tag, var);
02846
02847 p_ann->symbol_mem_tag = ali;
02848 TREE_READONLY (tag) = TREE_READONLY (var);
02849 MTAG_GLOBAL (tag) = is_global_var (var);
02850 }
02851
02852
02853
02854 typedef struct used_part
02855 {
02856 HOST_WIDE_INT minused;
02857 HOST_WIDE_INT maxused;
02858
02859
02860 bool explicit_uses;
02861
02862
02863
02864 bool implicit_uses;
02865
02866 bool write_only;
02867 } *used_part_t;
02868
02869
02870
02871 static htab_t used_portions;
02872
02873 struct used_part_map
02874 {
02875 unsigned int uid;
02876 used_part_t to;
02877 };
02878
02879
02880
02881 static int
02882 used_part_map_eq (const void *va, const void *vb)
02883 {
02884 const struct used_part_map *a = (const struct used_part_map *) va;
02885 const struct used_part_map *b = (const struct used_part_map *) vb;
02886 return (a->uid == b->uid);
02887 }
02888
02889
02890
02891 static unsigned int
02892 used_part_map_hash (const void *item)
02893 {
02894 return ((const struct used_part_map *)item)->uid;
02895 }
02896
02897
02898
02899 static void
02900 free_used_part_map (void *item)
02901 {
02902 free (((struct used_part_map *)item)->to);
02903 free (item);
02904 }
02905
02906
02907
02908 static used_part_t
02909 up_lookup (unsigned int uid)
02910 {
02911 struct used_part_map *h, in;
02912 in.uid = uid;
02913 h = (struct used_part_map *) htab_find_with_hash (used_portions, &in, uid);
02914 if (!h)
02915 return NULL;
02916 return h->to;
02917 }
02918
02919
02920
02921 static void
02922 up_insert (unsigned int uid, used_part_t to)
02923 {
02924 struct used_part_map *h;
02925 void **loc;
02926
02927 h = XNEW (struct used_part_map);
02928 h->uid = uid;
02929 h->to = to;
02930 loc = htab_find_slot_with_hash (used_portions, h,
02931 uid, INSERT);
02932 if (*loc != NULL)
02933 free (*loc);
02934 *(struct used_part_map **) loc = h;
02935 }
02936
02937
02938
02939
02940
02941 static used_part_t
02942 get_or_create_used_part_for (size_t uid)
02943 {
02944 used_part_t up;
02945 if ((up = up_lookup (uid)) == NULL)
02946 {
02947 up = XCNEW (struct used_part);
02948 up->minused = INT_MAX;
02949 up->maxused = 0;
02950 up->explicit_uses = false;
02951 up->implicit_uses = false;
02952 up->write_only = true;
02953 }
02954
02955 return up;
02956 }
02957
02958
02959
02960
02961
02962 static tree
02963 create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
02964 unsigned HOST_WIDE_INT size)
02965 {
02966 var_ann_t ann;
02967 tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
02968
02969
02970
02971 DECL_CONTEXT (subvar) = DECL_CONTEXT (var);
02972 MTAG_GLOBAL (subvar) = DECL_EXTERNAL (var);
02973 TREE_PUBLIC (subvar) = TREE_PUBLIC (var);
02974 TREE_STATIC (subvar) = TREE_STATIC (var);
02975 TREE_READONLY (subvar) = TREE_READONLY (var);
02976 TREE_ADDRESSABLE (subvar) = TREE_ADDRESSABLE (var);
02977
02978
02979 ann = get_var_ann (subvar);
02980 ann->symbol_mem_tag = NULL;
02981 add_referenced_var (subvar);
02982 SFT_PARENT_VAR (subvar) = var;
02983 SFT_OFFSET (subvar) = offset;
02984 SFT_SIZE (subvar) = size;
02985 return subvar;
02986 }
02987
02988
02989
02990
02991
02992 static void
02993 create_overlap_variables_for (tree var)
02994 {
02995 VEC(fieldoff_s,heap) *fieldstack = NULL;
02996 used_part_t up;
02997 size_t uid = DECL_UID (var);
02998
02999 up = up_lookup (uid);
03000 if (!up
03001 || up->write_only)
03002 return;
03003
03004 push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL);
03005 if (VEC_length (fieldoff_s, fieldstack) != 0)
03006 {
03007 subvar_t *subvars;
03008 fieldoff_s *fo;
03009 bool notokay = false;
03010 int fieldcount = 0;
03011 int i;
03012 HOST_WIDE_INT lastfooffset = -1;
03013 HOST_WIDE_INT lastfosize = -1;
03014 tree lastfotype = NULL_TREE;
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025 for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
03026 {
03027 if (!fo->size
03028 || TREE_CODE (fo->size) != INTEGER_CST
03029 || fo->offset < 0)
03030 {
03031 notokay = true;
03032 break;
03033 }
03034 fieldcount++;
03035 }
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049 if (fieldcount >= SALIAS_MAX_IMPLICIT_FIELDS
03050 && !up->explicit_uses)
03051 {
03052 if (dump_file && (dump_flags & TDF_DETAILS))
03053 {
03054 fprintf (dump_file, "Variable ");
03055 print_generic_expr (dump_file, var, 0);
03056 fprintf (dump_file, " has no explicit uses in this function, and is > SALIAS_MAX_IMPLICIT_FIELDS, so skipping\n");
03057 }
03058 notokay = true;
03059 }
03060
03061
03062 if (notokay)
03063 {
03064 VEC_free (fieldoff_s, heap, fieldstack);
03065 return;
03066 }
03067
03068
03069 subvars = lookup_subvars_for_var (var);
03070
03071 sort_fieldstack (fieldstack);
03072
03073 for (i = VEC_length (fieldoff_s, fieldstack);
03074 VEC_iterate (fieldoff_s, fieldstack, --i, fo);)
03075 {
03076 subvar_t sv;
03077 HOST_WIDE_INT fosize;
03078 tree currfotype;
03079
03080 fosize = TREE_INT_CST_LOW (fo->size);
03081 currfotype = fo->type;
03082
03083
03084
03085
03086
03087 if (((fo->offset <= up->minused
03088 && fo->offset + fosize <= up->minused)
03089 || fo->offset >= up->maxused)
03090 || (fo->offset == lastfooffset
03091 && fosize == lastfosize
03092 && currfotype == lastfotype))
03093 continue;
03094 sv = GGC_NEW (struct subvar);
03095 sv->next = *subvars;
03096 sv->var = create_sft (var, fo->type, fo->offset, fosize);
03097
03098 if (dump_file)
03099 {
03100 fprintf (dump_file, "structure field tag %s created for var %s",
03101 get_name (sv->var), get_name (var));
03102 fprintf (dump_file, " offset " HOST_WIDE_INT_PRINT_DEC,
03103 SFT_OFFSET (sv->var));
03104 fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
03105 SFT_SIZE (sv->var));
03106 fprintf (dump_file, "\n");
03107 }
03108
03109 lastfotype = currfotype;
03110 lastfooffset = fo->offset;
03111 lastfosize = fosize;
03112 *subvars = sv;
03113 }
03114
03115
03116
03117
03118
03119
03120
03121
03122 clear_call_clobbered (var);
03123 }
03124
03125 VEC_free (fieldoff_s, heap, fieldstack);
03126 }
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136 static tree
03137 find_used_portions (tree *tp, int *walk_subtrees, void *lhs_p)
03138 {
03139 switch (TREE_CODE (*tp))
03140 {
03141 case MODIFY_EXPR:
03142
03143
03144 find_used_portions (&TREE_OPERAND (*tp, 0), walk_subtrees, tp);
03145 return find_used_portions (&TREE_OPERAND (*tp, 1), walk_subtrees, NULL);
03146 case REALPART_EXPR:
03147 case IMAGPART_EXPR:
03148 case COMPONENT_REF:
03149 case ARRAY_REF:
03150 {
03151 HOST_WIDE_INT bitsize;
03152 HOST_WIDE_INT bitmaxsize;
03153 HOST_WIDE_INT bitpos;
03154 tree ref;
03155 ref = get_ref_base_and_extent (*tp, &bitpos, &bitsize, &bitmaxsize);
03156 if (DECL_P (ref)
03157 && var_can_have_subvars (ref)
03158 && bitmaxsize != -1)
03159 {
03160 size_t uid = DECL_UID (ref);
03161 used_part_t up;
03162
03163 up = get_or_create_used_part_for (uid);
03164
03165 if (bitpos <= up->minused)
03166 up->minused = bitpos;
03167 if ((bitpos + bitmaxsize >= up->maxused))
03168 up->maxused = bitpos + bitmaxsize;
03169
03170 if (bitsize == bitmaxsize)
03171 up->explicit_uses = true;
03172 else
03173 up->implicit_uses = true;
03174 if (!lhs_p)
03175 up->write_only = false;
03176 up_insert (uid, up);
03177
03178 *walk_subtrees = 0;
03179 return NULL_TREE;
03180 }
03181 }
03182 break;
03183
03184
03185
03186
03187 case ADDR_EXPR:
03188 {
03189 tree var = get_base_address (TREE_OPERAND (*tp, 0));
03190
03191 if (var
03192 && DECL_P (var)
03193 && DECL_SIZE (var)
03194 && var_can_have_subvars (var)
03195 && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
03196 {
03197 used_part_t up;
03198 size_t uid = DECL_UID (var);
03199
03200 up = get_or_create_used_part_for (uid);
03201
03202 up->minused = 0;
03203 up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
03204 up->implicit_uses = true;
03205 if (!lhs_p)
03206 up->write_only = false;
03207
03208 up_insert (uid, up);
03209 *walk_subtrees = 0;
03210 return NULL_TREE;
03211 }
03212 }
03213 break;
03214 case CALL_EXPR:
03215 {
03216 tree *arg;
03217 for (arg = &TREE_OPERAND (*tp, 1); *arg; arg = &TREE_CHAIN (*arg))
03218 {
03219 if (TREE_CODE (TREE_VALUE (*arg)) != ADDR_EXPR)
03220 find_used_portions (&TREE_VALUE (*arg), walk_subtrees, NULL);
03221 }
03222 *walk_subtrees = 0;
03223 return NULL_TREE;
03224 }
03225 case VAR_DECL:
03226 case PARM_DECL:
03227 case RESULT_DECL:
03228 {
03229 tree var = *tp;
03230 if (DECL_SIZE (var)
03231 && var_can_have_subvars (var)
03232 && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
03233 {
03234 used_part_t up;
03235 size_t uid = DECL_UID (var);
03236
03237 up = get_or_create_used_part_for (uid);
03238
03239 up->minused = 0;
03240 up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
03241 up->implicit_uses = true;
03242
03243 up_insert (uid, up);
03244 *walk_subtrees = 0;
03245 return NULL_TREE;
03246 }
03247 }
03248 break;
03249
03250 default:
03251 break;
03252
03253 }
03254 return NULL_TREE;
03255 }
03256
03257
03258
03259 static unsigned int
03260 create_structure_vars (void)
03261 {
03262 basic_block bb;
03263 safe_referenced_var_iterator rvi;
03264 VEC (tree, heap) *varvec = NULL;
03265 tree var;
03266
03267 used_portions = htab_create (10, used_part_map_hash, used_part_map_eq,
03268 free_used_part_map);
03269
03270 FOR_EACH_BB (bb)
03271 {
03272 block_stmt_iterator bsi;
03273 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
03274 {
03275 walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
03276 find_used_portions,
03277 NULL);
03278 }
03279 }
03280 FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
03281 {
03282
03283 if (var
03284 && DECL_SIZE (var)
03285 && var_can_have_subvars (var)
03286 && !MTAG_P (var)
03287 && TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
03288 create_overlap_variables_for (var);
03289 }
03290 htab_delete (used_portions);
03291 VEC_free (tree, heap, varvec);
03292 return 0;
03293 }
03294
03295 static bool
03296 gate_structure_vars (void)
03297 {
03298 return flag_tree_salias != 0;
03299 }
03300
03301 struct tree_opt_pass pass_create_structure_vars =
03302 {
03303 "salias",
03304 gate_structure_vars,
03305 create_structure_vars,
03306 NULL,
03307 NULL,
03308 0,
03309 0,
03310 PROP_cfg,
03311 0,
03312 0,
03313 0,
03314 TODO_dump_func,
03315 0
03316 };
03317
03318
03319
03320
03321 static unsigned int
03322 reset_cc_flags (void)
03323 {
03324 tree var;
03325 referenced_var_iterator rvi;
03326
03327 FOR_EACH_REFERENCED_VAR (var, rvi)
03328 DECL_CALL_CLOBBERED (var) = false;
03329 return 0;
03330 }
03331
03332 struct tree_opt_pass pass_reset_cc_flags =
03333 {
03334 NULL,
03335 NULL,
03336 reset_cc_flags,
03337 NULL,
03338 NULL,
03339 0,
03340 0,
03341 PROP_referenced_vars |PROP_cfg,
03342 0,
03343 0,
03344 0,
03345 0,
03346 0
03347 };