OSDN Git Service

2006-01-14 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Jan 2006 14:30:33 +0000 (14:30 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Jan 2006 14:30:33 +0000 (14:30 +0000)
PR tree-optimization/22548
PR tree-optimization/22555
PR tree-optimization/22501
* Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
* params.def (salias-max-array-elements): New parameter.
* params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
* doc/invoke.texi (salias-max-array-elements): Document.
* tree-flow-inline.h (var_can_have_subvars): We also handle
arrays now.
* tree-ssa-alias.c (find_used_portions): Handle ARRAY_REF like
COMPONENT_REF.
* tree-ssa-structalias.c (params.h): Include.
(push_fields_onto_fieldstack): Handle ARRAY_TYPE.
(find_func_aliases): Handle multiple constraints from ARRAY_REF.
(get_constraint_for): For ADDR_EXPR operating on something
containing an ARRAY_REF, add all subvars to the solution.
(handle_ptr_arith): Handle ARRAY_TYPE like RECORD_TYPE types.
* tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
for creating MUST_DEFs.
(get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.

* gcc.dg/tree-ssa/alias-4.c: New testcase.
* gcc.dg/tree-ssa/alias-5.c: Likewise.
* gcc.dg/tree-ssa/alias-6.c: Likewise.
* gcc.dg/tree-ssa/alias-7.c: Likewise.
* gcc.dg/tree-ssa/alias-8.c: Likewise.
* gcc.dg/tree-ssa/alias-9.c: Likewise.
* gcc.dg/tree-ssa/alias-10.c: Likewise.
* gcc.dg/tree-ssa/alias-11.c: Likewise.
* gcc.dg/tree-ssa/alias-12.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109703 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/doc/invoke.texi
gcc/params.def
gcc/params.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/alias-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-11.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-9.c [new file with mode: 0644]
gcc/tree-flow-inline.h
gcc/tree-ssa-alias.c
gcc/tree-ssa-operands.c
gcc/tree-ssa-structalias.c

index 2422704..b9dc3c2 100644 (file)
@@ -1,3 +1,26 @@
+2006-01-14  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/22548
+       PR tree-optimization/22555
+       PR tree-optimization/22501
+       * Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
+       * params.def (salias-max-array-elements): New parameter.
+       * params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
+       * doc/invoke.texi (salias-max-array-elements): Document.
+       * tree-flow-inline.h (var_can_have_subvars): We also handle
+       arrays now.
+       * tree-ssa-alias.c (find_used_portions): Handle ARRAY_REF like
+       COMPONENT_REF.
+       * tree-ssa-structalias.c (params.h): Include.
+       (push_fields_onto_fieldstack): Handle ARRAY_TYPE.
+       (find_func_aliases): Handle multiple constraints from ARRAY_REF.
+       (get_constraint_for): For ADDR_EXPR operating on something
+       containing an ARRAY_REF, add all subvars to the solution.
+       (handle_ptr_arith): Handle ARRAY_TYPE like RECORD_TYPE types.
+       * tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
+       for creating MUST_DEFs.
+       (get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.
+
 2006-01-14  Zdenek Dvorak <dvorakz@suse.cz>
 
        * tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
index aa3c301..45152ae 100644 (file)
@@ -1792,7 +1792,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
    $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
    $(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H) \
-   gt-tree-ssa-structalias.h
+   gt-tree-ssa-structalias.h $(PARAMS_H)
 tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
    toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
index b428f2d..032f3ad 100644 (file)
@@ -5744,6 +5744,10 @@ The maximum number of fields in a variable without direct
 structure accesses for which structure aliasing will consider trying 
 to track each field.  The default is 5
 
+@item salias-max-array-elements
+The maximum number of elements an array can have and its elements
+still be tracked individually by structure aliasing. The default is 4
+
 @item sra-max-structure-size
 The maximum structure size, in bytes, at which the scalar replacement
 of aggregates (SRA) optimization will perform block copies.  The
index 7690383..33fa444 100644 (file)
@@ -47,7 +47,14 @@ DEFPARAM (PARAM_SALIAS_MAX_IMPLICIT_FIELDS,
          "salias-max-implicit-fields",
          "The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
          5, 0, 0)
-   
+
+/* The maximum number of array elements structure aliasing will decompose
+   an array for.  The default is 4.  */
+DEFPARAM (PARAM_SALIAS_MAX_ARRAY_ELEMENTS,
+         "salias-max-array-elements",
+         "The maximum number of elements in an array for wich we track its elements separately",
+         4, 0, 0)
+
 /* The maximum structure size at which the scalar replacement of
    aggregates (SRA) pass will perform block copies.  The default
    value, 0, implies that GCC will select the most appropriate size
index 6c9f7d6..f641939 100644 (file)
@@ -91,6 +91,8 @@ typedef enum compiler_param
 /* Macros for the various parameters.  */
 #define SALIAS_MAX_IMPLICIT_FIELDS \
   PARAM_VALUE (PARAM_SALIAS_MAX_IMPLICIT_FIELDS)
+#define SALIAS_MAX_ARRAY_ELEMENTS \
+  PARAM_VALUE (PARAM_SALIAS_MAX_ARRAY_ELEMENTS)
 #define SRA_MAX_STRUCTURE_SIZE \
   PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
 #define SRA_MAX_STRUCTURE_COUNT \
index ffe0dc9..318cc53 100644 (file)
@@ -1,3 +1,18 @@
+2006-01-14  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/22548
+       PR tree-optimization/22555
+       PR tree-optimization/22501
+       * gcc.dg/tree-ssa/alias-4.c: New testcase.
+       * gcc.dg/tree-ssa/alias-5.c: Likewise.
+       * gcc.dg/tree-ssa/alias-6.c: Likewise.
+       * gcc.dg/tree-ssa/alias-7.c: Likewise.
+       * gcc.dg/tree-ssa/alias-8.c: Likewise.
+       * gcc.dg/tree-ssa/alias-9.c: Likewise.
+       * gcc.dg/tree-ssa/alias-10.c: Likewise.
+       * gcc.dg/tree-ssa/alias-11.c: Likewise.
+       * gcc.dg/tree-ssa/alias-12.c: Likewise.
+
 2005-01-14  Zdenek Dvorak <dvorakz@suse.cz>
 
        * gcc.dg/tree-ssa/pr19210-1.c: Update outcome.  Add new test loop.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c
new file mode 100644 (file)
index 0000000..0395610
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct {
+       int i;
+       int x[2];
+       int j;
+} a;
+
+int foo(int i)
+{
+       a.i = 1;
+       a.j = 2;
+       a.x[i] = 0;
+       return a.i + a.j;
+}
+
+/* { dg-final { scan-tree-dump "return 3;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c
new file mode 100644 (file)
index 0000000..cccc512
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct param { int *a; };
+void foo(struct param *p);
+int bar(void)
+{
+  int a[32];
+  struct param p;
+  a[0] = 1;
+  a[1] = 1;
+  p.a = &a[0];
+  foo(&p);
+  return a[0] + *p.a;
+}
+
+/* { dg-final { scan-tree-dump "return \\*p\\.a \\\+ a.0.;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c
new file mode 100644 (file)
index 0000000..dbd3301
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-alias1-vops" } */
+
+struct {
+       int i;
+       int x[128];
+       int j;
+} a;
+
+int foo(int i)
+{
+       a.x[i] = 0;
+       return a.x[i];
+}
+
+/* { dg-final { scan-tree-dump "V_MAY_DEF" "alias1" } } */
+/* { dg-final { cleanup-tree-dump "alias1" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c
new file mode 100644 (file)
index 0000000..e039432
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct {
+       int i;
+       struct {
+               int x[2];
+       } b;
+} a;
+
+int foo(void)
+{
+       a.i = 1;
+       a.b.x[0] = 0;
+       a.b.x[1] = 1;
+       return a.i + a.b.x[0];
+}
+
+/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c
new file mode 100644 (file)
index 0000000..f1faae5
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct {
+       int i;
+       struct {
+               struct {
+                       int i;
+               } x[2];
+       } b;
+} a;
+
+int foo(void)
+{
+       a.i = 1;
+       a.b.x[0].i = 0;
+       a.b.x[1].i = 1;
+       return a.i + a.b.x[0].i;
+}
+
+/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c
new file mode 100644 (file)
index 0000000..460dd11
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct param { int *a; };
+void foo(struct param *p);
+int bar(void)
+{
+  int a[2];
+  struct param p;
+  a[0] = 1;
+  a[1] = 1;
+  p.a = &a[0];
+  foo(&p);
+  return a[0] + *p.a;
+}
+
+/* { dg-final { scan-tree-dump "return \\*p\\.a \\\+ a.0.;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c
new file mode 100644 (file)
index 0000000..7ef604b
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort(void);
+int main()
+{
+  int a[2];
+  int *p = a;
+  int i;
+  a[0] = 1;
+  a[1] = 2;
+  for (i=0; i<2; ++i)
+    if (p[i] != i+1)
+      abort();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c
new file mode 100644 (file)
index 0000000..7c825f9
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort(void);
+int main()
+{
+  int a[2];
+  int i = 1;
+  a[0] = 1;
+  a[1] = 2;
+  if (*(a + i) != 2)
+    abort();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c
new file mode 100644 (file)
index 0000000..0a20e05
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort(void);
+int main()
+{
+  int a[32];
+  int i = 1;
+  a[0] = 1;
+  a[1] = 2;
+  if (*(a + i) != 2)
+    abort();
+  return 0;
+}
+
index 3f8e89d..7e36ccc 100644 (file)
@@ -1489,8 +1489,7 @@ get_subvar_at (tree var, unsigned HOST_WIDE_INT offset)
 }
 
 /* Return true if V is a tree that we can have subvars for.
-   Normally, this is any aggregate type, however, due to implementation
-   limitations ATM, we exclude array types as well.  Also complex
+   Normally, this is any aggregate type.  Also complex
    types which are not gimple registers can have subvars.  */
 
 static inline bool
@@ -1500,9 +1499,8 @@ var_can_have_subvars (tree v)
   if (!DECL_P (v) || MTAG_P (v))
     return false;
 
-  /* Aggregates besides arrays can have subvars.  */
-  if (AGGREGATE_TYPE_P (TREE_TYPE (v))
-      && TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+  /* Aggregates can have subvars.  */
+  if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
     return true;
 
   /* Complex types variables which are not also a gimple register can
index 6676303..353e7bd 100644 (file)
@@ -2698,6 +2698,7 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case COMPONENT_REF:
+    case ARRAY_REF:
       {
        HOST_WIDE_INT bitsize;
        HOST_WIDE_INT bitmaxsize;
index 6787dc2..87a1fc6 100644 (file)
@@ -732,8 +732,7 @@ parse_ssa_operands (tree stmt)
        if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
          lhs = TREE_OPERAND (lhs, 0);
 
-       if (TREE_CODE (lhs) != ARRAY_REF
-           && TREE_CODE (lhs) != ARRAY_RANGE_REF
+       if (TREE_CODE (lhs) != ARRAY_RANGE_REF
            && TREE_CODE (lhs) != BIT_FIELD_REF)
          lhs_flags |= opf_kill_def;
 
@@ -1101,7 +1100,6 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       get_tmr_operands (stmt, expr, flags);
       return;
 
-    case ARRAY_REF:
     case ARRAY_RANGE_REF:
       /* Treat array references as references to the virtual variable
         representing the array.  The virtual variable for an ARRAY_REF
@@ -1115,6 +1113,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
       return;
 
+    case ARRAY_REF:
     case COMPONENT_REF:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
@@ -1162,6 +1161,12 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
              s_ann->has_volatile_ops = true; 
            get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
          }
+       else if (code == ARRAY_REF)
+         {
+            get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
+            get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+            get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
+         }
        return;
       }
     case WITH_SIZE_EXPR:
@@ -1192,8 +1197,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
        op = TREE_OPERAND (expr, 0);
        if (TREE_CODE (op) == WITH_SIZE_EXPR)
          op = TREE_OPERAND (expr, 0);
-       if (TREE_CODE (op) == ARRAY_REF
-           || TREE_CODE (op) == ARRAY_RANGE_REF
+       if (TREE_CODE (op) == ARRAY_RANGE_REF
            || TREE_CODE (op) == REALPART_EXPR
            || TREE_CODE (op) == IMAGPART_EXPR)
          subflags = opf_is_def;
index e7b47fc..90bd037 100644 (file)
@@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #include "timevar.h"
 #include "alloc-pool.h"
 #include "splay-tree.h"
+#include "params.h"
 #include "tree-ssa-structalias.h"
 #include "cgraph.h"
 
@@ -2493,8 +2494,30 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
            {
              struct constraint_expr *c;
              unsigned int i;
-
-             get_constraint_for (TREE_OPERAND (t, 0), results);
+             tree exp = TREE_OPERAND (t, 0);
+
+             get_constraint_for (exp, results);
+             /* Make sure we capture constraints to all elements
+                of an array.  */
+             if ((handled_component_p (exp)
+                  && ref_contains_array_ref (exp))
+                 || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+               {
+                 struct constraint_expr *origrhs;
+                 varinfo_t origvar;
+                 struct constraint_expr tmp;
+
+                 gcc_assert (VEC_length (ce_s, *results) == 1);
+                 origrhs = VEC_last (ce_s, *results);
+                 tmp = *origrhs;
+                 VEC_pop (ce_s, *results);
+                 origvar = get_varinfo (origrhs->var);
+                 for (; origvar; origvar = origvar->next)
+                   {
+                     tmp.var = origvar->id;
+                     VEC_safe_push (ce_s, heap, *results, &tmp);
+                   }
+               }
              for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
                {
                  if (c->type == DEREF)
@@ -3151,7 +3174,6 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
 
   get_constraint_for (op0, &temp);
   if (POINTER_TYPE_P (TREE_TYPE (op0))
-      && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == RECORD_TYPE
       && TREE_CODE (op1) == INTEGER_CST)
     {
       rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
@@ -3378,7 +3400,8 @@ find_func_aliases (tree origt)
                        
                        get_constraint_for (rhsop, &rhsc);
                        if (TREE_CODE (strippedrhs) == ADDR_EXPR
-                           && AGGREGATE_TYPE_P (TREE_TYPE (rhstype)))
+                           && AGGREGATE_TYPE_P (TREE_TYPE (rhstype))
+                           && VEC_length (ce_s, rhsc) == 1)
                          {
                            struct constraint_expr *origrhs;
                            varinfo_t origvar;
@@ -3568,6 +3591,63 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       return 2;
     }
 
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree sz = TYPE_SIZE (type);
+      tree elsz = TYPE_SIZE (TREE_TYPE (type));
+      HOST_WIDE_INT nr;
+      int i;
+
+      if (! sz
+         || ! host_integerp (sz, 1)
+         || TREE_INT_CST_LOW (sz) == 0
+         || ! elsz
+         || ! host_integerp (elsz, 1)
+         || TREE_INT_CST_LOW (elsz) == 0)
+       return 0;
+
+      nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
+      if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
+       return 0;
+
+      for (i = 0; i < nr; ++i)
+       {
+         bool push = false;
+         int pushed = 0;
+       
+         if (has_union 
+             && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
+                 || TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
+           *has_union = true;
+       
+         if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
+           push = true;
+         else if (!(pushed = push_fields_onto_fieldstack
+                    (TREE_TYPE (type), fieldstack,
+                     offset + i * TREE_INT_CST_LOW (elsz), has_union)))
+           /* Empty structures may have actual size, like in C++. So
+              see if we didn't push any subfields and the size is
+              nonzero, push the field onto the stack */
+           push = true;
+
+         if (push)
+           {
+             fieldoff_s *pair;
+
+             pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+             pair->type = TREE_TYPE (type);
+             pair->size = elsz;
+             pair->decl = NULL_TREE;
+             pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
+             count++;
+           }
+         else
+           count += pushed;
+       }
+
+      return count;
+    }
+
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
       {