OSDN Git Service

* tree-dfa.c (referenced_vars, add_referenced_var): Use VEC
[pf3gnuchains/gcc-fork.git] / gcc / tree-dfa.c
1 /* Data flow functions for trees.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3    Contributed by Diego Novillo <dnovillo@redhat.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "hashtab.h"
27 #include "pointer-set.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "tm_p.h"
31 #include "hard-reg-set.h"
32 #include "basic-block.h"
33 #include "output.h"
34 #include "errors.h"
35 #include "timevar.h"
36 #include "expr.h"
37 #include "ggc.h"
38 #include "langhooks.h"
39 #include "flags.h"
40 #include "function.h"
41 #include "diagnostic.h"
42 #include "tree-dump.h"
43 #include "tree-gimple.h"
44 #include "tree-flow.h"
45 #include "tree-inline.h"
46 #include "tree-pass.h"
47 #include "convert.h"
48 #include "params.h"
49 #include "cgraph.h"
50
51 /* Build and maintain data flow information for trees.  */
52
53 /* Counters used to display DFA and SSA statistics.  */
54 struct dfa_stats_d
55 {
56   long num_stmt_anns;
57   long num_var_anns;
58   long num_defs;
59   long num_uses;
60   long num_phis;
61   long num_phi_args;
62   int max_num_phi_args;
63   long num_v_may_defs;
64   long num_vuses;
65   long num_v_must_defs;
66 };
67
68
69 /* State information for find_vars_r.  */
70 struct walk_state
71 {
72   /* Hash table used to avoid adding the same variable more than once.  */
73   htab_t vars_found;
74 };
75
76
77 /* Local functions.  */
78 static void collect_dfa_stats (struct dfa_stats_d *);
79 static tree collect_dfa_stats_r (tree *, int *, void *);
80 static tree find_vars_r (tree *, int *, void *);
81 static void add_referenced_var (tree, struct walk_state *);
82
83
84 /* Global declarations.  */
85
86 /* Array of all variables referenced in the function.  */
87 VEC(tree,gc) *referenced_vars;
88
89
90 /*---------------------------------------------------------------------------
91                         Dataflow analysis (DFA) routines
92 ---------------------------------------------------------------------------*/
93 /* Find all the variables referenced in the function.  This function
94    builds the global arrays REFERENCED_VARS and CALL_CLOBBERED_VARS.
95
96    Note that this function does not look for statement operands, it simply
97    determines what variables are referenced in the program and detects
98    various attributes for each variable used by alias analysis and the
99    optimizer.  */
100
101 static void
102 find_referenced_vars (void)
103 {
104   htab_t vars_found;
105   basic_block bb;
106   block_stmt_iterator si;
107   struct walk_state walk_state;
108
109   vars_found = htab_create (50, htab_hash_pointer, htab_eq_pointer, NULL);
110   memset (&walk_state, 0, sizeof (walk_state));
111   walk_state.vars_found = vars_found;
112
113   FOR_EACH_BB (bb)
114     for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
115       {
116         tree *stmt_p = bsi_stmt_ptr (si);
117         walk_tree (stmt_p, find_vars_r, &walk_state, NULL);
118       }
119
120   htab_delete (vars_found);
121 }
122
123 struct tree_opt_pass pass_referenced_vars =
124 {
125   NULL,                                 /* name */
126   NULL,                                 /* gate */
127   find_referenced_vars,                 /* execute */
128   NULL,                                 /* sub */
129   NULL,                                 /* next */
130   0,                                    /* static_pass_number */
131   TV_FIND_REFERENCED_VARS,              /* tv_id */
132   PROP_gimple_leh | PROP_cfg,           /* properties_required */
133   PROP_referenced_vars,                 /* properties_provided */
134   0,                                    /* properties_destroyed */
135   0,                                    /* todo_flags_start */
136   0,                                    /* todo_flags_finish */
137   0                                     /* letter */
138 };
139
140
141 /*---------------------------------------------------------------------------
142                             Manage annotations
143 ---------------------------------------------------------------------------*/
144 /* Create a new annotation for a _DECL node T.  */
145
146 var_ann_t
147 create_var_ann (tree t)
148 {
149   var_ann_t ann;
150
151   gcc_assert (t);
152   gcc_assert (DECL_P (t));
153   gcc_assert (!t->common.ann || t->common.ann->common.type == VAR_ANN);
154
155   ann = ggc_alloc (sizeof (*ann));
156   memset ((void *) ann, 0, sizeof (*ann));
157
158   ann->common.type = VAR_ANN;
159
160   t->common.ann = (tree_ann_t) ann;
161
162   return ann;
163 }
164
165
166 /* Create a new annotation for a statement node T.  */
167
168 stmt_ann_t
169 create_stmt_ann (tree t)
170 {
171   stmt_ann_t ann;
172
173   gcc_assert (is_gimple_stmt (t));
174   gcc_assert (!t->common.ann || t->common.ann->common.type == STMT_ANN);
175
176   ann = ggc_alloc (sizeof (*ann));
177   memset ((void *) ann, 0, sizeof (*ann));
178
179   ann->common.type = STMT_ANN;
180
181   /* Since we just created the annotation, mark the statement modified.  */
182   ann->modified = true;
183
184   t->common.ann = (tree_ann_t) ann;
185
186   return ann;
187 }
188
189
190 /* Create a new annotation for a tree T.  */
191
192 tree_ann_t
193 create_tree_ann (tree t)
194 {
195   tree_ann_t ann;
196
197   gcc_assert (t);
198   gcc_assert (!t->common.ann || t->common.ann->common.type == TREE_ANN_COMMON);
199
200   ann = ggc_alloc (sizeof (*ann));
201   memset ((void *) ann, 0, sizeof (*ann));
202
203   ann->common.type = TREE_ANN_COMMON;
204   t->common.ann = ann;
205
206   return ann;
207 }
208
209 /* Build a temporary.  Make sure and register it to be renamed.  */
210
211 tree
212 make_rename_temp (tree type, const char *prefix)
213 {
214   tree t = create_tmp_var (type, prefix);
215   if (referenced_vars)
216     {
217       add_referenced_tmp_var (t);
218       mark_sym_for_renaming (t);
219     }
220
221   return t;
222 }
223
224
225
226 /*---------------------------------------------------------------------------
227                               Debugging functions
228 ---------------------------------------------------------------------------*/
229 /* Dump the list of all the referenced variables in the current function to
230    FILE.  */
231
232 void
233 dump_referenced_vars (FILE *file)
234 {
235   size_t i;
236
237   fprintf (file, "\nReferenced variables in %s: %u\n\n",
238            get_name (current_function_decl), (unsigned) num_referenced_vars);
239
240   for (i = 0; i < num_referenced_vars; i++)
241     {
242       tree var = referenced_var (i);
243       fprintf (file, "Variable: ");
244       dump_variable (file, var);
245       fprintf (file, "\n");
246     }
247 }
248
249
250 /* Dump the list of all the referenced variables to stderr.  */
251
252 void
253 debug_referenced_vars (void)
254 {
255   dump_referenced_vars (stderr);
256 }
257
258
259 /* Dump variable VAR and its may-aliases to FILE.  */
260
261 void
262 dump_variable (FILE *file, tree var)
263 {
264   var_ann_t ann;
265
266   if (TREE_CODE (var) == SSA_NAME)
267     {
268       if (POINTER_TYPE_P (TREE_TYPE (var)))
269         dump_points_to_info_for (file, var);
270       var = SSA_NAME_VAR (var);
271     }
272
273   if (var == NULL_TREE)
274     {
275       fprintf (file, "<nil>");
276       return;
277     }
278
279   print_generic_expr (file, var, dump_flags);
280
281   ann = var_ann (var);
282
283   fprintf (file, ", UID %u", (unsigned) ann->uid);
284
285   fprintf (file, ", ");
286   print_generic_expr (file, TREE_TYPE (var), dump_flags);
287
288   if (ann->type_mem_tag)
289     {
290       fprintf (file, ", type memory tag: ");
291       print_generic_expr (file, ann->type_mem_tag, dump_flags);
292     }
293
294   if (ann->is_alias_tag)
295     fprintf (file, ", is an alias tag");
296
297   if (TREE_ADDRESSABLE (var))
298     fprintf (file, ", is addressable");
299   
300   if (is_global_var (var))
301     fprintf (file, ", is global");
302
303   if (TREE_THIS_VOLATILE (var))
304     fprintf (file, ", is volatile");
305
306   if (is_call_clobbered (var))
307     fprintf (file, ", call clobbered");
308
309   if (ann->default_def)
310     {
311       fprintf (file, ", default def: ");
312       print_generic_expr (file, ann->default_def, dump_flags);
313     }
314
315   if (ann->may_aliases)
316     {
317       fprintf (file, ", may aliases: ");
318       dump_may_aliases_for (file, var);
319     }
320
321   fprintf (file, "\n");
322 }
323
324
325 /* Dump variable VAR and its may-aliases to stderr.  */
326
327 void
328 debug_variable (tree var)
329 {
330   dump_variable (stderr, var);
331 }
332
333
334 /* Dump various DFA statistics to FILE.  */
335
336 void
337 dump_dfa_stats (FILE *file)
338 {
339   struct dfa_stats_d dfa_stats;
340
341   unsigned long size, total = 0;
342   const char * const fmt_str   = "%-30s%-13s%12s\n";
343   const char * const fmt_str_1 = "%-30s%13lu%11lu%c\n";
344   const char * const fmt_str_3 = "%-43s%11lu%c\n";
345   const char *funcname
346     = lang_hooks.decl_printable_name (current_function_decl, 2);
347
348   collect_dfa_stats (&dfa_stats);
349
350   fprintf (file, "\nDFA Statistics for %s\n\n", funcname);
351
352   fprintf (file, "---------------------------------------------------------\n");
353   fprintf (file, fmt_str, "", "  Number of  ", "Memory");
354   fprintf (file, fmt_str, "", "  instances  ", "used ");
355   fprintf (file, "---------------------------------------------------------\n");
356
357   size = num_referenced_vars * sizeof (tree);
358   total += size;
359   fprintf (file, fmt_str_1, "Referenced variables", (unsigned long)num_referenced_vars,
360            SCALE (size), LABEL (size));
361
362   size = dfa_stats.num_stmt_anns * sizeof (struct stmt_ann_d);
363   total += size;
364   fprintf (file, fmt_str_1, "Statements annotated", dfa_stats.num_stmt_anns,
365            SCALE (size), LABEL (size));
366
367   size = dfa_stats.num_var_anns * sizeof (struct var_ann_d);
368   total += size;
369   fprintf (file, fmt_str_1, "Variables annotated", dfa_stats.num_var_anns,
370            SCALE (size), LABEL (size));
371
372   size = dfa_stats.num_uses * sizeof (tree *);
373   total += size;
374   fprintf (file, fmt_str_1, "USE operands", dfa_stats.num_uses,
375            SCALE (size), LABEL (size));
376
377   size = dfa_stats.num_defs * sizeof (tree *);
378   total += size;
379   fprintf (file, fmt_str_1, "DEF operands", dfa_stats.num_defs,
380            SCALE (size), LABEL (size));
381
382   size = dfa_stats.num_vuses * sizeof (tree *);
383   total += size;
384   fprintf (file, fmt_str_1, "VUSE operands", dfa_stats.num_vuses,
385            SCALE (size), LABEL (size));
386
387   size = dfa_stats.num_v_may_defs * sizeof (tree *);
388   total += size;
389   fprintf (file, fmt_str_1, "V_MAY_DEF operands", dfa_stats.num_v_may_defs,
390            SCALE (size), LABEL (size));
391
392   size = dfa_stats.num_v_must_defs * sizeof (tree *);
393   total += size;
394   fprintf (file, fmt_str_1, "V_MUST_DEF operands", dfa_stats.num_v_must_defs,
395            SCALE (size), LABEL (size));
396
397   size = dfa_stats.num_phis * sizeof (struct tree_phi_node);
398   total += size;
399   fprintf (file, fmt_str_1, "PHI nodes", dfa_stats.num_phis,
400            SCALE (size), LABEL (size));
401
402   size = dfa_stats.num_phi_args * sizeof (struct phi_arg_d);
403   total += size;
404   fprintf (file, fmt_str_1, "PHI arguments", dfa_stats.num_phi_args,
405            SCALE (size), LABEL (size));
406
407   fprintf (file, "---------------------------------------------------------\n");
408   fprintf (file, fmt_str_3, "Total memory used by DFA/SSA data", SCALE (total),
409            LABEL (total));
410   fprintf (file, "---------------------------------------------------------\n");
411   fprintf (file, "\n");
412
413   if (dfa_stats.num_phis)
414     fprintf (file, "Average number of arguments per PHI node: %.1f (max: %d)\n",
415              (float) dfa_stats.num_phi_args / (float) dfa_stats.num_phis,
416              dfa_stats.max_num_phi_args);
417
418   fprintf (file, "\n");
419 }
420
421
422 /* Dump DFA statistics on stderr.  */
423
424 void
425 debug_dfa_stats (void)
426 {
427   dump_dfa_stats (stderr);
428 }
429
430
431 /* Collect DFA statistics and store them in the structure pointed by
432    DFA_STATS_P.  */
433
434 static void
435 collect_dfa_stats (struct dfa_stats_d *dfa_stats_p)
436 {
437   struct pointer_set_t *pset;
438   basic_block bb;
439   block_stmt_iterator i;
440
441   gcc_assert (dfa_stats_p);
442
443   memset ((void *)dfa_stats_p, 0, sizeof (struct dfa_stats_d));
444
445   /* Walk all the trees in the function counting references.  Start at
446      basic block 0, but don't stop at block boundaries.  */
447   pset = pointer_set_create ();
448
449   for (i = bsi_start (BASIC_BLOCK (0)); !bsi_end_p (i); bsi_next (&i))
450     walk_tree (bsi_stmt_ptr (i), collect_dfa_stats_r, (void *) dfa_stats_p,
451                pset);
452
453   pointer_set_destroy (pset);
454
455   FOR_EACH_BB (bb)
456     {
457       tree phi;
458       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
459         {
460           dfa_stats_p->num_phis++;
461           dfa_stats_p->num_phi_args += PHI_NUM_ARGS (phi);
462           if (PHI_NUM_ARGS (phi) > dfa_stats_p->max_num_phi_args)
463             dfa_stats_p->max_num_phi_args = PHI_NUM_ARGS (phi);
464         }
465     }
466 }
467
468
469 /* Callback for walk_tree to collect DFA statistics for a tree and its
470    children.  */
471
472 static tree
473 collect_dfa_stats_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
474                      void *data)
475 {
476   tree t = *tp;
477   struct dfa_stats_d *dfa_stats_p = (struct dfa_stats_d *)data;
478
479   if (t->common.ann)
480     {
481       switch (ann_type (t->common.ann))
482         {
483         case STMT_ANN:
484           {
485             dfa_stats_p->num_stmt_anns++;
486             dfa_stats_p->num_defs += NUM_SSA_OPERANDS (t, SSA_OP_DEF);
487             dfa_stats_p->num_uses += NUM_SSA_OPERANDS (t, SSA_OP_USE);
488             dfa_stats_p->num_v_may_defs += NUM_SSA_OPERANDS (t, SSA_OP_VMAYDEF);
489             dfa_stats_p->num_vuses += NUM_SSA_OPERANDS (t, SSA_OP_VUSE);
490             dfa_stats_p->num_v_must_defs += 
491                                   NUM_SSA_OPERANDS (t, SSA_OP_VMUSTDEF);
492             break;
493           }
494
495         case VAR_ANN:
496           dfa_stats_p->num_var_anns++;
497           break;
498
499         default:
500           break;
501         }
502     }
503
504   return NULL;
505 }
506
507
508 /*---------------------------------------------------------------------------
509                              Miscellaneous helpers
510 ---------------------------------------------------------------------------*/
511 /* Callback for walk_tree.  Used to collect variables referenced in
512    the function.  */
513
514 static tree
515 find_vars_r (tree *tp, int *walk_subtrees, void *data)
516 {
517   struct walk_state *walk_state = (struct walk_state *) data;
518
519   /* If T is a regular variable that the optimizers are interested
520      in, add it to the list of variables.  */
521   if (SSA_VAR_P (*tp))
522     add_referenced_var (*tp, walk_state);
523
524   /* Type, _DECL and constant nodes have no interesting children.
525      Ignore them.  */
526   else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
527     *walk_subtrees = 0;
528
529   return NULL_TREE;
530 }
531
532
533 /* Add VAR to the list of dereferenced variables.
534
535    WALK_STATE contains a hash table used to avoid adding the same
536       variable more than once. Note that this function assumes that
537       VAR is a valid SSA variable.  If WALK_STATE is NULL, no
538       duplicate checking is done.  */
539
540 static void
541 add_referenced_var (tree var, struct walk_state *walk_state)
542 {
543   void **slot;
544   var_ann_t v_ann;
545
546   v_ann = get_var_ann (var);
547
548   if (walk_state)
549     slot = htab_find_slot (walk_state->vars_found, (void *) var, INSERT);
550   else
551     slot = NULL;
552
553   if (slot == NULL || *slot == NULL)
554     {
555       /* This is the first time we find this variable, add it to the
556          REFERENCED_VARS array and annotate it with attributes that are
557          intrinsic to the variable.  */
558       if (slot)
559         *slot = (void *) var;
560       v_ann->uid = num_referenced_vars;
561       VEC_safe_push (tree, gc, referenced_vars, var);
562
563       /* Global variables are always call-clobbered.  */
564       if (is_global_var (var))
565         mark_call_clobbered (var);
566
567       /* Scan DECL_INITIAL for pointer variables as they may contain
568          address arithmetic referencing the address of other
569          variables.  */
570       if (DECL_INITIAL (var)
571           /* Initializers of external variables are not useful to the
572              optimizers.  */
573           && !DECL_EXTERNAL (var)
574           /* It's not necessary to walk the initial value of non-constant
575              public variables because it cannot be propagated by the
576              optimizers.  */
577           && (!TREE_PUBLIC (var) || !TREE_CONSTANT (var)))
578         walk_tree (&DECL_INITIAL (var), find_vars_r, walk_state, 0);
579     }
580 }
581
582
583 /* Return the virtual variable associated to the non-scalar variable VAR.  */
584
585 tree
586 get_virtual_var (tree var)
587 {
588   STRIP_NOPS (var);
589
590   if (TREE_CODE (var) == SSA_NAME)
591     var = SSA_NAME_VAR (var);
592
593   while (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR
594          || handled_component_p (var))
595     var = TREE_OPERAND (var, 0);
596
597   /* Treating GIMPLE registers as virtual variables makes no sense.
598      Also complain if we couldn't extract a _DECL out of the original
599      expression.  */
600   gcc_assert (SSA_VAR_P (var));
601   gcc_assert (!is_gimple_reg (var));
602
603   return var;
604 }
605
606 /* Add a temporary variable to REFERENCED_VARS.  This is similar to
607    add_referenced_var, but is used by passes that need to add new temps to
608    the REFERENCED_VARS array after the program has been scanned for
609    variables.  The variable will just receive a new UID and be added
610    to the REFERENCED_VARS array without checking for duplicates.  */
611
612 void
613 add_referenced_tmp_var (tree var)
614 {
615   add_referenced_var (var, NULL);
616 }
617
618
619 /* Mark all the non-SSA variables found in STMT's operands to be
620    processed by update_ssa.  */
621
622 void
623 mark_new_vars_to_rename (tree stmt)
624 {
625   ssa_op_iter iter;
626   tree val;
627   bitmap vars_in_vops_to_rename;
628   bool found_exposed_symbol = false;
629   int v_may_defs_before, v_may_defs_after;
630   int v_must_defs_before, v_must_defs_after;
631
632   vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
633
634   /* Before re-scanning the statement for operands, mark the existing
635      virtual operands to be renamed again.  We do this because when new
636      symbols are exposed, the virtual operands that were here before due to
637      aliasing will probably be removed by the call to get_stmt_operand.
638      Therefore, we need to flag them to be renamed beforehand.
639
640      We flag them in a separate bitmap because we don't really want to
641      rename them if there are not any newly exposed symbols in the
642      statement operands.  */
643   v_may_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
644   v_must_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
645
646   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, 
647                              SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
648     {
649       if (!DECL_P (val))
650         val = SSA_NAME_VAR (val);
651       bitmap_set_bit (vars_in_vops_to_rename, var_ann (val)->uid);
652     }
653
654   /* Now force an operand re-scan on the statement and mark any newly
655      exposed variables.  */
656   update_stmt (stmt);
657
658   v_may_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
659   v_must_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
660
661   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
662     if (DECL_P (val))
663       {
664         found_exposed_symbol = true;
665         mark_sym_for_renaming (val);
666       }
667
668   /* If we found any newly exposed symbols, or if there are fewer VDEF
669      operands in the statement, add the variables we had set in
670      VARS_IN_VOPS_TO_RENAME to VARS_TO_RENAME.  We need to check for
671      vanishing VDEFs because in those cases, the names that were formerly
672      generated by this statement are not going to be available anymore.  */
673   if (found_exposed_symbol
674       || v_may_defs_before > v_may_defs_after
675       || v_must_defs_before > v_must_defs_after)
676     mark_set_for_renaming (vars_in_vops_to_rename);
677
678   BITMAP_FREE (vars_in_vops_to_rename);
679 }
680
681 /* Find all variables within the gimplified statement that were not previously
682    visible to the function and add them to the referenced variables list.  */
683
684 static tree
685 find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
686                             void *data ATTRIBUTE_UNUSED)
687 {
688   tree t = *tp;
689
690   if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
691     {
692       add_referenced_tmp_var (t);
693       mark_sym_for_renaming (t);
694     }
695
696   if (IS_TYPE_OR_DECL_P (t))
697     *walk_subtrees = 0;
698
699   return NULL;
700 }
701
702 void
703 find_new_referenced_vars (tree *stmt_p)
704 {
705   walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
706 }
707
708
709 /* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
710    we know where REF is accessing, return the variable in REF that has the
711    sub-variables.  If the return value is not NULL, POFFSET will be the
712    offset, in bits, of REF inside the return value, and PSIZE will be the
713    size, in bits, of REF inside the return value.  */
714
715 tree
716 okay_component_ref_for_subvars (tree ref, HOST_WIDE_INT *poffset,
717                                 HOST_WIDE_INT *psize)
718 {
719   tree result = NULL;
720   HOST_WIDE_INT bitsize;
721   HOST_WIDE_INT bitpos;
722   tree offset;
723   enum machine_mode mode;
724   int unsignedp;
725   int volatilep;
726
727   gcc_assert (!SSA_VAR_P (ref));
728   *poffset = 0;  
729   *psize = (unsigned int) -1;
730   
731   if (ref_contains_array_ref (ref))
732     return result;
733   ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
734                              &unsignedp, &volatilep, false);
735   if (TREE_CODE (ref) == INDIRECT_REF)
736     return result;
737   else if (offset == NULL && bitsize != -1 && SSA_VAR_P (ref))
738     {
739       *poffset = bitpos;      
740       *psize = bitsize;
741       if (get_subvars_for_var (ref) != NULL)
742         return ref;
743     }
744   else if (SSA_VAR_P (ref))
745     {
746       if (get_subvars_for_var (ref) != NULL)
747         return ref;
748     }
749   return NULL_TREE;
750 }