]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/33870 (miscompiles sqlite)
authorRichard Guenther <rguenther@suse.de>
Fri, 16 Nov 2007 14:40:04 +0000 (14:40 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 16 Nov 2007 14:40:04 +0000 (14:40 +0000)
2007-11-16  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/33870
* tree.h (struct tree_memory_tag): Add base_for_components flag.
(struct tree_struct_field_tag): Remove nesting_level field.
(SFT_NESTING_LEVEL): Remove.
(SFT_BASE_FOR_COMPONENTS_P): Add.
* tree-flow.h (struct fieldoff): Remove nesting_level field.  Add
base_for_components flag.
(push_fields_onto_fieldstack): Remove nesting_level parameter.
* tree-ssa-alias.c (create_sft): Likewise.  Add base_for_components
parameter.
(create_overlap_variables_for): Deal with it.
* tree-dfa.c (dump_subvars_for): Likewise.
(dump_variable): Likewise.
* tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
Set base_for_components for first elements of sub-structures.
(create_variable_info_for): Handle base_for_components.
(set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
* tree-ssa-operands.c (ref_nesting_level): Remove.
(add_vars_for_offset): Remove full_ref parameter, always add
the offset of the pointed-to SFT.
(add_virtual_operand): Adjust for changed signature of
add_vars_for_offset.

* gcc.dg/torture/pr33870.c: New testcase.

From-SVN: r130231

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr33870.c [new file with mode: 0644]
gcc/tree-dfa.c
gcc/tree-flow.h
gcc/tree-ssa-alias.c
gcc/tree-ssa-operands.c
gcc/tree-ssa-structalias.c
gcc/tree.h

index bcbedcc521403bc18236f98c27cc63d04ec73843..007aff185f3bffbce32f3a0abde503b6fbf029a4 100644 (file)
@@ -1,3 +1,29 @@
+2007-11-16  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/33870
+       * tree.h (struct tree_memory_tag): Add base_for_components flag.
+       (struct tree_struct_field_tag): Remove nesting_level field.
+       (SFT_NESTING_LEVEL): Remove.
+       (SFT_BASE_FOR_COMPONENTS_P): Add.
+       * tree-flow.h (struct fieldoff): Remove nesting_level field.  Add
+       base_for_components flag.
+       (push_fields_onto_fieldstack): Remove nesting_level parameter.
+       * tree-ssa-alias.c (create_sft): Likewise.  Add base_for_components
+       parameter.
+       (create_overlap_variables_for): Deal with it.
+       * tree-dfa.c (dump_subvars_for): Likewise.
+       (dump_variable): Likewise.
+       * tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
+       Set base_for_components for first elements of sub-structures.
+       (create_variable_info_for): Handle base_for_components.
+       (set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
+       pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
+       * tree-ssa-operands.c (ref_nesting_level): Remove.
+       (add_vars_for_offset): Remove full_ref parameter, always add
+       the offset of the pointed-to SFT.
+       (add_virtual_operand): Adjust for changed signature of
+       add_vars_for_offset.
+
 2007-11-16  Sa Liu  <saliu@de.ibm.com>
 
        * config/spu/spu.md (floatunssidf2, floatunsdidf2): Inlined 
index 49c708ce9e18d73a8f2a1a4945d20dc489165f78..dc2c207a328d32836fde09425254ea41452a1bbb 100644 (file)
@@ -1,3 +1,8 @@
+2007-11-16  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/33870
+       * gcc.dg/torture/pr33870.c: New testcase.
+
 2007-11-16  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/33986
diff --git a/gcc/testsuite/gcc.dg/torture/pr33870.c b/gcc/testsuite/gcc.dg/torture/pr33870.c
new file mode 100644 (file)
index 0000000..519efd3
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "--param max-aliased-vops=1" } */
+
+struct X {
+  int i;
+  int a[4];
+} m;
+
+int a[4];
+
+int __attribute__((noinline)) foo(int b)
+{
+  int (*p)[4] = b ? &a : &m.a;
+  a[3] = 0;
+  (*p)[3] = 1;
+  return (*p)[3] + (*p)[2] + (*p)[1] + a[0] + a[3];
+}
+
+extern void abort (void);
+
+int main()
+{
+  int i;
+  for (i = 0; i < 4; ++i)
+    a[i] = 0;
+  if (foo(1) != 2)
+    abort ();
+  return 0;
+}
+
index 65a32d935d1abdce0c6d4ceb024914fe2b668d29..f79df0bb2b83703ffa45a324b98efea3b83f76a5 100644 (file)
@@ -288,7 +288,8 @@ dump_subvars_for (FILE *file, tree var)
     {
       print_generic_expr (file, subvar, dump_flags);
       fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));
-      fprintf (file, "[%u]", SFT_NESTING_LEVEL (subvar));
+      if (SFT_BASE_FOR_COMPONENTS_P (subvar))
+        fprintf (file, "[B]");
       fprintf (file, " ");
     }
 
@@ -424,7 +425,8 @@ dump_variable (FILE *file, tree var)
        {
          fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
                   SFT_OFFSET (var));
-         fprintf (file, ", nesting: %u", SFT_NESTING_LEVEL (var));
+         fprintf (file, ", base for components: %s",
+                  SFT_BASE_FOR_COMPONENTS_P (var) ? "NO" : "YES");
          fprintf (file, ", partitionable: %s",
                   SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
        }
index 83761951859e1e50ad9267ef3190a3883bf38aea..4424922613c667533827ef1dd324becccaf81f25 100644 (file)
@@ -1159,22 +1159,21 @@ struct fieldoff
   /* Field.  */
   tree decl;
 
-  /* Nesting level.  This number represents how many structures are
-     wrapping this field.  */
-  unsigned nesting_level;
-
   /* Offset from the base of the base containing object to this field.  */
   HOST_WIDE_INT offset;  
 
   /* Alias set for the field.  */
   alias_set_type alias_set;
+
+  /* True, if this offset can be a base for further component accesses.  */
+  unsigned base_for_components : 1;
 };
 typedef struct fieldoff fieldoff_s;
 
 DEF_VEC_O(fieldoff_s);
 DEF_VEC_ALLOC_O(fieldoff_s,heap);
-int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **, HOST_WIDE_INT,
-                                bool *, tree, unsigned);
+int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **,
+                                HOST_WIDE_INT, bool *, tree);
 void sort_fieldstack (VEC(fieldoff_s,heap) *);
 
 void init_alias_heapvars (void);
index 43d5ab23ea749cd3a40606e99e2615023de0aaef..7d6c0e1fad1f7a3a763c022922f20cd383cc20ee 100644 (file)
@@ -3791,7 +3791,7 @@ get_or_create_used_part_for (size_t uid)
 static tree
 create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
            unsigned HOST_WIDE_INT size, alias_set_type alias_set,
-           unsigned nesting_level)
+           bool base_for_components)
 {
   tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
 
@@ -3811,7 +3811,8 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
   SFT_OFFSET (subvar) = offset;
   SFT_SIZE (subvar) = size;
   SFT_ALIAS_SET (subvar) = alias_set;
-  SFT_NESTING_LEVEL (subvar) = nesting_level;
+  SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components;
+  SFT_UNPARTITIONABLE_P (subvar) = false;
 
   return subvar;
 }
@@ -3833,7 +3834,7 @@ create_overlap_variables_for (tree var)
     return;
 
   push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
-                              TREE_TYPE (var), 0);
+                              TREE_TYPE (var));
   /* Make sure to not create SFTs for structs we won't generate variable
      infos for.  See tree-ssa-structalias.c:create_variable_info_for ().  */
   if (VEC_length (fieldoff_s, fieldstack) != 0
@@ -3919,6 +3920,7 @@ create_overlap_variables_for (tree var)
             field, skip it.  Note that we always need the field at
             offset 0 so we can properly handle pointers to the
             structure.  */
+
          if ((fo->offset != 0
               && ((fo->offset <= up->minused
                    && fo->offset + fosize <= up->minused)
@@ -3927,9 +3929,8 @@ create_overlap_variables_for (tree var)
                  && fosize == lastfosize
                  && currfotype == lastfotype))
            continue;
-
-         subvar = create_sft (var, fo->type, fo->offset, fosize,
-                              fo->alias_set, fo->nesting_level);
+         subvar = create_sft (var, fo->type, fo->offset,
+                              fosize, fo->alias_set, fo->base_for_components);
          VEC_quick_push (tree, *subvars, subvar);
 
          if (dump_file)
@@ -3940,8 +3941,7 @@ create_overlap_variables_for (tree var)
                       SFT_OFFSET (subvar));
              fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
                       SFT_SIZE (subvar));
-             fprintf (dump_file, " nesting level %d\n",
-                      SFT_NESTING_LEVEL (subvar));
+             fprintf (dump_file, "\n");
            }
          
          lastfotype = currfotype;
index cd8ade686393c0d06b6faa978b093eeb71cf8402..1f491cabf627a2588dc8e6e30e2851ffe9e5fbd1 100644 (file)
@@ -1367,36 +1367,10 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
   return true;
 }
 
-
-/* Given an aggregate expression FULL_REF, return the number of
-   aggregates that are containing FULL_REF.  So, given a structure
-   reference a.b.c.d, the nesting level for this expression is 2 (the
-   number of '.' in the expression minus 1).  */
-
-static unsigned
-ref_nesting_level (tree full_ref)
-{
-  unsigned nesting_level = 0;
-
-  if (!handled_component_p (full_ref))
-    return 0;
-
-  full_ref = TREE_OPERAND (full_ref, 0);
-  while (handled_component_p (full_ref))
-    {
-      nesting_level++;
-      full_ref = TREE_OPERAND (full_ref, 0);
-    }
-
-  return nesting_level;
-}
-
-
-/* Add the actual variables FULL_REF can access, given a member of
-   FULL_REF's points-to set VAR, where FULL_REF is an access of SIZE at
-   OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
-   is true if this is supposed to be a vdef, and false if this should
-   be a VUSE.
+/* Add the actual variables accessed, given a member of a points-to set
+   that is the SFT VAR, where the access is of SIZE at OFFSET from VAR.
+   IS_CALL_SITE is true if this is a call, and IS_DEF is true if this is
+   supposed to be a vdef, and false if this should be a VUSE.
 
    The real purpose of this function is to take a points-to set for a
    pointer to a structure, say
@@ -1411,12 +1385,10 @@ ref_nesting_level (tree full_ref)
    This is necessary because foop only actually points to foo's first
    member, so that is all the points-to set contains.  However, an access
    to foop->a may be touching some single SFT if we have created some
-   SFT's for a structure.
-
-   FULL_REF is the original memory expression being analyzed.  */
+   SFT's for a structure.  */
 
 static bool
-add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset,
+add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset,
                     unsigned HOST_WIDE_INT size, bool is_def)
 {
   bool added = false;
@@ -1424,55 +1396,8 @@ add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset,
   subvar_t sv;
   unsigned int i;
 
-  if (full_ref
-      && SFT_NESTING_LEVEL (var) > 0
-      && ref_nesting_level (full_ref) < SFT_NESTING_LEVEL (var))
-    {
-      /* Since VAR is an SFT inside a nested structure, the OFFSET
-        computed by get_ref_base_and_extent is the offset from the
-        start of the immediately containing structure.  If VAR is an
-        SFT inside a nested structure, then FULL_REF may be a
-        reference to the structure immediately enclosing SFT, and so
-        OFFSET will be the offset from the start of the immediately
-        enclosing structure.
-
-        However, to find out what other SFTs are affected by this
-        reference, we need to know the offsets starting at the root
-        structure in the nesting hierarchy.
-
-        For instance, given the following structure:
-
-               struct X {
-                 int a;
-                 struct Y {
-                   int b;
-                   struct Z {
-                     int c[3];
-                   } d;
-                 } e;
-               } m;
-
-        and the following address expression:
-
-               p_1 = &m.e.d;
-
-        This structure will receive 5 SFTs, namely 2 for fields 'a'
-        and 'b' and 3 for the array 'c' in struct Z.  So, the
-        reference p_1->c[2] and m.e.d.c[2] access the exact same
-        memory location (ie, SFT.5).
-
-        Now, alias analysis computed the points-to set for pointer
-        p_1 as  { SFT.3 } because that is the first field that p_1
-        actually points to.  When the expression p_1->c[2] is
-        analyzed, get_ref_base_and_extent will return an offset of 96
-        because we are accessing the third element of the array.  But
-        the SFT we are looking for is actually at offset 160,
-        counting from the top of struct X.
-
-        Therefore, we adjust OFFSET by the offset of VAR so that we
-        can get at all the fields starting at VAR.  */
-      offset += SFT_OFFSET (var);
-    }
+  /* Adjust offset by the pointed-to location.  */
+  offset += SFT_OFFSET (var);
 
   /* Add all subvars of var that overlap with the access.
      Binary search for the first relevant SFT.  */
@@ -1575,8 +1500,25 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
             if it is a potential points-to location.  */
          if (TREE_CODE (al) == STRUCT_FIELD_TAG
              && TREE_CODE (var) == NAME_MEMORY_TAG)
-           none_added &= !add_vars_for_offset (full_ref, al, offset, size,
-                                               flags & opf_def);
+           {
+             if (SFT_BASE_FOR_COMPONENTS_P (al))
+               {
+                 /* If AL is the first SFT of a component, it can be used
+                    to find other SFTs at [offset, size] adjacent to it.  */
+                 none_added &= !add_vars_for_offset (al, offset, size,
+                                                     flags & opf_def);
+               }
+             else if ((unsigned HOST_WIDE_INT)offset < SFT_SIZE (al))
+               {
+                 /* Otherwise, we only need to consider it if
+                    [offset, size] overlaps with AL.  */
+                 if (flags & opf_def)
+                   append_vdef (al);
+                 else
+                   append_vuse (al);
+                 none_added = false;
+               }
+           }
          else
            {
              /* Call-clobbered tags may have non-call-clobbered
index b175d252608146a56d2ad7aa2f9f65654c78e3b5..5fbcfc5cc55ed2fac84a1bb5ee91b11d3b4db390 100644 (file)
@@ -4053,19 +4053,16 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
    TYPE.
 
    ADDRESSABLE_TYPE is the type of the outermost object that could
-   have its address taken.
-
-   NESTING_LEVEL indicates whether TYPE is a structure nested inside
-   another, it starts at 0 and it is incremented by one on every
-   structure recursed into.  */
+   have its address taken.  */
 
 int
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                             HOST_WIDE_INT offset, bool *has_union,
-                            tree addressable_type, unsigned nesting_level)
+                            tree addressable_type)
 {
   tree field;
   int count = 0;
+  int first_element = VEC_length (fieldoff_s, *fieldstack);
 
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
@@ -4076,6 +4073,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       real_part->offset = offset;
       real_part->decl = NULL_TREE;
       real_part->alias_set = -1;
+      real_part->base_for_components = false;
 
       img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
       img_part->type = TREE_TYPE (type);
@@ -4083,11 +4081,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
       img_part->decl = NULL_TREE;
       img_part->alias_set = -1;
+      img_part->base_for_components = false;
 
-      return 2;
+      count = 2;
     }
 
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree sz = TYPE_SIZE (type);
       tree elsz = TYPE_SIZE (TREE_TYPE (type));
@@ -4125,8 +4124,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                      has_union,
                      (TYPE_NONALIASED_COMPONENT (type)
                       ? addressable_type
-                      : TREE_TYPE (type)),
-                     nesting_level + 1)))
+                      : TREE_TYPE (type)))))
            /* 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 */
@@ -4145,64 +4143,69 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                pair->alias_set = get_alias_set (addressable_type);
              else
                pair->alias_set = -1;
-             pair->nesting_level = nesting_level;
+             pair->base_for_components = false;
              count++;
            }
          else
            count += pushed;
        }
-
-      return count;
     }
 
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-    if (TREE_CODE (field) == FIELD_DECL)
-      {
-       bool push = false;
-       int pushed = 0;
-
-       if (has_union
-           && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
-               || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
-         *has_union = true;
-
-       if (!var_can_have_subvars (field))
-         push = true;
-       else if (!(pushed = push_fields_onto_fieldstack
-                  (TREE_TYPE (field),
-                   fieldstack,
-                   offset + bitpos_of_field (field),
-                   has_union,
-                   (DECL_NONADDRESSABLE_P (field)
-                    ? addressable_type
-                    : TREE_TYPE (field)),
-                   nesting_level + 1))
-                && DECL_SIZE (field)
-                && !integer_zerop (DECL_SIZE (field)))
-         /* 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)
+  else
+    {
+      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       if (TREE_CODE (field) == FIELD_DECL)
          {
-           fieldoff_s *pair;
-
-           pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
-           pair->type = TREE_TYPE (field);
-           pair->size = DECL_SIZE (field);
-           pair->decl = field;
-           pair->offset = offset + bitpos_of_field (field);
-           if (DECL_NONADDRESSABLE_P (field))
-             pair->alias_set = get_alias_set (addressable_type);
+           bool push = false;
+           int pushed = 0;
+
+           if (has_union
+               && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
+                   || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
+             *has_union = true;
+
+           if (!var_can_have_subvars (field))
+             push = true;
+           else if (!(pushed = push_fields_onto_fieldstack
+                      (TREE_TYPE (field),
+                       fieldstack,
+                       offset + bitpos_of_field (field),
+                       has_union,
+                       (DECL_NONADDRESSABLE_P (field)
+                        ? addressable_type
+                        : TREE_TYPE (field))))
+                    && DECL_SIZE (field)
+                    && !integer_zerop (DECL_SIZE (field)))
+             /* 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 (field);
+               pair->size = DECL_SIZE (field);
+               pair->decl = field;
+               pair->offset = offset + bitpos_of_field (field);
+               if (DECL_NONADDRESSABLE_P (field))
+                 pair->alias_set = get_alias_set (addressable_type);
+               else
+                 pair->alias_set = -1;
+               pair->base_for_components = false;
+               count++;
+             }
            else
-             pair->alias_set = -1;
-           pair->nesting_level = nesting_level;
-           count++;
-         }
-       else
-         count += pushed;
-      }
+             count += pushed;
+          }
+    }
+
+  /* Make sure the first pushed field is marked as eligible for
+     being a base for component references.  */
+  if (count > 0)
+    VEC_index (fieldoff_s, *fieldstack, first_element)->base_for_components = true;
 
   return count;
 }
@@ -4397,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
   if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
     {
       push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
-                                  decltype, 0);
+                                  decltype);
       if (hasunion)
        {
          VEC_free (fieldoff_s, heap, fieldstack);
@@ -4774,15 +4777,15 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
                    {
                      bitmap_set_bit (into, DECL_UID (sft));
                      
-                     /* If SFT is inside a nested structure, it will
-                        be needed by the operand scanner to adjust
-                        offsets when adding operands to memory
+                     /* Pointed-to SFTs are needed by the operand scanner
+                        to adjust offsets when adding operands to memory
                         expressions that dereference PTR.  This means
                         that memory partitioning may not partition
                         this SFT because the operand scanner will not
                         be able to find the other SFTs next to this
-                        one.  */
-                     if (SFT_NESTING_LEVEL (sft) > 0)
+                        one.  But we only need to do this if the pointed
+                        to type is aggregate.  */
+                     if (SFT_BASE_FOR_COMPONENTS_P (sft))
                        SFT_UNPARTITIONABLE_P (sft) = true;
                    }
                }
index 00b193fd77faf4d0cebe216302c86c31a5d8fc4b..0fb68ed7fd9e2a947383ae7e809ac8774f5a449d 100644 (file)
@@ -2557,6 +2557,10 @@ struct tree_memory_tag GTY(())
   /* True if this tag has global scope.  */
   unsigned int is_global : 1;
 
+  /* True if this tag is the first field of an aggregate type that
+     can be used to find adjacent SFTs belonging to the same aggregate.  */
+  unsigned int base_for_components : 1;
+
   /* True if this tag should not be grouped into a memory partition.  */
   unsigned int unpartitionable : 1;
 };
@@ -2579,23 +2583,17 @@ struct tree_struct_field_tag GTY(())
 
   /* Alias set for a DECL_NONADDRESSABLE_P field.  Otherwise -1.  */
   alias_set_type alias_set;
-
-  /* Nesting level for this subvariable.  This indicates how many
-     structures are wrapping this field.  Fields at the top level have
-     a nesting level of 0.  */
-  unsigned int nesting_level;
 };
-
 #define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var)
 #define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset)
 #define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size)
 #define SFT_NONADDRESSABLE_P(NODE) \
   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1)
 #define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set)
-#define SFT_NESTING_LEVEL(NODE) \
-  (STRUCT_FIELD_TAG_CHECK (NODE)->sft.nesting_level)
 #define SFT_UNPARTITIONABLE_P(NODE) \
   (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable)
+#define SFT_BASE_FOR_COMPONENTS_P(NODE) \
+  (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.base_for_components)
 
 /* Memory Partition Tags (MPTs) group memory symbols under one
    common name for the purposes of placing memory PHI nodes.  */