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 "hashtab.h"
00027 #include "pointer-set.h"
00028 #include "tree.h"
00029 #include "rtl.h"
00030 #include "tm_p.h"
00031 #include "hard-reg-set.h"
00032 #include "basic-block.h"
00033 #include "output.h"
00034 #include "timevar.h"
00035 #include "expr.h"
00036 #include "ggc.h"
00037 #include "langhooks.h"
00038 #include "flags.h"
00039 #include "function.h"
00040 #include "diagnostic.h"
00041 #include "tree-dump.h"
00042 #include "tree-gimple.h"
00043 #include "tree-flow.h"
00044 #include "tree-inline.h"
00045 #include "tree-pass.h"
00046 #include "convert.h"
00047 #include "params.h"
00048 #include "cgraph.h"
00049
00050
00051
00052
00053 struct dfa_stats_d
00054 {
00055 long num_stmt_anns;
00056 long num_var_anns;
00057 long num_defs;
00058 long num_uses;
00059 long num_phis;
00060 long num_phi_args;
00061 int max_num_phi_args;
00062 long num_v_may_defs;
00063 long num_vuses;
00064 long num_v_must_defs;
00065 };
00066
00067
00068
00069 static void collect_dfa_stats (struct dfa_stats_d *);
00070 static tree collect_dfa_stats_r (tree *, int *, void *);
00071 static tree find_vars_r (tree *, int *, void *);
00072
00073
00074
00075
00076
00077 htab_t referenced_vars;
00078
00079
00080
00081
00082
00083 htab_t default_defs;
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static unsigned int
00098 find_referenced_vars (void)
00099 {
00100 basic_block bb;
00101 block_stmt_iterator si;
00102
00103 FOR_EACH_BB (bb)
00104 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00105 {
00106 tree *stmt_p = bsi_stmt_ptr (si);
00107 walk_tree (stmt_p, find_vars_r, NULL, NULL);
00108 }
00109
00110 return 0;
00111 }
00112
00113 struct tree_opt_pass pass_referenced_vars =
00114 {
00115 NULL,
00116 NULL,
00117 find_referenced_vars,
00118 NULL,
00119 NULL,
00120 0,
00121 TV_FIND_REFERENCED_VARS,
00122 PROP_gimple_leh | PROP_cfg,
00123 PROP_referenced_vars,
00124 0,
00125 0,
00126 0,
00127 0
00128 };
00129
00130
00131
00132
00133
00134
00135
00136 var_ann_t
00137 create_var_ann (tree t)
00138 {
00139 var_ann_t ann;
00140
00141 gcc_assert (t);
00142 gcc_assert (DECL_P (t));
00143 gcc_assert (!t->common.ann || t->common.ann->common.type == VAR_ANN);
00144
00145 ann = GGC_CNEW (struct var_ann_d);
00146
00147 ann->common.type = VAR_ANN;
00148
00149 t->common.ann = (tree_ann_t) ann;
00150
00151 return ann;
00152 }
00153
00154
00155
00156 function_ann_t
00157 create_function_ann (tree t)
00158 {
00159 function_ann_t ann;
00160
00161 gcc_assert (t);
00162 gcc_assert (TREE_CODE (t) == FUNCTION_DECL);
00163 gcc_assert (!t->common.ann || t->common.ann->common.type == FUNCTION_ANN);
00164
00165 ann = ggc_alloc (sizeof (*ann));
00166 memset ((void *) ann, 0, sizeof (*ann));
00167
00168 ann->common.type = FUNCTION_ANN;
00169
00170 t->common.ann = (tree_ann_t) ann;
00171
00172 return ann;
00173 }
00174
00175
00176
00177 stmt_ann_t
00178 create_stmt_ann (tree t)
00179 {
00180 stmt_ann_t ann;
00181
00182 gcc_assert (is_gimple_stmt (t));
00183 gcc_assert (!t->common.ann || t->common.ann->common.type == STMT_ANN);
00184
00185 ann = GGC_CNEW (struct stmt_ann_d);
00186
00187 ann->common.type = STMT_ANN;
00188
00189
00190 ann->modified = true;
00191
00192 t->common.ann = (tree_ann_t) ann;
00193
00194 return ann;
00195 }
00196
00197
00198
00199 tree_ann_common_t
00200 create_tree_common_ann (tree t)
00201 {
00202 tree_ann_common_t ann;
00203
00204 gcc_assert (t);
00205 gcc_assert (!t->common.ann || t->common.ann->common.type == TREE_ANN_COMMON);
00206
00207 ann = GGC_CNEW (struct tree_ann_common_d);
00208
00209 ann->type = TREE_ANN_COMMON;
00210 t->common.ann = (tree_ann_t) ann;
00211
00212 return ann;
00213 }
00214
00215
00216
00217 tree
00218 make_rename_temp (tree type, const char *prefix)
00219 {
00220 tree t = create_tmp_var (type, prefix);
00221
00222 if (TREE_CODE (type) == COMPLEX_TYPE)
00223 DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
00224
00225 if (referenced_vars)
00226 {
00227 add_referenced_var (t);
00228 mark_sym_for_renaming (t);
00229 }
00230
00231 return t;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 void
00243 dump_referenced_vars (FILE *file)
00244 {
00245 tree var;
00246 referenced_var_iterator rvi;
00247
00248 fprintf (file, "\nReferenced variables in %s: %u\n\n",
00249 get_name (current_function_decl), (unsigned) num_referenced_vars);
00250
00251 FOR_EACH_REFERENCED_VAR (var, rvi)
00252 {
00253 fprintf (file, "Variable: ");
00254 dump_variable (file, var);
00255 fprintf (file, "\n");
00256 }
00257 }
00258
00259
00260
00261
00262 void
00263 debug_referenced_vars (void)
00264 {
00265 dump_referenced_vars (stderr);
00266 }
00267
00268
00269
00270
00271 void
00272 dump_subvars_for (FILE *file, tree var)
00273 {
00274 subvar_t sv = get_subvars_for_var (var);
00275
00276 if (!sv)
00277 return;
00278
00279 fprintf (file, "{ ");
00280
00281 for (; sv; sv = sv->next)
00282 {
00283 print_generic_expr (file, sv->var, dump_flags);
00284 fprintf (file, " ");
00285 }
00286
00287 fprintf (file, "}");
00288 }
00289
00290
00291
00292
00293 void
00294 debug_subvars_for (tree var)
00295 {
00296 dump_subvars_for (stderr, var);
00297 }
00298
00299
00300
00301
00302 void
00303 dump_variable (FILE *file, tree var)
00304 {
00305 var_ann_t ann;
00306
00307 if (TREE_CODE (var) == SSA_NAME)
00308 {
00309 if (POINTER_TYPE_P (TREE_TYPE (var)))
00310 dump_points_to_info_for (file, var);
00311 var = SSA_NAME_VAR (var);
00312 }
00313
00314 if (var == NULL_TREE)
00315 {
00316 fprintf (file, "<nil>");
00317 return;
00318 }
00319
00320 print_generic_expr (file, var, dump_flags);
00321
00322 ann = var_ann (var);
00323
00324 fprintf (file, ", UID %u", (unsigned) DECL_UID (var));
00325
00326 fprintf (file, ", ");
00327 print_generic_expr (file, TREE_TYPE (var), dump_flags);
00328
00329 if (ann && ann->symbol_mem_tag)
00330 {
00331 fprintf (file, ", symbol memory tag: ");
00332 print_generic_expr (file, ann->symbol_mem_tag, dump_flags);
00333 }
00334
00335 if (ann && ann->is_aliased)
00336 fprintf (file, ", is aliased");
00337
00338 if (TREE_ADDRESSABLE (var))
00339 fprintf (file, ", is addressable");
00340
00341 if (is_global_var (var))
00342 fprintf (file, ", is global");
00343
00344 if (TREE_THIS_VOLATILE (var))
00345 fprintf (file, ", is volatile");
00346
00347 if (is_call_clobbered (var))
00348 {
00349 fprintf (file, ", call clobbered");
00350 if (dump_flags & TDF_DETAILS)
00351 {
00352 var_ann_t va = var_ann (var);
00353 unsigned int escape_mask = va->escape_mask;
00354
00355 fprintf (file, " (");
00356 if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
00357 fprintf (file, ", stored in global");
00358 if (escape_mask & ESCAPE_TO_ASM)
00359 fprintf (file, ", goes through ASM");
00360 if (escape_mask & ESCAPE_TO_CALL)
00361 fprintf (file, ", passed to call");
00362 if (escape_mask & ESCAPE_BAD_CAST)
00363 fprintf (file, ", bad cast");
00364 if (escape_mask & ESCAPE_TO_RETURN)
00365 fprintf (file, ", returned from func");
00366 if (escape_mask & ESCAPE_TO_PURE_CONST)
00367 fprintf (file, ", passed to pure/const");
00368 if (escape_mask & ESCAPE_IS_GLOBAL)
00369 fprintf (file, ", is global var");
00370 if (escape_mask & ESCAPE_IS_PARM)
00371 fprintf (file, ", is incoming pointer");
00372 if (escape_mask & ESCAPE_UNKNOWN)
00373 fprintf (file, ", unknown escape");
00374 fprintf (file, " )");
00375 }
00376 }
00377
00378 if (default_def (var))
00379 {
00380 fprintf (file, ", default def: ");
00381 print_generic_expr (file, default_def (var), dump_flags);
00382 }
00383
00384 if (may_aliases (var))
00385 {
00386 fprintf (file, ", may aliases: ");
00387 dump_may_aliases_for (file, var);
00388 }
00389
00390 if (get_subvars_for_var (var))
00391 {
00392 fprintf (file, ", sub-vars: ");
00393 dump_subvars_for (file, var);
00394 }
00395
00396 fprintf (file, "\n");
00397 }
00398
00399
00400
00401
00402 void
00403 debug_variable (tree var)
00404 {
00405 dump_variable (stderr, var);
00406 }
00407
00408
00409
00410
00411 void
00412 dump_dfa_stats (FILE *file)
00413 {
00414 struct dfa_stats_d dfa_stats;
00415
00416 unsigned long size, total = 0;
00417 const char * const fmt_str = "%-30s%-13s%12s\n";
00418 const char * const fmt_str_1 = "%-30s%13lu%11lu%c\n";
00419 const char * const fmt_str_3 = "%-43s%11lu%c\n";
00420 const char *funcname
00421 = lang_hooks.decl_printable_name (current_function_decl, 2);
00422
00423 collect_dfa_stats (&dfa_stats);
00424
00425 fprintf (file, "\nDFA Statistics for %s\n\n", funcname);
00426
00427 fprintf (file, "---------------------------------------------------------\n");
00428 fprintf (file, fmt_str, "", " Number of ", "Memory");
00429 fprintf (file, fmt_str, "", " instances ", "used ");
00430 fprintf (file, "---------------------------------------------------------\n");
00431
00432 size = num_referenced_vars * sizeof (tree);
00433 total += size;
00434 fprintf (file, fmt_str_1, "Referenced variables", (unsigned long)num_referenced_vars,
00435 SCALE (size), LABEL (size));
00436
00437 size = dfa_stats.num_stmt_anns * sizeof (struct stmt_ann_d);
00438 total += size;
00439 fprintf (file, fmt_str_1, "Statements annotated", dfa_stats.num_stmt_anns,
00440 SCALE (size), LABEL (size));
00441
00442 size = dfa_stats.num_var_anns * sizeof (struct var_ann_d);
00443 total += size;
00444 fprintf (file, fmt_str_1, "Variables annotated", dfa_stats.num_var_anns,
00445 SCALE (size), LABEL (size));
00446
00447 size = dfa_stats.num_uses * sizeof (tree *);
00448 total += size;
00449 fprintf (file, fmt_str_1, "USE operands", dfa_stats.num_uses,
00450 SCALE (size), LABEL (size));
00451
00452 size = dfa_stats.num_defs * sizeof (tree *);
00453 total += size;
00454 fprintf (file, fmt_str_1, "DEF operands", dfa_stats.num_defs,
00455 SCALE (size), LABEL (size));
00456
00457 size = dfa_stats.num_vuses * sizeof (tree *);
00458 total += size;
00459 fprintf (file, fmt_str_1, "VUSE operands", dfa_stats.num_vuses,
00460 SCALE (size), LABEL (size));
00461
00462 size = dfa_stats.num_v_may_defs * sizeof (tree *);
00463 total += size;
00464 fprintf (file, fmt_str_1, "V_MAY_DEF operands", dfa_stats.num_v_may_defs,
00465 SCALE (size), LABEL (size));
00466
00467 size = dfa_stats.num_v_must_defs * sizeof (tree *);
00468 total += size;
00469 fprintf (file, fmt_str_1, "V_MUST_DEF operands", dfa_stats.num_v_must_defs,
00470 SCALE (size), LABEL (size));
00471
00472 size = dfa_stats.num_phis * sizeof (struct tree_phi_node);
00473 total += size;
00474 fprintf (file, fmt_str_1, "PHI nodes", dfa_stats.num_phis,
00475 SCALE (size), LABEL (size));
00476
00477 size = dfa_stats.num_phi_args * sizeof (struct phi_arg_d);
00478 total += size;
00479 fprintf (file, fmt_str_1, "PHI arguments", dfa_stats.num_phi_args,
00480 SCALE (size), LABEL (size));
00481
00482 fprintf (file, "---------------------------------------------------------\n");
00483 fprintf (file, fmt_str_3, "Total memory used by DFA/SSA data", SCALE (total),
00484 LABEL (total));
00485 fprintf (file, "---------------------------------------------------------\n");
00486 fprintf (file, "\n");
00487
00488 if (dfa_stats.num_phis)
00489 fprintf (file, "Average number of arguments per PHI node: %.1f (max: %d)\n",
00490 (float) dfa_stats.num_phi_args / (float) dfa_stats.num_phis,
00491 dfa_stats.max_num_phi_args);
00492
00493 fprintf (file, "\n");
00494 }
00495
00496
00497
00498
00499 void
00500 debug_dfa_stats (void)
00501 {
00502 dump_dfa_stats (stderr);
00503 }
00504
00505
00506
00507
00508
00509 static void
00510 collect_dfa_stats (struct dfa_stats_d *dfa_stats_p)
00511 {
00512 struct pointer_set_t *pset;
00513 basic_block bb;
00514 block_stmt_iterator i;
00515
00516 gcc_assert (dfa_stats_p);
00517
00518 memset ((void *)dfa_stats_p, 0, sizeof (struct dfa_stats_d));
00519
00520
00521
00522 pset = pointer_set_create ();
00523
00524 for (i = bsi_start (BASIC_BLOCK (NUM_FIXED_BLOCKS));
00525 !bsi_end_p (i); bsi_next (&i))
00526 walk_tree (bsi_stmt_ptr (i), collect_dfa_stats_r, (void *) dfa_stats_p,
00527 pset);
00528
00529 pointer_set_destroy (pset);
00530
00531 FOR_EACH_BB (bb)
00532 {
00533 tree phi;
00534 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00535 {
00536 dfa_stats_p->num_phis++;
00537 dfa_stats_p->num_phi_args += PHI_NUM_ARGS (phi);
00538 if (PHI_NUM_ARGS (phi) > dfa_stats_p->max_num_phi_args)
00539 dfa_stats_p->max_num_phi_args = PHI_NUM_ARGS (phi);
00540 }
00541 }
00542 }
00543
00544
00545
00546
00547
00548 static tree
00549 collect_dfa_stats_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
00550 void *data)
00551 {
00552 tree t = *tp;
00553 struct dfa_stats_d *dfa_stats_p = (struct dfa_stats_d *)data;
00554
00555 if (t->common.ann)
00556 {
00557 switch (ann_type (t->common.ann))
00558 {
00559 case STMT_ANN:
00560 {
00561 dfa_stats_p->num_stmt_anns++;
00562 dfa_stats_p->num_defs += NUM_SSA_OPERANDS (t, SSA_OP_DEF);
00563 dfa_stats_p->num_uses += NUM_SSA_OPERANDS (t, SSA_OP_USE);
00564 dfa_stats_p->num_v_may_defs += NUM_SSA_OPERANDS (t, SSA_OP_VMAYDEF);
00565 dfa_stats_p->num_vuses += NUM_SSA_OPERANDS (t, SSA_OP_VUSE);
00566 dfa_stats_p->num_v_must_defs +=
00567 NUM_SSA_OPERANDS (t, SSA_OP_VMUSTDEF);
00568 break;
00569 }
00570
00571 case VAR_ANN:
00572 dfa_stats_p->num_var_anns++;
00573 break;
00574
00575 default:
00576 break;
00577 }
00578 }
00579
00580 return NULL;
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590 static tree
00591 find_vars_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
00592 {
00593
00594
00595 if (SSA_VAR_P (*tp))
00596 add_referenced_var (*tp);
00597
00598
00599
00600 else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
00601 *walk_subtrees = 0;
00602
00603 return NULL_TREE;
00604 }
00605
00606
00607
00608
00609 tree
00610 referenced_var_lookup (unsigned int uid)
00611 {
00612 struct int_tree_map *h, in;
00613 in.uid = uid;
00614 h = (struct int_tree_map *) htab_find_with_hash (referenced_vars, &in, uid);
00615 gcc_assert (h || uid == 0);
00616 if (h)
00617 return h->to;
00618 return NULL_TREE;
00619 }
00620
00621
00622
00623
00624 bool
00625 referenced_var_check_and_insert (tree to)
00626 {
00627 struct int_tree_map *h, in;
00628 void **loc;
00629 unsigned int uid = DECL_UID (to);
00630
00631 in.uid = uid;
00632 in.to = to;
00633 h = (struct int_tree_map *) htab_find_with_hash (referenced_vars, &in, uid);
00634
00635 if (h)
00636 {
00637
00638
00639 gcc_assert (h->to == to);
00640 return false;
00641 }
00642
00643 h = GGC_NEW (struct int_tree_map);
00644 h->uid = uid;
00645 h->to = to;
00646 loc = htab_find_slot_with_hash (referenced_vars, h, uid, INSERT);
00647 *(struct int_tree_map **) loc = h;
00648 return true;
00649 }
00650
00651
00652
00653
00654 tree
00655 default_def (tree var)
00656 {
00657 struct int_tree_map *h, in;
00658 gcc_assert (SSA_VAR_P (var));
00659 in.uid = DECL_UID (var);
00660 h = (struct int_tree_map *) htab_find_with_hash (default_defs, &in,
00661 DECL_UID (var));
00662 if (h)
00663 return h->to;
00664 return NULL_TREE;
00665 }
00666
00667
00668
00669 void
00670 set_default_def (tree var, tree def)
00671 {
00672 struct int_tree_map in;
00673 struct int_tree_map *h;
00674 void **loc;
00675
00676 gcc_assert (SSA_VAR_P (var));
00677 in.uid = DECL_UID (var);
00678 if (!def && default_def (var))
00679 {
00680 loc = htab_find_slot_with_hash (default_defs, &in, DECL_UID (var), INSERT);
00681 htab_remove_elt (default_defs, *loc);
00682 return;
00683 }
00684 gcc_assert (TREE_CODE (def) == SSA_NAME);
00685 loc = htab_find_slot_with_hash (default_defs, &in, DECL_UID (var), INSERT);
00686
00687 if (!*loc)
00688 {
00689 h = GGC_NEW (struct int_tree_map);
00690 h->uid = DECL_UID (var);
00691 h->to = def;
00692 *(struct int_tree_map **) loc = h;
00693 }
00694 else
00695 {
00696 h = (struct int_tree_map *) *loc;
00697 h->to = def;
00698 }
00699 }
00700
00701
00702
00703 void
00704 add_referenced_var (tree var)
00705 {
00706 var_ann_t v_ann;
00707
00708 v_ann = get_var_ann (var);
00709 gcc_assert (DECL_P (var));
00710
00711
00712 if (referenced_var_check_and_insert (var))
00713 {
00714
00715
00716
00717
00718 if (MTAG_P (var))
00719 return;
00720
00721
00722
00723
00724 if (DECL_INITIAL (var)
00725
00726
00727 && !DECL_EXTERNAL (var)
00728
00729
00730
00731 && (TREE_CONSTANT (var) || TREE_READONLY (var)))
00732 walk_tree (&DECL_INITIAL (var), find_vars_r, NULL, 0);
00733 }
00734 }
00735
00736
00737
00738
00739 tree
00740 get_virtual_var (tree var)
00741 {
00742 STRIP_NOPS (var);
00743
00744 if (TREE_CODE (var) == SSA_NAME)
00745 var = SSA_NAME_VAR (var);
00746
00747 while (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR
00748 || handled_component_p (var))
00749 var = TREE_OPERAND (var, 0);
00750
00751
00752
00753
00754 gcc_assert (SSA_VAR_P (var));
00755 gcc_assert (!is_gimple_reg (var));
00756
00757 return var;
00758 }
00759
00760
00761
00762
00763 void
00764 mark_new_vars_to_rename (tree stmt)
00765 {
00766 ssa_op_iter iter;
00767 tree val;
00768 bitmap vars_in_vops_to_rename;
00769 bool found_exposed_symbol = false;
00770 int v_may_defs_before, v_may_defs_after;
00771 int v_must_defs_before, v_must_defs_after;
00772
00773 if (TREE_CODE (stmt) == PHI_NODE)
00774 return;
00775
00776 get_stmt_ann (stmt);
00777 vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 v_may_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
00789 v_must_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
00790
00791 FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter,
00792 SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
00793 {
00794 if (!DECL_P (val))
00795 val = SSA_NAME_VAR (val);
00796 bitmap_set_bit (vars_in_vops_to_rename, DECL_UID (val));
00797 }
00798
00799
00800
00801 update_stmt (stmt);
00802
00803 v_may_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
00804 v_must_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
00805
00806 FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
00807 if (DECL_P (val))
00808 {
00809 found_exposed_symbol = true;
00810 mark_sym_for_renaming (val);
00811 }
00812
00813
00814
00815
00816
00817
00818 if (found_exposed_symbol
00819 || v_may_defs_before > v_may_defs_after
00820 || v_must_defs_before > v_must_defs_after)
00821 mark_set_for_renaming (vars_in_vops_to_rename);
00822
00823 BITMAP_FREE (vars_in_vops_to_rename);
00824 }
00825
00826
00827
00828
00829 static tree
00830 find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
00831 void *data ATTRIBUTE_UNUSED)
00832 {
00833 tree t = *tp;
00834
00835 if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
00836 {
00837 add_referenced_var (t);
00838 mark_sym_for_renaming (t);
00839 }
00840
00841 if (IS_TYPE_OR_DECL_P (t))
00842 *walk_subtrees = 0;
00843
00844 return NULL;
00845 }
00846
00847 void
00848 find_new_referenced_vars (tree *stmt_p)
00849 {
00850 walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860 tree
00861 get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
00862 HOST_WIDE_INT *psize,
00863 HOST_WIDE_INT *pmax_size)
00864 {
00865 HOST_WIDE_INT bitsize = -1;
00866 HOST_WIDE_INT maxsize = -1;
00867 tree size_tree = NULL_TREE;
00868 tree bit_offset = bitsize_zero_node;
00869 bool seen_variable_array_ref = false;
00870
00871 gcc_assert (!SSA_VAR_P (exp));
00872
00873
00874 if (TREE_CODE (exp) == COMPONENT_REF)
00875 size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
00876 else if (TREE_CODE (exp) == BIT_FIELD_REF)
00877 size_tree = TREE_OPERAND (exp, 1);
00878 else
00879 {
00880 enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
00881 if (mode == BLKmode)
00882 size_tree = TYPE_SIZE (TREE_TYPE (exp));
00883 else
00884 bitsize = GET_MODE_BITSIZE (mode);
00885 }
00886 if (size_tree != NULL_TREE)
00887 {
00888 if (! host_integerp (size_tree, 1))
00889 bitsize = -1;
00890 else
00891 bitsize = TREE_INT_CST_LOW (size_tree);
00892 }
00893
00894
00895
00896 maxsize = bitsize;
00897
00898
00899
00900 while (1)
00901 {
00902 switch (TREE_CODE (exp))
00903 {
00904 case BIT_FIELD_REF:
00905 bit_offset = size_binop (PLUS_EXPR, bit_offset,
00906 TREE_OPERAND (exp, 2));
00907 break;
00908
00909 case COMPONENT_REF:
00910 {
00911 tree field = TREE_OPERAND (exp, 1);
00912 tree this_offset = component_ref_field_offset (exp);
00913
00914 if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
00915 {
00916 this_offset = size_binop (MULT_EXPR,
00917 fold_convert (bitsizetype,
00918 this_offset),
00919 bitsize_unit_node);
00920 bit_offset = size_binop (PLUS_EXPR,
00921 bit_offset, this_offset);
00922 bit_offset = size_binop (PLUS_EXPR, bit_offset,
00923 DECL_FIELD_BIT_OFFSET (field));
00924 }
00925 else
00926 {
00927 tree csize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00928
00929
00930
00931 if (maxsize != -1
00932 && csize && host_integerp (csize, 1))
00933 {
00934 maxsize = (TREE_INT_CST_LOW (csize)
00935 - TREE_INT_CST_LOW (bit_offset));
00936 }
00937 else
00938 maxsize = -1;
00939 }
00940 }
00941 break;
00942
00943 case ARRAY_REF:
00944 case ARRAY_RANGE_REF:
00945 {
00946 tree index = TREE_OPERAND (exp, 1);
00947 tree low_bound = array_ref_low_bound (exp);
00948 tree unit_size = array_ref_element_size (exp);
00949
00950 if (! integer_zerop (low_bound))
00951 index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
00952 index, low_bound);
00953 index = size_binop (MULT_EXPR,
00954 fold_convert (sizetype, index), unit_size);
00955 if (TREE_CODE (index) == INTEGER_CST)
00956 {
00957 index = size_binop (MULT_EXPR,
00958 fold_convert (bitsizetype, index),
00959 bitsize_unit_node);
00960 bit_offset = size_binop (PLUS_EXPR, bit_offset, index);
00961
00962
00963
00964
00965 seen_variable_array_ref = false;
00966 }
00967 else
00968 {
00969 tree asize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00970
00971
00972
00973 if (maxsize != -1
00974 && asize && host_integerp (asize, 1))
00975 {
00976 maxsize = (TREE_INT_CST_LOW (asize)
00977 - TREE_INT_CST_LOW (bit_offset));
00978 }
00979 else
00980 maxsize = -1;
00981
00982
00983
00984 seen_variable_array_ref = true;
00985 }
00986 }
00987 break;
00988
00989 case REALPART_EXPR:
00990 break;
00991
00992 case IMAGPART_EXPR:
00993 bit_offset = size_binop (PLUS_EXPR, bit_offset,
00994 bitsize_int (bitsize));
00995 break;
00996
00997 case VIEW_CONVERT_EXPR:
00998
00999 break;
01000
01001 default:
01002 goto done;
01003 }
01004
01005 exp = TREE_OPERAND (exp, 0);
01006 }
01007 done:
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 if (seen_variable_array_ref
01018 && maxsize != -1
01019 && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
01020 && TREE_INT_CST_LOW (bit_offset) + maxsize
01021 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))
01022 maxsize = -1;
01023
01024
01025
01026
01027 *poffset = TREE_INT_CST_LOW (bit_offset);
01028 *psize = bitsize;
01029 *pmax_size = maxsize;
01030
01031 return exp;
01032 }