OSDN Git Service

PR c/20740
[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 varray_type 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             stmt_ann_t ann = (stmt_ann_t) t->common.ann;
486             dfa_stats_p->num_stmt_anns++;
487             dfa_stats_p->num_defs += NUM_DEFS (DEF_OPS (ann));
488             dfa_stats_p->num_uses += NUM_USES (USE_OPS (ann));
489             dfa_stats_p->num_v_may_defs +=
490                          NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann));
491             dfa_stats_p->num_vuses += NUM_VUSES (VUSE_OPS (ann));
492             dfa_stats_p->num_v_must_defs +=
493                          NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann));
494             break;
495           }
496
497         case VAR_ANN:
498           dfa_stats_p->num_var_anns++;
499           break;
500
501         default:
502           break;
503         }
504     }
505
506   return NULL;
507 }
508
509
510 /*---------------------------------------------------------------------------
511                              Miscellaneous helpers
512 ---------------------------------------------------------------------------*/
513 /* Callback for walk_tree.  Used to collect variables referenced in
514    the function.  */
515
516 static tree
517 find_vars_r (tree *tp, int *walk_subtrees, void *data)
518 {
519   struct walk_state *walk_state = (struct walk_state *) data;
520
521   /* If T is a regular variable that the optimizers are interested
522      in, add it to the list of variables.  */
523   if (SSA_VAR_P (*tp))
524     add_referenced_var (*tp, walk_state);
525
526   /* Type, _DECL and constant nodes have no interesting children.
527      Ignore them.  */
528   else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
529     *walk_subtrees = 0;
530
531   return NULL_TREE;
532 }
533
534
535 /* Add VAR to the list of dereferenced variables.
536
537    WALK_STATE contains a hash table used to avoid adding the same
538       variable more than once. Note that this function assumes that
539       VAR is a valid SSA variable.  If WALK_STATE is NULL, no
540       duplicate checking is done.  */
541
542 static void
543 add_referenced_var (tree var, struct walk_state *walk_state)
544 {
545   void **slot;
546   var_ann_t v_ann;
547
548   v_ann = get_var_ann (var);
549
550   if (walk_state)
551     slot = htab_find_slot (walk_state->vars_found, (void *) var, INSERT);
552   else
553     slot = NULL;
554
555   if (slot == NULL || *slot == NULL)
556     {
557       /* This is the first time we find this variable, add it to the
558          REFERENCED_VARS array and annotate it with attributes that are
559          intrinsic to the variable.  */
560       if (slot)
561         *slot = (void *) var;
562       v_ann->uid = num_referenced_vars;
563       VARRAY_PUSH_TREE (referenced_vars, var);
564
565       /* Global variables are always call-clobbered.  */
566       if (is_global_var (var))
567         mark_call_clobbered (var);
568
569       /* Scan DECL_INITIAL for pointer variables as they may contain
570          address arithmetic referencing the address of other
571          variables.  */
572       if (DECL_INITIAL (var)
573           /* Initializers of external variables are not useful to the
574              optimizers.  */
575           && !DECL_EXTERNAL (var)
576           /* It's not necessary to walk the initial value of non-constant
577              public variables because it cannot be propagated by the
578              optimizers.  */
579           && (!TREE_PUBLIC (var) || !TREE_CONSTANT (var)))
580         walk_tree (&DECL_INITIAL (var), find_vars_r, walk_state, 0);
581     }
582 }
583
584
585 /* Return the virtual variable associated to the non-scalar variable VAR.  */
586
587 tree
588 get_virtual_var (tree var)
589 {
590   STRIP_NOPS (var);
591
592   if (TREE_CODE (var) == SSA_NAME)
593     var = SSA_NAME_VAR (var);
594
595   while (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR
596          || handled_component_p (var))
597     var = TREE_OPERAND (var, 0);
598
599   /* Treating GIMPLE registers as virtual variables makes no sense.
600      Also complain if we couldn't extract a _DECL out of the original
601      expression.  */
602   gcc_assert (SSA_VAR_P (var));
603   gcc_assert (!is_gimple_reg (var));
604
605   return var;
606 }
607
608 /* Add a temporary variable to REFERENCED_VARS.  This is similar to
609    add_referenced_var, but is used by passes that need to add new temps to
610    the REFERENCED_VARS array after the program has been scanned for
611    variables.  The variable will just receive a new UID and be added
612    to the REFERENCED_VARS array without checking for duplicates.  */
613
614 void
615 add_referenced_tmp_var (tree var)
616 {
617   add_referenced_var (var, NULL);
618 }
619
620
621 /* Mark all the non-SSA variables found in STMT's operands to be
622    processed by update_ssa.  */
623
624 void
625 mark_new_vars_to_rename (tree stmt)
626 {
627   ssa_op_iter iter;
628   tree val;
629   bitmap vars_in_vops_to_rename;
630   bool found_exposed_symbol = false;
631   int v_may_defs_before, v_may_defs_after;
632   int v_must_defs_before, v_must_defs_after;
633
634   vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
635
636   /* Before re-scanning the statement for operands, mark the existing
637      virtual operands to be renamed again.  We do this because when new
638      symbols are exposed, the virtual operands that were here before due to
639      aliasing will probably be removed by the call to get_stmt_operand.
640      Therefore, we need to flag them to be renamed beforehand.
641
642      We flag them in a separate bitmap because we don't really want to
643      rename them if there are not any newly exposed symbols in the
644      statement operands.  */
645   v_may_defs_before = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
646   v_must_defs_before = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
647
648   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, 
649                              SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
650     {
651       if (!DECL_P (val))
652         val = SSA_NAME_VAR (val);
653       bitmap_set_bit (vars_in_vops_to_rename, var_ann (val)->uid);
654     }
655
656   /* Now force an operand re-scan on the statement and mark any newly
657      exposed variables.  */
658   update_stmt (stmt);
659
660   v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
661   v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
662
663   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
664     if (DECL_P (val))
665       {
666         found_exposed_symbol = true;
667         mark_sym_for_renaming (val);
668       }
669
670   /* If we found any newly exposed symbols, or if there are fewer VDEF
671      operands in the statement, add the variables we had set in
672      VARS_IN_VOPS_TO_RENAME to VARS_TO_RENAME.  We need to check for
673      vanishing VDEFs because in those cases, the names that were formerly
674      generated by this statement are not going to be available anymore.  */
675   if (found_exposed_symbol
676       || v_may_defs_before > v_may_defs_after
677       || v_must_defs_before > v_must_defs_after)
678     mark_set_for_renaming (vars_in_vops_to_rename);
679
680   BITMAP_FREE (vars_in_vops_to_rename);
681 }
682
683 /* Find all variables within the gimplified statement that were not previously
684    visible to the function and add them to the referenced variables list.  */
685
686 static tree
687 find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
688                             void *data ATTRIBUTE_UNUSED)
689 {
690   tree t = *tp;
691
692   if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
693     {
694       add_referenced_tmp_var (t);
695       mark_sym_for_renaming (t);
696     }
697
698   if (IS_TYPE_OR_DECL_P (t))
699     *walk_subtrees = 0;
700
701   return NULL;
702 }
703
704 void
705 find_new_referenced_vars (tree *stmt_p)
706 {
707   walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
708 }
709
710
711 /* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
712    we know where REF is accessing, return the variable in REF that has the
713    sub-variables.  If the return value is not NULL, POFFSET will be the
714    offset, in bits, of REF inside the return value, and PSIZE will be the
715    size, in bits, of REF inside the return value.  */
716
717 tree
718 okay_component_ref_for_subvars (tree ref, HOST_WIDE_INT *poffset,
719                                 HOST_WIDE_INT *psize)
720 {
721   tree result = NULL;
722   HOST_WIDE_INT bitsize;
723   HOST_WIDE_INT bitpos;
724   tree offset;
725   enum machine_mode mode;
726   int unsignedp;
727   int volatilep;
728
729   gcc_assert (!SSA_VAR_P (ref));
730   *poffset = 0;  
731   *psize = (unsigned int) -1;
732   
733   if (ref_contains_array_ref (ref))
734     return result;
735   ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
736                              &unsignedp, &volatilep, false);
737   if (TREE_CODE (ref) == INDIRECT_REF)
738     return result;
739   else if (offset == NULL && bitsize != -1 && SSA_VAR_P (ref))
740     {
741       *poffset = bitpos;      
742       *psize = bitsize;
743       if (get_subvars_for_var (ref) != NULL)
744         return ref;
745     }
746   else if (SSA_VAR_P (ref))
747     {
748       if (get_subvars_for_var (ref) != NULL)
749         return ref;
750     }
751   return NULL_TREE;
752 }