OSDN Git Service

* system.h: Poison PARAMS.
[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       bitmap_set_bit (vars_to_rename, var_ann (t)->uid);
219     }
220   return t;
221 }
222
223
224
225 /*---------------------------------------------------------------------------
226                               Debugging functions
227 ---------------------------------------------------------------------------*/
228 /* Dump the list of all the referenced variables in the current function to
229    FILE.  */
230
231 void
232 dump_referenced_vars (FILE *file)
233 {
234   size_t i;
235
236   fprintf (file, "\nReferenced variables in %s: %u\n\n",
237            get_name (current_function_decl), (unsigned) num_referenced_vars);
238
239   for (i = 0; i < num_referenced_vars; i++)
240     {
241       tree var = referenced_var (i);
242       fprintf (file, "Variable: ");
243       dump_variable (file, var);
244       fprintf (file, "\n");
245     }
246 }
247
248
249 /* Dump the list of all the referenced variables to stderr.  */
250
251 void
252 debug_referenced_vars (void)
253 {
254   dump_referenced_vars (stderr);
255 }
256
257
258 /* Dump variable VAR and its may-aliases to FILE.  */
259
260 void
261 dump_variable (FILE *file, tree var)
262 {
263   var_ann_t ann;
264
265   if (TREE_CODE (var) == SSA_NAME)
266     {
267       if (POINTER_TYPE_P (TREE_TYPE (var)))
268         dump_points_to_info_for (file, var);
269       var = SSA_NAME_VAR (var);
270     }
271
272   if (var == NULL_TREE)
273     {
274       fprintf (file, "<nil>");
275       return;
276     }
277
278   print_generic_expr (file, var, dump_flags);
279
280   ann = var_ann (var);
281
282   fprintf (file, ", UID %u", (unsigned) ann->uid);
283
284   fprintf (file, ", ");
285   print_generic_expr (file, TREE_TYPE (var), dump_flags);
286
287   if (ann->type_mem_tag)
288     {
289       fprintf (file, ", type memory tag: ");
290       print_generic_expr (file, ann->type_mem_tag, dump_flags);
291     }
292
293   if (ann->is_alias_tag)
294     fprintf (file, ", is an alias tag");
295
296   if (TREE_ADDRESSABLE (var))
297     fprintf (file, ", is addressable");
298   
299   if (is_global_var (var))
300     fprintf (file, ", is global");
301
302   if (TREE_THIS_VOLATILE (var))
303     fprintf (file, ", is volatile");
304
305   if (is_call_clobbered (var))
306     fprintf (file, ", call clobbered");
307
308   if (ann->default_def)
309     {
310       fprintf (file, ", default def: ");
311       print_generic_expr (file, ann->default_def, dump_flags);
312     }
313
314   if (ann->may_aliases)
315     {
316       fprintf (file, ", may aliases: ");
317       dump_may_aliases_for (file, var);
318     }
319
320   fprintf (file, "\n");
321 }
322
323
324 /* Dump variable VAR and its may-aliases to stderr.  */
325
326 void
327 debug_variable (tree var)
328 {
329   dump_variable (stderr, var);
330 }
331
332
333 /* Dump various DFA statistics to FILE.  */
334
335 void
336 dump_dfa_stats (FILE *file)
337 {
338   struct dfa_stats_d dfa_stats;
339
340   unsigned long size, total = 0;
341   const char * const fmt_str   = "%-30s%-13s%12s\n";
342   const char * const fmt_str_1 = "%-30s%13lu%11lu%c\n";
343   const char * const fmt_str_3 = "%-43s%11lu%c\n";
344   const char *funcname
345     = lang_hooks.decl_printable_name (current_function_decl, 2);
346
347   collect_dfa_stats (&dfa_stats);
348
349   fprintf (file, "\nDFA Statistics for %s\n\n", funcname);
350
351   fprintf (file, "---------------------------------------------------------\n");
352   fprintf (file, fmt_str, "", "  Number of  ", "Memory");
353   fprintf (file, fmt_str, "", "  instances  ", "used ");
354   fprintf (file, "---------------------------------------------------------\n");
355
356   size = num_referenced_vars * sizeof (tree);
357   total += size;
358   fprintf (file, fmt_str_1, "Referenced variables", (unsigned long)num_referenced_vars,
359            SCALE (size), LABEL (size));
360
361   size = dfa_stats.num_stmt_anns * sizeof (struct stmt_ann_d);
362   total += size;
363   fprintf (file, fmt_str_1, "Statements annotated", dfa_stats.num_stmt_anns,
364            SCALE (size), LABEL (size));
365
366   size = dfa_stats.num_var_anns * sizeof (struct var_ann_d);
367   total += size;
368   fprintf (file, fmt_str_1, "Variables annotated", dfa_stats.num_var_anns,
369            SCALE (size), LABEL (size));
370
371   size = dfa_stats.num_uses * sizeof (tree *);
372   total += size;
373   fprintf (file, fmt_str_1, "USE operands", dfa_stats.num_uses,
374            SCALE (size), LABEL (size));
375
376   size = dfa_stats.num_defs * sizeof (tree *);
377   total += size;
378   fprintf (file, fmt_str_1, "DEF operands", dfa_stats.num_defs,
379            SCALE (size), LABEL (size));
380
381   size = dfa_stats.num_vuses * sizeof (tree *);
382   total += size;
383   fprintf (file, fmt_str_1, "VUSE operands", dfa_stats.num_vuses,
384            SCALE (size), LABEL (size));
385
386   size = dfa_stats.num_v_may_defs * sizeof (tree *);
387   total += size;
388   fprintf (file, fmt_str_1, "V_MAY_DEF operands", dfa_stats.num_v_may_defs,
389            SCALE (size), LABEL (size));
390
391   size = dfa_stats.num_v_must_defs * sizeof (tree *);
392   total += size;
393   fprintf (file, fmt_str_1, "V_MUST_DEF operands", dfa_stats.num_v_must_defs,
394            SCALE (size), LABEL (size));
395
396   size = dfa_stats.num_phis * sizeof (struct tree_phi_node);
397   total += size;
398   fprintf (file, fmt_str_1, "PHI nodes", dfa_stats.num_phis,
399            SCALE (size), LABEL (size));
400
401   size = dfa_stats.num_phi_args * sizeof (struct phi_arg_d);
402   total += size;
403   fprintf (file, fmt_str_1, "PHI arguments", dfa_stats.num_phi_args,
404            SCALE (size), LABEL (size));
405
406   fprintf (file, "---------------------------------------------------------\n");
407   fprintf (file, fmt_str_3, "Total memory used by DFA/SSA data", SCALE (total),
408            LABEL (total));
409   fprintf (file, "---------------------------------------------------------\n");
410   fprintf (file, "\n");
411
412   if (dfa_stats.num_phis)
413     fprintf (file, "Average number of arguments per PHI node: %.1f (max: %d)\n",
414              (float) dfa_stats.num_phi_args / (float) dfa_stats.num_phis,
415              dfa_stats.max_num_phi_args);
416
417   fprintf (file, "\n");
418 }
419
420
421 /* Dump DFA statistics on stderr.  */
422
423 void
424 debug_dfa_stats (void)
425 {
426   dump_dfa_stats (stderr);
427 }
428
429
430 /* Collect DFA statistics and store them in the structure pointed by
431    DFA_STATS_P.  */
432
433 static void
434 collect_dfa_stats (struct dfa_stats_d *dfa_stats_p)
435 {
436   struct pointer_set_t *pset;
437   basic_block bb;
438   block_stmt_iterator i;
439
440   gcc_assert (dfa_stats_p);
441
442   memset ((void *)dfa_stats_p, 0, sizeof (struct dfa_stats_d));
443
444   /* Walk all the trees in the function counting references.  Start at
445      basic block 0, but don't stop at block boundaries.  */
446   pset = pointer_set_create ();
447
448   for (i = bsi_start (BASIC_BLOCK (0)); !bsi_end_p (i); bsi_next (&i))
449     walk_tree (bsi_stmt_ptr (i), collect_dfa_stats_r, (void *) dfa_stats_p,
450                pset);
451
452   pointer_set_destroy (pset);
453
454   FOR_EACH_BB (bb)
455     {
456       tree phi;
457       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
458         {
459           dfa_stats_p->num_phis++;
460           dfa_stats_p->num_phi_args += PHI_NUM_ARGS (phi);
461           if (PHI_NUM_ARGS (phi) > dfa_stats_p->max_num_phi_args)
462             dfa_stats_p->max_num_phi_args = PHI_NUM_ARGS (phi);
463         }
464     }
465 }
466
467
468 /* Callback for walk_tree to collect DFA statistics for a tree and its
469    children.  */
470
471 static tree
472 collect_dfa_stats_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
473                      void *data)
474 {
475   tree t = *tp;
476   struct dfa_stats_d *dfa_stats_p = (struct dfa_stats_d *)data;
477
478   if (t->common.ann)
479     {
480       switch (ann_type (t->common.ann))
481         {
482         case STMT_ANN:
483           {
484             stmt_ann_t ann = (stmt_ann_t) t->common.ann;
485             dfa_stats_p->num_stmt_anns++;
486             dfa_stats_p->num_defs += NUM_DEFS (DEF_OPS (ann));
487             dfa_stats_p->num_uses += NUM_USES (USE_OPS (ann));
488             dfa_stats_p->num_v_may_defs +=
489                          NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann));
490             dfa_stats_p->num_vuses += NUM_VUSES (VUSE_OPS (ann));
491             dfa_stats_p->num_v_must_defs +=
492                          NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann));
493             break;
494           }
495
496         case VAR_ANN:
497           dfa_stats_p->num_var_anns++;
498           break;
499
500         default:
501           break;
502         }
503     }
504
505   return NULL;
506 }
507
508
509 /*---------------------------------------------------------------------------
510                              Miscellaneous helpers
511 ---------------------------------------------------------------------------*/
512 /* Callback for walk_tree.  Used to collect variables referenced in
513    the function.  */
514
515 static tree
516 find_vars_r (tree *tp, int *walk_subtrees, void *data)
517 {
518   struct walk_state *walk_state = (struct walk_state *) data;
519
520   /* If T is a regular variable that the optimizers are interested
521      in, add it to the list of variables.  */
522   if (SSA_VAR_P (*tp))
523     add_referenced_var (*tp, walk_state);
524
525   /* Type, _DECL and constant nodes have no interesting children.
526      Ignore them.  */
527   else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
528     *walk_subtrees = 0;
529
530   return NULL_TREE;
531 }
532
533
534 /* Add VAR to the list of dereferenced variables.
535
536    WALK_STATE contains a hash table used to avoid adding the same
537       variable more than once. Note that this function assumes that
538       VAR is a valid SSA variable.  If WALK_STATE is NULL, no
539       duplicate checking is done.  */
540
541 static void
542 add_referenced_var (tree var, struct walk_state *walk_state)
543 {
544   void **slot;
545   var_ann_t v_ann;
546
547   v_ann = get_var_ann (var);
548
549   if (walk_state)
550     slot = htab_find_slot (walk_state->vars_found, (void *) var, INSERT);
551   else
552     slot = NULL;
553
554   if (slot == NULL || *slot == NULL)
555     {
556       /* This is the first time we find this variable, add it to the
557          REFERENCED_VARS array and annotate it with attributes that are
558          intrinsic to the variable.  */
559       if (slot)
560         *slot = (void *) var;
561       v_ann->uid = num_referenced_vars;
562       VARRAY_PUSH_TREE (referenced_vars, var);
563
564       /* Global variables are always call-clobbered.  */
565       if (is_global_var (var))
566         mark_call_clobbered (var);
567
568       /* Scan DECL_INITIAL for pointer variables as they may contain
569          address arithmetic referencing the address of other
570          variables.  */
571       if (DECL_INITIAL (var)
572           /* Initializers of external variables are not useful to the
573              optimizers.  */
574           && !DECL_EXTERNAL (var)
575           /* It's not necessary to walk the initial value of non-constant
576              public variables because it cannot be propagated by the
577              optimizers.  */
578           && (!TREE_PUBLIC (var) || !TREE_CONSTANT (var)))
579         walk_tree (&DECL_INITIAL (var), find_vars_r, walk_state, 0);
580     }
581 }
582
583
584 /* Return the virtual variable associated to the non-scalar variable VAR.  */
585
586 tree
587 get_virtual_var (tree var)
588 {
589   STRIP_NOPS (var);
590
591   if (TREE_CODE (var) == SSA_NAME)
592     var = SSA_NAME_VAR (var);
593
594   while (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR
595          || handled_component_p (var))
596     var = TREE_OPERAND (var, 0);
597
598   /* Treating GIMPLE registers as virtual variables makes no sense.
599      Also complain if we couldn't extract a _DECL out of the original
600      expression.  */
601   gcc_assert (SSA_VAR_P (var));
602   gcc_assert (!is_gimple_reg (var));
603
604   return var;
605 }
606
607 /* Add a temporary variable to REFERENCED_VARS.  This is similar to
608    add_referenced_var, but is used by passes that need to add new temps to
609    the REFERENCED_VARS array after the program has been scanned for
610    variables.  The variable will just receive a new UID and be added
611    to the REFERENCED_VARS array without checking for duplicates.  */
612
613 void
614 add_referenced_tmp_var (tree var)
615 {
616   add_referenced_var (var, NULL);
617 }
618
619
620 /* Add all the non-SSA variables found in STMT's operands to the bitmap
621    VARS_TO_RENAME.  */
622
623 void
624 mark_new_vars_to_rename (tree stmt, bitmap vars_to_rename)
625 {
626   ssa_op_iter iter;
627   tree val;
628   bitmap vars_in_vops_to_rename;
629   bool found_exposed_symbol = false;
630   int v_may_defs_before, v_may_defs_after;
631   int v_must_defs_before, v_must_defs_after;
632
633   vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
634
635   /* Before re-scanning the statement for operands, mark the existing
636      virtual operands to be renamed again.  We do this because when new
637      symbols are exposed, the virtual operands that were here before due to
638      aliasing will probably be removed by the call to get_stmt_operand.
639      Therefore, we need to flag them to be renamed beforehand.
640
641      We flag them in a separate bitmap because we don't really want to
642      rename them if there are not any newly exposed symbols in the
643      statement operands.  */
644   v_may_defs_before = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
645   v_must_defs_before = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
646
647   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, 
648                              SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
649     {
650       if (!DECL_P (val))
651         val = SSA_NAME_VAR (val);
652       bitmap_set_bit (vars_in_vops_to_rename, var_ann (val)->uid);
653     }
654
655   /* Now force an operand re-scan on the statement and mark any newly
656      exposed variables.  */
657   update_stmt (stmt);
658
659   v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
660   v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
661
662   FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
663     {
664       if (DECL_P (val))
665         {
666           found_exposed_symbol = true;
667           bitmap_set_bit (vars_to_rename, var_ann (val)->uid);
668         }
669     }
670
671   /* If we found any newly exposed symbols, or if there are fewer VDEF
672      operands in the statement, add the variables we had set in
673      VARS_IN_VOPS_TO_RENAME to VARS_TO_RENAME.  We need to check for
674      vanishing VDEFs because in those cases, the names that were formerly
675      generated by this statement are not going to be available anymore.  */
676   if (found_exposed_symbol
677       || v_may_defs_before > v_may_defs_after
678       || v_must_defs_before > v_must_defs_after)
679     bitmap_ior_into (vars_to_rename, vars_in_vops_to_rename);
680
681   BITMAP_FREE (vars_in_vops_to_rename);
682 }
683
684 /* Find all variables within the gimplified statement that were not previously
685    visible to the function and add them to the referenced variables list.  */
686
687 static tree
688 find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
689                             void *data ATTRIBUTE_UNUSED)
690 {
691   tree t = *tp;
692
693   if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
694     add_referenced_tmp_var (t);
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 /* Mark all call-clobbered variables for renaming.  */
710
711 void
712 mark_call_clobbered_vars_to_rename (void)
713 {
714   unsigned i;
715   bitmap_iterator bi;
716   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
717     {
718       tree var = referenced_var (i);
719       bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
720     }
721 }
722
723 /* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
724    we know where REF is accessing, return the variable in REF that has the
725    sub-variables.  If the return value is not NULL, POFFSET will be the
726    offset, in bits, of REF inside the return value, and PSIZE will be the
727    size, in bits, of REF inside the return value.  */
728
729 tree
730 okay_component_ref_for_subvars (tree ref, HOST_WIDE_INT *poffset,
731                                 HOST_WIDE_INT *psize)
732 {
733   tree result = NULL;
734   HOST_WIDE_INT bitsize;
735   HOST_WIDE_INT bitpos;
736   tree offset;
737   enum machine_mode mode;
738   int unsignedp;
739   int volatilep;
740
741   gcc_assert (!SSA_VAR_P (ref));
742   *poffset = 0;  
743   *psize = (unsigned int) -1;
744   
745   if (ref_contains_array_ref (ref))
746     return result;
747   ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
748                              &unsignedp, &volatilep, false);
749   if (TREE_CODE (ref) == INDIRECT_REF)
750     return result;
751   else if (offset == NULL && bitsize != -1 && SSA_VAR_P (ref))
752     {
753       *poffset = bitpos;      
754       *psize = bitsize;
755       if (get_subvars_for_var (ref) != NULL)
756         return ref;
757     }
758   else if (SSA_VAR_P (ref))
759     {
760       if (get_subvars_for_var (ref) != NULL)
761         return ref;
762     }
763   return NULL_TREE;
764 }